Skip to content

Commit 41a0eae

Browse files
author
Commitfest Bot
committed
[CF 4735] v12 - Support a wildcard in backtrace_functions
This branch was automatically generated by a robot using patches from an email thread registered at: https://commitfest.postgresql.org/patch/4735 The branch will be overwritten each time a new patch version is posted to the thread, and also periodically to check for bitrot caused by changes on the master branch. Patch(es): https://www.postgresql.org/message-id/CAGECzQThxK+ZNLNasmiMXXN_TfUJEVDC49pZ2LB_aSvjW2tigA@mail.gmail.com Author(s): Jelte Fennema-Nio
2 parents 9d924db + 6cf7750 commit 41a0eae

File tree

6 files changed

+161
-11
lines changed

6 files changed

+161
-11
lines changed

doc/src/sgml/config.sgml

+75-7
Original file line numberDiff line numberDiff line change
@@ -7435,6 +7435,44 @@ local0.* /var/log/postgresql
74357435
</listitem>
74367436
</varlistentry>
74377437

7438+
<varlistentry id="guc-log-backtrace-mode" xreflabel="log_backtrace_mode">
7439+
<term><varname>log_backtrace_mode</varname> (<type>boolean</type>)
7440+
<indexterm>
7441+
<primary><varname>log_backtrace_mode</varname> configuration parameter</primary>
7442+
</indexterm>
7443+
</term>
7444+
<listitem>
7445+
<para>
7446+
If this parameter is set to <literal>all</literal> then for all log
7447+
entries a backtrace is written to the server log together with the log
7448+
message. If this parameter is set to <literal>internal_error</literal> then
7449+
such a backtrace is only written for logs with error code XX000
7450+
(internal error; see also <xref linkend="errcodes-appendix"/>).
7451+
This can be used to debug such internal errors (which should normally
7452+
not happen in production). Finally, if this parameter is set to
7453+
<literal>none</literal> (the default), no backtraces are ever written
7454+
to the server log.
7455+
</para>
7456+
7457+
<para>
7458+
The logs for which a backtrace is written can be further restricted
7459+
using <xref linkend="guc-backtrace-min-level"/> (default:
7460+
<literal>ERROR</literal>) and <xref linkend="guc-backtrace-functions"/>
7461+
(default: empty string, meaning all).
7462+
</para>
7463+
7464+
<para>
7465+
Backtrace support is not available on all platforms, and the quality
7466+
of the backtraces depends on compilation options.
7467+
</para>
7468+
7469+
<para>
7470+
Only superusers and users with the appropriate <literal>SET</literal>
7471+
privilege can change this setting.
7472+
</para>
7473+
</listitem>
7474+
</varlistentry>
7475+
74387476
<varlistentry id="guc-log-checkpoints" xreflabel="log_checkpoints">
74397477
<term><varname>log_checkpoints</varname> (<type>boolean</type>)
74407478
<indexterm>
@@ -12088,16 +12126,45 @@ dynamic_library_path = '/usr/local/lib/postgresql:$libdir'
1208812126
</term>
1208912127
<listitem>
1209012128
<para>
12091-
This parameter contains a comma-separated list of C function names.
12092-
If an error is raised and the name of the internal C function where
12093-
the error happens matches a value in the list, then a backtrace is
12094-
written to the server log together with the error message. This can
12095-
be used to debug specific areas of the source code.
12129+
This parameter can contain a comma-separated list of C function names,
12130+
which can be used to filter for which logs a backtrace is written to
12131+
the server log.
12132+
If a log entry is raised and the name of the
12133+
internal C function where the error happens does not match any of the
12134+
values in the list, then no backtrace is written to the server log.
12135+
This can be used to only debug specific areas of the source code.
1209612136
</para>
1209712137

1209812138
<para>
12099-
Backtrace support is not available on all platforms, and the quality
12100-
of the backtraces depends on compilation options.
12139+
The empty string (the default) disables any such filtering. So for any
12140+
logs that match both <xref linkend="guc-log-backtrace-mode"/> and
12141+
<xref linkend="guc-backtrace-min-level"/> a backtrace is
12142+
written to the server log.
12143+
</para>
12144+
</listitem>
12145+
</varlistentry>
12146+
12147+
<varlistentry id="guc-backtrace-min-level" xreflabel="backtrace_min_level">
12148+
<term><varname>backtrace_min_level</varname> (<type>string</type>)
12149+
<indexterm>
12150+
<primary><varname>backtrace_min_level</varname> configuration parameter</primary>
12151+
</indexterm>
12152+
</term>
12153+
<listitem>
12154+
<para>
12155+
Controls which <link linkend="runtime-config-severity-levels">message
12156+
levels</link> cause backtraces to be written to the log, for log
12157+
messages that match both <xref linkend="guc-log-backtrace-mode"/> and
12158+
<xref linkend="guc-backtrace-functions"/>.
12159+
Valid values are <literal>DEBUG5</literal>, <literal>DEBUG4</literal>,
12160+
<literal>DEBUG3</literal>, <literal>DEBUG2</literal>, <literal>DEBUG1</literal>,
12161+
<literal>LOG</literal>, <literal>INFO</literal>, <literal>NOTICE</literal>,
12162+
<literal>WARNING</literal>, <literal>ERROR</literal>, <literal>FATAL</literal>,
12163+
and <literal>PANIC</literal>. Each level includes all the levels that
12164+
follow it. The later the level, the fewer messages result in a
12165+
backtrace. The default is <literal>ERROR</literal>. Note that
12166+
<literal>LOG</literal> has a different rank here than in
12167+
<xref linkend="guc-log-min-messages"/>.
1210112168
</para>
1210212169

1210312170
<para>
@@ -12130,6 +12197,7 @@ dynamic_library_path = '/usr/local/lib/postgresql:$libdir'
1213012197
</listitem>
1213112198
</varlistentry>
1213212199

12200+
1213312201
<varlistentry id="guc-debug-discard-caches" xreflabel="debug_discard_caches">
1213412202
<term><varname>debug_discard_caches</varname> (<type>integer</type>)
1213512203
<indexterm>

src/backend/utils/error/elog.c

+26-4
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ int Log_error_verbosity = PGERROR_DEFAULT;
110110
char *Log_line_prefix = NULL; /* format for extra log line info */
111111
int Log_destination = LOG_DESTINATION_STDERR;
112112
char *Log_destination_string = NULL;
113+
int log_backtrace = LOGBACKTRACE_NONE;
113114
bool syslog_sequence_numbers = true;
114115
bool syslog_split_messages = true;
115116

@@ -178,6 +179,7 @@ static void set_stack_entry_domain(ErrorData *edata, const char *domain);
178179
static void set_stack_entry_location(ErrorData *edata,
179180
const char *filename, int lineno,
180181
const char *funcname);
182+
static bool matches_backtrace_gucs(ErrorData *edata);
181183
static bool matches_backtrace_functions(const char *funcname);
182184
static pg_noinline void set_backtrace(ErrorData *edata, int num_skip);
183185
static void set_errdata_field(MemoryContextData *cxt, char **ptr, const char *str);
@@ -493,10 +495,7 @@ errfinish(const char *filename, int lineno, const char *funcname)
493495
oldcontext = MemoryContextSwitchTo(ErrorContext);
494496

495497
/* Collect backtrace, if enabled and we didn't already */
496-
if (!edata->backtrace &&
497-
edata->funcname &&
498-
backtrace_functions &&
499-
matches_backtrace_functions(edata->funcname))
498+
if (!edata->backtrace && matches_backtrace_gucs(edata))
500499
set_backtrace(edata, 2);
501500

502501
/*
@@ -816,6 +815,26 @@ set_stack_entry_location(ErrorData *edata,
816815
edata->funcname = funcname;
817816
}
818817

818+
/*
819+
* matches_backtrace_gucs --- checks whether the log entry matches
820+
* log_backtrace_mode, backtrace_min_level and backtrace_functions.
821+
*/
822+
static bool
823+
matches_backtrace_gucs(ErrorData *edata)
824+
{
825+
if (log_backtrace == LOGBACKTRACE_NONE)
826+
return false;
827+
828+
if (log_backtrace == LOGBACKTRACE_INTERNAL_ERROR &&
829+
edata->sqlerrcode != ERRCODE_INTERNAL_ERROR)
830+
return false;
831+
832+
if (backtrace_min_level > edata->elevel)
833+
return false;
834+
835+
return matches_backtrace_functions(edata->funcname);
836+
}
837+
819838
/*
820839
* matches_backtrace_functions --- checks whether the given funcname matches
821840
* backtrace_functions
@@ -827,6 +846,9 @@ matches_backtrace_functions(const char *funcname)
827846
{
828847
const char *p;
829848

849+
if (!backtrace_functions || backtrace_functions[0] == '\0')
850+
return true;
851+
830852
if (!backtrace_function_list || funcname == NULL || funcname[0] == '\0')
831853
return false;
832854

src/backend/utils/misc/guc_tables.c

+50
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,23 @@ static const struct config_enum_entry server_message_level_options[] = {
163163
{NULL, 0, false}
164164
};
165165

166+
static const struct config_enum_entry backtrace_level_options[] = {
167+
{"debug5", DEBUG5, false},
168+
{"debug4", DEBUG4, false},
169+
{"debug3", DEBUG3, false},
170+
{"debug2", DEBUG2, false},
171+
{"debug1", DEBUG1, false},
172+
{"debug", DEBUG2, true},
173+
{"log", LOG, false},
174+
{"info", INFO, true},
175+
{"notice", NOTICE, false},
176+
{"warning", WARNING, false},
177+
{"error", ERROR, false},
178+
{"fatal", FATAL, false},
179+
{"panic", PANIC, false},
180+
{NULL, 0, false}
181+
};
182+
166183
static const struct config_enum_entry intervalstyle_options[] = {
167184
{"postgres", INTSTYLE_POSTGRES, false},
168185
{"postgres_verbose", INTSTYLE_POSTGRES_VERBOSE, false},
@@ -200,6 +217,16 @@ static const struct config_enum_entry log_error_verbosity_options[] = {
200217
StaticAssertDecl(lengthof(log_error_verbosity_options) == (PGERROR_VERBOSE + 2),
201218
"array length mismatch");
202219

220+
static const struct config_enum_entry log_backtrace_options[] = {
221+
{"none", LOGBACKTRACE_NONE, false},
222+
{"internal_error", LOGBACKTRACE_INTERNAL_ERROR, false},
223+
{"all", LOGBACKTRACE_ALL, false},
224+
{NULL, 0, false}
225+
};
226+
227+
StaticAssertDecl(lengthof(log_backtrace_options) == (LOGBACKTRACE_ALL + 2),
228+
"array length mismatch");
229+
203230
static const struct config_enum_entry log_statement_options[] = {
204231
{"none", LOGSTMT_NONE, false},
205232
{"ddl", LOGSTMT_DDL, false},
@@ -546,6 +573,7 @@ int log_temp_files = -1;
546573
double log_statement_sample_rate = 1.0;
547574
double log_xact_sample_rate = 0;
548575
char *backtrace_functions;
576+
int backtrace_min_level = ERROR;
549577

550578
int temp_file_limit = -1;
551579

@@ -5004,6 +5032,18 @@ struct config_enum ConfigureNamesEnum[] =
50045032
NULL, NULL, NULL
50055033
},
50065034

5035+
{
5036+
{"backtrace_min_level", PGC_SUSET, DEVELOPER_OPTIONS,
5037+
gettext_noop("Sets the message levels that create backtraces when log_backtrace is configured."),
5038+
gettext_noop("Each level includes all the levels that follow it. The later"
5039+
" the level, the fewer backtraces are created."),
5040+
GUC_NOT_IN_SAMPLE
5041+
},
5042+
&backtrace_min_level,
5043+
ERROR, backtrace_level_options,
5044+
NULL, NULL, NULL
5045+
},
5046+
50075047
{
50085048
{"bytea_output", PGC_USERSET, CLIENT_CONN_STATEMENT,
50095049
gettext_noop("Sets the output format for bytea."),
@@ -5100,6 +5140,16 @@ struct config_enum ConfigureNamesEnum[] =
51005140
NULL, NULL, NULL
51015141
},
51025142

5143+
{
5144+
{"log_backtrace", PGC_SUSET, LOGGING_WHAT,
5145+
gettext_noop("Sets if logs should include a backtrace."),
5146+
NULL
5147+
},
5148+
&log_backtrace,
5149+
LOGBACKTRACE_NONE, log_backtrace_options,
5150+
NULL, NULL, NULL
5151+
},
5152+
51035153
{
51045154
{"log_error_verbosity", PGC_SUSET, LOGGING_WHAT,
51055155
gettext_noop("Sets the verbosity of logged messages."),

src/backend/utils/misc/postgresql.conf.sample

+1
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,7 @@
594594
# their durations, > 0 logs only
595595
# actions running at least this number
596596
# of milliseconds.
597+
#log_backtrace = 'none'
597598
#log_checkpoints = on
598599
#log_connections = '' # log aspects of connection setup
599600
# options include receipt, authentication, authorization,

src/include/utils/elog.h

+8
Original file line numberDiff line numberDiff line change
@@ -487,9 +487,17 @@ typedef enum
487487
PGERROR_VERBOSE, /* all the facts, ma'am */
488488
} PGErrorVerbosity;
489489

490+
enum
491+
{
492+
LOGBACKTRACE_NONE, /* no backtrace */
493+
LOGBACKTRACE_INTERNAL_ERROR, /* backtrace for internal error code */
494+
LOGBACKTRACE_ALL, /* backtrace for all logs */
495+
};
496+
490497
extern PGDLLIMPORT int Log_error_verbosity;
491498
extern PGDLLIMPORT char *Log_line_prefix;
492499
extern PGDLLIMPORT int Log_destination;
500+
extern PGDLLIMPORT int log_backtrace;
493501
extern PGDLLIMPORT char *Log_destination_string;
494502
extern PGDLLIMPORT bool syslog_sequence_numbers;
495503
extern PGDLLIMPORT bool syslog_split_messages;

src/include/utils/guc.h

+1
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ extern PGDLLIMPORT int log_temp_files;
279279
extern PGDLLIMPORT double log_statement_sample_rate;
280280
extern PGDLLIMPORT double log_xact_sample_rate;
281281
extern PGDLLIMPORT char *backtrace_functions;
282+
extern PGDLLIMPORT int backtrace_min_level;
282283

283284
extern PGDLLIMPORT int temp_file_limit;
284285

0 commit comments

Comments
 (0)