Thread
Commits
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
Fix log_statement_max_length test with verbose logs
- 9bfbf5bf6190 master landed
-
Add log_statement_max_length GUC to limit logged statement text
- c8bd8387c27a master landed
-
Improve user control over truncation of logged bind-parameter values.
- 0b34e7d307e6 13.0 cited
-
Truncate logs by max_log_size
Kirill Gavrilov <diphantxm@gmail.com> — 2024-09-26T18:30:08Z
Hi hackers, I would like to suggest a patch to truncate some long queries. I believe sometimes there is no need to log a query containing some gigabytes of blob, for example. In patch a new parameter, named max_log_size, is introduced. It defines the maximum size of logged query, in bytes. Everything beyond that size is truncated. Best regards, Kirill Gavrilov
-
Re: Truncate logs by max_log_size
Euler Taveira <euler@eulerto.com> — 2024-09-27T00:30:05Z
On Thu, Sep 26, 2024, at 3:30 PM, diPhantxm wrote: > I would like to suggest a patch to truncate some long queries. I believe sometimes there is no need to log a query containing some gigabytes of blob, for example. In patch a new parameter, named max_log_size, is introduced. It defines the maximum size of logged query, in bytes. Everything beyond that size is truncated. I don't know how useful is this proposal. IMO the whole query is usually crucial for an analysis. Let's say you arbitrarily provide max_log_size = 100 but it means you cannot see a WHERE clause and you have a performance issue in that query. It won't be possible to obtain the whole query for an EXPLAIN. It would break audit systems that requires the whole query. I don't know if there are some log-based replication systems but it would break such tools too. There are other ways to avoid logging such long queries. The GRANT ... ON PARAMETER and SET LOCAL commands are your friends. Hence, you can disable specific long queries even if you are not a superuser. If your main problem is disk space, you can adjust the rotation settings or have an external tool to manage your log files (or even use syslog). -- Euler Taveira EDB https://www.enterprisedb.com/
-
Re: Truncate logs by max_log_size
Andrey Borodin <x4mmm@yandex-team.ru> — 2024-09-27T10:36:58Z
> On 27 Sep 2024, at 03:30, Euler Taveira <euler@eulerto.com> wrote: > > Let's say you arbitrarily provide max_log_size = 100 Consider max_log_size = 10Mb. The perspective might look very different. It’s not about WHERE anymore. It's a guard against heavy abuse. The feature looks very important for me. Best regards, Andrey Borodin.
-
Re: Truncate logs by max_log_size
Jim Jones <jim.jones@uni-muenster.de> — 2024-10-01T11:46:44Z
On 27.09.24 12:36, Andrey M. Borodin wrote: > Consider max_log_size = 10Mb. The perspective might look very different. > It’s not about WHERE anymore. It's a guard against heavy abuse. > > The feature looks very important for me. I have the same opinion. As a fail safe it sounds very useful to me. Unfortunately, the patch does not apply: $ git apply ~/patches/max_log_query/0001-parameter-max_log_size-to-truncate-logs.patch -v Checking patch src/backend/utils/error/elog.c... error: while searching for: char *Log_destination_string = NULL; bool syslog_sequence_numbers = true; bool syslog_split_messages = true; /* Processed form of backtrace_symbols GUC */ static char *backtrace_symbol_list; error: patch failed: src/backend/utils/error/elog.c:114 error: src/backend/utils/error/elog.c: patch does not apply Checking patch src/backend/utils/misc/guc_tables.c... Hunk #1 succeeded at 3714 (offset 247 lines). Checking patch src/backend/utils/misc/postgresql.conf.sample... Hunk #1 succeeded at 615 (offset 23 lines). Checking patch src/bin/pg_ctl/t/004_logrotate.pl... error: while searching for: check_log_pattern('csvlog', $new_current_logfiles, 'syntax error', $node); check_log_pattern('jsonlog', $new_current_logfiles, 'syntax error', $node); $node->stop(); done_testing(); error: patch failed: src/bin/pg_ctl/t/004_logrotate.pl:135 error: src/bin/pg_ctl/t/004_logrotate.pl: patch does not apply Checking patch src/include/utils/elog.h... Hunk #1 succeeded at 502 (offset 1 line). Does it truncate only single queries or also a transaction with many statements? Thanks! Best, Jim -
Re: Truncate logs by max_log_size
Greg Sabino Mullane <htamfids@gmail.com> — 2024-10-01T12:43:20Z
On Fri, Sep 27, 2024 at 6:37 AM Andrey M. Borodin <x4mmm@yandex-team.ru> wrote: > Consider max_log_size = 10Mb. The perspective might look very different. > It’s not about WHERE anymore. It's a guard against heavy abuse. > Can you elaborate on this? Do you mean someone purposefully writing large entries to your log file?
-
Re: Truncate logs by max_log_size
Kirill Gavrilov <diphantxm@gmail.com> — 2024-10-01T15:46:32Z
On Tue, Oct 1, 2024 at 2:46 PM Jim Jones <jim.jones@uni-muenster.de> wrote: > > On 27.09.24 12:36, Andrey M. Borodin wrote: > > Consider max_log_size = 10Mb. The perspective might look very different. > > It’s not about WHERE anymore. It's a guard against heavy abuse. > > > > The feature looks very important for me. > I have the same opinion. As a fail safe it sounds very useful to me. > > Unfortunately, the patch does not apply: > > $ git apply > ~/patches/max_log_query/0001-parameter-max_log_size-to-truncate-logs.patch > -v > Checking patch src/backend/utils/error/elog.c... > error: while searching for: > char *Log_destination_string = NULL; > bool syslog_sequence_numbers = true; > bool syslog_split_messages = true; > > /* Processed form of backtrace_symbols GUC */ > static char *backtrace_symbol_list; > > error: patch failed: src/backend/utils/error/elog.c:114 > error: src/backend/utils/error/elog.c: patch does not apply > Checking patch src/backend/utils/misc/guc_tables.c... > Hunk #1 succeeded at 3714 (offset 247 lines). > Checking patch src/backend/utils/misc/postgresql.conf.sample... > Hunk #1 succeeded at 615 (offset 23 lines). > Checking patch src/bin/pg_ctl/t/004_logrotate.pl... > error: while searching for: > check_log_pattern('csvlog', $new_current_logfiles, 'syntax error', $node); > check_log_pattern('jsonlog', $new_current_logfiles, 'syntax error', $node); > > $node->stop(); > > done_testing(); > > error: patch failed: src/bin/pg_ctl/t/004_logrotate.pl:135 > error: src/bin/pg_ctl/t/004_logrotate.pl: patch does not apply > Checking patch src/include/utils/elog.h... > Hunk #1 succeeded at 502 (offset 1 line). > > Does it truncate only single queries or also a transaction with many > statements? > > Thanks! > > Best, Jim > My apologies, attached patch should work on master branch. It truncates single queries and a statement in transaction that occurred an error. -
Re: Truncate logs by max_log_size
Jim Jones <jim.jones@uni-muenster.de> — 2024-10-01T23:08:43Z
On 01.10.24 17:46, Kirill Gavrilov wrote: > My apologies, attached patch should work on master branch. Nice. I tested the feature and it does what it is intended to. postgres=# SHOW max_log_size; max_log_size -------------- 10 (1 row) postgres=# INSERT INTO t VALUES (1,2,3,4,5,6,7,8,9,0); ERROR: relation "t" does not exist LINE 1: INSERT INTO t VALUES (1,2,3,4,5,6,7,8,9,0); Log file: 2024-10-02 00:57:13.618 CEST [1975926] ERROR: relation "t" does not exist at character 13 2024-10-02 00:57:13.618 CEST [1975926] STATEMENT: INSERT INT A few observations: 1) You missed a const qualifier in elog.c: elog.c: In function ‘EmitErrorReport’: elog.c:1699:29: warning: initialization discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers] 1699 | char* str = debug_query_string; | ^~~~~~~~~~~~~~~~~~ 2) The new parameter cannot be set within a session with SET. Is it supposed to be like this? IMHO it would be nice to able to temporarily set this parameter without having to reload the postgresql.conf postgres=# SET max_log_size TO 100; ERROR: parameter "max_log_size" cannot be changed now 3) I personally find -1 more intuitive than 0 to disable a parameter, but I have no strong opinion about it. 4) It still lacks documentation. -- Jim
-
Re: Truncate logs by max_log_size
Kirill Reshke <reshkekirill@gmail.com> — 2024-11-25T16:52:17Z
On Tue, 1 Oct 2024 at 20:46, Kirill Gavrilov <diphantxm@gmail.com> wrote: > > On Tue, Oct 1, 2024 at 2:46 PM Jim Jones <jim.jones@uni-muenster.de> wrote: >> >> >> On 27.09.24 12:36, Andrey M. Borodin wrote: >> > Consider max_log_size = 10Mb. The perspective might look very different. >> > It’s not about WHERE anymore. It's a guard against heavy abuse. >> > >> > The feature looks very important for me. >> I have the same opinion. As a fail safe it sounds very useful to me. >> >> Unfortunately, the patch does not apply: >> >> $ git apply >> ~/patches/max_log_query/0001-parameter-max_log_size-to-truncate-logs.patch >> -v >> Checking patch src/backend/utils/error/elog.c... >> error: while searching for: >> char *Log_destination_string = NULL; >> bool syslog_sequence_numbers = true; >> bool syslog_split_messages = true; >> >> /* Processed form of backtrace_symbols GUC */ >> static char *backtrace_symbol_list; >> >> error: patch failed: src/backend/utils/error/elog.c:114 >> error: src/backend/utils/error/elog.c: patch does not apply >> Checking patch src/backend/utils/misc/guc_tables.c... >> Hunk #1 succeeded at 3714 (offset 247 lines). >> Checking patch src/backend/utils/misc/postgresql.conf.sample... >> Hunk #1 succeeded at 615 (offset 23 lines). >> Checking patch src/bin/pg_ctl/t/004_logrotate.pl... >> error: while searching for: >> check_log_pattern('csvlog', $new_current_logfiles, 'syntax error', $node); >> check_log_pattern('jsonlog', $new_current_logfiles, 'syntax error', $node); >> >> $node->stop(); >> >> done_testing(); >> >> error: patch failed: src/bin/pg_ctl/t/004_logrotate.pl:135 >> error: src/bin/pg_ctl/t/004_logrotate.pl: patch does not apply >> Checking patch src/include/utils/elog.h... >> Hunk #1 succeeded at 502 (offset 1 line). >> >> Does it truncate only single queries or also a transaction with many >> statements? >> >> Thanks! >> >> Best, Jim > > > My apologies, attached patch should work on master branch. > It truncates single queries and a statement in transaction that occurred an error. > Hello! Please deliver the most recent patch version and fix the issues Jim identified [0] as the current commitfest draws to a close. Do not forget to include both parts of this patch (This was actually developed off-list, and we are now using this on our cloud PostgreSQL distribution on versions 12–17). [0] https://www.postgresql.org/message-id/35096a36-04d4-480b-a7cd-a2d8151fb737%40uni-muenster.de -- Best regards, Kirill Reshke -
Re: Truncate logs by max_log_size
Jim Jones <jim.jones@uni-muenster.de> — 2024-11-28T14:22:55Z
On 25.11.24 17:52, Kirill Reshke wrote: > Hello! Please deliver the most recent patch version and fix the issues > Jim identified [0] as the current commitfest draws to a close. > Do not forget to include both parts of this patch (This was actually > developed off-list, and we are now using this on our cloud PostgreSQL > distribution on versions 12–17). > > [0] https://www.postgresql.org/message-id/35096a36-04d4-480b-a7cd-a2d8151fb737%40uni-muenster.de In addition to these points, this feature seems to fail with queries containing special characters (more than one byte): With this "max_log_size".. postgres=# SHOW max_log_size; max_log_size -------------- 20 (1 row) ... and this query .. postgres=# SELECT "ÄÜÖ" FROM t; ERROR: relation "t" does not exist LINE 1: SELECT "ÄÜÖ" FROM t; .. this is the [truncated] log entry we get .. 2024-11-28 14:58:57.912 CET [2258876] ERROR: relation "t" does not exist at character 19 2024-11-28 14:58:57.912 CET [2258876] STATEMENT: SELECT "ÄÜÖ" FROM ... although the query originally had exactly 20 characters: postgres=# SELECT length('SELECT "ÄÜÖ" FROM t;'); length -------- 20 (1 row) postgres=# SELECT length('ÄÜÖ'::bytea), length('AUO'::bytea); length | length --------+-------- 6 | 3 (1 row) If it is supposed to be like this, it should be clearly stated so in the docs. -- Jim -
Re: Truncate logs by max_log_size
Kirill Gavrilov <diphantxm@gmail.com> — 2024-11-28T19:20:42Z
On Thu, Nov 28, 2024 at 5:23 PM Jim Jones <jim.jones@uni-muenster.de> wrote: > > > On 25.11.24 17:52, Kirill Reshke wrote: > > Hello! Please deliver the most recent patch version and fix the issues > > Jim identified [0] as the current commitfest draws to a close. > > Do not forget to include both parts of this patch (This was actually > > developed off-list, and we are now using this on our cloud PostgreSQL > > distribution on versions 12–17). > > > > [0] > https://www.postgresql.org/message-id/35096a36-04d4-480b-a7cd-a2d8151fb737%40uni-muenster.de > > In addition to these points, this feature seems to fail with queries > containing special characters (more than one byte): > > With this "max_log_size".. > > postgres=# SHOW max_log_size; > max_log_size > -------------- > 20 > (1 row) > > ... and this query .. > > postgres=# SELECT "ÄÜÖ" FROM t; > ERROR: relation "t" does not exist > LINE 1: SELECT "ÄÜÖ" FROM t; > > .. this is the [truncated] log entry we get .. > > 2024-11-28 14:58:57.912 CET [2258876] ERROR: relation "t" does not > exist at character 19 > 2024-11-28 14:58:57.912 CET [2258876] STATEMENT: SELECT "ÄÜÖ" FROM > > ... although the query originally had exactly 20 characters: > > postgres=# SELECT length('SELECT "ÄÜÖ" FROM t;'); > length > -------- > 20 > (1 row) > > > postgres=# SELECT length('ÄÜÖ'::bytea), length('AUO'::bytea); > length | length > --------+-------- > 6 | 3 > (1 row) > > If it is supposed to be like this, it should be clearly stated so in the > docs. > > -- > Jim > > Here is version 3 of this patch. I found another place where this setting can be applied. Also added some documentation and specified that this setting truncates queries by size in bytes. -
Re: Truncate logs by max_log_size
Jim Jones <jim.jones@uni-muenster.de> — 2024-11-29T00:24:24Z
On 28.11.24 20:20, Kirill Gavrilov wrote: > Here is version 3 of this patch. I found another place where this > setting can be applied. > Also added some documentation and specified that this setting > truncates queries by size in bytes. Thanks. It is now possible to change the parameter using SET postgres=# SET max_log_size TO 15; SET postgres=# SHOW max_log_size ; max_log_size -------------- 15 (1 row) In the postgresql.conf the default value is set to 0 #max_log_size = 0 But if we take a look at the parameter it shows something else postgres=# SHOW max_log_size ; max_log_size -------------- 5242880 (1 row) Perhaps it would be best to keep the default value in the postgresql.conf consistent with the documentation and the actual max_log_size value. IMHO 0 (or -1) should disable it. There are also several compilation issues: postgres.c: In function ‘exec_simple_query’: postgres.c:1040:9: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] 1040 | bool copied = false; | ^~~~ elog.c: In function ‘EmitErrorReport’: elog.c:1697:9: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] 1697 | const char* old_query_string = debug_query_string; | ^~~~~ elog.c:1744:23: warning: passing argument 1 of ‘pfree’ discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers] 1744 | pfree(debug_query_string); | ^~~~~~~~~~~~~~~~~~ In file included from ../../../../src/include/postgres.h:47, from elog.c:55: ../../../../src/include/utils/palloc.h:86:25: note: expected ‘void *’ but argument is of type ‘const char *’ 86 | extern void pfree(void *pointer); | ~~~~~~^~~~~~~ elog.c: In function ‘build_query_log’: elog.c:3798:9: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] 3798 | size_t query_len = strlen(query); | ^~~~~~ elog.c:3801:24: warning: return discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers] 3801 | return query; | ^~~~~ elog.c:3805:9: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] 3805 | size_t query_log_len = pg_mbcliplen(query, query_len, max_log_size); | ^~~~~~ and there is a trailing whitespace at: + * If query needs to be truncated, copied will be set to true /home/jim/patches/max_log_query/V3-0001-parameter-max_log_size-to-truncate-logs.patch:141: trailing whitespace. * If query needs to be truncated, copied will be set to true Checking patch doc/src/sgml/config.sgml... Hunk #1 succeeded at 7865 (offset -48 lines). Checking patch src/backend/tcop/postgres.c... Hunk #1 succeeded at 71 (offset 1 line). Hunk #2 succeeded at 1031 (offset 1 line). Hunk #3 succeeded at 1083 (offset 1 line). Hunk #4 succeeded at 1382 (offset 1 line). Hunk #5 succeeded at 1393 (offset 1 line). Checking patch src/backend/utils/error/elog.c... Hunk #4 succeeded at 3781 (offset -3 lines). Checking patch src/backend/utils/misc/guc_tables.c... Hunk #1 succeeded at 3714 (offset -10 lines). Checking patch src/backend/utils/misc/postgresql.conf.sample... Hunk #1 succeeded at 615 (offset -2 lines). Checking patch src/bin/pg_ctl/t/004_logrotate.pl... Checking patch src/include/utils/elog.h... Applied patch doc/src/sgml/config.sgml cleanly. Applied patch src/backend/tcop/postgres.c cleanly. Applied patch src/backend/utils/error/elog.c cleanly. Applied patch src/backend/utils/misc/guc_tables.c cleanly. Applied patch src/backend/utils/misc/postgresql.conf.sample cleanly. Applied patch src/bin/pg_ctl/t/004_logrotate.pl cleanly. Applied patch src/include/utils/elog.h cleanly. warning: 1 line adds whitespace errors. -- Jim
-
Re: Truncate logs by max_log_size
Kirill Gavrilov <diphantxm@gmail.com> — 2024-11-29T11:05:01Z
On Fri, Nov 29, 2024 at 3:24 AM Jim Jones <jim.jones@uni-muenster.de> wrote: > > > On 28.11.24 20:20, Kirill Gavrilov wrote: > > Here is version 3 of this patch. I found another place where this > > setting can be applied. > > Also added some documentation and specified that this setting > > truncates queries by size in bytes. > > Thanks. It is now possible to change the parameter using SET > > postgres=# SET max_log_size TO 15; > SET > postgres=# SHOW max_log_size ; > max_log_size > -------------- > 15 > (1 row) > > In the postgresql.conf the default value is set to 0 > > #max_log_size = 0 > > But if we take a look at the parameter it shows something else > > postgres=# SHOW max_log_size ; > max_log_size > -------------- > 5242880 > (1 row) > > Perhaps it would be best to keep the default value in the > postgresql.conf consistent with the documentation and the actual > max_log_size value. IMHO 0 (or -1) should disable it. > > There are also several compilation issues: > > postgres.c: In function ‘exec_simple_query’: > postgres.c:1040:9: warning: ISO C90 forbids mixed declarations and code > [-Wdeclaration-after-statement] > 1040 | bool copied = false; > | ^~~~ > elog.c: In function ‘EmitErrorReport’: > elog.c:1697:9: warning: ISO C90 forbids mixed declarations and code > [-Wdeclaration-after-statement] > 1697 | const char* old_query_string = debug_query_string; > | ^~~~~ > elog.c:1744:23: warning: passing argument 1 of ‘pfree’ discards ‘const’ > qualifier from pointer target type [-Wdiscarded-qualifiers] > 1744 | pfree(debug_query_string); > | ^~~~~~~~~~~~~~~~~~ > In file included from ../../../../src/include/postgres.h:47, > from elog.c:55: > ../../../../src/include/utils/palloc.h:86:25: note: expected ‘void *’ > but argument is of type ‘const char *’ > 86 | extern void pfree(void *pointer); > | ~~~~~~^~~~~~~ > elog.c: In function ‘build_query_log’: > elog.c:3798:9: warning: ISO C90 forbids mixed declarations and code > [-Wdeclaration-after-statement] > 3798 | size_t query_len = strlen(query); > | ^~~~~~ > elog.c:3801:24: warning: return discards ‘const’ qualifier from pointer > target type [-Wdiscarded-qualifiers] > 3801 | return query; > | ^~~~~ > elog.c:3805:9: warning: ISO C90 forbids mixed declarations and code > [-Wdeclaration-after-statement] > 3805 | size_t query_log_len = pg_mbcliplen(query, query_len, > max_log_size); > | ^~~~~~ > > and there is a trailing whitespace at: > > + * If query needs to be truncated, copied will be set to true > > > /home/jim/patches/max_log_query/V3-0001-parameter-max_log_size-to-truncate-logs.patch:141: > trailing whitespace. > * If query needs to be truncated, copied will be set to true > Checking patch doc/src/sgml/config.sgml... > Hunk #1 succeeded at 7865 (offset -48 lines). > Checking patch src/backend/tcop/postgres.c... > Hunk #1 succeeded at 71 (offset 1 line). > Hunk #2 succeeded at 1031 (offset 1 line). > Hunk #3 succeeded at 1083 (offset 1 line). > Hunk #4 succeeded at 1382 (offset 1 line). > Hunk #5 succeeded at 1393 (offset 1 line). > Checking patch src/backend/utils/error/elog.c... > Hunk #4 succeeded at 3781 (offset -3 lines). > Checking patch src/backend/utils/misc/guc_tables.c... > Hunk #1 succeeded at 3714 (offset -10 lines). > Checking patch src/backend/utils/misc/postgresql.conf.sample... > Hunk #1 succeeded at 615 (offset -2 lines). > Checking patch src/bin/pg_ctl/t/004_logrotate.pl... > Checking patch src/include/utils/elog.h... > Applied patch doc/src/sgml/config.sgml cleanly. > Applied patch src/backend/tcop/postgres.c cleanly. > Applied patch src/backend/utils/error/elog.c cleanly. > Applied patch src/backend/utils/misc/guc_tables.c cleanly. > Applied patch src/backend/utils/misc/postgresql.conf.sample cleanly. > Applied patch src/bin/pg_ctl/t/004_logrotate.pl cleanly. > Applied patch src/include/utils/elog.h cleanly. > warning: 1 line adds whitespace errors. > > -- > Jim > > Thanks for spotting mistakes. Setting max_log_size to 0 already disables truncation. I changed guc units to bytes, just to make it more human-friendly. Did some refactoring and fixed all warnings. Set default value in postgresql.conf.
-
Re: Truncate logs by max_log_size
Jim Jones <jim.jones@uni-muenster.de> — 2024-11-29T19:12:44Z
On 29.11.24 12:05, Kirill Gavrilov wrote: > Setting max_log_size to 0 already disables truncation. > I changed guc units to bytes, just to make it more human-friendly. > Did some refactoring and fixed all warnings. Set default value in > postgresql.conf. Nice. The patch applies cleanly and the warnings are gone. A few other things: IMHO the documentation can be a bit clearer. It says to input the values in bytes, but the default value is in megabytes. + If greater than zero, each query logged is truncated to this many bytes. + Zero disables the setting. + Default value is 5MB. Perhaps something like "If this value is specified without units, it is taken as bytes." (see wal_keep_size) And a pedantic note: This hint suggests that you can use TB as unit .. postgres=# set max_log_size = '1foo'; ERROR: invalid value for parameter "max_log_size": "1foo" HINT: Valid units for this parameter are "B", "kB", "MB", "GB", and "TB". .. but it can never be used, as it exceeds the integer range: postgres=# SET max_log_size = '1TB'; ERROR: invalid value for parameter "max_log_size": "1TB" HINT: Value exceeds integer range. Thanks -- Jim
-
Re: Truncate logs by max_log_size
Kirill Gavrilov <diphantxm@gmail.com> — 2024-11-29T20:57:38Z
On Fri, Nov 29, 2024 at 10:12 PM Jim Jones <jim.jones@uni-muenster.de> wrote: > > > On 29.11.24 12:05, Kirill Gavrilov wrote: > > Setting max_log_size to 0 already disables truncation. > > I changed guc units to bytes, just to make it more human-friendly. > > Did some refactoring and fixed all warnings. Set default value in > > postgresql.conf. > > Nice. The patch applies cleanly and the warnings are gone. > > A few other things: > > IMHO the documentation can be a bit clearer. It says to input the values > in bytes, but the default value is in megabytes. > > + If greater than zero, each query logged is truncated to this > many bytes. > + Zero disables the setting. > + Default value is 5MB. > > Perhaps something like "If this value is specified without units, it is > taken as bytes." (see wal_keep_size) > Added to documentation. I hope it's clear now. > > And a pedantic note: This hint suggests that you can use TB as unit .. > > postgres=# set max_log_size = '1foo'; > ERROR: invalid value for parameter "max_log_size": "1foo" > HINT: Valid units for this parameter are "B", "kB", "MB", "GB", and "TB". > > .. but it can never be used, as it exceeds the integer range: > > postgres=# SET max_log_size = '1TB'; > ERROR: invalid value for parameter "max_log_size": "1TB" > HINT: Value exceeds integer range. > > Thanks > > -- > Jim > Same thing applies to log_parameter_max_length, for example. postgres=# set log_parameter_max_length = '1foo'; ERROR: invalid value for parameter "log_parameter_max_length": "1foo" HINT: Valid units for this parameter are "B", "kB", "MB", "GB", and "TB". postgres=# set log_parameter_max_length = '1TB'; ERROR: invalid value for parameter "log_parameter_max_length": "1TB" HINT: Value exceeds integer range. I think we can leave it as is.
-
Re: Truncate logs by max_log_size
Kirill Reshke <reshkekirill@gmail.com> — 2024-11-30T06:58:38Z
On Sat, 30 Nov 2024 at 01:57, Kirill Gavrilov <diphantxm@gmail.com> wrote: > > On Fri, Nov 29, 2024 at 10:12 PM Jim Jones <jim.jones@uni-muenster.de> wrote: >> >> >> >> On 29.11.24 12:05, Kirill Gavrilov wrote: >> > Setting max_log_size to 0 already disables truncation. >> > I changed guc units to bytes, just to make it more human-friendly. >> > Did some refactoring and fixed all warnings. Set default value in >> > postgresql.conf. >> >> Nice. The patch applies cleanly and the warnings are gone. >> >> A few other things: >> >> IMHO the documentation can be a bit clearer. It says to input the values >> in bytes, but the default value is in megabytes. >> >> + If greater than zero, each query logged is truncated to this >> many bytes. >> + Zero disables the setting. >> + Default value is 5MB. >> >> Perhaps something like "If this value is specified without units, it is >> taken as bytes." (see wal_keep_size) > > > Added to documentation. I hope it's clear now. > >> >> >> And a pedantic note: This hint suggests that you can use TB as unit .. >> >> postgres=# set max_log_size = '1foo'; >> ERROR: invalid value for parameter "max_log_size": "1foo" >> HINT: Valid units for this parameter are "B", "kB", "MB", "GB", and "TB". >> >> .. but it can never be used, as it exceeds the integer range: >> >> postgres=# SET max_log_size = '1TB'; >> ERROR: invalid value for parameter "max_log_size": "1TB" >> HINT: Value exceeds integer range. >> >> Thanks >> >> -- >> Jim > > > Same thing applies to log_parameter_max_length, for example. > > postgres=# set log_parameter_max_length = '1foo'; > ERROR: invalid value for parameter "log_parameter_max_length": "1foo" > HINT: Valid units for this parameter are "B", "kB", "MB", "GB", and "TB". > postgres=# set log_parameter_max_length = '1TB'; > ERROR: invalid value for parameter "log_parameter_max_length": "1TB" > HINT: Value exceeds integer range. > > I think we can leave it as is. Hi > +for (my $attempts = 0; $attempts < $max_attempts; $attempts++) > +{ > + eval { > + $current_logfiles = slurp_file($node->data_dir . '/current_logfiles'); > + }; > + last unless $@; > + usleep(100_000); > +} `usleep` in tap tests is usually a bad pattern. Do we have a chance to test this using `wait_for_log` or similar? -- Best regards, Kirill Reshke -
Re: Truncate logs by max_log_size
Kirill Gavrilov <diphantxm@gmail.com> — 2024-11-30T08:44:00Z
> > > Hi > > > +for (my $attempts = 0; $attempts < $max_attempts; $attempts++) > > +{ > > + eval { > > + $current_logfiles = slurp_file($node->data_dir . '/current_logfiles'); > > + }; > > + last unless $@; > > + usleep(100_000); > > +} > > > `usleep` in tap tests is usually a bad pattern. Do we have a chance to > test this using `wait_for_log` or similar? > I'm not sure we can use `wait_for_log` because it checks for only one logfile. But even if it's possible, I don't think it's a good idea to use different checks in the same file or to change tests for another feature. I used test case from above as an example for mine. -
Re: Truncate logs by max_log_size
Jim Jones <jim.jones@uni-muenster.de> — 2024-12-02T10:08:55Z
On 29.11.24 21:57, Kirill Gavrilov wrote: > Same thing applies to log_parameter_max_length, for example. > > postgres=# set log_parameter_max_length = '1foo'; > ERROR: invalid value for parameter "log_parameter_max_length": "1foo" > HINT: Valid units for this parameter are "B", "kB", "MB", "GB", and "TB". > postgres=# set log_parameter_max_length = '1TB'; > ERROR: invalid value for parameter "log_parameter_max_length": "1TB" > HINT: Value exceeds integer range. > > I think we can leave it as is. I see. So I guess it is out of scope to change this message here. Small nitpicks: 1) The indentation of the comment at postgresql.conf.sample is a little bit off #max_log_size = 0 # max size of logged statement # 0 disables the feature IMHO it looks better like this: #max_log_size = 0 # max size of logged statement # 0 disables the feature 2) You introduced a trailing whitespace at L34 (Not critical :)) + Zero disables the setting. It happens to me all the time, so I usually try to apply my patches in a clean branch just to make sure I didn't miss anything. Other than that, I have nothing more to add at this point. Thanks -- Jim
-
Re: Truncate logs by max_log_size
Kirill Gavrilov <diphantxm@gmail.com> — 2025-01-31T10:46:37Z
On Mon, Dec 2, 2024 at 1:09 PM Jim Jones <jim.jones@uni-muenster.de> wrote: > > > On 29.11.24 21:57, Kirill Gavrilov wrote: > > Same thing applies to log_parameter_max_length, for example. > > > > postgres=# set log_parameter_max_length = '1foo'; > > ERROR: invalid value for parameter "log_parameter_max_length": "1foo" > > HINT: Valid units for this parameter are "B", "kB", "MB", "GB", and > "TB". > > postgres=# set log_parameter_max_length = '1TB'; > > ERROR: invalid value for parameter "log_parameter_max_length": "1TB" > > HINT: Value exceeds integer range. > > > > I think we can leave it as is. > > I see. So I guess it is out of scope to change this message here. > > Small nitpicks: > > 1) The indentation of the comment at postgresql.conf.sample is a little > bit off > > #max_log_size = 0 # max size of logged statement > # 0 disables the feature > > IMHO it looks better like this: > > #max_log_size = 0 # max size of logged statement > # 0 disables the feature > > > 2) You introduced a trailing whitespace at L34 (Not critical :)) > > + Zero disables the setting. > > It happens to me all the time, so I usually try to apply my patches in a > clean branch just to make sure I didn't miss anything. > > Other than that, I have nothing more to add at this point. > > Thanks > > -- > Jim > > Sorry for the long silence. I fixed the indentation and a trailing whitespace. Should look fine now.
-
Re: Truncate logs by max_log_size
Jim Jones <jim.jones@uni-muenster.de> — 2025-02-03T10:31:07Z
Hi Kirill On 31.01.25 11:46, Kirill Gavrilov wrote: > Sorry for the long silence. I fixed the indentation and a trailing > whitespace. Should look fine now. The patch applies cleanly, the documentation is clear, and all tests pass. It is possible to change this new parameter session-wise, which is nice! postgres=# SET max_log_size TO 7; SET postgres=# SHOW max_log_size; max_log_size -------------- 7B (1 row) The default value now is clear and it corresponds to the value set on postgresql.conf: #max_log_size = 0 # max size of logged statement postgres=# SHOW max_log_size; max_log_size -------------- 0 (1 row) Logs are truncated as expected: postgres=# SET max_log_size TO 6; SET postgres=# SELECT length('CALL xyz;'); length -------- 9 (1 row) postgres=# CALL xyz; ERROR: syntax error at or near ";" LINE 1: CALL xyz; log entry: 2025-02-03 10:58:19.975 CET [123945] ERROR: syntax error at or near ";" at character 9 2025-02-03 10:58:19.975 CET [123945] STATEMENT: CALL x The issue with log entry sizes for queries containing special characters was resolved by setting the unit to bytes. Overall, everythingLGTM. The new status of this patch is: Ready for Committer Jim -
Re: Truncate logs by max_log_size
Fujii Masao <masao.fujii@oss.nttdata.com> — 2025-03-31T18:20:36Z
On 2025/02/03 19:31, Jim Jones wrote: > Hi Kirill > > On 31.01.25 11:46, Kirill Gavrilov wrote: >> Sorry for the long silence. I fixed the indentation and a trailing >> whitespace. Should look fine now. > > > The patch applies cleanly, the documentation is clear, and all tests pass. > > It is possible to change this new parameter session-wise, which is nice! > > postgres=# SET max_log_size TO 7; > SET > postgres=# SHOW max_log_size; > max_log_size > -------------- > 7B > (1 row) > > > The default value now is clear and it corresponds to the value set on > postgresql.conf: > > #max_log_size = 0 # max size of logged statement > > postgres=# SHOW max_log_size; > max_log_size > -------------- > 0 > (1 row) > > > Logs are truncated as expected: > > postgres=# SET max_log_size TO 6; > SET > postgres=# SELECT length('CALL xyz;'); > length > -------- > 9 > (1 row) > > postgres=# CALL xyz; > ERROR: syntax error at or near ";" > LINE 1: CALL xyz; > > > log entry: > > 2025-02-03 10:58:19.975 CET [123945] ERROR: syntax error at or near ";" > at character 9 > 2025-02-03 10:58:19.975 CET [123945] STATEMENT: CALL x > > > The issue with log entry sizes for queries containing special characters > was resolved by setting the unit to bytes. > > Overall, everythingLGTM. > > The new status of this patch is: Ready for Committer Since this patch is marked as ready-for-committer, I started reviewing it. Basically I like the proposed idea. When I set log_statement to 'all', max_log_size to 3, and ran "SELECT 1/0", only the first three bytes of the query were logged by log_statement. However, no query statement appeared under STATEMENT, as shown below. Is this a bug? -------------------------- =# SET log_statement TO 'all'; =# SET max_log_size TO 3; =# SELECT 1/0; LOG: statement: SEL ERROR: division by zero STATEMENT: -------------------------- When log_replication_commands is enabled, replication commands are logged. Should max_log_size apply to these logs as well to prevent excessively large commands from being logged in full? The parameter name max_log_size seems misleading. It sounds like it controls the maximum log file size. Would a name like log_statement_max_length be clearer? The functions like exec_parse_message(), exec_bind_message(), and exec_execute_message() may log query statements (e.g., via log_min_duration_statement), but the patch doesn't seem to update them to consider max_log_size. Queries can also be logged in the CONTEXT line, such as when running "DO $$ BEGIN SELECT 1/0; END $$;", but max_log_size doesn't seem to apply in this case. There might be other cases where queries are logged, but the patch doesn't handle them. I'm not sure we can identify and address all of them before the feature freeze. Regards, -- Fujii Masao Advanced Computing Technology Center Research and Development Headquarters NTT DATA CORPORATION -
Re: Truncate logs by max_log_size
Álvaro Herrera <alvherre@kurilemu.de> — 2026-02-04T09:48:23Z
On 2025-Apr-01, Fujii Masao wrote: > Since this patch is marked as ready-for-committer, I started reviewing it. > Basically I like the proposed idea. Hello, is this something that anybody is working on? https://commitfest.postgresql.org/patch/5272/ Apparently it was very close to done but was abandoned after several rounds of review at the start of the cycle. -- Álvaro Herrera PostgreSQL Developer — https://www.EnterpriseDB.com/ "Computing is too important to be left to men." (Karen Spärck Jones)
-
Re: Truncate logs by max_log_size
Fujii Masao <masao.fujii@gmail.com> — 2026-02-05T02:17:45Z
On Wed, Feb 4, 2026 at 6:48 PM Álvaro Herrera <alvherre@kurilemu.de> wrote: > > On 2025-Apr-01, Fujii Masao wrote: > > > Since this patch is marked as ready-for-committer, I started reviewing it. > > Basically I like the proposed idea. > > Hello, is this something that anybody is working on? > https://commitfest.postgresql.org/patch/5272/ At least I'm not for now. So please feel free to work on the patch if you'd like! Regards, -- Fujii Masao
-
Re: Truncate logs by max_log_size
Jim Jones <jim.jones@uni-muenster.de> — 2026-02-05T09:08:22Z
On 05/02/2026 03:17, Fujii Masao wrote: > At least I'm not for now. So please feel free to work on the patch if > you'd like! If nobody is planning to work on this, I can take a look at it next week. Best, Jim
-
Re: Truncate logs by max_log_size
Álvaro Herrera <alvherre@kurilemu.de> — 2026-02-05T10:22:19Z
On 2026-Feb-05, Jim Jones wrote: > On 05/02/2026 03:17, Fujii Masao wrote: > > At least I'm not for now. So please feel free to work on the patch if > > you'd like! > > If nobody is planning to work on this, I can take a look at it next week. That'd be swell. My only comment at this point is that the proposed GUC name is not great. I think it should be something like log_statement_max_length, or something like that. Reading just the thread subject, people would imagine this is about the size of the log file. Another point is that the current patch does strlen() twice on each query. It might be better to do away with need_truncate_query_log() and have a single routine that both determines whether the truncation is needed and returns the truncated query if it is. If it returns NULL then caller assumes it's not needed. -- Álvaro Herrera 48°01'N 7°57'E — https://www.EnterpriseDB.com/
-
Re: Truncate logs by max_log_size
Jim Jones <jim.jones@uni-muenster.de> — 2026-02-05T11:53:22Z
On 05/02/2026 11:22, Álvaro Herrera wrote: > My only comment at this point is that the proposed GUC name is not > great. I think it should be something like log_statement_max_length, or > something like that. Reading just the thread subject, people would > imagine this is about the size of the log file. +1 for log_statement_max_length > > Another point is that the current patch does strlen() twice on each > query. It might be better to do away with need_truncate_query_log() and > have a single routine that both determines whether the truncation is > needed and returns the truncated query if it is. If it returns NULL > then caller assumes it's not needed. I'll take a look at this. Another thing that we could adjust is the default/disable value: I personally find 0 to disable the feature a bit confusing. 0 might be interpreted as "log 0 bytes", and the user ends up with the full statement logged. What about -1? Best, Jim
-
Re: Truncate logs by max_log_size
Jim Jones <jim.jones@uni-muenster.de> — 2026-02-06T07:50:03Z
On 05/02/2026 11:22, Álvaro Herrera wrote: > My only comment at this point is that the proposed GUC name is not > great. I think it should be something like log_statement_max_length, or > something like that. Reading just the thread subject, people would > imagine this is about the size of the log file. Done. GUC changed to log_statement_max_length. > Another point is that the current patch does strlen() twice on each > query. It might be better to do away with need_truncate_query_log() and > have a single routine that both determines whether the truncation is > needed and returns the truncated query if it is. If it returns NULL > then caller assumes it's not needed. Done. Now truncate_query_log() returns a palloc'd truncated copy of the statement if truncation is needed, and NULL otherwise. == issue with issue with empty STATEMENT == This issue was mentioned by Fujii upthread. It is now fixed: postgres=# SET log_statement TO 'all'; SET postgres=# SET log_statement_max_length TO 3; SET postgres=# SELECT 1/0; ERROR: division by zero Log entries: 2026-02-05 17:54:47.521 CET [570568] LOG: statement: SEL 2026-02-05 17:54:47.521 CET [570568] ERROR: division by zero 2026-02-05 17:54:47.521 CET [570568] STATEMENT: SELECT 1/0; == default value == To be consistent with other parameters, such as log_parameter_max_length, the default (disabled) value is now -1. == tests == Added new tests for -1 and multi-byte characters. Best, Jim
-
Re: Truncate logs by max_log_size
Jim Jones <jim.jones@uni-muenster.de> — 2026-03-20T11:08:59Z
rebase Jim
-
Re: Truncate logs by max_log_size
Kirill Reshke <reshkekirill@gmail.com> — 2026-03-20T17:33:21Z
On Fri, 20 Mar 2026 at 16:09, Jim Jones <jim.jones@uni-muenster.de> wrote: > > rebase > > Jim Hi! We discussed this patch off-list with Andrey @x4mmm in sight of CVE-2026-2006. Looks like this patch is not vulnerable, and its use of pg_mbcliplen are correct. But I anyway raise this question in lists just for record. -- Best regards, Kirill Reshke
-
Re: Truncate logs by max_log_size
Jim Jones <jim.jones@uni-muenster.de> — 2026-04-03T21:59:48Z
Hi Kirill On 20/03/2026 18:33, Kirill Reshke wrote: > We discussed this patch off-list with Andrey @x4mmm in sight of > CVE-2026-2006. Looks like this patch is not vulnerable, and its use of > pg_mbcliplen are correct. Thanks for checking! I spent some time revisiting this patch today and realised that it only applied truncation in exec_simple_query. I believe the original intent of this feature was to cover other paths as well, so I added the same logic in exec_execute_message (which handles log_statement logging for the extended query protocol), and in exec_parse_message and exec_bind_message (which log statement text when log_min_duration_statement fires). v9 attached. Thoughts on this approach? Best, Jim
-
Re: Truncate logs by max_log_size
Fujii Masao <masao.fujii@gmail.com> — 2026-04-08T16:18:45Z
On Sat, Apr 4, 2026 at 6:59 AM Jim Jones <jim.jones@uni-muenster.de> wrote: > v9 attached. Thanks for updating the patch! I tried to review this in time for the feature freeze, but unfortunately didn't make it. Still, I'd like to share some comments for future work. + If greater than zero, each statement written to the server log + is truncated to at most this many bytes. It would be good to clarify which query logging this parameter affects. As I understand it, it applies only to statements logged by log_statement and log_min_duration_statement, and not to statements included in other messages (e.g., errors). Is that correct? + truncated_query = truncate_query_log(query_string); + query_log = truncated_query ? truncated_query : query_string; In the patch, truncate_query_log() is called unconditionally in exec_simple_query(), even when the query isn't logged. This adds unnecessary overhead. It would be better to call it only when logging is actually performed (e.g., under check_log_statement() or check_log_duration()). For example, ------------------------------------------- /* Log immediately if dictated by log_statement */ if (check_log_statement(parsetree_list)) { + char *truncated_stmt = NULL; + + if (log_statement_max_length >= 0) + truncated_stmt = truncate_query_log(query_string); + ereport(LOG, - (errmsg("statement: %s", query_string), + (errmsg("statement: %s", (truncated_stmt != NULL) ? truncated_stmt : query_string), errhidestmt(true), errdetail_execute(parsetree_list))); was_logged = true; + + if (truncated_stmt != NULL) + pfree(truncated_stmt); } <snip> case 2: - ereport(LOG, - (errmsg("duration: %s ms statement: %s", - msec_str, query_string), - errhidestmt(true), - errdetail_execute(parsetree_list))); - break; + { + char *truncated_stmt = NULL; + + if (log_statement_max_length >= 0) + truncated_stmt = truncate_query_log(query_string); + + ereport(LOG, + (errmsg("duration: %s ms statement: %s", + msec_str, (truncated_stmt != NULL) ? truncated_stmt : query_string), + errhidestmt(true), + errdetail_execute(parsetree_list))); + + if (truncated_stmt != NULL) + pfree(truncated_stmt); + break; + } } ------------------------------------------- + char *truncated_query = NULL; + const char *query_log; In exec_parse_message(), exec_bind_message(), and exec_execute_message(), variables like truncated_query can be declared closer to where they are used (e.g., inside the check_log_duration() switch case) to improve readability. For example, ------------------------------------------- break; case 2: - ereport(LOG, - (errmsg("duration: %s ms parse %s: %s", - msec_str, - *stmt_name ? stmt_name : "<unnamed>", - query_string), - errhidestmt(true))); - break; + { + char *truncated_stmt = NULL; + + if (log_statement_max_length >= 0) + truncated_stmt = truncate_query_log(query_string); + + ereport(LOG, + (errmsg("duration: %s ms parse %s: %s", + msec_str, + *stmt_name ? stmt_name : "<unnamed>", + (truncated_stmt != NULL) ? truncated_stmt : query_string), + errhidestmt(true))); + + if (truncated_stmt != NULL) + pfree(truncated_stmt); + break; + } } ------------------------------------------- + long_desc => '-1 means no truncation.', +#log_statement_max_length = -1 # max length of logged statements + # -1 disables truncation I like the description like "-1 means log statement in full", which seems clearer and easier to understand for users. Thought? Regarding the regression test, testing log_statement_max_length in pg_ctl test looks a bit odd to me. It might be better to place it under src/test/modules/test_misc, for example? Regards, -- Fujii Masao -
Re: Truncate logs by max_log_size
Jim Jones <jim.jones@uni-muenster.de> — 2026-04-08T20:52:27Z
Hi Fujii On 08/04/2026 18:18, Fujii Masao wrote: > + If greater than zero, each statement written to the server log > + is truncated to at most this many bytes. > > It would be good to clarify which query logging this parameter affects. > As I understand it, it applies only to statements logged by log_statement and > log_min_duration_statement, and not to statements included in other messages > (e.g., errors). Is that correct? Agreed. Changed text to: If greater than zero, each statement logged by <xref linkend="guc-log-statement"/> or <xref linkend="guc-log-min-duration-statement"/> is truncated to at most this many bytes. A value of zero causes statements to be logged with an empty body. <literal>-1</literal> (the default) logs statements in full. If this value is specified without units, it is taken as bytes. Only superusers and users with the appropriate <literal>SET</literal> privilege can change this setting. > + truncated_query = truncate_query_log(query_string); > + query_log = truncated_query ? truncated_query : query_string; > > In the patch, truncate_query_log() is called unconditionally in > exec_simple_query(), even when the query isn't logged. This adds unnecessary > overhead. It would be better to call it only when logging is actually performed > (e.g., under check_log_statement() or check_log_duration()). > + char *truncated_query = NULL; > + const char *query_log; > > In exec_parse_message(), exec_bind_message(), and exec_execute_message(), > variables like truncated_query can be declared closer to where they are used > (e.g., inside the check_log_duration() switch case) to improve readability. Done. Removed the top-level declarations and unconditional truncate_query_log() call from all four functions. Truncation is now performed lazily, with local variables declared inside check_log_statement and case 2 of check_log_duration. > + long_desc => '-1 means no truncation.', > > +#log_statement_max_length = -1 # max length of logged statements > + # -1 disables truncation > > I like the description like "-1 means log statement in full", which seems > clearer and easier to understand for users. Thought? Done. Changed long_desc and comment in postgresql.conf.sqmple from "-1 means no truncation" to "-1 means log statement in full" > Regarding the regression test, testing log_statement_max_length in pg_ctl test > looks a bit odd to me. It might be better to place it under > src/test/modules/test_misc, for example? Done. Moved tests to: src/test/modules/test_misc/t/012_log_statement_max_length.pl Something I just noticed: the command that enables truncation is the first victim of its own effect. $ psql postgres psql (19devel) Type "help" for help. postgres=# SET log_min_duration_statement = 0; SET log_statement_max_length = 20; SET SET postgres=# \q $ tail /usr/local/postgres-dev/logfile 2026-04-08 22:17:41.958 CEST [206029] LOG: duration: 0.450 ms statement: SET log_min_duration_statement = 0; 2026-04-08 22:17:41.958 CEST [206029] LOG: duration: 0.085 ms statement: SET log_statement_ma I guess it is technically correct.. just a bit funny :) Thanks for the thorough review! Best, Jim
-
Re: Truncate logs by max_log_size
Fujii Masao <masao.fujii@gmail.com> — 2026-04-09T18:11:38Z
On Thu, Apr 9, 2026 at 5:52 AM Jim Jones <jim.jones@uni-muenster.de> wrote: > Moved tests to: > src/test/modules/test_misc/t/012_log_statement_max_length.pl Thanks for updating the patch! It looks good to me except the following comments. +$node->append_conf('postgresql.conf', "log_statement = 'all'\n"); This doesn't seem necessary, since $node->init already sets log_statement = 'all'. +$node->append_conf('postgresql.conf', "log_statement_max_length = 20\n"); +$node->reload(); +my $log_offset = -s $node->logfile; +$node->psql('postgres', "SELECT '123456789ABCDEF'"); Would it be simpler (and cheaper) to use SET instead of reloading the config? For example: --------------------------- my $log_offset = -s $node->logfile; $node->psql( 'postgres', " SET log_statement_max_length TO 20; SELECT '123456789ABCDEF'; "); --------------------------- +char * +truncate_query_log(const char *query) In elog.c, truncate_query_log() is currently placed between write_stderr() and vwrite_stderr(). Since those two functions are related, it might be better to move truncate_query_log() to a more appropriate location. Thoughts? I see the patch has been moved to CommitFest PG20-1. Once development for v20 starts, I'd like to commit it. Regards, -- Fujii Masao -
Re: Truncate logs by max_log_size
Jim Jones <jim.jones@uni-muenster.de> — 2026-04-09T22:35:59Z
On 09/04/2026 20:11, Fujii Masao wrote: > +$node->append_conf('postgresql.conf', "log_statement = 'all'\n"); > > This doesn't seem necessary, since $node->init already sets > log_statement = 'all'. Removed. Most likely still leftovers from previous attempts. > +$node->append_conf('postgresql.conf', "log_statement_max_length = 20\n"); > +$node->reload(); > +my $log_offset = -s $node->logfile; > +$node->psql('postgres', "SELECT '123456789ABCDEF'"); > > Would it be simpler (and cheaper) to use SET instead of reloading the > config? For example: > > --------------------------- > my $log_offset = -s $node->logfile; > $node->psql( > 'postgres', " > SET log_statement_max_length TO 20; > SELECT '123456789ABCDEF'; > "); > --------------------------- Done. It's indeed much simpler this way. I replaced all append + reload postgresql.conf calls with SET. > +char * > +truncate_query_log(const char *query) > > In elog.c, truncate_query_log() is currently placed between write_stderr() and > vwrite_stderr(). Since those two functions are related, it might be better to > move truncate_query_log() to a more appropriate location. Thoughts? Agreed. The function now lives between check_log_of_query() and get_backend_type_for_log(), which have more semantic overlap :) > I see the patch has been moved to CommitFest PG20-1. Once development for v20 > starts, I'd like to commit it. Terrific. Thanks! Best, Jim -
Re: Truncate logs by max_log_size
Fujii Masao <masao.fujii@gmail.com> — 2026-04-10T02:01:12Z
On Fri, Apr 10, 2026 at 7:36 AM Jim Jones <jim.jones@uni-muenster.de> wrote: > > I see the patch has been moved to CommitFest PG20-1. Once development for v20 > > starts, I'd like to commit it. > > > Terrific. Thanks! Thanks for updating the patch! LGTM. Let's wait for next CF for v20 to begin. Regards, -- Fujii Masao
-
Re: Truncate logs by max_log_size
Maxym Kharchenko <maxymkharchenko@gmail.com> — 2026-04-17T17:03:49Z
Hello Fujii-san, There seems to be an inconsistency in the current patch. When a statement has errors (for example, when it hits a table that does not exist), the full statement is still being logged. Similar parameter: `log_parameter_max_length` has a companion `log_parameter_max_length_on_error` to handle this case (commit: 0b34e7d307e6, https://github.com/postgres/postgres/commit/0b34e7d307e6a142ee94800e6d5f3e73449eeffd ). Should the same treatment be added for `log_statement_max_length`? Have a nice day, Maxym Kharchenko On Fri, Apr 17, 2026 at 6:32 AM Fujii Masao <masao.fujii@gmail.com> wrote: > On Fri, Apr 10, 2026 at 7:36 AM Jim Jones <jim.jones@uni-muenster.de> > wrote: > > > I see the patch has been moved to CommitFest PG20-1. Once development > for v20 > > > starts, I'd like to commit it. > > > > > > Terrific. Thanks! > > Thanks for updating the patch! LGTM. Let's wait for next CF for v20 to > begin. > > Regards, > > -- > Fujii Masao > > > > >
-
Re: Truncate logs by max_log_size
Fujii Masao <masao.fujii@gmail.com> — 2026-04-20T08:04:17Z
On Sat, Apr 18, 2026 at 2:04 AM Maxym Kharchenko <maxymkharchenko@gmail.com> wrote: > > Hello Fujii-san, > > There seems to be an inconsistency in the current patch. When a statement has errors (for example, when it hits a table that does not exist), the full statement is still being logged. > > Similar parameter: `log_parameter_max_length` has a companion `log_parameter_max_length_on_error` to handle this case (commit: 0b34e7d307e6, https://github.com/postgres/postgres/commit/0b34e7d307e6a142ee94800e6d5f3e73449eeffd). > > Should the same treatment be added for `log_statement_max_length`? I think extending log_statement_max_length, or adding something like log_statement_max_length_on_error, would be a good idea to cover statements logged on error. However, I think the current patch is good as it stands, so I'd recommend pursuing that as a separate patch after the current one is committed. Regards, -- Fujii Masao
-
Re: Truncate logs by max_log_size
Jim Jones <jim.jones@uni-muenster.de> — 2026-04-20T17:33:27Z
Hi Maxym, Hi Fujii On 20/04/2026 10:04, Fujii Masao wrote: > On Sat, Apr 18, 2026 at 2:04 AM Maxym Kharchenko > <maxymkharchenko@gmail.com> wrote: >> Hello Fujii-san, >> >> There seems to be an inconsistency in the current patch. When a statement has errors (for example, when it hits a table that does not exist), the full statement is still being logged. >> >> Similar parameter: `log_parameter_max_length` has a companion `log_parameter_max_length_on_error` to handle this case (commit: 0b34e7d307e6, https://github.com/postgres/postgres/ >> commit/0b34e7d307e6a142ee94800e6d5f3e73449eeffd). Thanks for the input! It's an interesting idea. However, I am not entirely convinced it applies to this patch. IIUC log_parameter_max_length_on_error can be used if you want to see the parameter values (for debugging), which might contain sensitive information. So it is more like a security/privacy control? psql (19devel) Type "help" for help. postgres=# SELECT 1/$1 \bind 000 \g ERROR: division by zero postgres=# SET log_parameter_max_length_on_error = -1; SELECT 1/$1 \bind 000 \g SET ERROR: division by zero CONTEXT: unnamed portal with parameters: $1 = '000' postgres=# SET log_parameter_max_length_on_error = 2; SELECT 1/$1 \bind 000 \g SET ERROR: division by zero CONTEXT: unnamed portal with parameters: $1 = '00...' Please correct me if I am wrong, but a statement is not sensitive in the way parameter values can be. The reason to truncate statements is purely log size management. > I think extending log_statement_max_length, or adding something like > log_statement_max_length_on_error, would be a good idea to cover statements > logged on error. However, I think the current patch is good as it stands, > so I'd recommend pursuing that as a separate patch after the current one > is committed. +1 Best, Jim
-
Re: Truncate logs by max_log_size
Jim Jones <jim.jones@uni-muenster.de> — 2026-04-30T21:33:18Z
rebase Jim
-
Re: Truncate logs by max_log_size
Jim Jones <jim.jones@uni-muenster.de> — 2026-05-15T10:48:52Z
rebase due to recent changes in src/test/modules/test_misc/meson.build Jim
-
Re: Truncate logs by max_log_size
Fujii Masao <masao.fujii@gmail.com> — 2026-07-02T15:49:24Z
On Fri, May 15, 2026 at 7:48 PM Jim Jones <jim.jones@uni-muenster.de> wrote: > > rebase due to recent changes in src/test/modules/test_misc/meson.build I reviewed the patch again and made a few additional changes. The updated patch is attached. Barring any objections, I'm thinking to commit it. If greater than zero, each statement logged by - <xref linkend="guc-log-statement"/> or - <xref linkend="guc-log-min-duration-statement"/> is truncated to - at most this many bytes. + <xref linkend="guc-log-statement"/>, + <xref linkend="guc-log-min-duration-statement"/>, + <xref linkend="guc-log-min-duration-sample"/>, or + <xref linkend="guc-log-transaction-sample-rate"/> + is truncated to at most this many bytes. Since this parameter also affects statements logged by log_min_duration_sample and log_transaction_sample_rate, I added those parameters to the description. + This setting does not affect statements logged because of + <xref linkend="guc-log-min-error-statement"/>. I also clarified that this parameter does not affect statements logged by log_min_error_statement. +static char * +truncate_query_log(const char *query) Since truncate_query_log() is only used in postgres.c, I moved it from elog.c and made it a static function. -ok( $node->log_contains( - qr/statement: SELECT '123456789ABC(?!D)/, $log_offset), +ok($node->log_contains(qr/statement: SELECT '123456789ABC$/m, $log_offset), I tightened the test to verify that the truncated statement ends exactly at the 20th byte. -# character (the 🐘 emoji is 4 bytes; with limit=12 it must be kept whole -# and the following 't' must not appear). -note "Multibyte truncation respects character boundaries"; +# character when the byte limit falls in the middle of it. +SKIP: Using an emoji directly in the test seems fragile and the behavior may depend on the test platform. To make the test more robust, I changed it to construct the multibyte character with pack() and run the test only when the server encoding is UTF-8. Regards, -- Fujii Masao -
Re: Truncate logs by max_log_size
Jim Jones <jim.jones@uni-muenster.de> — 2026-07-02T18:47:48Z
Hi Fujii On 02/07/2026 17:49, Fujii Masao wrote: > I reviewed the patch again and made a few additional changes. The updated > patch is attached. Barring any objections, I'm thinking to commit it. The changes seem reasonable to me. Thanks for taking care of it! Best, Jim
-
Re: Truncate logs by max_log_size
Fujii Masao <masao.fujii@gmail.com> — 2026-07-03T00:56:04Z
On Fri, Jul 3, 2026 at 3:47 AM Jim Jones <jim.jones@uni-muenster.de> wrote: > > Hi Fujii > > On 02/07/2026 17:49, Fujii Masao wrote: > > I reviewed the patch again and made a few additional changes. The updated > > patch is attached. Barring any objections, I'm thinking to commit it. > > > The changes seem reasonable to me. > Thanks for taking care of it! Thanks for the review! I've pushed the patch. While working on it, I found a few possible follow-up improvements. (1) When log_statement is enabled, executing a prepared statement logs the prepared query in a DETAIL message. For example: =# SET log_statement_max_length TO 10; =# PREPARE test AS SELECT * FROM pgbench_accounts WHERE aid = $1; LOG: statement: PREPARE te =# EXECUTE test(1); LOG: statement: EXECUTE te DETAIL: prepare: PREPARE test AS SELECT * FROM pgbench_accounts WHERE aid = $1; Should log_statement_max_length also apply to such query string in the DETAIL message? (2) When a bind parameter is truncated by log_parameter_max_length, an ellipsis (...) is appended: =# SET log_parameter_max_length TO 5; =# SELECT $1::text \bind 'abcdefghijk' \g LOG: execute <unnamed>: SELECT $1::text DETAIL: Parameters: $1 = 'abcde...' Would it make sense for log_statement_max_length to append an ellipsis as well, so that users can easily tell when a statement has been truncated? (3) + query_len = strlen(query); truncate_query_log() uses strlen() only to determine whether the query exceeds log_statement_max_length. Since the query can be very large, would it be better to use strnlen(query, log_statement_max_length + MAX_MULTIBYTE_CHAR_LEN) instead, to avoid scanning the entire string? Regards, -- Fujii Masao -
Re: Truncate logs by max_log_size
Fujii Masao <masao.fujii@gmail.com> — 2026-07-03T04:24:21Z
On Fri, Jul 3, 2026 at 9:56 AM Fujii Masao <masao.fujii@gmail.com> wrote: > Thanks for the review! I've pushed the patch. The buildfarm member prion reported the failure [1]. It looks like the failure occurs because prion runs with log_error_verbosity = verbose, which inserts the SQLSTATE between "LOG:" and the message text. The log_statement_max_length = 0 test expected "statement:" to appear immediately after "LOG:", so it failed even though the server correctly logged an empty statement body. The attached patch fixes the test. Regards, [1] https://buildfarm.postgresql.org/cgi-bin/show_log.pl?nm=prion&dt=2026-07-03%2002%3A23%3A06 -- Fujii Masao
-
Re: Truncate logs by max_log_size
Jim Jones <jim.jones@uni-muenster.de> — 2026-07-03T07:34:22Z
On 03/07/2026 02:56, Fujii Masao wrote: > Thanks for the review! I've pushed the patch. Awesome. Thanks! > While working on it, I found a few possible follow-up improvements. > > (1) > When log_statement is enabled, executing a prepared statement logs the > prepared query in a DETAIL message. For example: > > =# SET log_statement_max_length TO 10; > =# PREPARE test AS SELECT * FROM pgbench_accounts WHERE aid = $1; > LOG: statement: PREPARE te > =# EXECUTE test(1); > LOG: statement: EXECUTE te > DETAIL: prepare: PREPARE test AS SELECT * FROM pgbench_accounts > WHERE aid = $1; > > Should log_statement_max_length also apply to such query string in the > DETAIL message? > > (2) > When a bind parameter is truncated by > log_parameter_max_length, an ellipsis (...) is appended: > > =# SET log_parameter_max_length TO 5; > =# SELECT $1::text \bind 'abcdefghijk' \g > LOG: execute <unnamed>: SELECT $1::text > DETAIL: Parameters: $1 = 'abcde...' > > Would it make sense for log_statement_max_length to append an > ellipsis as well, so that users can easily tell when a statement has > been truncated? +1 Nice additions -- the feature gap is obvious, IMHO. Are you planning to work on it? I'm drowning in work right now and can only jump on it next week. > (3) > + query_len = strlen(query); > > truncate_query_log() uses strlen() only to determine whether the > query exceeds log_statement_max_length. Since the query can be very > large, would it be better to use > > strnlen(query, log_statement_max_length + MAX_MULTIBYTE_CHAR_LEN) > > instead, to avoid scanning the entire string? I'm not so sure about this one. At this point, isn't "query" already \0 terminated? I'm also wondering if it could affect pg_mbcliplen() down the road, since strnlen() can return a different value (log_statement_max_length + MAX_MULTIBYTE_CHAR_LEN) on large queries -- not tested yet. Thanks! Best, Jim
-
Re: Truncate logs by max_log_size
Fujii Masao <masao.fujii@gmail.com> — 2026-07-03T15:06:44Z
On Fri, Jul 3, 2026 at 1:24 PM Fujii Masao <masao.fujii@gmail.com> wrote: > > On Fri, Jul 3, 2026 at 9:56 AM Fujii Masao <masao.fujii@gmail.com> wrote: > > Thanks for the review! I've pushed the patch. > > The buildfarm member prion reported the failure [1]. > > It looks like the failure occurs because prion runs with > log_error_verbosity = verbose, which inserts the SQLSTATE between > "LOG:" and the message text. The log_statement_max_length = 0 test > expected "statement:" to appear immediately after "LOG:", so it failed > even though the server correctly logged an empty statement body. > > The attached patch fixes the test. I've pushed the patch, and confirmed that prion is green again. Regards, -- Fujii Masao
-
Re: Truncate logs by max_log_size
Fujii Masao <masao.fujii@gmail.com> — 2026-07-03T15:46:46Z
On Fri, Jul 3, 2026 at 4:34 PM Jim Jones <jim.jones@uni-muenster.de> wrote: > +1 > Nice additions -- the feature gap is obvious, IMHO. > > Are you planning to work on it? I'm drowning in work right now and can > only jump on it next week. I don't have plans to work on those at the moment, so please feel free to take them on if you have time! > I'm not so sure about this one. At this point, isn't "query" already \0 > terminated? I'm also wondering if it could affect pg_mbcliplen() down > the road, since strnlen() can return a different value > (log_statement_max_length + MAX_MULTIBYTE_CHAR_LEN) on large queries -- > not tested yet. Yes, "query" should already be NUL-terminated here. The reason for using strnlen() is not to handle an unterminated string, but to avoid scanning the entire query when it's very large and we only need to know whether it exceeds log_statement_max_length. I think it's fine to pass the bounded length to pg_mbcliplen(). It only needs enough input to find a multibyte-safe clipping point at or before log_statement_max_length, i.e., it doesn't need the full query length. The extra MAX_MULTIBYTE_CHAR_LEN bytes provide enough lookahead to handle a multibyte character boundary correctly. - query_len = strlen(query); + query_len = strnlen(query, + (size_t) log_statement_max_length + MAX_MULTIBYTE_CHAR_LEN); Regards, -- Fujii Masao
-
Re: Truncate logs by max_log_size
Jim Jones <jim.jones@uni-muenster.de> — 2026-07-04T11:01:51Z
On 03/07/2026 17:46, Fujii Masao wrote: > On Fri, Jul 3, 2026 at 4:34 PM Jim Jones <jim.jones@uni-muenster.de> wrote: >> +1 >> Nice additions -- the feature gap is obvious, IMHO. >> >> Are you planning to work on it? I'm drowning in work right now and can >> only jump on it next week. > I don't have plans to work on those at the moment, so please feel free > to take them on if you have time! > > >> I'm not so sure about this one. At this point, isn't "query" already \0 >> terminated? I'm also wondering if it could affect pg_mbcliplen() down >> the road, since strnlen() can return a different value >> (log_statement_max_length + MAX_MULTIBYTE_CHAR_LEN) on large queries -- >> not tested yet. > Yes, "query" should already be NUL-terminated here. The reason for > using strnlen() is not to handle an unterminated string, but to avoid > scanning the entire query when it's very large and we only need to > know whether it exceeds log_statement_max_length. > > I think it's fine to pass the bounded length to pg_mbcliplen(). > It only needs enough input to find a multibyte-safe clipping point at > or before log_statement_max_length, i.e., it doesn't need the full > query length. The extra MAX_MULTIBYTE_CHAR_LEN bytes provide enough > lookahead to handle a multibyte character boundary correctly. > > - query_len = strlen(query); > + query_len = strnlen(query, > + (size_t) log_statement_max_length + MAX_MULTIBYTE_CHAR_LEN); All right, thanks for the explanation. I'll give it a try next week. Have a nice weekend! Best, Jim
-
Re: Truncate logs by max_log_size
Jim Jones <jim.jones@uni-muenster.de> — 2026-07-08T17:02:40Z
Hi Fujii On 03.07.26 17:46, Fujii Masao wrote: > On Fri, Jul 3, 2026 at 4:34 PM Jim Jones <jim.jones@uni-muenster.de> wrote: >> +1 >> Nice additions -- the feature gap is obvious, IMHO. >> >> Are you planning to work on it? I'm drowning in work right now and can >> only jump on it next week. > > I don't have plans to work on those at the moment, so please feel free > to take them on if you have time! > > >> I'm not so sure about this one. At this point, isn't "query" already \0 >> terminated? I'm also wondering if it could affect pg_mbcliplen() down >> the road, since strnlen() can return a different value >> (log_statement_max_length + MAX_MULTIBYTE_CHAR_LEN) on large queries -- >> not tested yet. > > Yes, "query" should already be NUL-terminated here. The reason for > using strnlen() is not to handle an unterminated string, but to avoid > scanning the entire query when it's very large and we only need to > know whether it exceeds log_statement_max_length. > > I think it's fine to pass the bounded length to pg_mbcliplen(). > It only needs enough input to find a multibyte-safe clipping point at > or before log_statement_max_length, i.e., it doesn't need the full > query length. The extra MAX_MULTIBYTE_CHAR_LEN bytes provide enough > lookahead to handle a multibyte character boundary correctly. > > - query_len = strlen(query); > + query_len = strnlen(query, > + (size_t) log_statement_max_length + MAX_MULTIBYTE_CHAR_LEN); Attached 0001 addressing the points you made: * appending ellipsis to the query to indicate truncation (docs and tests also updated accordingly). A side effect of this change is that setting the parameter to 0 logs an ellipsis, which is not zero in length, but is arguably correct, as it indicates that the whole query has been truncated - just noting. * use of strnlen to avoid scanning the whole query. * truncation of prepared statements in DETAIL. While working on this I noticed some redundant checks to call truncate_query_log(), e.g. in exec_execute_message(): if (log_statement_max_length >= 0) truncated_source = truncate_query_log(sourceText); truncate_query_log() already returns NULL when query logging is disabled or when no truncation is needed: /* Truncation is disabled when the limit is negative */ if (!query || log_statement_max_length < 0) return NULL; So I'd argue that we don't need any checks in the caller. - char *truncated_source = NULL; - - if (log_statement_max_length >= 0) - truncated_source = truncate_query_log(sourceText); + char *truncated_source = truncate_query_log(sourceText); 0002 attached does this. Thoughts? BTW, should I open a new CF entry for this? Best, Jim