Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit affebd2

Browse files
JelteFCommitfest Bot
authored and
Commitfest Bot
committed
Allow logging backtraces in more cases
We previously only had the backtrace_functions GUC to control when backtraces were logged. Based on mailinglist discussion there were two common cases that people wanted backtraces that were not covered by this GUC though: 1. Logging backtraces for all internal errors 2. Logging backtraces for all errors To support those two usecases, as well as to allow users to continue to log backtraces for specific warnings using `backtrace_functions`, this modifies the GUCs in the following way: 1. Adds a `log_backtrace` GUC, which can be set to `none` (default), `internal_error` and `all` to log different types of backtraces. 2. Change `backtrace_functions` to behave as an additional filter on top of `log_backtrace`. The empty string (the default) is now interpreted as doing no filtering based on function name. 3. Add a `backtrace_min_level` GUC, which limits for which log entries backtraces are written, based on their log level. This defaults to ERROR. This does mean that setting `backtrace_functions=some_func` alone is not enough to get backtraces for some_func. You now need to combine that with `log_backtrace_mode=all` and if you want to get backtraces for non-errors (which you previously got), you also need to change backtrace_min_level to whichever level you want backtraces for.
1 parent 03c53a7 commit affebd2

File tree

6 files changed

+161
-11
lines changed

6 files changed

+161
-11
lines changed

doc/src/sgml/config.sgml

Lines changed: 75 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7451,6 +7451,44 @@ local0.* /var/log/postgresql
74517451
</listitem>
74527452
</varlistentry>
74537453

7454+
<varlistentry id="guc-log-backtrace-mode" xreflabel="log_backtrace_mode">
7455+
<term><varname>log_backtrace_mode</varname> (<type>boolean</type>)
7456+
<indexterm>
7457+
<primary><varname>log_backtrace_mode</varname> configuration parameter</primary>
7458+
</indexterm>
7459+
</term>
7460+
<listitem>
7461+
<para>
7462+
If this parameter is set to <literal>all</literal> then for all log
7463+
entries a backtrace is written to the server log together with the log
7464+
message. If this parameter is set to <literal>internal_error</literal> then
7465+
such a backtrace is only written for logs with error code XX000
7466+
(internal error; see also <xref linkend="errcodes-appendix"/>).
7467+
This can be used to debug such internal errors (which should normally
7468+
not happen in production). Finally, if this parameter is set to
7469+
<literal>none</literal> (the default), no backtraces are ever written
7470+
to the server log.
7471+
</para>
7472+
7473+
<para>
7474+
The logs for which a backtrace is written can be further restricted
7475+
using <xref linkend="guc-backtrace-min-level"/> (default:
7476+
<literal>ERROR</literal>) and <xref linkend="guc-backtrace-functions"/>
7477+
(default: empty string, meaning all).
7478+
</para>
7479+
7480+
<para>
7481+
Backtrace support is not available on all platforms, and the quality
7482+
of the backtraces depends on compilation options.
7483+
</para>
7484+
7485+
<para>
7486+
Only superusers and users with the appropriate <literal>SET</literal>
7487+
privilege can change this setting.
7488+
</para>
7489+
</listitem>
7490+
</varlistentry>
7491+
74547492
<varlistentry id="guc-log-checkpoints" xreflabel="log_checkpoints">
74557493
<term><varname>log_checkpoints</varname> (<type>boolean</type>)
74567494
<indexterm>
@@ -12089,16 +12127,45 @@ dynamic_library_path = '/usr/local/lib/postgresql:$libdir'
1208912127
</term>
1209012128
<listitem>
1209112129
<para>
12092-
This parameter contains a comma-separated list of C function names.
12093-
If an error is raised and the name of the internal C function where
12094-
the error happens matches a value in the list, then a backtrace is
12095-
written to the server log together with the error message. This can
12096-
be used to debug specific areas of the source code.
12130+
This parameter can contain a comma-separated list of C function names,
12131+
which can be used to filter for which logs a backtrace is written to
12132+
the server log.
12133+
If a log entry is raised and the name of the
12134+
internal C function where the error happens does not match any of the
12135+
values in the list, then no backtrace is written to the server log.
12136+
This can be used to only debug specific areas of the source code.
1209712137
</para>
1209812138

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

1210412171
<para>
@@ -12131,6 +12198,7 @@ dynamic_library_path = '/usr/local/lib/postgresql:$libdir'
1213112198
</listitem>
1213212199
</varlistentry>
1213312200

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

src/backend/utils/error/elog.c

Lines changed: 26 additions & 4 deletions
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

Lines changed: 50 additions & 0 deletions
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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,7 @@
590590
# their durations, > 0 logs only
591591
# actions running at least this number
592592
# of milliseconds.
593+
#log_backtrace = 'none'
593594
#log_checkpoints = on
594595
#log_connections = '' # log aspects of connection setup
595596
# options include receipt, authentication, authorization,

src/include/utils/elog.h

Lines changed: 8 additions & 0 deletions
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

Lines changed: 1 addition & 0 deletions
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)