mirror of
https://github.com/postgres/postgres.git
synced 2025-07-07 00:36:50 +03:00
Replace log_filename_prefix with more general log_filename parameter,
to allow DBA to choose the form in which log filenames reflect the current time. Also allow for truncating instead of appending to pre-existing files --- this is convenient when the log filename pattern rewrites the same names cyclically. Per Ed L.
This commit is contained in:
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$PostgreSQL: pgsql/doc/src/sgml/runtime.sgml,v 1.279 2004/08/24 00:06:50 neilc Exp $
|
$PostgreSQL: pgsql/doc/src/sgml/runtime.sgml,v 1.280 2004/08/31 04:53:43 tgl Exp $
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<Chapter Id="runtime">
|
<Chapter Id="runtime">
|
||||||
@ -1925,14 +1925,21 @@ archive_command = 'copy "%p" /mnt/server/archivedir/"%f"' # Win32
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry id="guc-log-filename-prefix" xreflabel="log_filename_prefix">
|
<varlistentry id="guc-log-filename" xreflabel="log_filename">
|
||||||
<term><varname>log_filename_prefix</varname> (<type>string</type>)</term>
|
<term><varname>log_filename</varname> (<type>string</type>)</term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
When <varname>redirect_stderr</> is enabled, this option
|
When <varname>redirect_stderr</> is enabled, this option
|
||||||
sets the prefix of the file names of the created log files.
|
sets the file names of the created log files. The value
|
||||||
The postmaster PID and the current time are appended to this
|
is treated as a <systemitem>strftime</> pattern,
|
||||||
prefix to form an exact log file name.
|
so <literal>%</>-escapes
|
||||||
|
can be used to specify time-varying file names.
|
||||||
|
If no <literal>%</>-escapes are present,
|
||||||
|
<productname>PostgreSQL</productname> will
|
||||||
|
append the epoch of the new log file's open time. For example,
|
||||||
|
if <varname>log_filename</> were <literal>server_log</>, then the
|
||||||
|
chosen file name would be <literal>server_log.1093827753</>
|
||||||
|
for a log starting at Sun Aug 29 19:02:33 2004 MST.
|
||||||
This option can only be set at server start or in the
|
This option can only be set at server start or in the
|
||||||
<filename>postgresql.conf</filename> configuration file.
|
<filename>postgresql.conf</filename> configuration file.
|
||||||
</para>
|
</para>
|
||||||
@ -1969,6 +1976,26 @@ archive_command = 'copy "%p" /mnt/server/archivedir/"%f"' # Win32
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry id="guc-log-truncate-on-rotation" xreflabel="log_truncate_on_rotation">
|
||||||
|
<term><varname>log_truncate_on_rotation</varname> (<type>boolean</type>)</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
When <varname>redirect_stderr</> is enabled, this option will cause
|
||||||
|
<productname>PostgreSQL</productname> to truncate (overwrite),
|
||||||
|
rather than append to, any existing log file of the same name.
|
||||||
|
However, truncation will occur only when a new file is being opened
|
||||||
|
due to time-based rotation, not during server startup or size-based
|
||||||
|
rotation. When false, pre-existing files will be appended to in
|
||||||
|
all cases. For example, using this option in combination with
|
||||||
|
a <varname>log_filename</> like <literal>postgresql-%H.log</>
|
||||||
|
would result in generating twenty-four hourly log files and then
|
||||||
|
cyclically overwriting them.
|
||||||
|
This option can only be set at server start or in the
|
||||||
|
<filename>postgresql.conf</filename> configuration file.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry id="guc-syslog-facility" xreflabel="syslog_facility">
|
<varlistentry id="guc-syslog-facility" xreflabel="syslog_facility">
|
||||||
<term><varname>syslog_facility</varname> (<type>string</type>)</term>
|
<term><varname>syslog_facility</varname> (<type>string</type>)</term>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/postmaster/syslogger.c,v 1.7 2004/08/29 05:06:46 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/postmaster/syslogger.c,v 1.8 2004/08/31 04:53:44 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -61,8 +61,9 @@
|
|||||||
bool Redirect_stderr = false;
|
bool Redirect_stderr = false;
|
||||||
int Log_RotationAge = 24 * 60;
|
int Log_RotationAge = 24 * 60;
|
||||||
int Log_RotationSize = 10 * 1024;
|
int Log_RotationSize = 10 * 1024;
|
||||||
char *Log_directory = "pg_log";
|
char *Log_directory = NULL;
|
||||||
char *Log_filename_prefix = "postgresql-";
|
char *Log_filename = NULL;
|
||||||
|
bool Log_truncate_on_rotation = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Globally visible state (used by elog.c)
|
* Globally visible state (used by elog.c)
|
||||||
@ -72,7 +73,7 @@ bool am_syslogger = false;
|
|||||||
/*
|
/*
|
||||||
* Private state
|
* Private state
|
||||||
*/
|
*/
|
||||||
static pg_time_t last_rotation_time = 0;
|
static pg_time_t next_rotation_time;
|
||||||
|
|
||||||
static bool redirection_done = false;
|
static bool redirection_done = false;
|
||||||
|
|
||||||
@ -109,8 +110,9 @@ static void write_syslogger_file_binary(const char *buffer, int count);
|
|||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
static unsigned int __stdcall pipeThread(void *arg);
|
static unsigned int __stdcall pipeThread(void *arg);
|
||||||
#endif
|
#endif
|
||||||
static void logfile_rotate(void);
|
static void logfile_rotate(bool time_based_rotation);
|
||||||
static char *logfile_getname(pg_time_t timestamp);
|
static char *logfile_getname(pg_time_t timestamp);
|
||||||
|
static void set_next_rotation_time(void);
|
||||||
static void sigHupHandler(SIGNAL_ARGS);
|
static void sigHupHandler(SIGNAL_ARGS);
|
||||||
|
|
||||||
|
|
||||||
@ -121,7 +123,9 @@ static void sigHupHandler(SIGNAL_ARGS);
|
|||||||
NON_EXEC_STATIC void
|
NON_EXEC_STATIC void
|
||||||
SysLoggerMain(int argc, char *argv[])
|
SysLoggerMain(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
char currentLogDir[MAXPGPATH];
|
char *currentLogDir;
|
||||||
|
char *currentLogFilename;
|
||||||
|
int currentLogRotationAge;
|
||||||
|
|
||||||
IsUnderPostmaster = true; /* we are a postmaster subprocess now */
|
IsUnderPostmaster = true; /* we are a postmaster subprocess now */
|
||||||
|
|
||||||
@ -218,15 +222,18 @@ SysLoggerMain(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
#endif /* WIN32 */
|
#endif /* WIN32 */
|
||||||
|
|
||||||
/* remember age of initial logfile */
|
/* remember active logfile parameters */
|
||||||
last_rotation_time = time(NULL);
|
currentLogDir = pstrdup(Log_directory);
|
||||||
/* remember active logfile directory */
|
currentLogFilename = pstrdup(Log_filename);
|
||||||
strncpy(currentLogDir, Log_directory, MAXPGPATH);
|
currentLogRotationAge = Log_RotationAge;
|
||||||
|
/* set next planned rotation time */
|
||||||
|
set_next_rotation_time();
|
||||||
|
|
||||||
/* main worker loop */
|
/* main worker loop */
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
bool rotation_requested = false;
|
bool rotation_requested = false;
|
||||||
|
bool time_based_rotation = false;
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
char logbuffer[1024];
|
char logbuffer[1024];
|
||||||
@ -242,46 +249,51 @@ SysLoggerMain(int argc, char *argv[])
|
|||||||
ProcessConfigFile(PGC_SIGHUP);
|
ProcessConfigFile(PGC_SIGHUP);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if the log directory changed in postgresql.conf. If
|
* Check if the log directory or filename pattern changed in
|
||||||
* so, force rotation to make sure we're writing the logfiles
|
* postgresql.conf. If so, force rotation to make sure we're
|
||||||
* in the right place.
|
* writing the logfiles in the right place.
|
||||||
*
|
|
||||||
* XXX is it worth responding similarly to a change of
|
|
||||||
* Log_filename_prefix?
|
|
||||||
*/
|
*/
|
||||||
if (strncmp(Log_directory, currentLogDir, MAXPGPATH) != 0)
|
if (strcmp(Log_directory, currentLogDir) != 0)
|
||||||
{
|
{
|
||||||
strncpy(currentLogDir, Log_directory, MAXPGPATH);
|
pfree(currentLogDir);
|
||||||
|
currentLogDir = pstrdup(Log_directory);
|
||||||
rotation_requested = true;
|
rotation_requested = true;
|
||||||
}
|
}
|
||||||
}
|
if (strcmp(Log_filename, currentLogFilename) != 0)
|
||||||
|
|
||||||
if (!rotation_requested &&
|
|
||||||
last_rotation_time != 0 &&
|
|
||||||
Log_RotationAge > 0)
|
|
||||||
{
|
{
|
||||||
|
pfree(currentLogFilename);
|
||||||
|
currentLogFilename = pstrdup(Log_filename);
|
||||||
|
rotation_requested = true;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Do a logfile rotation if too much time has elapsed since
|
* If rotation time parameter changed, reset next rotation time,
|
||||||
* the last one.
|
* but don't immediately force a rotation.
|
||||||
*/
|
*/
|
||||||
pg_time_t now = time(NULL);
|
if (currentLogRotationAge != Log_RotationAge)
|
||||||
int elapsed_secs = now - last_rotation_time;
|
{
|
||||||
|
currentLogRotationAge = Log_RotationAge;
|
||||||
|
set_next_rotation_time();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (elapsed_secs >= Log_RotationAge * 60)
|
if (!rotation_requested && Log_RotationAge > 0)
|
||||||
rotation_requested = true;
|
{
|
||||||
|
/* Do a logfile rotation if it's time */
|
||||||
|
pg_time_t now = time(NULL);
|
||||||
|
|
||||||
|
if (now >= next_rotation_time)
|
||||||
|
rotation_requested = time_based_rotation = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rotation_requested && Log_RotationSize > 0)
|
if (!rotation_requested && Log_RotationSize > 0)
|
||||||
{
|
{
|
||||||
/*
|
/* Do a rotation if file is too big */
|
||||||
* Do a rotation if file is too big
|
|
||||||
*/
|
|
||||||
if (ftell(syslogFile) >= Log_RotationSize * 1024L)
|
if (ftell(syslogFile) >= Log_RotationSize * 1024L)
|
||||||
rotation_requested = true;
|
rotation_requested = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rotation_requested)
|
if (rotation_requested)
|
||||||
logfile_rotate();
|
logfile_rotate(time_based_rotation);
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
|
|
||||||
@ -365,7 +377,6 @@ int
|
|||||||
SysLogger_Start(void)
|
SysLogger_Start(void)
|
||||||
{
|
{
|
||||||
pid_t sysloggerPid;
|
pid_t sysloggerPid;
|
||||||
pg_time_t now;
|
|
||||||
char *filename;
|
char *filename;
|
||||||
|
|
||||||
if (!Redirect_stderr)
|
if (!Redirect_stderr)
|
||||||
@ -424,8 +435,7 @@ SysLogger_Start(void)
|
|||||||
* The initial logfile is created right in the postmaster, to verify
|
* The initial logfile is created right in the postmaster, to verify
|
||||||
* that the Log_directory is writable.
|
* that the Log_directory is writable.
|
||||||
*/
|
*/
|
||||||
now = time(NULL);
|
filename = logfile_getname(time(NULL));
|
||||||
filename = logfile_getname(now);
|
|
||||||
|
|
||||||
syslogFile = fopen(filename, "a");
|
syslogFile = fopen(filename, "a");
|
||||||
|
|
||||||
@ -736,16 +746,26 @@ pipeThread(void *arg)
|
|||||||
* perform logfile rotation
|
* perform logfile rotation
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
logfile_rotate(void)
|
logfile_rotate(bool time_based_rotation)
|
||||||
{
|
{
|
||||||
char *filename;
|
char *filename;
|
||||||
pg_time_t now;
|
|
||||||
FILE *fh;
|
FILE *fh;
|
||||||
|
|
||||||
now = time(NULL);
|
/*
|
||||||
filename = logfile_getname(now);
|
* When doing a time-based rotation, invent the new logfile name based
|
||||||
|
* on the planned rotation time, not current time, to avoid "slippage"
|
||||||
|
* in the file name when we don't do the rotation immediately.
|
||||||
|
*/
|
||||||
|
if (time_based_rotation)
|
||||||
|
filename = logfile_getname(next_rotation_time);
|
||||||
|
else
|
||||||
|
filename = logfile_getname(time(NULL));
|
||||||
|
|
||||||
|
if (Log_truncate_on_rotation && time_based_rotation)
|
||||||
|
fh = fopen(filename, "w");
|
||||||
|
else
|
||||||
fh = fopen(filename, "a");
|
fh = fopen(filename, "a");
|
||||||
|
|
||||||
if (!fh)
|
if (!fh)
|
||||||
{
|
{
|
||||||
int saveerrno = errno;
|
int saveerrno = errno;
|
||||||
@ -784,7 +804,7 @@ logfile_rotate(void)
|
|||||||
LeaveCriticalSection(&sysfileSection);
|
LeaveCriticalSection(&sysfileSection);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
last_rotation_time = now;
|
set_next_rotation_time();
|
||||||
|
|
||||||
pfree(filename);
|
pfree(filename);
|
||||||
}
|
}
|
||||||
@ -799,25 +819,60 @@ static char *
|
|||||||
logfile_getname(pg_time_t timestamp)
|
logfile_getname(pg_time_t timestamp)
|
||||||
{
|
{
|
||||||
char *filename;
|
char *filename;
|
||||||
char stamptext[128];
|
int len;
|
||||||
|
struct pg_tm *tm;
|
||||||
pg_strftime(stamptext, sizeof(stamptext), "%Y-%m-%d_%H%M%S",
|
|
||||||
pg_localtime(×tamp));
|
|
||||||
|
|
||||||
filename = palloc(MAXPGPATH);
|
filename = palloc(MAXPGPATH);
|
||||||
|
|
||||||
if (is_absolute_path(Log_directory))
|
if (is_absolute_path(Log_directory))
|
||||||
snprintf(filename, MAXPGPATH, "%s/%s%05u_%s.log",
|
snprintf(filename, MAXPGPATH, "%s/", Log_directory);
|
||||||
Log_directory, Log_filename_prefix,
|
|
||||||
(unsigned int) PostmasterPid, stamptext);
|
|
||||||
else
|
else
|
||||||
snprintf(filename, MAXPGPATH, "%s/%s/%s%05u_%s.log",
|
snprintf(filename, MAXPGPATH, "%s/%s/", DataDir, Log_directory);
|
||||||
DataDir, Log_directory, Log_filename_prefix,
|
|
||||||
(unsigned int) PostmasterPid, stamptext);
|
len = strlen(filename);
|
||||||
|
|
||||||
|
if (strchr(Log_filename, '%'))
|
||||||
|
{
|
||||||
|
/* treat it as a strftime pattern */
|
||||||
|
tm = pg_localtime(×tamp);
|
||||||
|
pg_strftime(filename + len, MAXPGPATH - len, Log_filename, tm);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* no strftime escapes, so append timestamp to new filename */
|
||||||
|
snprintf(filename + len, MAXPGPATH - len, "%s.%lu",
|
||||||
|
Log_filename, (unsigned long) timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
return filename;
|
return filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine the next planned rotation time, and store in next_rotation_time.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
set_next_rotation_time(void)
|
||||||
|
{
|
||||||
|
pg_time_t now;
|
||||||
|
int rotinterval;
|
||||||
|
|
||||||
|
/* nothing to do if time-based rotation is disabled */
|
||||||
|
if (Log_RotationAge <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The requirements here are to choose the next time > now that is a
|
||||||
|
* "multiple" of the log rotation interval. "Multiple" can be interpreted
|
||||||
|
* fairly loosely --- in particular, for intervals larger than an hour,
|
||||||
|
* it might be interesting to align to local time instead of GMT.
|
||||||
|
*/
|
||||||
|
rotinterval = Log_RotationAge * 60; /* convert to seconds */
|
||||||
|
now = time(NULL);
|
||||||
|
now -= now % rotinterval;
|
||||||
|
now += rotinterval;
|
||||||
|
next_rotation_time = now;
|
||||||
|
}
|
||||||
|
|
||||||
/* --------------------------------
|
/* --------------------------------
|
||||||
* signal handler routines
|
* signal handler routines
|
||||||
* --------------------------------
|
* --------------------------------
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
* Written by Peter Eisentraut <peter_e@gmx.net>.
|
* Written by Peter Eisentraut <peter_e@gmx.net>.
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.235 2004/08/30 02:54:40 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.236 2004/08/31 04:53:44 tgl Exp $
|
||||||
*
|
*
|
||||||
*--------------------------------------------------------------------
|
*--------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -812,6 +812,14 @@ static struct config_bool ConfigureNamesBool[] =
|
|||||||
&Redirect_stderr,
|
&Redirect_stderr,
|
||||||
false, NULL, NULL
|
false, NULL, NULL
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
{"log_truncate_on_rotation", PGC_SIGHUP, LOGGING_WHERE,
|
||||||
|
gettext_noop("Truncate existing log files of same name during log rotation"),
|
||||||
|
NULL
|
||||||
|
},
|
||||||
|
&Log_truncate_on_rotation,
|
||||||
|
false, NULL, NULL
|
||||||
|
},
|
||||||
|
|
||||||
#ifdef WAL_DEBUG
|
#ifdef WAL_DEBUG
|
||||||
{
|
{
|
||||||
@ -1673,12 +1681,12 @@ static struct config_string ConfigureNamesString[] =
|
|||||||
"pg_log", NULL, NULL
|
"pg_log", NULL, NULL
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
{"log_filename_prefix", PGC_SIGHUP, LOGGING_WHERE,
|
{"log_filename", PGC_SIGHUP, LOGGING_WHERE,
|
||||||
gettext_noop("Prefix for file names created in the log_directory."),
|
gettext_noop("Sets the file name pattern for log files."),
|
||||||
NULL
|
NULL
|
||||||
},
|
},
|
||||||
&Log_filename_prefix,
|
&Log_filename,
|
||||||
"postgresql-", NULL, NULL
|
"postgresql-%Y-%m-%d_%H%M%S.log", NULL, NULL
|
||||||
},
|
},
|
||||||
|
|
||||||
#ifdef HAVE_SYSLOG
|
#ifdef HAVE_SYSLOG
|
||||||
|
@ -173,7 +173,15 @@
|
|||||||
# These are only relevant if redirect_stderr is true:
|
# These are only relevant if redirect_stderr is true:
|
||||||
#log_directory = 'pg_log' # Directory where log files are written.
|
#log_directory = 'pg_log' # Directory where log files are written.
|
||||||
# May be specified absolute or relative to PGDATA
|
# May be specified absolute or relative to PGDATA
|
||||||
#log_filename_prefix = 'postgresql_' # Prefix for logfile names.
|
#log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log' # Log file name pattern.
|
||||||
|
# May include strftime() escapes
|
||||||
|
#log_truncate_on_rotation = false # If true, any existing log file of the
|
||||||
|
# same name as the new log file will be truncated
|
||||||
|
# rather than appended to. But such truncation
|
||||||
|
# only occurs on time-driven rotation,
|
||||||
|
# not on restarts or size-driven rotation.
|
||||||
|
# Default is false, meaning append to existing
|
||||||
|
# files in all cases.
|
||||||
#log_rotation_age = 1440 # Automatic rotation of logfiles will happen after
|
#log_rotation_age = 1440 # Automatic rotation of logfiles will happen after
|
||||||
# so many minutes. 0 to disable.
|
# so many minutes. 0 to disable.
|
||||||
#log_rotation_size = 10240 # Automatic rotation of logfiles will happen after
|
#log_rotation_size = 10240 # Automatic rotation of logfiles will happen after
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2004, PostgreSQL Global Development Group
|
* Copyright (c) 2004, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/postmaster/syslogger.h,v 1.2 2004/08/29 05:06:58 momjian Exp $
|
* $PostgreSQL: pgsql/src/include/postmaster/syslogger.h,v 1.3 2004/08/31 04:53:44 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -17,7 +17,8 @@ extern bool Redirect_stderr;
|
|||||||
extern int Log_RotationAge;
|
extern int Log_RotationAge;
|
||||||
extern int Log_RotationSize;
|
extern int Log_RotationSize;
|
||||||
extern char *Log_directory;
|
extern char *Log_directory;
|
||||||
extern char *Log_filename_prefix;
|
extern char *Log_filename;
|
||||||
|
extern bool Log_truncate_on_rotation;
|
||||||
|
|
||||||
extern bool am_syslogger;
|
extern bool am_syslogger;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user