Allow log_min_messages to be set per process type

Change log_min_messages from being a single element to a comma-separated
list of type:level elements, with 'type' representing a process type,
and 'level' being a log level to use for that type of process.  The list
must also have a freestanding level specification which is used for
process types not listed, which convenientely makes the whole thing
backwards-compatible.

Some choices made here could be contested; for instance, we use the
process type `backend` to affect regular backends as well as dead-end
backends and the standalone backend, and `autovacuum` means both the
launcher and the workers.  I think it's largely sensible though, and it
can easily be tweaked if desired.

Author: Euler Taveira <euler@eulerto.com>
Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Reviewed-by: Japin Li <japinli@hotmail.com>
Reviewed-by: Tan Yang <332696245@qq.com>
Discussion: https://postgr.es/m/e85c6671-1600-4112-8887-f97a8a5d07b2@app.fastmail.com
This commit is contained in:
Álvaro Herrera 2026-02-09 13:23:10 +01:00
parent c67bef3f32
commit 38e0190ced
No known key found for this signature in database
GPG key ID: 1C20ACB9D5C564AE
13 changed files with 428 additions and 44 deletions

View file

@ -7120,27 +7120,57 @@ local0.* /var/log/postgresql
<variablelist>
<varlistentry id="guc-log-min-messages" xreflabel="log_min_messages">
<term><varname>log_min_messages</varname> (<type>enum</type>)
<term><varname>log_min_messages</varname> (<type>string</type>)
<indexterm>
<primary><varname>log_min_messages</varname> configuration parameter</primary>
</indexterm>
</term>
<listitem>
<para>
Controls which <link linkend="runtime-config-severity-levels">message
levels</link> are written to the server log.
Valid values are <literal>DEBUG5</literal>, <literal>DEBUG4</literal>,
<literal>DEBUG3</literal>, <literal>DEBUG2</literal>, <literal>DEBUG1</literal>,
<literal>INFO</literal>, <literal>NOTICE</literal>, <literal>WARNING</literal>,
<literal>ERROR</literal>, <literal>LOG</literal>, <literal>FATAL</literal>, and
<literal>PANIC</literal>. Each level includes all the levels that
follow it. The later the level, the fewer messages are sent
to the log. The default is <literal>WARNING</literal>. Note that
<literal>LOG</literal> has a different rank here than in
Controls which
<link linkend="runtime-config-severity-levels">message levels</link>
are written to the server log. The value is a comma-separated
list of zero or more
<literal><replaceable>process type</replaceable>:<replaceable>level</replaceable></literal>
entries and exactly one mandatory
<literal><replaceable>level</replaceable></literal> entry,
which becomes the default for process types not listed.
Valid process types are listed in the table below.
<simplelist type="vert" columns="4">
<member><literal>archiver</literal></member>
<member><literal>autovacuum</literal></member>
<member><literal>backend</literal></member>
<member><literal>bgworker</literal></member>
<member><literal>bgwriter</literal></member>
<member><literal>checkpointer</literal></member>
<member><literal>ioworker</literal></member>
<member><literal>postmaster</literal></member>
<member><literal>syslogger</literal></member>
<member><literal>slotsyncworker</literal></member>
<member><literal>startup</literal></member>
<member><literal>walreceiver</literal></member>
<member><literal>walsender</literal></member>
<member><literal>walsummarizer</literal></member>
<member><literal>walwriter</literal></member>
</simplelist>
Valid <literal>level</literal> values are <literal>DEBUG5</literal>,
<literal>DEBUG4</literal>, <literal>DEBUG3</literal>, <literal>DEBUG2</literal>,
<literal>DEBUG1</literal>, <literal>INFO</literal>, <literal>NOTICE</literal>,
<literal>WARNING</literal>, <literal>ERROR</literal>, <literal>LOG</literal>,
<literal>FATAL</literal>, and <literal>PANIC</literal>. Each level includes
all the levels that follow it. The later the level, the fewer messages are sent
to the log. The default is <literal>WARNING</literal>, which
applies that level to all process types.
Note that <literal>LOG</literal> has a different rank here than in
<xref linkend="guc-client-min-messages"/>.
Only superusers and users with the appropriate <literal>SET</literal>
privilege can change this setting.
</para>
<para>
Example: To log <literal>walsender</literal> and <literal>autovacuum</literal>
at level <literal>DEBUG1</literal> and everything else at <literal>ERROR</literal>,
set <varname>log_min_messages</varname> to <literal>error, walsender:debug1, autovacuum:debug1</literal>.
</para>
</listitem>
</varlistentry>

View file

@ -1191,7 +1191,7 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control,
(void) set_config_option("client_min_messages", "warning",
PGC_USERSET, PGC_S_SESSION,
GUC_ACTION_SAVE, true, 0, false);
if (log_min_messages < WARNING)
if (log_min_messages[MyBackendType] < WARNING)
(void) set_config_option_ext("log_min_messages", "warning",
PGC_SUSET, PGC_S_SESSION,
BOOTSTRAP_SUPERUSERID,

View file

@ -178,7 +178,7 @@ typedef struct
} child_process_kind;
static child_process_kind child_process_kinds[] = {
#define PG_PROCTYPE(bktype, description, main_func, shmem_attach) \
#define PG_PROCTYPE(bktype, bkcategory, description, main_func, shmem_attach) \
[bktype] = {description, main_func, shmem_attach},
#include "postmaster/proctypelist.h"
#undef PG_PROCTYPE

View file

@ -182,6 +182,7 @@ static bool matches_backtrace_functions(const char *funcname);
static pg_noinline void set_backtrace(ErrorData *edata, int num_skip);
static void set_errdata_field(MemoryContextData *cxt, char **ptr, const char *str);
static void FreeErrorDataContents(ErrorData *edata);
static int log_min_messages_cmp(const ListCell *a, const ListCell *b);
static void write_console(const char *line, int len);
static const char *process_log_prefix_padding(const char *p, int *ppadding);
static void log_line_prefix(StringInfo buf, ErrorData *edata);
@ -235,7 +236,7 @@ is_log_level_output(int elevel, int log_min_level)
static inline bool
should_output_to_server(int elevel)
{
return is_log_level_output(elevel, log_min_messages);
return is_log_level_output(elevel, log_min_messages[MyBackendType]);
}
/*
@ -2170,6 +2171,250 @@ DebugFileOpen(void)
}
/*
* GUC check_hook for log_min_messages
*
* This value is parsed as a comma-separated list of zero or more TYPE:LEVEL
* elements. For each element, TYPE corresponds to a bk_category value (see
* postmaster/proctypelist.h); LEVEL is one of server_message_level_options.
*
* In addition, there must be a single LEVEL element (with no TYPE part)
* which sets the default level for process types that aren't specified.
*/
bool
check_log_min_messages(char **newval, void **extra, GucSource source)
{
char *rawstring;
List *elemlist;
StringInfoData buf;
char *result;
int newlevel[BACKEND_NUM_TYPES];
bool assigned[BACKEND_NUM_TYPES] = {0};
int genericlevel = -1; /* -1 means not assigned */
const char *const process_types[] = {
#define PG_PROCTYPE(bktype, bkcategory, description, main_func, shmem_attach) \
[bktype] = bkcategory,
#include "postmaster/proctypelist.h"
#undef PG_PROCTYPE
};
/* Need a modifiable copy of string. */
rawstring = guc_strdup(LOG, *newval);
if (rawstring == NULL)
return false;
/* Parse the string into a list. */
if (!SplitGUCList(rawstring, ',', &elemlist))
{
/* syntax error in list */
GUC_check_errdetail("List syntax is invalid.");
list_free(elemlist);
guc_free(rawstring);
return false;
}
/* Validate and assign log level and process type. */
foreach_ptr(char, elem, elemlist)
{
char *sep = strchr(elem, ':');
/*
* If there's no ':' separator in the entry, this is the default log
* level. Otherwise it's a process type-specific entry.
*/
if (sep == NULL)
{
const struct config_enum_entry *entry;
bool found;
/* Reject duplicates for generic log level. */
if (genericlevel != -1)
{
GUC_check_errdetail("Redundant specification of default log level.");
goto lmm_fail;
}
/* Validate the log level */
found = false;
for (entry = server_message_level_options; entry && entry->name; entry++)
{
if (pg_strcasecmp(entry->name, elem) == 0)
{
genericlevel = entry->val;
found = true;
break;
}
}
if (!found)
{
GUC_check_errdetail("Unrecognized log level: \"%s\".", elem);
goto lmm_fail;
}
}
else
{
char *loglevel = sep + 1;
char *ptype = elem;
bool found;
int level;
const struct config_enum_entry *entry;
/*
* Temporarily clobber the ':' with a string terminator, so that
* we can validate it. We restore this at the bottom.
*/
*sep = '\0';
/* Validate the log level */
found = false;
for (entry = server_message_level_options; entry && entry->name; entry++)
{
if (pg_strcasecmp(entry->name, loglevel) == 0)
{
level = entry->val;
found = true;
break;
}
}
if (!found)
{
GUC_check_errdetail("Unrecognized log level for process type \"%s\": \"%s\".",
ptype, loglevel);
goto lmm_fail;
}
/* Is the process type name valid and unique? */
found = false;
for (int i = 0; i < BACKEND_NUM_TYPES; i++)
{
if (pg_strcasecmp(process_types[i], ptype) == 0)
{
/* Reject duplicates for a process type. */
if (assigned[i])
{
GUC_check_errdetail("Redundant log level specification for process type \"%s\".",
ptype);
goto lmm_fail;
}
newlevel[i] = level;
assigned[i] = true;
found = true;
/*
* note: we must keep looking! some process types appear
* multiple times in proctypelist.h.
*/
}
}
if (!found)
{
GUC_check_errdetail("Unrecognized process type \"%s\".", ptype);
goto lmm_fail;
}
/* Put the separator back in place */
*sep = ':';
}
/* all good */
continue;
lmm_fail:
guc_free(rawstring);
list_free(elemlist);
return false;
}
/*
* The generic log level must be specified. It is the fallback value.
*/
if (genericlevel == -1)
{
GUC_check_errdetail("Default log level was not defined.");
guc_free(rawstring);
list_free(elemlist);
return false;
}
/* Apply the default log level to all processes not listed. */
for (int i = 0; i < BACKEND_NUM_TYPES; i++)
{
if (!assigned[i])
newlevel[i] = genericlevel;
}
/*
* Save an ordered representation of the user-specified string, for the
* show_hook.
*/
list_sort(elemlist, log_min_messages_cmp);
initStringInfoExt(&buf, strlen(rawstring) + 1);
foreach_ptr(char, elem, elemlist)
{
if (foreach_current_index(elem) == 0)
appendStringInfoString(&buf, elem);
else
appendStringInfo(&buf, ", %s", elem);
}
result = (char *) guc_malloc(LOG, buf.len + 1);
if (!result)
return false;
memcpy(result, buf.data, buf.len);
result[buf.len] = '\0';
guc_free(*newval);
*newval = result;
guc_free(rawstring);
list_free(elemlist);
pfree(buf.data);
/*
* Pass back data for assign_log_min_messages to use.
*/
*extra = guc_malloc(LOG, BACKEND_NUM_TYPES * sizeof(int));
if (!*extra)
return false;
memcpy(*extra, newlevel, BACKEND_NUM_TYPES * sizeof(int));
return true;
}
/*
* list_sort() callback for check_log_min_messages. The default element
* goes first; the rest are ordered by strcmp() of the process type.
*/
static int
log_min_messages_cmp(const ListCell *a, const ListCell *b)
{
const char *s = lfirst(a);
const char *t = lfirst(b);
if (strchr(s, ':') == NULL)
return -1;
else if (strchr(t, ':') == NULL)
return 1;
else
return strcmp(s, t);
}
/*
* GUC assign_hook for log_min_messages
*/
void
assign_log_min_messages(const char *newval, void *extra)
{
for (int i = 0; i < BACKEND_NUM_TYPES; i++)
log_min_messages[i] = ((int *) extra)[i];
}
/*
* GUC check_hook for backtrace_functions
*

View file

@ -266,7 +266,7 @@ GetBackendTypeDesc(BackendType backendType)
switch (backendType)
{
#define PG_PROCTYPE(bktype, description, main_func, shmem_attach) \
#define PG_PROCTYPE(bktype, bkcategory, description, main_func, shmem_attach) \
case bktype: backendDesc = description; break;
#include "postmaster/proctypelist.h"
#undef PG_PROCTYPE

View file

@ -1693,12 +1693,14 @@
options => 'server_message_level_options',
},
{ name => 'log_min_messages', type => 'enum', context => 'PGC_SUSET', group => 'LOGGING_WHEN',
{ name => 'log_min_messages', type => 'string', context => 'PGC_SUSET', group => 'LOGGING_WHEN',
short_desc => 'Sets the message levels that are logged.',
long_desc => 'Each level includes all the levels that follow it. The later the level, the fewer messages are sent.',
variable => 'log_min_messages',
boot_val => 'WARNING',
options => 'server_message_level_options',
flags => 'GUC_LIST_INPUT',
variable => 'log_min_messages_string',
boot_val => '"WARNING"',
check_hook => 'check_log_min_messages',
assign_hook => 'assign_log_min_messages',
},
{ name => 'log_parameter_max_length', type => 'int', context => 'PGC_SUSET', group => 'LOGGING_WHAT',

View file

@ -147,7 +147,7 @@ static const struct config_enum_entry client_message_level_options[] = {
{NULL, 0, false}
};
static const struct config_enum_entry server_message_level_options[] = {
const struct config_enum_entry server_message_level_options[] = {
{"debug5", DEBUG5, false},
{"debug4", DEBUG4, false},
{"debug3", DEBUG3, false},
@ -546,7 +546,6 @@ static bool standard_conforming_strings = true;
bool current_role_is_superuser;
int log_min_error_statement = ERROR;
int log_min_messages = WARNING;
int client_min_messages = NOTICE;
int log_min_duration_sample = -1;
int log_min_duration_statement = -1;
@ -604,6 +603,7 @@ static char *server_version_string;
static int server_version_num;
static char *debug_io_direct_string;
static char *restrict_nonsystem_relation_kind_string;
static char *log_min_messages_string;
#ifdef HAVE_SYSLOG
#define DEFAULT_SYSLOG_FACILITY LOG_LOCAL0
@ -656,6 +656,15 @@ char *role_string;
/* should be static, but guc.c needs to get at this */
bool in_hot_standby_guc;
/*
* set default log_min_messages to WARNING for all process types
*/
int log_min_messages[] = {
#define PG_PROCTYPE(bktype, bkcategory, description, main_func, shmem_attach) \
[bktype] = WARNING,
#include "postmaster/proctypelist.h"
#undef PG_PROCTYPE
};
/*
* Displayable names for context types (enum GucContext)

View file

@ -532,7 +532,21 @@
# - When to Log -
#log_min_messages = warning # values in order of decreasing detail:
#log_min_messages = warning # comma-separated list of
# process_type:level entries, plus
# one freestanding level as default.
# Valid process types are:
# archiver autovacuum
# backend bgworker
# bgwriter checkpointer
# ioworker postmaster
# slotsyncworker startup
# syslogger walreceiver
# walsummarizer walwriter
# walsender
#
# Level values in order of decreasing
# detail:
# debug5
# debug4
# debug3

View file

@ -25,27 +25,27 @@
*/
/*
* List of process types (symbol, description, Main function, shmem_attach)
* entries.
* List of process types (symbol, category, description, Main function,
* shmem_attach, message level) entries.
*/
/* bktype, description, main_func, shmem_attach */
PG_PROCTYPE(B_ARCHIVER, gettext_noop("archiver"), PgArchiverMain, true)
PG_PROCTYPE(B_AUTOVAC_LAUNCHER, gettext_noop("autovacuum launcher"), AutoVacLauncherMain, true)
PG_PROCTYPE(B_AUTOVAC_WORKER, gettext_noop("autovacuum worker"), AutoVacWorkerMain, true)
PG_PROCTYPE(B_BACKEND, gettext_noop("client backend"), BackendMain, true)
PG_PROCTYPE(B_BG_WORKER, gettext_noop("background worker"), BackgroundWorkerMain, true)
PG_PROCTYPE(B_BG_WRITER, gettext_noop("background writer"), BackgroundWriterMain, true)
PG_PROCTYPE(B_CHECKPOINTER, gettext_noop("checkpointer"), CheckpointerMain, true)
PG_PROCTYPE(B_DEAD_END_BACKEND, gettext_noop("dead-end client backend"), BackendMain, true)
PG_PROCTYPE(B_INVALID, gettext_noop("unrecognized"), NULL, false)
PG_PROCTYPE(B_IO_WORKER, gettext_noop("io worker"), IoWorkerMain, true)
PG_PROCTYPE(B_LOGGER, gettext_noop("syslogger"), SysLoggerMain, false)
PG_PROCTYPE(B_SLOTSYNC_WORKER, gettext_noop("slotsync worker"), ReplSlotSyncWorkerMain, true)
PG_PROCTYPE(B_STANDALONE_BACKEND, gettext_noop("standalone backend"), NULL, false)
PG_PROCTYPE(B_STARTUP, gettext_noop("startup"), StartupProcessMain, true)
PG_PROCTYPE(B_WAL_RECEIVER, gettext_noop("walreceiver"), WalReceiverMain, true)
PG_PROCTYPE(B_WAL_SENDER, gettext_noop("walsender"), NULL, true)
PG_PROCTYPE(B_WAL_SUMMARIZER, gettext_noop("walsummarizer"), WalSummarizerMain, true)
PG_PROCTYPE(B_WAL_WRITER, gettext_noop("walwriter"), WalWriterMain, true)
/* bktype, bkcategory, description, main_func, shmem_attach */
PG_PROCTYPE(B_ARCHIVER, "archiver", gettext_noop("archiver"), PgArchiverMain, true)
PG_PROCTYPE(B_AUTOVAC_LAUNCHER, "autovacuum", gettext_noop("autovacuum launcher"), AutoVacLauncherMain, true)
PG_PROCTYPE(B_AUTOVAC_WORKER, "autovacuum", gettext_noop("autovacuum worker"), AutoVacWorkerMain, true)
PG_PROCTYPE(B_BACKEND, "backend", gettext_noop("client backend"), BackendMain, true)
PG_PROCTYPE(B_BG_WORKER, "bgworker", gettext_noop("background worker"), BackgroundWorkerMain, true)
PG_PROCTYPE(B_BG_WRITER, "bgwriter", gettext_noop("background writer"), BackgroundWriterMain, true)
PG_PROCTYPE(B_CHECKPOINTER, "checkpointer", gettext_noop("checkpointer"), CheckpointerMain, true)
PG_PROCTYPE(B_DEAD_END_BACKEND, "backend", gettext_noop("dead-end client backend"), BackendMain, true)
PG_PROCTYPE(B_INVALID, "postmaster", gettext_noop("unrecognized"), NULL, false)
PG_PROCTYPE(B_IO_WORKER, "ioworker", gettext_noop("io worker"), IoWorkerMain, true)
PG_PROCTYPE(B_LOGGER, "syslogger", gettext_noop("syslogger"), SysLoggerMain, false)
PG_PROCTYPE(B_SLOTSYNC_WORKER, "slotsyncworker", gettext_noop("slotsync worker"), ReplSlotSyncWorkerMain, true)
PG_PROCTYPE(B_STANDALONE_BACKEND, "backend", gettext_noop("standalone backend"), NULL, false)
PG_PROCTYPE(B_STARTUP, "startup", gettext_noop("startup"), StartupProcessMain, true)
PG_PROCTYPE(B_WAL_RECEIVER, "walreceiver", gettext_noop("walreceiver"), WalReceiverMain, true)
PG_PROCTYPE(B_WAL_SENDER, "walsender", gettext_noop("walsender"), NULL, true)
PG_PROCTYPE(B_WAL_SUMMARIZER, "walsummarizer", gettext_noop("walsummarizer"), WalSummarizerMain, true)
PG_PROCTYPE(B_WAL_WRITER, "walwriter", gettext_noop("walwriter"), WalWriterMain, true)

View file

@ -295,7 +295,7 @@ extern PGDLLIMPORT bool log_duration;
extern PGDLLIMPORT int log_parameter_max_length;
extern PGDLLIMPORT int log_parameter_max_length_on_error;
extern PGDLLIMPORT int log_min_error_statement;
extern PGDLLIMPORT int log_min_messages;
extern PGDLLIMPORT int log_min_messages[];
extern PGDLLIMPORT int client_min_messages;
extern PGDLLIMPORT int log_min_duration_sample;
extern PGDLLIMPORT int log_min_duration_statement;
@ -329,6 +329,8 @@ extern PGDLLIMPORT bool trace_sort;
extern PGDLLIMPORT bool optimize_bounded_sort;
#endif
extern PGDLLIMPORT const char *const log_min_messages_process_types[];
/*
* Declarations for options for enum values
*
@ -344,6 +346,7 @@ extern PGDLLIMPORT const struct config_enum_entry archive_mode_options[];
extern PGDLLIMPORT const struct config_enum_entry dynamic_shared_memory_options[];
extern PGDLLIMPORT const struct config_enum_entry io_method_options[];
extern PGDLLIMPORT const struct config_enum_entry recovery_target_action_options[];
extern PGDLLIMPORT const struct config_enum_entry server_message_level_options[];
extern PGDLLIMPORT const struct config_enum_entry wal_level_options[];
extern PGDLLIMPORT const struct config_enum_entry wal_sync_method_options[];

View file

@ -177,5 +177,7 @@ extern void assign_wal_sync_method(int new_wal_sync_method, void *extra);
extern bool check_synchronized_standby_slots(char **newval, void **extra,
GucSource source);
extern void assign_synchronized_standby_slots(const char *newval, void *extra);
extern bool check_log_min_messages(char **newval, void **extra, GucSource source);
extern void assign_log_min_messages(const char *newval, void *extra);
#endif /* GUC_HOOKS_H */

View file

@ -711,6 +711,63 @@ select current_schemas(false);
reset search_path;
--
-- Test parsing of log_min_messages
--
SET log_min_messages TO foo; -- fail
ERROR: invalid value for parameter "log_min_messages": "foo"
DETAIL: Unrecognized log level: "foo".
SET log_min_messages TO fatal;
SHOW log_min_messages;
log_min_messages
------------------
fatal
(1 row)
SET log_min_messages TO 'fatal';
SHOW log_min_messages;
log_min_messages
------------------
fatal
(1 row)
SET log_min_messages TO 'checkpointer:debug2, autovacuum:debug1'; -- fail
ERROR: invalid value for parameter "log_min_messages": "checkpointer:debug2, autovacuum:debug1"
DETAIL: Default log level was not defined.
SET log_min_messages TO 'debug1, backend:error, fatal'; -- fail
ERROR: invalid value for parameter "log_min_messages": "debug1, backend:error, fatal"
DETAIL: Redundant specification of default log level.
SET log_min_messages TO 'backend:error, debug1, backend:warning'; -- fail
ERROR: invalid value for parameter "log_min_messages": "backend:error, debug1, backend:warning"
DETAIL: Redundant log level specification for process type "backend".
SET log_min_messages TO 'backend:error, foo:fatal, archiver:debug1'; -- fail
ERROR: invalid value for parameter "log_min_messages": "backend:error, foo:fatal, archiver:debug1"
DETAIL: Unrecognized process type "foo".
SET log_min_messages TO 'backend:error, checkpointer:bar, archiver:debug1'; -- fail
ERROR: invalid value for parameter "log_min_messages": "backend:error, checkpointer:bar, archiver:debug1"
DETAIL: Unrecognized log level for process type "checkpointer": "bar".
SET log_min_messages TO 'backend:error, checkpointer:debug3, fatal, archiver:debug2, autovacuum:debug1, walsender:debug3';
SHOW log_min_messages;
log_min_messages
-------------------------------------------------------------------------------------------------
fatal, archiver:debug2, autovacuum:debug1, backend:error, checkpointer:debug3, walsender:debug3
(1 row)
SET log_min_messages TO 'warning, autovacuum:debug1';
SHOW log_min_messages;
log_min_messages
----------------------------
warning, autovacuum:debug1
(1 row)
SET log_min_messages TO 'autovacuum:debug1, warning';
SHOW log_min_messages;
log_min_messages
----------------------------
warning, autovacuum:debug1
(1 row)
RESET log_min_messages;
--
-- Tests for function-local GUC settings
--
set work_mem = '3MB';

View file

@ -232,6 +232,28 @@ drop schema not_there_initially;
select current_schemas(false);
reset search_path;
--
-- Test parsing of log_min_messages
--
SET log_min_messages TO foo; -- fail
SET log_min_messages TO fatal;
SHOW log_min_messages;
SET log_min_messages TO 'fatal';
SHOW log_min_messages;
SET log_min_messages TO 'checkpointer:debug2, autovacuum:debug1'; -- fail
SET log_min_messages TO 'debug1, backend:error, fatal'; -- fail
SET log_min_messages TO 'backend:error, debug1, backend:warning'; -- fail
SET log_min_messages TO 'backend:error, foo:fatal, archiver:debug1'; -- fail
SET log_min_messages TO 'backend:error, checkpointer:bar, archiver:debug1'; -- fail
SET log_min_messages TO 'backend:error, checkpointer:debug3, fatal, archiver:debug2, autovacuum:debug1, walsender:debug3';
SHOW log_min_messages;
SET log_min_messages TO 'warning, autovacuum:debug1';
SHOW log_min_messages;
SET log_min_messages TO 'autovacuum:debug1, warning';
SHOW log_min_messages;
RESET log_min_messages;
--
-- Tests for function-local GUC settings
--