From 91d002469c1fe87f459534860d2ba271c905025d Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <jelte.fennema@microsoft.com>
Date: Tue, 27 Feb 2024 17:31:24 +0100
Subject: [PATCH v7 1/2] Add backtrace_functions_min_level

Before this change a backtrace would be attached to all logs messages
in a function that matched backtrace_functions. But in most cases people
only care about the backtraces for messages with an ERROR level. This
changes that default to only log backtraces for ERROR messages but
keeps the option open of logging backtraces for different log levels
too by having users configure the new backtrace_functions_min_level GUC.
---
 doc/src/sgml/config.sgml            | 41 ++++++++++++++++++++++++++---
 src/backend/utils/error/elog.c      |  1 +
 src/backend/utils/misc/guc_tables.c | 30 +++++++++++++++++++++
 src/include/utils/guc.h             |  1 +
 4 files changed, 69 insertions(+), 4 deletions(-)

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 65a6e6c4086..c76e97d2d33 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -11306,10 +11306,12 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir'
       <listitem>
        <para>
         This parameter contains a comma-separated list of C function names.
-        If an error is raised and the name of the internal C function where
-        the error happens matches a value in the list, then a backtrace is
-        written to the server log together with the error message.  This can
-        be used to debug specific areas of the source code.
+        If a log entry is raised with a level equal to or higher than
+        <xref linkend="guc-backtrace-functions-min-level"/> and the name of the
+        internal C function where the error happens matches a value in the
+        list, then a backtrace is written to the server log together with the
+        error message. This can be used to debug specific areas of the source
+        code.
        </para>
 
        <para>
@@ -11324,6 +11326,37 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir'
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-backtrace-functions-min-level" xreflabel="backtrace_functions_min_level">
+      <term><varname>backtrace_functions_min_level</varname> (<type>string</type>)
+      <indexterm>
+        <primary><varname>backtrace_functions_min_level</varname> configuration parameter</primary>
+      </indexterm>
+      </term>
+      <listitem>
+       <para>
+        Controls which <link linkend="runtime-config-severity-levels">message
+        levels</link> cause backtraces to be written to the log, for messages
+        raised from C functions that match the configured
+        <xref linkend="guc-backtrace-functions"/>.
+        Valid values are <literal>DEBUG5</literal>, <literal>DEBUG4</literal>,
+        <literal>DEBUG3</literal>, <literal>DEBUG2</literal>, <literal>DEBUG1</literal>,
+        <literal>LOG</literal>, <literal>INFO</literal>, <literal>NOTICE</literal>,
+        <literal>WARNING</literal>, <literal>ERROR</literal>, <literal>FATAL</literal>,
+        and <literal>PANIC</literal>.  Each level includes all the levels that
+        follow it.  The later the level, the fewer messages result in a
+        backtrace.  The default is <literal>ERROR</literal>.  Note that
+        <literal>LOG</literal> has a different rank here than in
+        <xref linkend="guc-log-min-messages"/>.
+       </para>
+
+       <para>
+        Only superusers and users with the appropriate <literal>SET</literal>
+        privilege can change this setting.
+       </para>
+      </listitem>
+     </varlistentry>
+
+
      <varlistentry id="guc-backtrace-on-internal-error" xreflabel="backtrace_on_internal_error">
       <term><varname>backtrace_on_internal_error</varname> (<type>boolean</type>)
       <indexterm>
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index ed8aa5c9fa4..b214747500c 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -499,6 +499,7 @@ errfinish(const char *filename, int lineno, const char *funcname)
 	if (!edata->backtrace &&
 		((edata->funcname &&
 		  backtrace_functions &&
+		  edata->elevel >= backtrace_functions_min_level &&
 		  matches_backtrace_functions(edata->funcname)) ||
 		 (edata->sqlerrcode == ERRCODE_INTERNAL_ERROR &&
 		  backtrace_on_internal_error)))
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index d77214795de..7a19214ee0a 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -162,6 +162,23 @@ static const struct config_enum_entry server_message_level_options[] = {
 	{NULL, 0, false}
 };
 
+static const struct config_enum_entry backtrace_functions_level_options[] = {
+	{"debug5", DEBUG5, false},
+	{"debug4", DEBUG4, false},
+	{"debug3", DEBUG3, false},
+	{"debug2", DEBUG2, false},
+	{"debug1", DEBUG1, false},
+	{"debug", DEBUG2, true},
+	{"log", LOG, false},
+	{"info", INFO, true},
+	{"notice", NOTICE, false},
+	{"warning", WARNING, false},
+	{"error", ERROR, false},
+	{"fatal", FATAL, false},
+	{"panic", PANIC, false},
+	{NULL, 0, false}
+};
+
 static const struct config_enum_entry intervalstyle_options[] = {
 	{"postgres", INTSTYLE_POSTGRES, false},
 	{"postgres_verbose", INTSTYLE_POSTGRES_VERBOSE, false},
@@ -530,6 +547,7 @@ double		log_statement_sample_rate = 1.0;
 double		log_xact_sample_rate = 0;
 char	   *backtrace_functions;
 bool		backtrace_on_internal_error = false;
+int			backtrace_functions_min_level = ERROR;
 
 int			temp_file_limit = -1;
 
@@ -4703,6 +4721,18 @@ struct config_enum ConfigureNamesEnum[] =
 		NULL, NULL, NULL
 	},
 
+	{
+		{"backtrace_functions_min_level", PGC_SUSET, DEVELOPER_OPTIONS,
+			gettext_noop("Sets the message levels that create backtraces when backtrace_functions is configured."),
+			gettext_noop("Each level includes all the levels that follow it. The later"
+						 " the level, the fewer backtraces are created."),
+			GUC_NOT_IN_SAMPLE
+		},
+		&backtrace_functions_min_level,
+		ERROR, backtrace_functions_level_options,
+		NULL, NULL, NULL
+	},
+
 	{
 		{"bytea_output", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Sets the output format for bytea."),
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 3712aba09b0..66dbf637c68 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -267,6 +267,7 @@ extern PGDLLIMPORT double log_statement_sample_rate;
 extern PGDLLIMPORT double log_xact_sample_rate;
 extern PGDLLIMPORT char *backtrace_functions;
 extern PGDLLIMPORT bool backtrace_on_internal_error;
+extern PGDLLIMPORT int backtrace_functions_min_level;
 
 extern PGDLLIMPORT int temp_file_limit;
 

base-commit: 6d9751fa8fd40c988541c9c72ac7a2095ba73c19
-- 
2.34.1

