Le 11/03/2016 15:22, Tom Lane a écrit : > Gilles Darold <gilles.dar...@dalibo.com> writes: >> Le 11/03/2016 10:49, Shulgin, Oleksandr a écrit : >>> Would it make sense to have it as a symlink instead? >> The only cons I see is that it can be more "difficult" with some >> language to gather the real path, but do we really need it? There is >> also little time where the symlink doesn't exist, this is when it needs >> to be removed before being recreated to point to the new log file. > Yeah, a symlink is impossible to update atomically (on most platforms > anyway). Plain file containing the pathname seems better. > > Another point is that we might not necessarily want *only* the pathname in > there. postmaster.pid has accreted more stuff over time, and this file > might too. I can see wanting the syslogger PID in there, for example, > so that onlookers can detect a totally stale file. (Not proposing this > right now, just pointing out that it's a conceivable future feature.) > > regards, tom lane
Here is the patch rewritten to use alternate file $PGDATA/pg_log_filename to store the current log filename used by syslogger. All examples used in the first mail of this thread work the exact same way. If there's no other remarks, I will add the patch to the next commit fest. Here are some additional examples with this feature. To obtain the filling percentage of the log file when log_rotation_size is used: postgres=# SELECT pg_current_logfile(), (select setting::int*1000 from pg_settings where name='log_rotation_size'), a.size size, ((a.size*100)/(select setting::int*1000 from pg_settings where name='log_rotation_size')) percent_used FROM pg_stat_file(pg_current_logfile()) a(size,access,modification,change,creation,isdir); -[ RECORD 1 ]------+---------------------------------------- pg_current_logfile | pg_log/postgresql-2016-03-11_160817.log log_rotation_size | 10240000 size | 1246000 percent_used | 12 This can help to know if the file is near to be rotated. Or if you use time based rotation: postgres=# select pg_current_logfile(), (select setting::int*60 from pg_settings where name='log_rotation_age') log_rotation_age,a.access,a.modification, (((extract(epoch from a.modification) - extract(epoch from a.access)) * 100) / (select setting::int*60 from pg_settings where name='log_rotation_age')) percent_used FROM pg_stat_file(pg_current_logfile()) a(size,access,modification,change,creation,isdir); -[ RECORD 1 ]------+---------------------------------------- pg_current_logfile | pg_log/postgresql-2016-03-11_162143.log log_rotation_age | 3600 access | 2016-03-11 16:21:43+01 modification | 2016-03-11 16:33:12+01 percent_used | 19.1388888888889 Best regards, -- Gilles Darold Consultant PostgreSQL http://dalibo.com - http://dalibo.org
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 4b5ee81..e6a18fc 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -15026,6 +15026,11 @@ SELECT * FROM pg_ls_dir('.') WITH ORDINALITY AS t(ls,n); <entry>channel names that the session is currently listening on</entry> </row> + <entry><literal><function>pg_current_logfile()</function></literal></entry> + <entry><type>text</type></entry> + <entry>current log file used by the logging collector</entry> + </row> + <row> <entry><literal><function>pg_notification_queue_usage()</function></literal></entry> <entry><type>double</type></entry> @@ -15264,6 +15269,16 @@ SET search_path TO <replaceable>schema</> <optional>, <replaceable>schema</>, .. </para> <indexterm> + <primary>pg_current_logfile</primary> + </indexterm> + + <para> + <function>pg_current_logfile</function> returns the name of the current log + file used by the logging collector, as a <type>text</type>. Log collection + must be active. + </para> + + <indexterm> <primary>pg_postmaster_start_time</primary> </indexterm> diff --git a/src/backend/postmaster/syslogger.c b/src/backend/postmaster/syslogger.c index e7e488a..4769dc5 100644 --- a/src/backend/postmaster/syslogger.c +++ b/src/backend/postmaster/syslogger.c @@ -145,6 +145,7 @@ static char *logfile_getname(pg_time_t timestamp, const char *suffix); static void set_next_rotation_time(void); static void sigHupHandler(SIGNAL_ARGS); static void sigUsr1Handler(SIGNAL_ARGS); +static void store_current_log_filename(char *filename); /* @@ -571,6 +572,9 @@ SysLogger_Start(void) syslogFile = logfile_open(filename, "a", false); + /* store information about current log filename used by log collection */ + store_current_log_filename(filename); + pfree(filename); #ifdef EXEC_BACKEND @@ -1209,6 +1213,9 @@ logfile_rotate(bool time_based_rotation, int size_rotation_for) fclose(syslogFile); syslogFile = fh; + /* store information about current log filename used by log collection */ + store_current_log_filename(filename); + /* instead of pfree'ing filename, remember it for next time */ if (last_file_name != NULL) pfree(last_file_name); @@ -1253,6 +1260,9 @@ logfile_rotate(bool time_based_rotation, int size_rotation_for) fclose(csvlogFile); csvlogFile = fh; + /* store information about current log filename used by log collection */ + store_current_log_filename(csvfilename); + /* instead of pfree'ing filename, remember it for next time */ if (last_csv_file_name != NULL) pfree(last_csv_file_name); @@ -1362,3 +1372,35 @@ sigUsr1Handler(SIGNAL_ARGS) errno = save_errno; } + +/* + * Store the name of the file where current log messages are written when + * log collector is enabled. Useful to find the name of the current log file + * when a time-based rotation is defined. + */ +static void +store_current_log_filename(char *filename) +{ + FILE *fh; + char logpathfilename[MAXPGPATH]; + + snprintf(logpathfilename, sizeof(logpathfilename), "%s", + CURRENT_LOG_FILENAME); + if ((fh = fopen(logpathfilename, "w")) == NULL) + { + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not open log file \"%s\": %m", + logpathfilename))); + return; + } + if (fprintf(fh, "%s\n", filename) < 0) + { + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not write log file \"%s\": %m", + logpathfilename))); + } + fclose(fh); +} + diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c index 43f36db..d9b6435 100644 --- a/src/backend/utils/adt/misc.c +++ b/src/backend/utils/adt/misc.c @@ -719,3 +719,62 @@ pg_column_is_updatable(PG_FUNCTION_ARGS) PG_RETURN_BOOL((events & REQ_EVENTS) == REQ_EVENTS); } + +/* + * Report current log file used by log collector + */ +Datum +pg_current_logfile(PG_FUNCTION_ARGS) +{ + FILE *fd; + char log_filename[MAXPGPATH]; + + if (!Logging_collector) + { + ereport(WARNING, + (errmsg("current log can not be reported because log collection is not active"))); + PG_RETURN_NULL(); + } + + /* + * See if current log file is present + */ + fd = AllocateFile(CURRENT_LOG_FILENAME, "r"); + if (fd == NULL) + { + if (errno != ENOENT) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not read file \"%s\": %m", + CURRENT_LOG_FILENAME))); + PG_RETURN_NULL(); + } + + /* + * Read first line of the file to gather current log filename + * registered by the syslogger. + */ + fgets(log_filename, sizeof(log_filename), fd); + + /* Check for a read error. */ + if (ferror(fd)) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not read file \"%s\": %m", CURRENT_LOG_FILENAME))); + + /* Close the current log filename file. */ + if (FreeFile(fd)) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not close file \"%s\": %m", CURRENT_LOG_FILENAME))); + + /* remove trailing newline */ + if (strchr(log_filename, '\n') != NULL) + *strchr(log_filename, '\n') = '\0'; + + if (log_filename[0] == '\0') + PG_RETURN_NULL(); + + PG_RETURN_TEXT_P(cstring_to_text(log_filename)); +} + diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 451bad7..0dc44cf 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -3125,6 +3125,8 @@ DATA(insert OID = 2621 ( pg_reload_conf PGNSP PGUID 12 1 0 0 0 f f f f t f v s DESCR("reload configuration files"); DATA(insert OID = 2622 ( pg_rotate_logfile PGNSP PGUID 12 1 0 0 0 f f f f t f v s 0 0 16 "" _null_ _null_ _null_ _null_ _null_ pg_rotate_logfile _null_ _null_ _null_ )); DESCR("rotate log file"); +DATA(insert OID = 3794 ( pg_current_logfile PGNSP PGUID 12 1 0 0 0 f f f f t f v s 0 0 25 "" _null_ _null_ _null_ _null_ _null_ pg_current_logfile _null_ _null_ _null_ )); +DESCR("current logging collector file location"); DATA(insert OID = 2623 ( pg_stat_file PGNSP PGUID 12 1 0 0 0 f f f f t f v s 1 0 2249 "25" "{25,20,1184,1184,1184,1184,16}" "{i,o,o,o,o,o,o}" "{filename,size,access,modification,change,creation,isdir}" _null_ _null_ pg_stat_file_1arg _null_ _null_ _null_ )); DESCR("get information about file"); diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index cc7833e..5a388ba 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -464,4 +464,13 @@ extern bool has_rolreplication(Oid roleid); extern bool BackupInProgress(void); extern void CancelBackup(void); +/* in backend/utils/adt/misc.c and backend/postmaster/syslogger.c */ +/* + * Name of file where current log messages are written when log collector is + * enabled. Useful to find the name of the current log file when a time-based + * rotation is defined. + */ +#define CURRENT_LOG_FILENAME "pg_log_filename" + + #endif /* MISCADMIN_H */ diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 115f8af..fd2c4ea 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -509,6 +509,7 @@ extern Datum pg_typeof(PG_FUNCTION_ARGS); extern Datum pg_collation_for(PG_FUNCTION_ARGS); extern Datum pg_relation_is_updatable(PG_FUNCTION_ARGS); extern Datum pg_column_is_updatable(PG_FUNCTION_ARGS); +extern Datum pg_current_logfile(PG_FUNCTION_ARGS); /* oid.c */ extern Datum oidin(PG_FUNCTION_ARGS);
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers