summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/src/sgml/runtime.sgml39
-rw-r--r--src/backend/postmaster/syslogger.c157
-rw-r--r--src/backend/utils/misc/guc.c20
-rw-r--r--src/backend/utils/misc/postgresql.conf.sample12
-rw-r--r--src/include/postmaster/syslogger.h5
5 files changed, 166 insertions, 67 deletions
diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml
index bdf029fa640..1a2f24500f3 100644
--- a/doc/src/sgml/runtime.sgml
+++ b/doc/src/sgml/runtime.sgml
@@ -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">
@@ -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>
diff --git a/src/backend/postmaster/syslogger.c b/src/backend/postmaster/syslogger.c
index 56bb3813888..a1e8870e924 100644
--- a/src/backend/postmaster/syslogger.c
+++ b/src/backend/postmaster/syslogger.c
@@ -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
* --------------------------------
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 252d4a7f9ee..c5919c47fe1 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -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
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index cdd427f04b6..67b9dbadafc 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -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
diff --git a/src/include/postmaster/syslogger.h b/src/include/postmaster/syslogger.h
index 2e1adc6900e..12f2ffe5cf9 100644
--- a/src/include/postmaster/syslogger.h
+++ b/src/include/postmaster/syslogger.h
@@ -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;