Michael: Hello and welcome to Postgres.FM,
a weekly show about

all things PostgreSQL.

I am Michael founder of pgMustard.

I'm joined as always by Nik, founder
of PostgresAI.

Hey Nik.

Nikolay: Hello Michael.

Michael: And we have a special
guest Fabrízio Mello, who is owner

of Timbira, software engineer at
PlanetScale and creator of pg_stat_log,

which is a new extension that we're
going to be talking about

today.

Welcome Fabrízio.

We're really glad you could join
us.

So pg_stat_log, do you want to give
us a little bit of what it

is and why you started work on
it.

Fabrízio: Well, pg_stat_log, it's
supposed to be an extension.

That solves, at least tries to
solve, a very tricky problem on

Postgres observability, that is,
collect information about your

logs in several different ways.

For example, you need to check
your logs for an error.

For example, your application is
erroring out for some reason

and you need to check what the
error is happening after some

deploy or something.

You need to go search the logs,
grab the logs, and depending

on where your Postgres is running,
it can be even tricky, right?

Because you have managed service
containers and all of different

environments running Postgres.

So you can have a bunch of different
ways to go to the logs and

look for some.

And pg_stat_log is essentially
a view.

It's a pg_stat view inside Postgres
that you collect counters,

collect information about what
is happening in your log.

It is grouped by backend types,
user ID, database ID, SQL error

code, and error level.

And you can configure pg_stat_log
to collect different error levels,

depending on how much information
you want to process those

counters.

So essentially a brief introduction
is this.

So make your life easier.

Instead of you go to jump into
weird tools to access log, you

have all the information you need,
the least basic information

inside your Postgres, then you
can attach some monitor to it

and collect this information.

And for example, see over the time,
error rate based on

a specific application, for example.

If you collect information for
a given user.

Nikolay: So I agree with you.

This is a big gap in Postgres observability
that we cannot understand

error rates beyond a couple of
things.

There is a rollback counter, like
transaction xact_commit, xact_

rollback, 2 counters in pg_stat_
database.

But what if some other error happened,
right?

And also, what kind of error?

Is it just like uniqueness violation
or it's corruption, like

codes, there are 3 codes for like
most painful codes, XX000,

XX001, XX002.

You mentioned error codes, there
is a registry of error codes,

but it's not possible to monitor
them other than just going to

logs.

But logs, I agree with you, it's
hard to reach them often.

But also they contain sometimes
personal data.

This PII, for example, Our stack
for PostgresAI, companies come

to us to analyze health of database,
and we don't deal with logs

directly, never.

Because we don't want to tell them
we deal with PII, because

everything we deal with is just
metadata, some counters, And

we want error rates like that,
right?

Grouped by, as you mentioned, by
multiple things.

For me, the most interesting is
error codes.

I want to know exactly, like, in
the past month, did we have

any XX codes in this database or
not?

It's not possible to answer.

It's insane that it's not possible
to answer, right?

There's another thing which is
not possible to answer.

It's queries per 2nd.

Not possible to answer.

You can extract it from pg_stat_database,
but it's maybe not the

whole iceberg, right?

Yeah, but it's a different story.

I'm also thinking, why is it not
like, why nobody's attacking

this missing piece?

But that's great.

So you built this extension and
1st question, you mentioned all

these things to group by, why there
is no query ID there?

Fabrízio: I think just because
I didn't add it yet, maybe for

the next version we can introduce
a query ID.

We are jumbling the query and providing
the query ID, we can

collect and store that as a new
key for this.

Nikolay: Because I want to know
which, for example, which queries

had these errors.

Right?

Fabrízio: That makes sense.

Makes sense.

Nikolay: Maybe it's expensive in
terms of overhead.

We can discuss overhead slightly
later maybe because it's a big

topic.

But another question I had, why
did you call it pg_stat_log, not

pg_stat_errors or something?

Fabrízio: Because we can collect
normal log messages as well.

So I created this configuration,
min error level, that you can

define what is the minimum error
level you can, you want to collect.

Nikolay: Not only error, also warnings
and notices like...

Fabrízio: Everything.

You can collect everything.

The default is a warning, error
level is error, but you can define

any error level.

Even debug.

Michael: I think default is warning.

Fabrízio: Oh, default is warning,
sorry.

Michael: Which is the same as,
you had a really good caveat section

in the README.

You mentioned about log_min_messages
as well, which also defaults

to warning.

So by default, both match, which
is nice.

But if you want more than warnings,
you also need to change that

because otherwise they don't end
up in the logs in the 1st place

and you're using that hook.

I think it's really cool for all
the reasons Nik mentioned,

but also potentially for more.

I feel like there's probably quite
a few things that are warnings

in the logs that probably a lot
of maybe managed service users

or maybe users in general just
don't ever notice because they

don't think to look in the logs
for warnings.

So I think exposing those via some
Monitoring tools or other

tools could be really useful as
well.

Just show you you do have warnings
going on in your logs, by

the way

Nikolay: Let's name the core of
the problem the root of the problem

there are like all SREs know methodologies
like USE, right? Brendan

Gregg's USE and four golden signals
We cannot apply them to Postgres

right now without digging the logs
all the time.

And this is insane that they cannot
apply basic methodologies,

because all of them include question,
do we have a spike of errors,

right?

We cannot answer.

Let's go grab logs and answer.

It's an insane situation, which
means that demand in this tool

is huge.

Everyone needs it.

Fabrízio: Yeah, you can get rid
of some complex stack like Logstash,

and

Nikolay: Yeah, exactly.

And all

Fabrízio: this stuff, Kibana, and
just have your simple view

and a postgres_exporter or something
collecting time to time information

from this view and send out to
Prometheus.

Grafana or something.

Nikolay: Exactly.

Like you can analyze it inside
database.

I saw weird extensions.

Fabrízio: Yeah, using R2, your
pg_ash.

Nikolay: Yeah, like that.

Like just self-collecting samples
and understand buckets and

so on.

It's possible.

But also, Because of lacking this
observability piece, I saw

long ago, like RDS had it as well,
extensions like foreign data

wrappers over logs just to bring
this visibility about errors

and something to SQL context, which
is like absolutely crazy

thing.

So yeah, that's great and it's
great to have it, but everywhere

we discussed it so far, and this
podcast won't be an exclusion,

I say this must be, I'm not asking,
I'm just saying, this must

be in core.

So.

Fabrízio: Yeah, what I was about
to ask you why do you want do

you think this should be in core?

It truly in core not as an extension
because my plan right now

is package this as a contrib module
and submit it upstream.

I didn't do it yet just for final
review.

Michael: Like pg_stat_statements.

Nikolay: Right.

Fabrízio: Yeah.

Like pg_stat_statements.

Like pg_stat_statements.

Nikolay: That's great.

I think this is the absolute minimum
that needs to be done.

But I also think pg_stat_statements should
be in core to avoid this

friction of creating extensions.

And this should be in core just
because, Again, any serious methodology

includes error analysis, and it's
not available without digging

logs.

And digging logs is not always
possible because it has a PII

and not all people have access
to it.

Not all external people or internal
people sometimes don't have

access because there is PII, like
emails or something, right?

We just don't need to know basic
things like error rates.

Without building this stack with
Kibana or something, I never

saw it working really well.

I saw many companies build this,
But the only thing I saw that

was working quite well was Splunk,
which costs millions of dollars.

Splunk costs millions of dollars
and requires a whole team to

manage.

It's a great piece of software,
super expensive.

I don't see any startup that could
afford it actually, in terms

of money and people allocated to
manage it.

So it should be simple.

Like error analysis must be simple.

That's why it must be in core,
available to everyone.

Fabrízio: And you know that, talking
about simplicity, this extension

was something that I wanted to
work for a long time.

And the main reason I didn't start
it many years ago was because,

oh, I need to build an entire pg_
stat_statements-like extension.

With serializing the information
to somewhere, and then

deserializing information and all
of those.

It's a lot of work, right?

And then I always have something
else to do.

And I never do.

Then the new feature Postgres released
on PG 18, Custom Cumulative

Stats.

That is great because open the
doors for the extension authors

to create their own statistics
like that.

And then the statistics collector
of Postgres, you do the job

to collect your statistics.

So it abstracts a lot of complexity
of dealing with a lot of

memory, serializing, deserializing
stuff.

And Postgres, and on the extension
side, we need to deal only

with the business logic of the
thing, what you want to collect,

right?

So this is 1 of the reasons that
I started.

The 2nd reason is, okay, I need
to try more AI tools because

I'm an old guy trying new AI stuff
and then I tried it.

And the 3rd reason because Nik
liked it very much and pushed

me a bit.

Okay, we need to do this, we need
to have this in core.

So let's do this.

Then I bootstrap the 1st version
and then Nik, helping me using

AI tools, reviewing, testing, and
all of the edge cases.

So now we have a good state of
code that is good enough to send

to upstream like a contrib module
like pg_stat_statements.

Those are 1 of the reasons that
I decided to do this right now.

It means that this extension won't
work for example, with PG

17, 16 only on PG 18 and next versions.

Michael: Nice.

I saw you already added 19 support
as well.

Was that much additional work or
was that relatively straightforward

in the end?

Fabrízio: I think it was only 1

Nikolay: macro,

Fabrízio: only 1 small piece of
code.

It's just 1 commit to make it work.

The most part of it.

The issue is the same Because some
internal data structures was

renamed or moved around and then
I just used a macro or two to

make it compatible either on 18
or 19.

Even on main Postgres branch is
compatible right now.

Michael: Nice, perfect.

Fabrízio: For the 20 development
cycle.

Nikolay: That's good.

Let's talk a little bit about overhead
and observer effect.

What's the price of having all
those counters?

Fabrízio: I did some very basic
benchmarks.

The overhead I saw, setting the
min error level to log everything

and run some pgbench synthetic
workload I max around 2-3%

of overhead

Nikolay: What was QPS and how many
log messages per 2nd?

Fabrízio: Come on, I don't...

I think I have this information
in the issue.

Nikolay: Yeah, I'm very curious.

Maybe I want to dig myself.

I just need to find time.

Michael: Just to be clear though,
the default here is warning

and we're, but we're all saying
that it would be useful at warning

or even error, it would still be
extremely useful.

So presumably at those levels,
it's going to be near 0 overhead.

Fabrízio: Yes, exactly.

Yeah.

I tested on the worst case scenario.

1 of the worst case scenario, logging
everything and then collecting

everything.

And then now I discovered something
that I'm working on because

we need to configure the capacity
of how many lines we collect,

how many entries we collect in
this pg_stat_log, like pg_stat_statements.

Nikolay: And pg_stat_statements
is 5000 by default, pg_stat_statements

dot max.

Fabrízio: Yeah, exactly.

And then a new different entry
came.

I'm not doing O(1) now, brute
forcing.

And this make expensive.

I have 1 entry that should be discarded,
be dropped and not collected

because my list is full.

My list of entries that I'm collecting
right now is full.

So this, I think Nik advised me
to create this dropped information

on the pg_stat_log_info() to see
how many messages were not collected.

And when we reach to this point,
then the performance is even

worse.

The overhead is like 27% or 30%.

So I'm here working the main algorithm
to don't be so expensive.

Nikolay: Right.

We talk about overhead here on
the edge case when it's basically

a stress load, when we have a lot
of log messages happening.

Then it's worth noticing that these
messages go to logs as well,

right?

If we have so many log messages,
we have observer effects there

anyway.

Fabrízio: Yes, you have problem
anyway because your log is...

Nikolay: All queries, this is simple.

Let's set log_statement to all,
and let's go.

This is how you can put your server
down If it's loaded.

So it means that overhead you introduce
is like sister or brother

overhead of what we already have
in logs.

We're just slightly amplifying
it.

When amplifying, not badly, because
overhead from Writing to

disk is high.

If you write 1000 lines per 2nd
through a logging collector,

you will notice this.

And I know it.

You will notice it.

If you increment some count 1000
times per 2nd, you also probably

will notice it, but less.

So

Fabrízio: we should

Nikolay: log less, this should
be a rule, right?

And exploring overhead on edge
case makes sense just to understand

how much is...

Maybe we should explore with flame
graphs as well in normal conditions,

like how much is going to these
functions.

Also, contention risks.

Obviously you have some lightweight
lock introduced, right?

Fabrízio: Yes, I have some lightweight
lock introduced, but The

good news is that this is processed
by a stats collector, because

it's done on the stats collector
side.

But anyway, it's using the hot
path of the emit_log_hook.

So it creates contention.

But mostly CPU contention.

Memory contention is not too much,
but it's more CPU contention.

It's not disk contention because
we are not writing anything

on this, on the extension.

It's done on the stats collector
when you shut down server and

start the server because this is
done by another subsystem, not

in the extension itself.

We have a new abstraction that
Custom Cumulative Stats is created

that is great for extension developers.

Michael: Yeah, that's important.

So it means like a safe restart,
like not a crash, the stats

will persist.

Yeah.

Yeah.

But on crash it would be lost,
which makes sense.

Fabrízio: Yes.

It behaves like PG stats.

Nikolay: I think also granularity
matters, right?

Because you have some only some
limited number of aggregated

entries, right?

So aggregate by error code, by
database, user and severity level,

right?

But if we, for example, have very
volatile situation, I don't

know, like maybe a lot of users
we have, or maybe a lot of databases.

So we have a lot of entries, we
probably don't want them, right?

For example, my 1st thought is
maybe I don't want warnings, right?

Because it's too much, too much
information.

And I know I will be paying for
this overhead.

Maybe I want only errors.

But at the same time, I know some
warnings I definitely would

like to see.

For example, a warning about glibc
collation mismatch, like suggesting

that maybe we have some corruption,
silent corruption and so

on.

These were warnings I definitely
would love to catch.

Also, there are some errors I definitely
would like to ignore.

For example, uniqueness violation
counter is good.

But what if we start that database
and it says this very famous

error message, FATAL: the database
system is starting up.

It's not

Michael: an error

Nikolay: actually.

It's just like a quintal bit, but
it seems like an error and

we can have spike of errors.

Which means that, imagine we have
all of that.

To properly tune alerts, I probably
should make some decisions around

filtering.

What I want, what I don't want,
right?

And maybe it should be done not
later but sooner maybe I should

just cut some messages and this
could be some like filtering

Fabrízio: yeah some filtering
configuration yeah make a lot

of

Nikolay: I just give these warnings
shut them down so anything

like this it's more maybe wouldn't
let make life easier because

usually what I don't want is some
frequent noise for me.

And in this case, if we can discard
it, it makes the tool more

lightweight, right?

So overhead lower.

Just brainstorming a little bit.

Fabrízio: You can also create some
filtering for a specific user

you want only to track information
about a specific user.

Nikolay: But this is only later,
because you track all

Fabrízio: users.

Nikolay: I can't say I want only
this user.

There is no such filtering.

Anyway, so you mentioned this cumulative
statistics mechanism

appeared in Postgres 18, And this
is great.

Postgres once again became even
more extendable, extensible,

right?

Which is good.

I noticed you registered kind ID,
I don't know, 28, right?

The kind of statistics.

Right now the process is very interesting.

You go to wiki page and put it
there, right?

27 was pg_stat_plans from Lukas,
right?

I think now you 28 also after you,
who came, spock, pg_stat_login, right?

I think, yeah.

29 is spock and then number 30
is pg_stat_login.

So we have only 4 lines right now
because this is super fresh.

And you were number 2 actually
among these 4.

That's great.

I have 2 questions, actually.

I know there were some attempts
to create such like this thing,

like cumulative counters for errors.

1 of them was called extension,
or was called logerrors, right?

And I'm just curious, what are
the benefits from switching?

Because we use logerrors in a
few places.

I understand the internal benefit.

You use it in an official way right
now.

And I suspect data in your extension
will survive restarts, unlike

logerrors.

This is what I see easily.

Because they needed to implement
their own piece of shared memory

and all the machinery around it,
right?

Maybe it will survive as well if
they implemented it.

What else?

If, obviously, you take care of
warnings and your granularity

is better, maybe you will introduce
query ideas, which will be

nice, but dangerous and expensive,
right?

Like what else?

What's the benefit?

Fabrízio: So.

I wasn't aware about this extension
that you are mentioning?

I don't remember.

Nikolay: Yeah, logerrors, 1 word
without underscore.

Fabrízio: Ah, logerrors.

Okay, I found.

Nikolay: So, it's all I can answer
for you.

The main benefit will be if it
goes to core or at least as contrib

module, this will become packaging
much easier.

Fabrízio: Yes, absolutely.

Nikolay: Yeah.

Yeah.

And since you chose this new approach,
but what are the chances?

Obviously Postgres 19 is already
past beta 1, beta 2 is coming,

so cannot be included in Postgres
19.

Do you have plans for Postgres
20?

Fabrízio: Yeah, for Postgres 20.

For sure next year.

Next year, yeah.

I will publish it for next year.

Yes.

Nikolay: That's great.

I'm definitely willing to support
with any more testing and so

on.

I just want this to be there.

Because so many clusters I observed,
which needed.

And I just, honestly, like, when
we needed to analyze performance

using usually pgFouine and then
pgBadger.

Fabrízio: pgFouine.

Nikolay: I love it was pgFouine,
you remember?

And PHP.

Fabrízio: Yes, I remember.

You need to laugh.

Nikolay: Yeah, Perl, pgBadger.

And I remember guys who said, we're
going to switch on a logging

or everything for 5 minutes.

It will be hard for everybody,
but we need it because we need

to see the whole thing.

And now we have pg_stat_statements,
pg_wait_sampling, pg_stat_kcache,

and also another approach, like
Active Session History approach.

Great.

But errors are still a problem,
right?

And I just don't want to deal with
logs like that.

I want them to be a mechanism when
we already understood what's

happening at high level and we
need examples.

Then I want to go to logs, but
the scale of the problem, like

to triage the problem, I don't
need logs.

Fabrízio: Yeah.

Excellent.

Thanks for the question.

I think, do you have enough tools
now, you don't need pg

Badger?

Excellent.

Nikolay: I haven't touched it maybe
5 years.

I don't need it.

Fabrízio: Yeah, me neither.

It's been more than 5 years.

Nikolay: But in bigger companies
I deal with, we usually have

some already flow to process logs
either from RDS, CloudWatch,

pull them, put them somewhere.

So they have it, but they usually
have it not because of Postgres,

but for everything, right?

So some log collector and analysis,
Elastic, Kibana, all this,

right?

But I touch it less and less.

And I don't need it too often.

So yeah, this is, once this is
there, at least this contrib module,

life will become much easier when
we have incidents, right?

And we need to quickly understand
what's happening.

Michael has now.

Michael: I actually think this
is more interesting, not necessarily

from an incident point of view,
than from an ongoing minor issues

in the background type, things
that would go unnoticed otherwise.

I think incidents, normally somebody's
on the Zoom who can access

the logs and can check, does have
access to those things.

But I'm thinking the warnings that
are building up over time

that people aren't noticing, or
the errors that are, they're

affecting some users but not enough
to complain about.

Like those kinds of things.

What are our 10, what are this
application's top 10 errors this

month or this year or whatever?

I think that's super interesting,
even outside of incidents.

Maybe it helps with incidents too,
but I like the offering.

Nikolay: Inside incidents, usually
it's messy and the incident

produces a lot of logs.

It's really hard to deal with them.

You need tooling, you need expertise.

Of course AI helps to process in
large amounts, But when you

have a lot of basically bytes to
process, to fetch a few numbers,

it's easy to make mistakes.

And LLM makes mistakes when you
feed too much information to

it.

If you have very structured counters,
It's great.

Also, log can rotate.

You can analyze the wrong log file
in the middle of rotation

or something, and so on.

And storing those counters in some
time series, like snapshots,

over time is so much easier, so
much more manageable.

And in general Postgres moves in
this direction.

For example, we had checkpoints
and autovacuum, most data only

in logs.

Now it's slowly moving to the pg_stat
system.

For example, finally, pg_stat_bgwriter,
which always collected

information not about bgwriter,
but checkpointer and backends

as well.

Now it's already reorganized, so
there's pg_stat_checkpointer,

there's pg_stat_bgwriter, it's more
obvious.

And it's easier for LLM actually
to analyze what's happening

because naming matters a lot right
now.

That's why I asked pg_stat_log.

Is it like, I wish there was specifically
pg_stat_errors because

they all have errors, what kind
of, right?

But I understand the reasoning,
warnings and everything.

I understand that.

So counter-efficient, the process
of analysis efficient, that's

important.

And complete.

That's also important.

And fast.

Yeah, you can immediately understand
when exactly the spike happened

without grepping.

Fabrízio: Happens often again about
overhead.

I think the overhead introduced
by this extension is way less

than pg_stat_statements, for
example.

Nikolay: That's an interesting
statement.

We should maybe somehow with benchmarks
think about it.

Yeah, that's interesting.

Why do you think so, by the way?

Fabrízio: Because of what we do
in the extension, it's a very

simple hash.

Yeah, but pg_stat_statements need to normalize
the query and do a lot

of other stuff.

Oh, yes.

Yeah.

And it takes time.

It's a few cycles.

Nikolay: I proposed the introduction
of query ID, right?

You don't need to normalize, right?

Fabrízio: No, I don't need to normalize.

Nikolay: Yeah, because in logs
we also compute query ID mechanism,

right?

Michael: On the query ID front,
I think 1 of the downsides is

it would balloon the number of
entries you would need.

Like you've currently got the max
entries to 1024, which feels

not that high, but actually if
you think about how many people

actually run multiple databases
on the same server and actually

have like thousands of users is
probably pretty low.

Probably most people have a few
users that are doing a lot of

volume and each of those things
you mentioned is probably fairly

low cardinality so that by the
time they all multiply it's probably

still below 1000 which is great
But if you add query ID into

that as well, that's a much bigger
number.

Fabrízio: Yes.

1, 1 thinking about introducing
this, the query ID, maybe it

can be optional.

A Boolean configuration that you
can turn off.

And then you always have the query
ID and we issue don't collect

query ID to be 0 for example.

Michael: So what's the downside
of being What's the downside

of increase if I increase max entries
by a lot?

I guess that's just more shared
memory and slightly more delay

on writing it out on restart.

Are there any other downsides?

Fabrízio: It is a map in memory
that you to the time of how many

entries on your CPU.

And yes, but writing to the disk,
I don't think unless you have,

you know, not

Nikolay: a lot of bytes.

Fabrízio: Yeah, no, because I'm
not writing any text, only integers.

It's written.

Michael: It's very tiny.

Nikolay: Regarding query ID, pg_wait_sampling
also has this as

optional.

Fabrízio: This parameter you can
enable profiling per query,

so similar approach.

Nikolay: And I think it's even
off by default.

I think so, maybe I'm wrong.

And we usually enable it because
the information from pg_wait_sampling

is super useful, and we want it
to per query.

So, yeah.

Cool.

Michael: Maybe add query ID, but
also bump the default way up if

there's very little overhead to
having 10, 000 or more I don't

see why that should be limited.

What do you think?

Fabrízio: Thanks for asking this.

This was an arbitrary number

Nikolay: that I got

Fabrízio: from my, probably should
increase this and maybe match

with, for example, pg_stat_statements
because it don't require

too much memory.

Be honest.

Michael: Yeah.

Nice.

I noticed you labeled it version
0.1.

What else do you need in terms
of getting it to a version you

could commit to Postgres or 1.0
or whatever, however you want

to define like production ready.

Fabrízio: The thing that it's blocking
it's submit is this issue

that I find in the worst case when
we have all the entries allocated

and then new entries entering the
dropped message.

I will not collect information
because I don't have enough capacity

to collect.

And this is another worst case in
the corner.

It's simple.

And then I found that overhead,
it's not great.

It increased by 27, 30% of overhead.

And actually it was not great.

I think just this for now, a starting
point.

Maybe query IDs, something to
discuss with the community, I

don't know.

There are ongoing work in the past,
there was ongoing work in

the past, work in progress.

PR, no, maybe it's a patch.

We introduced pg_stat_log_error
or something.

It was proposed by Joe
Conway, And they collected this

old discussion.

They collected the file name, the
source code file name, the

line number, where it was coming
from, that I don't think for

real use case.

It's a good idea, I mean, for SREs,
DBREs, or people that actually

use it.

I don't know if it's useful to
know where is the C file that

the SQLSTATE came.

I don't know.

Maybe I'm wrong, but I thought
that was not useful.

And then I started by the base
stuff to really observe the log.

A backend type, what's the database
ID?

What is the error level and SQL
error code?

Because I think this is the basic
information we need.

Now that's enough information, right?

Yeah, right.

Yeah.

And be an option.

Nikolay: File is always the same.

It only can change after rotation,
right?

Fabrízio: Not the log file, the
source code file.

Sorry.

The C file.

Something dot C inside Postgres.

And the line number.

Because we have this information.

Nikolay: So I see.

So we have some error code, for
example, my favorite, XX001, for

example, right?

I think it's some corruption or
something, right?

Or 002.

And we know that in Postgres source
code, it happens and it can

occur in 5 places, for example.

And we want to know exact location
among those 5, right?

I think this can be useful.

It reminds me, like when programming,
you troubleshoot with printlining,

right?

And you have like, problem happened,
problem, test, test, or

like something.

And then you think, oh, they're
all this, you need to start distinguishing

them, right?

You say, okay, test 1, test 2,
test 3, and then which 1 of them

fired, right?

I can see it may be useful, but
again, what overhead?

What's the price, right?

Fabrízio: Yeah, the price is we
need to store variable-sized

strings.

The line number is not a problem,
but the source code file name,

it's a string with a variable size,
then it can increase the

memory.

Depending on how many entries you
store.

But yeah, the source code file
names are not very big names.

But I don't remember if you have
multiple file names, equal file

names with different directories.

I don't think so.

Nikolay: I think it might happen.

Fabrízio: It might happen.

So if we start only the file.c,
line number 1000, and then you

have 2 files the same name.

Nikolay: Can be compared somehow
I think quite easily so to a

few bytes only but is it really
needed?

Maybe no, but it's a nice feature
I can imagine like to trace

the exact location.

What I'm concerned about, not about
additional bytes, but it

will amplify number of entries
significantly.

If it's a common, if this error
is popular and we have 100 locations,

so now we have 100 different errors
basically, right?

But it's interesting.

It's interesting anyway.

Yeah.

We should have it and this information
should be present in logs.

This is very detailed information.

Go to logs and troubleshoot.

It's the level of this extension,
we just want counters to observe

holistically everything.

Right?

Then if you identify the spike,
go to logs.

Now the problem is we cannot identify
spikes at all.

So we're...

Yeah.

Yeah.

So I agree with you, it's too verbose
stuff.

Yeah.

Okay, it was some kind of brainstorming
session, a little bit.

What I think would help is If somebody
starts using it, maybe

not in production right away, but
in some benchmarking, like

I'm going to start using it in
some benchmarking activities in

lab environment, right?

So 1st, like low risk.

If it crashes, I will let you know.

But eventually I think the production,
it should be a production.

Fabrízio: It could be very useful.

Nowadays it's packaged for Debian
and RPM on the PGDG repositories.

So it's available there.

I can provide some Docker images,
but a Docker image is very

simple.

You can pick a PG 18 and just install
a new package there, pgdg

is there.

Nikolay: Cool, but also Postgres
20 development already started,

so we're already inside it.

Let's go there.

Let's

Fabrízio: publish it.

Yes, let's go there.

Nikolay: You know, let's get familiar
with it.

I want it to be in core.

This is a great start.

Fabrízio: Yeah, it should be.

Michael: Was there anything you
wanted to mention that we haven't

asked about?

Maybe some of the caveats that
you wrote about or anything else?

Fabrízio: 1 thing that everybody
can potentially ask is, it requires

a Postgres restart because I need to
allocate shared memory.

So there's no way nowadays in Postgres
to do this without something.

I think this is 1 of the reasons
that Nik would love to have

this truly in core, then we don't
need to restart Postgres.

But it depends on how it is implemented,
right?

Because there are some configurations
that we, when we change

it, it will restart anyways.

Nikolay: Yeah, this is definitely
why I think pg_stat_statements

should be in core as well.

We still have cases when it's not
installed and it's not present

in shared preload libraries, so
we need a restart.

Michael: And this requires shared
preload as well, doesn't it?

Fabrízio: And there's only another
caveat that we didn't talk

about is the parallel query, right,
because there are different

backend types, parallel queries.

There are like normal client in
backend that is the leader,

and then there will be a parallel
worker or something.

So don't count twice in the message
maybe.

Yeah.

So I'm not filtering anything.

I just collecting on the log because
it go to the log the information.

It passed through the emit_log_hook
hook and then I capture it,

the leader and also the parallel
workers.

So we filled a monitoring tool
and thought that I have parallel

workers, maybe you should filter
it out, but double count something.

It's 1 caveat, it is on the README.

Michael: Yeah, I thought it was
really interesting.

I thought that was a good 1 to
call out.

And I thought the other 1 that
was interesting for monitoring

tools was the fact that database
name or username could be null.

And that's expected, like some
errors happen before there's a

context of having a database?

Like that's something I would have
forgotten to do.

So for example, I knew I wanted
to monitor 1 database on Postgres.

I would have filtered by that and
only looked for errors, but

I need that database name or null.

And then I look at errors across
both of those.

Fabrízio: So that

Michael: was a really good call
out I thought.

Nice 1.

Fabrízio: I didn't thought too
much, but maybe another thing

that's interesting to collect and
aggregate is application name.

Nikolay: Oh, it's Pandora box.

Fabrízio: Yeah, I know.

Nikolay: There is a great idea
that, well, what about client

address and IP address and so on.

It could go far.

There's a great idea that all such
extensions like pg_stat_statements,

pg_stat_kcache, pg_wait_sampling,
and let's say pg_stat_log, they all

must have an additional extensibility
piece so I could define

my own dimensions.

For example, if my query contains
a comment which says, this

query originated from this part
of application and anything,

I just can tag my queries.

If those tags could be extracted
from comments and allow me to

group by tag value inside pg_stat_
statements or any such

extension.

This would be great.

This is a big lacking piece.

And right now, the way to go is
to avoid the cumulative statistics

approach completely and just use,
instead of counters, just use

sampling.

You can implement the same in Active
Session history approach.

You sample pg_stat_activity,
you have these comments, you

extract outside of Postgres, right?

And then you can finally answer,
okay, I/O wait event, we mostly

spend 90% of I/O registered in
wait event was in this piece

of application, this part, because
it was tagged.

In the case of your extension,
same thing.

If something is erroring out, group
by database, group by user,

Even application level, it's great,
but sometimes we need some

custom segmentation.

And now it's like it's difficult
right now.

This is maybe future of all those
extensions to have custom tagging

mechanism.

Maybe.

These discussions, I know people
and myself, we discussed it

over years.

You actually, Fabrízio, is a part
of the ground group where we

discussed it, I think, a couple
of times.

Great.

Thank you for coming.

I enjoyed it.

I wish all the best to this extension
and all your work.

Fabrízio: Thank you very much.

Nikolay: Thank you.

Thank you.

I hope

Michael: absolutely good luck for
version 20.

Creators and Guests

Some kind things our listeners have said