提交 8c603f2c 编写于 作者: T Tom Lane

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.
上级 25aba1ca
<!--
$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">
......@@ -1925,14 +1925,21 @@ archive_command = 'copy "%p" /mnt/server/archivedir/"%f"' # Win32
</listitem>
</varlistentry>
<varlistentry id="guc-log-filename-prefix" xreflabel="log_filename_prefix">
<term><varname>log_filename_prefix</varname> (<type>string</type>)</term>
<varlistentry id="guc-log-filename" xreflabel="log_filename">
<term><varname>log_filename</varname> (<type>string</type>)</term>
<listitem>
<para>
When <varname>redirect_stderr</> is enabled, this option
sets the prefix of the file names of the created log files.
The postmaster PID and the current time are appended to this
prefix to form an exact log file name.
sets the file names of the created log files. The value
is treated as a <systemitem>strftime</> pattern,
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
<filename>postgresql.conf</filename> configuration file.
</para>
......@@ -1969,6 +1976,26 @@ archive_command = 'copy "%p" /mnt/server/archivedir/"%f"' # Win32
</listitem>
</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">
<term><varname>syslog_facility</varname> (<type>string</type>)</term>
<listitem>
......
......@@ -18,7 +18,7 @@
*
*
* 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;
int Log_RotationAge = 24 * 60;
int Log_RotationSize = 10 * 1024;
char *Log_directory = "pg_log";
char *Log_filename_prefix = "postgresql-";
char *Log_directory = NULL;
char *Log_filename = NULL;
bool Log_truncate_on_rotation = false;
/*
* Globally visible state (used by elog.c)
......@@ -72,7 +73,7 @@ bool am_syslogger = false;
/*
* Private state
*/
static pg_time_t last_rotation_time = 0;
static pg_time_t next_rotation_time;
static bool redirection_done = false;
......@@ -109,8 +110,9 @@ static void write_syslogger_file_binary(const char *buffer, int count);
#ifdef WIN32
static unsigned int __stdcall pipeThread(void *arg);
#endif
static void logfile_rotate(void);
static void logfile_rotate(bool time_based_rotation);
static char *logfile_getname(pg_time_t timestamp);
static void set_next_rotation_time(void);
static void sigHupHandler(SIGNAL_ARGS);
......@@ -121,7 +123,9 @@ static void sigHupHandler(SIGNAL_ARGS);
NON_EXEC_STATIC void
SysLoggerMain(int argc, char *argv[])
{
char currentLogDir[MAXPGPATH];
char *currentLogDir;
char *currentLogFilename;
int currentLogRotationAge;
IsUnderPostmaster = true; /* we are a postmaster subprocess now */
......@@ -218,15 +222,18 @@ SysLoggerMain(int argc, char *argv[])
}
#endif /* WIN32 */
/* remember age of initial logfile */
last_rotation_time = time(NULL);
/* remember active logfile directory */
strncpy(currentLogDir, Log_directory, MAXPGPATH);
/* remember active logfile parameters */
currentLogDir = pstrdup(Log_directory);
currentLogFilename = pstrdup(Log_filename);
currentLogRotationAge = Log_RotationAge;
/* set next planned rotation time */
set_next_rotation_time();
/* main worker loop */
for (;;)
{
bool rotation_requested = false;
bool time_based_rotation = false;
#ifndef WIN32
char logbuffer[1024];
......@@ -242,46 +249,51 @@ SysLoggerMain(int argc, char *argv[])
ProcessConfigFile(PGC_SIGHUP);
/*
* Check if the log directory changed in postgresql.conf. If
* so, force rotation to make sure we're writing the logfiles
* in the right place.
*
* XXX is it worth responding similarly to a change of
* Log_filename_prefix?
* Check if the log directory or filename pattern changed in
* postgresql.conf. If so, force rotation to make sure we're
* writing the logfiles in the right place.
*/
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;
}
if (strcmp(Log_filename, currentLogFilename) != 0)
{
pfree(currentLogFilename);
currentLogFilename = pstrdup(Log_filename);
rotation_requested = true;
}
/*
* If rotation time parameter changed, reset next rotation time,
* but don't immediately force a rotation.
*/
if (currentLogRotationAge != Log_RotationAge)
{
currentLogRotationAge = Log_RotationAge;
set_next_rotation_time();
}
}
if (!rotation_requested &&
last_rotation_time != 0 &&
Log_RotationAge > 0)
if (!rotation_requested && Log_RotationAge > 0)
{
/*
* Do a logfile rotation if too much time has elapsed since
* the last one.
*/
/* Do a logfile rotation if it's time */
pg_time_t now = time(NULL);
int elapsed_secs = now - last_rotation_time;
if (elapsed_secs >= Log_RotationAge * 60)
rotation_requested = true;
if (now >= next_rotation_time)
rotation_requested = time_based_rotation = true;
}
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)
rotation_requested = true;
}
if (rotation_requested)
logfile_rotate();
logfile_rotate(time_based_rotation);
#ifndef WIN32
......@@ -365,7 +377,6 @@ int
SysLogger_Start(void)
{
pid_t sysloggerPid;
pg_time_t now;
char *filename;
if (!Redirect_stderr)
......@@ -424,8 +435,7 @@ SysLogger_Start(void)
* The initial logfile is created right in the postmaster, to verify
* that the Log_directory is writable.
*/
now = time(NULL);
filename = logfile_getname(now);
filename = logfile_getname(time(NULL));
syslogFile = fopen(filename, "a");
......@@ -736,16 +746,26 @@ pipeThread(void *arg)
* perform logfile rotation
*/
static void
logfile_rotate(void)
logfile_rotate(bool time_based_rotation)
{
char *filename;
pg_time_t now;
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)
{
int saveerrno = errno;
......@@ -784,7 +804,7 @@ logfile_rotate(void)
LeaveCriticalSection(&sysfileSection);
#endif
last_rotation_time = now;
set_next_rotation_time();
pfree(filename);
}
......@@ -799,25 +819,60 @@ static char *
logfile_getname(pg_time_t timestamp)
{
char *filename;
char stamptext[128];
pg_strftime(stamptext, sizeof(stamptext), "%Y-%m-%d_%H%M%S",
pg_localtime(&timestamp));
int len;
struct pg_tm *tm;
filename = palloc(MAXPGPATH);
if (is_absolute_path(Log_directory))
snprintf(filename, MAXPGPATH, "%s/%s%05u_%s.log",
Log_directory, Log_filename_prefix,
(unsigned int) PostmasterPid, stamptext);
snprintf(filename, MAXPGPATH, "%s/", Log_directory);
else
snprintf(filename, MAXPGPATH, "%s/%s/%s%05u_%s.log",
DataDir, Log_directory, Log_filename_prefix,
(unsigned int) PostmasterPid, stamptext);
snprintf(filename, MAXPGPATH, "%s/%s/", DataDir, Log_directory);
len = strlen(filename);
if (strchr(Log_filename, '%'))
{
/* treat it as a strftime pattern */
tm = pg_localtime(&timestamp);
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;
}
/*
* 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
* --------------------------------
......
......@@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
* 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,
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
{
......@@ -1665,7 +1673,7 @@ static struct config_string ConfigureNamesString[] =
},
{
{"log_directory", PGC_SIGHUP, LOGGING_WHERE,
gettext_noop("Sets the destination directory for logfiles."),
gettext_noop("Sets the destination directory for log files."),
gettext_noop("May be specified as relative to the cluster directory "
"or as absolute path.")
},
......@@ -1673,12 +1681,12 @@ static struct config_string ConfigureNamesString[] =
"pg_log", NULL, NULL
},
{
{"log_filename_prefix", PGC_SIGHUP, LOGGING_WHERE,
gettext_noop("Prefix for file names created in the log_directory."),
{"log_filename", PGC_SIGHUP, LOGGING_WHERE,
gettext_noop("Sets the file name pattern for log files."),
NULL
},
&Log_filename_prefix,
"postgresql-", NULL, NULL
&Log_filename,
"postgresql-%Y-%m-%d_%H%M%S.log", NULL, NULL
},
#ifdef HAVE_SYSLOG
......
......@@ -171,9 +171,17 @@
# This is relevant when logging to stderr:
#redirect_stderr = false # Enable capturing of stderr into log files.
# These are only relevant if redirect_stderr is true:
#log_directory = 'pg_log' # Directory where logfiles are written.
#log_directory = 'pg_log' # Directory where log files are written.
# 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
# so many minutes. 0 to disable.
#log_rotation_size = 10240 # Automatic rotation of logfiles will happen after
......
......@@ -5,7 +5,7 @@
*
* 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_RotationSize;
extern char *Log_directory;
extern char *Log_filename_prefix;
extern char *Log_filename;
extern bool Log_truncate_on_rotation;
extern bool am_syslogger;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册