Log all statements from a sample of transactions

This is useful to obtain a view of the different transaction types in an
application, regardless of the durations of the statements each runs.

Author: Adrien Nayrat
Reviewed-by: Masahiko Sawada, Hayato Kuroda, Andres Freund
This commit is contained in:
Alvaro Herrera 2019-04-03 18:43:59 -03:00
parent d8c0bd9fef
commit 799e220346
7 changed files with 60 additions and 3 deletions

View File

@ -5871,6 +5871,32 @@ local0.* /var/log/postgresql
</listitem>
</varlistentry>
<varlistentry id="guc-log-transaction-sample-rate" xreflabel="log_transaction_sample_rate">
<term><varname>log_transaction_sample_rate</varname> (<type>real</type>)
<indexterm>
<primary><varname>log_transaction_sample_rate</varname> configuration parameter</primary>
</indexterm>
</term>
<listitem>
<para>
Set the fraction of transactions whose statements are all logged,
in addition to statements logged for other reasons. It applies to
each new transaction regardless of its statements' durations.
The default is <literal>0</literal>, meaning not to log statements
from any additional transaction. Setting this to <literal>1</literal>
logs all statements for all transactions.
<varname>log_transaction_sample_rate</varname> is helpful to track a
sample of transaction.
</para>
<note>
<para>
Like all statement-logging options, this option can add significant
overhead.
</para>
</note>
</listitem>
</varlistentry>
</variablelist>
<para>

View File

@ -264,6 +264,9 @@ static char *prepareGID;
*/
static bool forceSyncCommit = false;
/* Flag for logging statements in a transaction. */
bool xact_is_sampled = false;
/*
* Private context for transaction-abort work --- we reserve space for this
* at startup to ensure that AbortTransaction and AbortSubTransaction can work
@ -1903,6 +1906,11 @@ StartTransaction(void)
s->state = TRANS_START;
s->fullTransactionId = InvalidFullTransactionId; /* until assigned */
/* Determine if statements are logged in this transaction */
xact_is_sampled = log_xact_sample_rate != 0 &&
(log_xact_sample_rate == 1 ||
random() <= log_xact_sample_rate * MAX_RANDOM_VALUE);
/*
* initialize current transaction state fields
*

View File

@ -2194,6 +2194,8 @@ check_log_statement(List *stmt_list)
* check_log_duration
* Determine whether current command's duration should be logged.
* If log_statement_sample_rate < 1.0, log only a sample.
* We also check if this statement in this transaction must be logged
* (regardless of its duration).
*
* Returns:
* 0 if no logging is needed
@ -2209,7 +2211,7 @@ check_log_statement(List *stmt_list)
int
check_log_duration(char *msec_str, bool was_logged)
{
if (log_duration || log_min_duration_statement >= 0)
if (log_duration || log_min_duration_statement >= 0 || xact_is_sampled)
{
long secs;
int usecs;
@ -2243,11 +2245,11 @@ check_log_duration(char *msec_str, bool was_logged)
(log_statement_sample_rate == 1 ||
random() <= log_statement_sample_rate * MAX_RANDOM_VALUE);
if ((exceeded && in_sample) || log_duration)
if ((exceeded && in_sample) || log_duration || xact_is_sampled)
{
snprintf(msec_str, 32, "%ld.%03d",
secs * 1000 + msecs, usecs % 1000);
if (exceeded && !was_logged)
if ((exceeded || xact_is_sampled) && !was_logged)
return 2;
else
return 1;

View File

@ -510,6 +510,7 @@ int client_min_messages = NOTICE;
int log_min_duration_statement = -1;
int log_temp_files = -1;
double log_statement_sample_rate = 1.0;
double log_xact_sample_rate = 0;
int trace_recovery_messages = LOG;
int temp_file_limit = -1;
@ -3386,6 +3387,18 @@ static struct config_real ConfigureNamesReal[] =
NULL, NULL, NULL
},
{
{"log_transaction_sample_rate", PGC_SUSET, LOGGING_WHEN,
gettext_noop("Set the fraction of transactions to log for new transactions."),
gettext_noop("Logs all statements from a fraction of transactions. "
"Use a value between 0.0 (never log) and 1.0 (log all "
"statements for all transactions).")
},
&log_xact_sample_rate,
0.0, 0.0, 1.0,
NULL, NULL, NULL
},
/* End-of-list marker */
{
{NULL, 0, 0, NULL, NULL}, NULL, 0.0, 0.0, 0.0, NULL, NULL, NULL

View File

@ -495,6 +495,10 @@
# log_min_duration_statement. 1.0 logs all statements,
# 0 never logs.
#log_transaction_sample_rate = 0.0 # Fraction of transactions whose statements
# are logged regardless of their duration. 1.0 logs all
# statements from all transactions, 0.0 never logs.
# - What to Log -
#debug_print_parse = off

View File

@ -55,6 +55,9 @@ extern PGDLLIMPORT int XactIsoLevel;
extern bool DefaultXactReadOnly;
extern bool XactReadOnly;
/* flag for logging statements in this transaction */
extern bool xact_is_sampled;
/*
* Xact is deferrable -- only meaningful (currently) for read only
* SERIALIZABLE transactions

View File

@ -252,6 +252,7 @@ extern PGDLLIMPORT int client_min_messages;
extern int log_min_duration_statement;
extern int log_temp_files;
extern double log_statement_sample_rate;
extern double log_xact_sample_rate;
extern int temp_file_limit;