Thread: Re: log_min_messages per backend type

Re: log_min_messages per backend type

From
Álvaro Herrera
Date:
Hello Euler,

On 2024-Dec-17, Euler Taveira wrote:

> Sometimes you need to inspect some debug messages from autovacuum worker but
> you cannot apply the same setting for backends (that could rapidly fill the log
> file). This proposal aims to change log_min_messages to have different log
> levels depending on which backend type the message comes from.
> 
> The syntax was changed from enum to string and it accepts a list of elements.
> 
> Instead of enum, it now accepts a comma-separated list of elements (string).
> Each element is LOGLEVEL:BACKENDTYPE.

This format seems unintuitive.  I would have thought you do it the other
way around, "backendtype:loglevel" ... that seems more natural because
it's like assigning the 'loglevel' value to the 'backendtype' element.
  SET log_min_messages TO 'checkpointer:debug2, autovacuum:debug1';


I dislike the array of names in variable.c.  We already have an array in
launch_backend.c (child_process_kinds), plus GetBackendTypeDesc in
miscinit.c.  Maybe not for this patch to clean up though.


I think it should be acceptable to configure one global setting with
exceptions for particular backend types:

log_min_messages = WARNING, autovacuum:DEBUG1

Right now I think the code only accepts the unadorned log level if there
are no other items in the list.  I think the proposal downthread is to
use the keyword ALL for this,

  log_min_messages = all:WARNING, autovacuum:DEBUG1   # I don't like this

but I think it's inferior, because then "all" is not really "all", and I
think it would be different if I had said

  log_min_messages = autovacuum:DEBUG1, all:WARNING   # I don't like this

because it looks like the "all" entry should override the one I set for
autovacuum before, which frankly would not make sense to me.

So I think these two lines,

log_min_messages = WARNING, autovacuum:DEBUG1
log_min_messages = autovacuum:DEBUG1, WARNING

should behave identically and mean "set the level for autovacuum to
DEBUG1, and to any other backend type to WARNING.


Also, I think it'd be better to reject duplicates in the list.  Right
now it looks like the last entry for one backend type overrides prior
ones.  I mean

log_min_messages = autovacuum:DEBUG1, autovacuum:ERROR

would set autovacuum to error, but that might be mistake prone if your
string is long.  So implementation-wise I suggest to initialize the
whole newlogminmsgs array to -1, then scan the list of entries (saving
an entry without backend type as the one to use later and) setting every
backend type to the number specified; if we see trying to set a value
that's already different from -1, throw error.  After scanning the whole
log_min_messages array, we scan the newlogminmsgs and set any entries
that are still -1 to the value that we saved before.


The new code in variable.c should be before the /* DATESTYLE */ comment
rather than at the end of the file.


You still have many XXX comments.  Also, postgresql.conf should list the
valid values for backendtype, as well as show an example of a valid
setting.  Please don't use ALLCAPS backend types in the docs, this looks
ugly:

> +        Valid <literal>BACKENDTYPE</literal> values are <literal>ARCHIVER</literal>,
> +        <literal>AUTOVACUUM</literal>, <literal>BACKEND</literal>,
> +        <literal>BGWORKER</literal>, <literal>BGWRITER</literal>,
> +        <literal>CHECKPOINTER</literal>, <literal>LOGGER</literal>,
> +        <literal>SLOTSYNCWORKER</literal>, <literal>WALRECEIVER</literal>,
> +        <literal>WALSENDER</literal>, <literal>WALSUMMARIZER</literal>, and
> +        <literal>WALWRITER</literal>.

-- 
Álvaro Herrera        Breisgau, Deutschland  —  https://www.EnterpriseDB.com/
"No necesitamos banderas
 No reconocemos fronteras"                  (Jorge González)



Re: log_min_messages per backend type

From
"Euler Taveira"
Date:
On Wed, Feb 5, 2025, at 3:51 PM, Álvaro Herrera wrote:
On 2024-Dec-17, Euler Taveira wrote:

> Sometimes you need to inspect some debug messages from autovacuum worker but
> you cannot apply the same setting for backends (that could rapidly fill the log
> file). This proposal aims to change log_min_messages to have different log
> levels depending on which backend type the message comes from.

> The syntax was changed from enum to string and it accepts a list of elements.

> Instead of enum, it now accepts a comma-separated list of elements (string).
> Each element is LOGLEVEL:BACKENDTYPE.

This format seems unintuitive.  I would have thought you do it the other
way around, "backendtype:loglevel" ... that seems more natural because
it's like assigning the 'loglevel' value to the 'backendtype' element.
  SET log_min_messages TO 'checkpointer:debug2, autovacuum:debug1';

Alvaro, thanks for your feedback. Your suggestion makes sense to me.

I dislike the array of names in variable.c.  We already have an array in
launch_backend.c (child_process_kinds), plus GetBackendTypeDesc in
miscinit.c.  Maybe not for this patch to clean up though.

I thought about using child_process_kinds but two details made me give
up on the idea: (a) multiple names per backend type (for example, 
B_BACKEND, B_DEAD_END_BACKEND, B_STANDALONE_BACKEND) and (b) spaces into
names. Maybe we should have a group into child_process_kinds but as you
said it seems material for another patch.

I think it should be acceptable to configure one global setting with
exceptions for particular backend types:

log_min_messages = WARNING, autovacuum:DEBUG1

Right now I think the code only accepts the unadorned log level if there
are no other items in the list.  I think the proposal downthread is to
use the keyword ALL for this,

  log_min_messages = all:WARNING, autovacuum:DEBUG1   # I don't like this

but I think it's inferior, because then "all" is not really "all", and I
think it would be different if I had said

  log_min_messages = autovacuum:DEBUG1, all:WARNING   # I don't like this

because it looks like the "all" entry should override the one I set for
autovacuum before, which frankly would not make sense to me.

Good point. After reflection, I agree that "all" is not a good keyword.
This patch turns backend type as optional so WARNING means apply this
log level as a final step to the backend types that are not specified in
the list.

So I think these two lines,

log_min_messages = WARNING, autovacuum:DEBUG1
log_min_messages = autovacuum:DEBUG1, WARNING

should behave identically and mean "set the level for autovacuum to
DEBUG1, and to any other backend type to WARNING.

Done.

Also, I think it'd be better to reject duplicates in the list.  Right
now it looks like the last entry for one backend type overrides prior
ones.  I mean

log_min_messages = autovacuum:DEBUG1, autovacuum:ERROR

would set autovacuum to error, but that might be mistake prone if your
string is long.  So implementation-wise I suggest to initialize the
whole newlogminmsgs array to -1, then scan the list of entries (saving
an entry without backend type as the one to use later and) setting every
backend type to the number specified; if we see trying to set a value
that's already different from -1, throw error.  After scanning the whole
log_min_messages array, we scan the newlogminmsgs and set any entries
that are still -1 to the value that we saved before.


The new code in variable.c should be before the /* DATESTYLE */ comment
rather than at the end of the file.

It was added into the MISCELLANEOUS section.


You still have many XXX comments.  Also, postgresql.conf should list the
valid values for backendtype, as well as show an example of a valid
setting.  Please don't use ALLCAPS backend types in the docs, this looks
ugly:

> +        Valid <literal>BACKENDTYPE</literal> values are <literal>ARCHIVER</literal>,
> +        <literal>AUTOVACUUM</literal>, <literal>BACKEND</literal>,
> +        <literal>BGWORKER</literal>, <literal>BGWRITER</literal>,
> +        <literal>CHECKPOINTER</literal>, <literal>LOGGER</literal>,
> +        <literal>SLOTSYNCWORKER</literal>, <literal>WALRECEIVER</literal>,
> +        <literal>WALSENDER</literal>, <literal>WALSUMMARIZER</literal>, and
> +        <literal>WALWRITER</literal>.

Done.

Just to recap what was changed:

- patch was rebased
- backend type is optional and means all unspecified backend types
- generic log level (without backend type) is mandatory and the order it
  ppears is not important (it is applied for the remaining backend types)
- fix Windows build
- new tests to cover the changes


--
Euler Taveira

Attachment

Re: log_min_messages per backend type

From
Andrew Dunstan
Date:


On 2025-03-04 Tu 7:33 PM, Euler Taveira wrote:
I think it should be acceptable to configure one global setting with
exceptions for particular backend types:

log_min_messages = WARNING, autovacuum:DEBUG1

Right now I think the code only accepts the unadorned log level if there
are no other items in the list.  I think the proposal downthread is to
use the keyword ALL for this,

  log_min_messages = all:WARNING, autovacuum:DEBUG1   # I don't like this

but I think it's inferior, because then "all" is not really "all", and I
think it would be different if I had said

  log_min_messages = autovacuum:DEBUG1, all:WARNING   # I don't like this

because it looks like the "all" entry should override the one I set for
autovacuum before, which frankly would not make sense to me.

Good point. After reflection, I agree that "all" is not a good keyword.
This patch turns backend type as optional so WARNING means apply this
log level as a final step to the backend types that are not specified in
the list.

So I think these two lines,

log_min_messages = WARNING, autovacuum:DEBUG1
log_min_messages = autovacuum:DEBUG1, WARNING

should behave identically and mean "set the level for autovacuum to
DEBUG1, and to any other backend type to WARNING.

Done.


Just bikeshedding a bit ...

I'm not mad keen on this design. I think the value should be either a single setting like "WARNING" or a set of type:setting pairs. I agree that "all" is a bad name, but I think "default" would make sense.

I can live with it but I think this just looks a bit odd.


cheers


andrew



--
Andrew Dunstan
EDB: https://www.enterprisedb.com

Re: log_min_messages per backend type

From
Fujii Masao
Date:

On 2025/03/05 9:33, Euler Taveira wrote:
>> > +        Valid <literal>BACKENDTYPE</literal> values are <literal>ARCHIVER</literal>,
>> > +        <literal>AUTOVACUUM</literal>, <literal>BACKEND</literal>,
>> > +        <literal>BGWORKER</literal>, <literal>BGWRITER</literal>,
>> > +        <literal>CHECKPOINTER</literal>, <literal>LOGGER</literal>,
>> > +        <literal>SLOTSYNCWORKER</literal>, <literal>WALRECEIVER</literal>,
>> > +        <literal>WALSENDER</literal>, <literal>WALSUMMARIZER</literal>, and
>> > +        <literal>WALWRITER</literal>.

What about postmaster?

For parallel workers launched for parallel queries, should they follow
the backend's log level or the background worker's? Since they operate
as part of a parallel query executed by a backend, it seems more logical
for them to follow the backend's setting.

+    [B_CHECKPOINTER] = "checkpointer",
+    [B_STARTUP] = "backend",    /* XXX same as backend? */

I like the idea of allowing log levels to be set per process.
There were times I wanted to use debug5 specifically for
the startup process when troubleshooting WAL replay. It would be
helpful to distinguish the startup process from a regular backend,
so we can set its log level independently.

Regards,

-- 
Fujii Masao
Advanced Computing Technology Center
Research and Development Headquarters
NTT DATA CORPORATION




Re: log_min_messages per backend type

From
Matheus Alcantara
Date:
Hi,

>
> On 2025-03-04 Tu 7:33 PM, Euler Taveira wrote:
>>> I think it should be acceptable to configure one global setting with
>>> exceptions for particular backend types:
>>>
>>> log_min_messages = WARNING, autovacuum:DEBUG1
>>>
>>> Right now I think the code only accepts the unadorned log level if
>>> there
>>> are no other items in the list.  I think the proposal downthread is to
>>> use the keyword ALL for this,
>>>
>>>   log_min_messages = all:WARNING, autovacuum:DEBUG1   # I don't
>>> like this
>>>
>>> but I think it's inferior, because then "all" is not really "all",
>>> and I
>>> think it would be different if I had said
>>>
>>>   log_min_messages = autovacuum:DEBUG1, all:WARNING   # I don't
>>> like this
>>>
>>> because it looks like the "all" entry should override the one I set
>>> for
>>> autovacuum before, which frankly would not make sense to me.
>>
>> Good point. After reflection, I agree that "all" is not a good keyword.
>> This patch turns backend type as optional so WARNING means apply this
>> log level as a final step to the backend types that are not
>> specified in
>> the list.
>>
>>> So I think these two lines,
>>>
>>> log_min_messages = WARNING, autovacuum:DEBUG1
>>> log_min_messages = autovacuum:DEBUG1, WARNING
>>>
>>> should behave identically and mean "set the level for autovacuum to
>>> DEBUG1, and to any other backend type to WARNING.
>>
>> Done.
>
>
> Just bikeshedding a bit ...
>
> I'm not mad keen on this design. I think the value should be either a
> single setting like "WARNING" or a set of type:setting pairs. I agree
> that "all" is a bad name, but I think "default" would make sense.
>
> I can live with it but I think this just looks a bit odd.
>

Just bringing some thoughts about it...

How about using something like *:WARNING? I'm not sure if it could also be
confusing as the "all" keyword, but I think it could also be interpreted as
"anything else use WARNING".

--
Matheus Alcantara



Re: log_min_messages per backend type

From
Andres Freund
Date:
Hi,

On 2025-03-04 21:33:39 -0300, Euler Taveira wrote:
> +/*
> + * This must match enum BackendType! It should be static, but
> + * commands/variable.c needs to get at this.
> + */
> +int            log_min_messages[] = {
> +    [B_INVALID] = WARNING,
> +    [B_BACKEND] = WARNING,
> +    [B_DEAD_END_BACKEND] = WARNING,
> +    [B_AUTOVAC_LAUNCHER] = WARNING,
> +    [B_AUTOVAC_WORKER] = WARNING,
> +    [B_BG_WORKER] = WARNING,
> +    [B_WAL_SENDER] = WARNING,
> +    [B_SLOTSYNC_WORKER] = WARNING,
> +    [B_STANDALONE_BACKEND] = WARNING,
> +    [B_ARCHIVER] = WARNING,
> +    [B_BG_WRITER] = WARNING,
> +    [B_CHECKPOINTER] = WARNING,
> +    [B_STARTUP] = WARNING,
> +    [B_WAL_RECEIVER] = WARNING,
> +    [B_WAL_SUMMARIZER] = WARNING,
> +    [B_WAL_WRITER] = WARNING,
> +    [B_LOGGER] = WARNING,
> +};

> +StaticAssertDecl(lengthof(log_min_messages) == BACKEND_NUM_TYPES,
> +                 "array length mismatch");
> +
> +/*
> + * This must match enum BackendType! It might be in commands/variable.c but for
> + * convenience it is near log_min_messages.
> + */
> +const char *const log_min_messages_backend_types[] = {
> +    [B_INVALID] = "backend",    /* XXX same as backend? */
> +    [B_BACKEND] = "backend",
> +    [B_DEAD_END_BACKEND] = "backend",    /* XXX same as backend? */
> +    [B_AUTOVAC_LAUNCHER] = "autovacuum",
> +    [B_AUTOVAC_WORKER] = "autovacuum",
> +    [B_BG_WORKER] = "bgworker",
> +    [B_WAL_SENDER] = "walsender",
> +    [B_SLOTSYNC_WORKER] = "slotsyncworker",
> +    [B_STANDALONE_BACKEND] = "backend", /* XXX same as backend? */
> +    [B_ARCHIVER] = "archiver",
> +    [B_BG_WRITER] = "bgwriter",
> +    [B_CHECKPOINTER] = "checkpointer",
> +    [B_STARTUP] = "backend",    /* XXX same as backend? */

Huh, the startup process is among the most crucial things to monitor?

> +    [B_WAL_RECEIVER] = "walreceiver",
> +    [B_WAL_SUMMARIZER] = "walsummarizer",
> +    [B_WAL_WRITER] = "walwriter",
> +    [B_LOGGER] = "logger",
> +};
> +
> +StaticAssertDecl(lengthof(log_min_messages_backend_types) == BACKEND_NUM_TYPES,
> +                 "array length mismatch");
> +

I don't know what I think about the whole patch, but I do want to voice
*strong* opposition to duplicating a list of all backend types into multiple
places. It's already painfull enough to add a new backend type, without having
to pointlessly go around and manually add a new backend type to mulltiple
arrays that have completely predictable content.

Greetings,

Andres Freund



Re: log_min_messages per backend type

From
"Euler Taveira"
Date:
On Wed, Mar 5, 2025, at 11:53 PM, Fujii Masao wrote:
On 2025/03/05 9:33, Euler Taveira wrote:
>> > +        Valid <literal>BACKENDTYPE</literal> values are <literal>ARCHIVER</literal>,
>> > +        <literal>AUTOVACUUM</literal>, <literal>BACKEND</literal>,
>> > +        <literal>BGWORKER</literal>, <literal>BGWRITER</literal>,
>> > +        <literal>CHECKPOINTER</literal>, <literal>LOGGER</literal>,
>> > +        <literal>SLOTSYNCWORKER</literal>, <literal>WALRECEIVER</literal>,
>> > +        <literal>WALSENDER</literal>, <literal>WALSUMMARIZER</literal>, and
>> > +        <literal>WALWRITER</literal>.

What about postmaster?

It is B_INVALID that is currently mapped to "backend". This state is used as an
initial phase for the child process. There might be messages before
MyBackendType is assigned (see ProcessStartupPacket, for example). Hence, I
refrain to create a special backend type for postmaster. Should we map it to
generic log level instead of backend?

For parallel workers launched for parallel queries, should they follow
the backend's log level or the background worker's? Since they operate
as part of a parallel query executed by a backend, it seems more logical
for them to follow the backend's setting.

Since we are using enum BackendType and there is no special entry for parallel
query processes. I'm afraid that introducing conditional logic for checking
special cases like the bgw_type for parallel queries or MyProcPid ==
PostmasterPid might slowdown that code path. (See that should_output_to_server
is an inline function.) I will run some tests to see if there is a considerable
impact.

+ [B_CHECKPOINTER] = "checkpointer",
+ [B_STARTUP] = "backend", /* XXX same as backend? */

I like the idea of allowing log levels to be set per process.
There were times I wanted to use debug5 specifically for
the startup process when troubleshooting WAL replay. It would be
helpful to distinguish the startup process from a regular backend,
so we can set its log level independently.

Although startup process is mapped to backend (hence, the XXX), we can
certainly create a separate backend type for it.


--
Euler Taveira

Re: log_min_messages per backend type

From
"Euler Taveira"
Date:
On Wed, Mar 5, 2025, at 1:40 PM, Andrew Dunstan wrote:

Just bikeshedding a bit ...

I'm not mad keen on this design. I think the value should be either a single setting like "WARNING" or a set of type:setting pairs. I agree that "all" is a bad name, but I think "default" would make sense.


One of my main concerns was a clear interface. I think "default" is less
confusing than "all". Your suggestion about single or list is aligned with what
Alvaro suggested. IIUC you are suggesting default:loglevel only if it is part
of the list; the single loglevel shouldn't contain the backend type to keep the
backward compatibility. The advantage of your proposal is that it make it clear
what the fallback log level is. However, someone could be confused asking if
the "default" is a valid backend type and if there is a difference between
WARNING and default:WARNING (both is a fallback for non-specified backend type
elements).


--
Euler Taveira