]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Allow log_min_messages to be set per process type
authorÁlvaro Herrera <alvherre@kurilemu.de>
Mon, 9 Feb 2026 12:23:10 +0000 (13:23 +0100)
committerÁlvaro Herrera <alvherre@kurilemu.de>
Mon, 9 Feb 2026 12:23:10 +0000 (13:23 +0100)
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

13 files changed:
doc/src/sgml/config.sgml
src/backend/commands/extension.c
src/backend/postmaster/launch_backend.c
src/backend/utils/error/elog.c
src/backend/utils/init/miscinit.c
src/backend/utils/misc/guc_parameters.dat
src/backend/utils/misc/guc_tables.c
src/backend/utils/misc/postgresql.conf.sample
src/include/postmaster/proctypelist.h
src/include/utils/guc.h
src/include/utils/guc_hooks.h
src/test/regress/expected/guc.out
src/test/regress/sql/guc.sql

index f1af1505cf321503b0682335b913dcf5cde7e190..3734298696938ec49444bd5b009ecb9b35cd529c 100644 (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>
 
index 596105ee078f5db435336728f9624581e033c051..688f1874f31f0931f4b9b2dea8728a1168567b1f 100644 (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,
index 926fd6f2700aac3bc3699787bd02e17a8e30eb48..05b1feef3cf1d746bae96495c53641fd4ed74163 100644 (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
index e6a4ef990596deec278a7e07ea5cbb7fde545839..129906e2daaebe97b3eee2323640f617136fe877 100644 (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
  *
index 563f20374ff9b0f4d3d4dfe2658725c371e615d9..03f6c8479f2face177338a8ebbd8ba8108e686d3 100644 (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
index c1f1603cd39d93815c5a8b78081fb8f6d91ef36c..762b8efe6b00367229a9b7595064e47ee8f33803 100644 (file)
   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',
index 5df3a36bf6429bb8f55bc30e613ffc40e0b69a87..741fce8dede5793594b5037421833e1a50d80e69 100644 (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)
index 1ae594af84310e7c46845401dffebdd1ea1d0ddf..6e82c8e055da0b5917c884b0a81de1693017fd38 100644 (file)
 
 # - 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
index 0b99eaabfd01ab065ef68538ff8359157726d283..4e259e84c2dda65b772a3701ed808176898f0f3c 100644 (file)
  */
 
 /*
- * 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)
index bf39878c43eadda0d7c680f50b2607cac94e78c1..8acbdba7ff5eea1913c1f1af36050d19bc9e49d8 100644 (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[];
 
index b6ecb0e769f91299a5feed5e4415e0f55fd5e141..9c90670d9b8d8d5d3b0c6763613b3e5e6c832890 100644 (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 */
index d6fb879f500826f6e454c225e26668dd338039d6..3fa2562f231f38b50a1a51b3e9f2e1531bd58d0d 100644 (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';
index bafaf067e82d00418fc446f9c16fe156a50b84f1..dfb843fd3aee63916f2711b472f326b067fe977f 100644 (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
 --