From 38e0190ced714b33c43c9676d768cc6814fc662a Mon Sep 17 00:00:00 2001 From: =?utf8?q?=C3=81lvaro=20Herrera?= Date: Mon, 9 Feb 2026 13:23:10 +0100 Subject: [PATCH] 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 Reviewed-by: Chao Li Reviewed-by: Japin Li Reviewed-by: Tan Yang <332696245@qq.com> Discussion: https://postgr.es/m/e85c6671-1600-4112-8887-f97a8a5d07b2@app.fastmail.com --- doc/src/sgml/config.sgml | 52 +++- src/backend/commands/extension.c | 2 +- src/backend/postmaster/launch_backend.c | 2 +- src/backend/utils/error/elog.c | 247 +++++++++++++++++- src/backend/utils/init/miscinit.c | 2 +- src/backend/utils/misc/guc_parameters.dat | 10 +- src/backend/utils/misc/guc_tables.c | 13 +- src/backend/utils/misc/postgresql.conf.sample | 16 +- src/include/postmaster/proctypelist.h | 42 +-- src/include/utils/guc.h | 5 +- src/include/utils/guc_hooks.h | 2 + src/test/regress/expected/guc.out | 57 ++++ src/test/regress/sql/guc.sql | 22 ++ 13 files changed, 428 insertions(+), 44 deletions(-) diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index f1af1505cf3..37342986969 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -7120,27 +7120,57 @@ local0.* /var/log/postgresql - log_min_messages (enum) + log_min_messages (string) log_min_messages configuration parameter - Controls which message - levels are written to the server log. - Valid values are DEBUG5, DEBUG4, - DEBUG3, DEBUG2, DEBUG1, - INFO, NOTICE, WARNING, - ERROR, LOG, FATAL, and - PANIC. Each level includes all the levels that - follow it. The later the level, the fewer messages are sent - to the log. The default is WARNING. Note that - LOG has a different rank here than in + Controls which + message levels + are written to the server log. The value is a comma-separated + list of zero or more + process type:level + entries and exactly one mandatory + level entry, + which becomes the default for process types not listed. + Valid process types are listed in the table below. + + archiver + autovacuum + backend + bgworker + bgwriter + checkpointer + ioworker + postmaster + syslogger + slotsyncworker + startup + walreceiver + walsender + walsummarizer + walwriter + + Valid level values are DEBUG5, + DEBUG4, DEBUG3, DEBUG2, + DEBUG1, INFO, NOTICE, + WARNING, ERROR, LOG, + FATAL, and PANIC. Each level includes + all the levels that follow it. The later the level, the fewer messages are sent + to the log. The default is WARNING, which + applies that level to all process types. + Note that LOG has a different rank here than in . Only superusers and users with the appropriate SET privilege can change this setting. + + Example: To log walsender and autovacuum + at level DEBUG1 and everything else at ERROR, + set log_min_messages to error, walsender:debug1, autovacuum:debug1. + diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c index 596105ee078..688f1874f31 100644 --- a/src/backend/commands/extension.c +++ b/src/backend/commands/extension.c @@ -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, diff --git a/src/backend/postmaster/launch_backend.c b/src/backend/postmaster/launch_backend.c index 926fd6f2700..05b1feef3cf 100644 --- a/src/backend/postmaster/launch_backend.c +++ b/src/backend/postmaster/launch_backend.c @@ -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 diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c index e6a4ef99059..129906e2daa 100644 --- a/src/backend/utils/error/elog.c +++ b/src/backend/utils/error/elog.c @@ -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 * diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c index 563f20374ff..03f6c8479f2 100644 --- a/src/backend/utils/init/miscinit.c +++ b/src/backend/utils/init/miscinit.c @@ -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 diff --git a/src/backend/utils/misc/guc_parameters.dat b/src/backend/utils/misc/guc_parameters.dat index c1f1603cd39..762b8efe6b0 100644 --- a/src/backend/utils/misc/guc_parameters.dat +++ b/src/backend/utils/misc/guc_parameters.dat @@ -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', diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c index 5df3a36bf64..741fce8dede 100644 --- a/src/backend/utils/misc/guc_tables.c +++ b/src/backend/utils/misc/guc_tables.c @@ -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) diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index 1ae594af843..6e82c8e055d 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -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 diff --git a/src/include/postmaster/proctypelist.h b/src/include/postmaster/proctypelist.h index 0b99eaabfd0..4e259e84c2d 100644 --- a/src/include/postmaster/proctypelist.h +++ b/src/include/postmaster/proctypelist.h @@ -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) diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h index bf39878c43e..8acbdba7ff5 100644 --- a/src/include/utils/guc.h +++ b/src/include/utils/guc.h @@ -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[]; diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h index b6ecb0e769f..9c90670d9b8 100644 --- a/src/include/utils/guc_hooks.h +++ b/src/include/utils/guc_hooks.h @@ -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 */ diff --git a/src/test/regress/expected/guc.out b/src/test/regress/expected/guc.out index d6fb879f500..3fa2562f231 100644 --- a/src/test/regress/expected/guc.out +++ b/src/test/regress/expected/guc.out @@ -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'; diff --git a/src/test/regress/sql/guc.sql b/src/test/regress/sql/guc.sql index bafaf067e82..dfb843fd3ae 100644 --- a/src/test/regress/sql/guc.sql +++ b/src/test/regress/sql/guc.sql @@ -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 -- -- 2.47.3