Hello, Per idea of Nikolay Samokhvalov[1] I propose this patch to add the possibility to log all statements from a fraction of transactions.
I have several questions: * Do we want this feature? * How can I add tests? I seems hard to handle tests when a there is duration in the output. * Should I handle the case when someone try to change the setting *inside* a transaction: # SET client_min_messages to LOG; SET # SET log_transaction_sample_rate to 1; SET # BEGIN; LOG: duration: 0.364 ms statement: BEGIN; BEGIN # SELECT 1; LOG: duration: 0.530 ms statement: SELECT 1; -[ RECORD 1 ] ?column? | 1 # SET log_transaction_sample_rate to 0; LOG: duration: 0.333 ms statement: SET log_transaction_sample_rate to 0; SET # SELECT 1; LOG: duration: 0.586 ms statement: SELECT 1; -[ RECORD 1 ] ?column? | 1 Thanks [1]: https://www.postgresql.org/message-id/CANNMO%2BLg65EFqHb%2BZYbMLKyE2y498HJzsdFrMnW1dQ6AFJ3Mpw%40mail.gmail.com -- Adrien NAYRAT
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 4a7121a51f..7312b1022f 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -5771,6 +5771,24 @@ local0.* /var/log/postgresql </listitem> </varlistentry> + <varlistentry id="guc-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 logged. It applies + to each new transaction regardless of their duration. The default is + <literal>0</literal>, meaning do not log statements from this 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> + </listitem> + </varlistentry> + </variablelist> <para> diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index d967400384..d622023ebe 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -75,6 +75,7 @@ int XactIsoLevel; bool DefaultXactReadOnly = false; bool XactReadOnly; +bool xact_is_sampled; bool DefaultXactDeferrable = false; bool XactDeferrable; @@ -1821,6 +1822,9 @@ StartTransaction(void) s->state = TRANS_START; s->transactionId = InvalidTransactionId; /* until assigned */ + /* Determine if we log statements in this transaction */ + xact_is_sampled = random() <= log_xact_sample_rate * MAX_RANDOM_VALUE; + /* * initialize current transaction state fields * diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 5ab7d3cd8d..8f1ae0a5dd 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -100,7 +100,8 @@ int max_stack_depth = 100; /* wait N seconds to allow attach from a debugger */ int PostAuthDelay = 0; - +/* flag for logging statements in this transaction */ +bool xact_is_sampled = false; /* ---------------- * private variables @@ -2203,6 +2204,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 @@ -2218,7 +2221,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; @@ -2252,11 +2255,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; diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 6fe1939881..160c725123 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -487,6 +487,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; @@ -3325,13 +3326,25 @@ static struct config_real ConfigureNamesReal[] = {"log_statement_sample_rate", PGC_SUSET, LOGGING_WHEN, gettext_noop("Fraction of statements over log_min_duration_statement to log."), gettext_noop("If you only want a sample, use a value between 0 (never " - "log) and 1.0 (always log).") + "log) and 1 (always log).") }, &log_statement_sample_rate, 1.0, 0.0, 1.0, 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 (never log) and 1 (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 diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index 1fa02d2c93..89553f5302 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -492,6 +492,10 @@ # log_min_duration_statement. 1.0 logs all statements, # 0 never logs. +#log_transaction_sample_rate = 0 # Fraction of transactions whose statements + # are logged regardless of their duration. 1.0 logs all + # statements from all transactions, 0 never logs. + # - What to Log - #debug_print_parse = off diff --git a/src/include/access/xact.h b/src/include/access/xact.h index 689c57c592..70759b63a0 100644 --- a/src/include/access/xact.h +++ b/src/include/access/xact.h @@ -54,6 +54,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 diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h index 64457c792a..e7325fbdb7 100644 --- a/src/include/utils/guc.h +++ b/src/include/utils/guc.h @@ -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;
signature.asc
Description: OpenPGP digital signature