Thread: Re: [HACKERS] serverlog function (log_destination file)
Magnus Hagander wrote: >Specifically about the logs, I still think there is a lot of value to >being able to read the logs remotely even if you can't restart >postmaster. > Since I believe that retrieving the logs easily without server file access is a feature that's welcomed by many users, here's my proposal. The attached diff will - add a guc-variable log_filename - extend log_destination to accept the keyword 'file' - elog to that file if configured - provide two functions pg_logfile_length() and pg_logfile to obtain the contents. int4 pg_logfile_length() cstring pg_logfile(int4 size, int4 position) size (may be null meaning max) is the chunk size (max: currently 50000) position (may be null meaning -size) is the start position; positive counting from log file start, negative from end. Regards, Andreas Index: backend/postmaster/postmaster.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/postmaster/postmaster.c,v retrieving revision 1.402 diff -u -r1.402 postmaster.c --- backend/postmaster/postmaster.c 3 Jun 2004 02:08:03 -0000 1.402 +++ backend/postmaster/postmaster.c 8 Jun 2004 18:07:30 -0000 @@ -532,6 +532,9 @@ /* If timezone is not set, determine what the OS uses */ pg_timezone_initialize(); + /* open alternate logfile, if any */ + LogFileOpen(); + #ifdef EXEC_BACKEND write_nondefault_variables(PGC_POSTMASTER); #endif Index: backend/storage/ipc/ipc.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/storage/ipc/ipc.c,v retrieving revision 1.87 diff -u -r1.87 ipc.c --- backend/storage/ipc/ipc.c 12 Dec 2003 18:45:09 -0000 1.87 +++ backend/storage/ipc/ipc.c 8 Jun 2004 18:07:31 -0000 @@ -111,6 +111,8 @@ on_proc_exit_list[on_proc_exit_index].arg); elog(DEBUG3, "exit(%d)", code); + + LogFileClose(); exit(code); } Index: backend/utils/adt/misc.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/adt/misc.c,v retrieving revision 1.34 diff -u -r1.34 misc.c --- backend/utils/adt/misc.c 2 Jun 2004 21:29:29 -0000 1.34 +++ backend/utils/adt/misc.c 8 Jun 2004 18:07:36 -0000 @@ -103,3 +103,64 @@ { PG_RETURN_INT32(pg_signal_backend(PG_GETARG_INT32(0),SIGINT)); } + +Datum pg_logfile_length(PG_FUNCTION_ARGS) +{ + extern FILE *logfile; // in elog.c + + if (logfile) + PG_RETURN_INT32(ftell(logfile)); + PG_RETURN_INT32(0); +} + + +#define MAXLOGFILECHUNK 50000 +Datum pg_logfile(PG_FUNCTION_ARGS) +{ + size_t size=MAXLOGFILECHUNK; + char *buf=0; + size_t nbytes; + + char *filename = LogFileName(); + if (filename) + { + if (!PG_ARGISNULL(0)) + size = PG_GETARG_INT32(0); + if (size > MAXLOGFILECHUNK) + { + size = MAXLOGFILECHUNK; + ereport(WARNING, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("Maximum size is %d.", MAXLOGFILECHUNK))); + } + + FILE *f=fopen(filename, "r"); + if (f) + { + if (PG_ARGISNULL(1)) + fseek(f, -size, SEEK_END); + else + { + long pos = PG_GETARG_INT32(1); + if (pos >= 0) + fseek(f, pos, SEEK_SET); + else + fseek(f, pos, SEEK_END); + } + buf = palloc(size+1); + nbytes = fread(buf, 1, size, f); + buf[nbytes] = 0; + + fclose(f); + } + else + { + ereport(WARNING, + (errcode(ERRCODE_NO_DATA), + errmsg("Could not open log file %s.", filename))); + } + free(filename); + } + + PG_RETURN_CSTRING(buf); +} Index: backend/utils/error/elog.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/error/elog.c,v retrieving revision 1.140 diff -u -r1.140 elog.c --- backend/utils/error/elog.c 3 Jun 2004 02:08:04 -0000 1.140 +++ backend/utils/error/elog.c 8 Jun 2004 18:07:39 -0000 @@ -71,8 +71,10 @@ PGErrorVerbosity Log_error_verbosity = PGERROR_VERBOSE; char *Log_line_prefix = NULL; /* format for extra log line info */ unsigned int Log_destination = LOG_DESTINATION_STDERR; +char *Log_filename = NULL; bool in_fatal_exit = false; +FILE *logfile = NULL; #ifdef HAVE_SYSLOG char *Syslog_facility; /* openlog() parameters */ @@ -936,6 +938,69 @@ /* + * Name of configured log file, or NULL + * must be freed after usage + */ +char* +LogFileName(void) +{ + if (Log_filename && (Log_destination & LOG_DESTINATION_FILE)) + { + if (is_absolute_path(Log_filename)) + return strdup(Log_filename); + else + { + char *buf = malloc(strlen(DataDir) + strlen(Log_filename) +2); + if (!buf) + ereport(FATAL, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + + sprintf(buf, "%s/%s", DataDir, Log_filename); + + return buf; + } + } + return NULL; +} + + +/* + * Open log file, if configured. + */ +void +LogFileOpen(void) +{ + char *filename = LogFileName(); + + if (filename) + { + LogFileClose(); + + logfile = fopen(filename, "at"); + + if (!logfile) + ereport(WARNING, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("could not open log file %s", filename))); + + free(filename); + } +} + + +/* + * Close log file, if open. + */ +void +LogFileClose(void) +{ + if (logfile) + fclose(logfile); + logfile = NULL; +} + +/* * Initialization of error output file */ void @@ -1445,6 +1510,11 @@ if ((Log_destination & LOG_DESTINATION_STDERR) || whereToSendOutput == Debug) { fprintf(stderr, "%s", buf.data); + } + + if (logfile && (Log_destination & LOG_DESTINATION_FILE)) + { + fprintf(logfile, "%s", buf.data); } pfree(buf.data); Index: backend/utils/misc/guc.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/misc/guc.c,v retrieving revision 1.210 diff -u -r1.210 guc.c --- backend/utils/misc/guc.c 30 May 2004 23:40:38 -0000 1.210 +++ backend/utils/misc/guc.c 8 Jun 2004 18:07:47 -0000 @@ -76,6 +76,8 @@ static const char *assign_log_destination(const char *value, bool doit, GucSource source); +extern char *Log_filename; + #ifdef HAVE_SYSLOG extern char *Syslog_facility; extern char *Syslog_ident; @@ -1644,13 +1646,23 @@ { {"log_destination", PGC_POSTMASTER, LOGGING_WHERE, gettext_noop("Sets the target for log output."), - gettext_noop("Valid values are combinations of stderr, syslog " + gettext_noop("Valid values are combinations of stderr, file, syslog " "and eventlog, depending on platform."), GUC_LIST_INPUT | GUC_REPORT }, &log_destination_string, "stderr", assign_log_destination, NULL }, + { + {"log_filename", PGC_POSTMASTER, LOGGING_WHERE, + gettext_noop("Sets the target filename for log output."), + gettext_noop("May be specified as relative to the cluster directory " + "or as absolute path."), + GUC_LIST_INPUT | GUC_REPORT + }, + &Log_filename, + "postgresql.log", NULL, NULL + }, #ifdef HAVE_SYSLOG { @@ -4775,6 +4787,8 @@ if (pg_strcasecmp(tok,"stderr") == 0) newlogdest |= LOG_DESTINATION_STDERR; + else if (pg_strcasecmp(tok,"file") == 0) + newlogdest |= LOG_DESTINATION_FILE; #ifdef HAVE_SYSLOG else if (pg_strcasecmp(tok,"syslog") == 0) newlogdest |= LOG_DESTINATION_SYSLOG; Index: backend/utils/misc/postgresql.conf.sample =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/misc/postgresql.conf.sample,v retrieving revision 1.113 diff -u -r1.113 postgresql.conf.sample --- backend/utils/misc/postgresql.conf.sample 7 Apr 2004 05:05:50 -0000 1.113 +++ backend/utils/misc/postgresql.conf.sample 8 Jun 2004 18:07:48 -0000 @@ -147,9 +147,10 @@ # - Where to Log - -#log_destination = 'stderr' # Valid values are combinations of stderr, +#log_destination = 'stderr' # Valid values are combinations of stderr, file, # syslog and eventlog, depending on # platform. +#log_filename = 'pgsql.log' #syslog_facility = 'LOCAL0' #syslog_ident = 'postgres' Index: include/catalog/pg_proc.h =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/include/catalog/pg_proc.h,v retrieving revision 1.334 diff -u -r1.334 pg_proc.h --- include/catalog/pg_proc.h 2 Jun 2004 21:29:29 -0000 1.334 +++ include/catalog/pg_proc.h 8 Jun 2004 18:08:03 -0000 @@ -3588,6 +3588,12 @@ DATA(insert OID = 2243 ( bit_or PGNSP PGUID 12 t f f f i 1 1560 "1560" _null_ aggregate_dummy- _null_)); DESCR("bitwise-or bit aggregate"); +DATA(insert OID = 2550( pg_logfile_length PGNSP PGUID 12 f f f f v 0 23 "" _null_ pg_logfile_length - _null_)); +DESCR("length of log file"); +DATA(insert OID = 2551( pg_logfile PGNSP PGUID 12 f f f f v 2 2275 "23 23" _null_ pg_logfile - _null_)); +DESCR("return log file contents"); + + /* * Symbolic values for provolatile column: these indicate whether the result * of a function is dependent *only* on the values of its explicit arguments, Index: include/utils/builtins.h =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/include/utils/builtins.h,v retrieving revision 1.241 diff -u -r1.241 builtins.h --- include/utils/builtins.h 2 Jun 2004 21:29:29 -0000 1.241 +++ include/utils/builtins.h 8 Jun 2004 18:08:05 -0000 @@ -356,6 +356,8 @@ extern Datum current_database(PG_FUNCTION_ARGS); extern Datum pg_terminate_backend(PG_FUNCTION_ARGS); extern Datum pg_cancel_backend(PG_FUNCTION_ARGS); +extern Datum pg_logfile_length(PG_FUNCTION_ARGS); +extern Datum pg_logfile(PG_FUNCTION_ARGS); /* not_in.c */ extern Datum int4notin(PG_FUNCTION_ARGS); Index: include/utils/elog.h =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/include/utils/elog.h,v retrieving revision 1.68 diff -u -r1.68 elog.h --- include/utils/elog.h 5 Apr 2004 03:02:10 -0000 1.68 +++ include/utils/elog.h 8 Jun 2004 18:08:06 -0000 @@ -182,8 +182,12 @@ #define LOG_DESTINATION_STDERR 1 #define LOG_DESTINATION_SYSLOG 2 #define LOG_DESTINATION_EVENTLOG 4 +#define LOG_DESTINATION_FILE 8 /* Other exported functions */ extern void DebugFileOpen(void); +extern char *LogFileName(void); +extern void LogFileOpen(void); +extern void LogFileClose(void); #endif /* ELOG_H */
Looks good to me. The only issue I saw was that the default file name mentioned in postgresql.conf doesn't match the actual default. Is this ready to be added to the patch queue? --------------------------------------------------------------------------- Andreas Pflug wrote: > Magnus Hagander wrote: > > >Specifically about the logs, I still think there is a lot of value to > >being able to read the logs remotely even if you can't restart > >postmaster. > > > Since I believe that retrieving the logs easily without server file > access is a feature that's welcomed by many users, here's my proposal. > > The attached diff will > - add a guc-variable log_filename > - extend log_destination to accept the keyword 'file' > - elog to that file if configured > - provide two functions pg_logfile_length() and pg_logfile to obtain the > contents. > > int4 pg_logfile_length() > cstring pg_logfile(int4 size, int4 position) > size (may be null meaning max) is the chunk size (max: currently 50000) > position (may be null meaning -size) is the start position; positive > counting from log file start, negative from end. > > > Regards, > Andreas > > Index: backend/postmaster/postmaster.c > =================================================================== > RCS file: /projects/cvsroot/pgsql-server/src/backend/postmaster/postmaster.c,v > retrieving revision 1.402 > diff -u -r1.402 postmaster.c > --- backend/postmaster/postmaster.c 3 Jun 2004 02:08:03 -0000 1.402 > +++ backend/postmaster/postmaster.c 8 Jun 2004 18:07:30 -0000 > @@ -532,6 +532,9 @@ > /* If timezone is not set, determine what the OS uses */ > pg_timezone_initialize(); > > + /* open alternate logfile, if any */ > + LogFileOpen(); > + > #ifdef EXEC_BACKEND > write_nondefault_variables(PGC_POSTMASTER); > #endif > Index: backend/storage/ipc/ipc.c > =================================================================== > RCS file: /projects/cvsroot/pgsql-server/src/backend/storage/ipc/ipc.c,v > retrieving revision 1.87 > diff -u -r1.87 ipc.c > --- backend/storage/ipc/ipc.c 12 Dec 2003 18:45:09 -0000 1.87 > +++ backend/storage/ipc/ipc.c 8 Jun 2004 18:07:31 -0000 > @@ -111,6 +111,8 @@ > on_proc_exit_list[on_proc_exit_index].arg); > > elog(DEBUG3, "exit(%d)", code); > + > + LogFileClose(); > exit(code); > } > > Index: backend/utils/adt/misc.c > =================================================================== > RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/adt/misc.c,v > retrieving revision 1.34 > diff -u -r1.34 misc.c > --- backend/utils/adt/misc.c 2 Jun 2004 21:29:29 -0000 1.34 > +++ backend/utils/adt/misc.c 8 Jun 2004 18:07:36 -0000 > @@ -103,3 +103,64 @@ > { > PG_RETURN_INT32(pg_signal_backend(PG_GETARG_INT32(0),SIGINT)); > } > + > +Datum pg_logfile_length(PG_FUNCTION_ARGS) > +{ > + extern FILE *logfile; // in elog.c > + > + if (logfile) > + PG_RETURN_INT32(ftell(logfile)); > + PG_RETURN_INT32(0); > +} > + > + > +#define MAXLOGFILECHUNK 50000 > +Datum pg_logfile(PG_FUNCTION_ARGS) > +{ > + size_t size=MAXLOGFILECHUNK; > + char *buf=0; > + size_t nbytes; > + > + char *filename = LogFileName(); > + if (filename) > + { > + if (!PG_ARGISNULL(0)) > + size = PG_GETARG_INT32(0); > + if (size > MAXLOGFILECHUNK) > + { > + size = MAXLOGFILECHUNK; > + ereport(WARNING, > + (errcode(ERRCODE_OUT_OF_MEMORY), > + errmsg("Maximum size is %d.", MAXLOGFILECHUNK))); > + } > + > + FILE *f=fopen(filename, "r"); > + if (f) > + { > + if (PG_ARGISNULL(1)) > + fseek(f, -size, SEEK_END); > + else > + { > + long pos = PG_GETARG_INT32(1); > + if (pos >= 0) > + fseek(f, pos, SEEK_SET); > + else > + fseek(f, pos, SEEK_END); > + } > + buf = palloc(size+1); > + nbytes = fread(buf, 1, size, f); > + buf[nbytes] = 0; > + > + fclose(f); > + } > + else > + { > + ereport(WARNING, > + (errcode(ERRCODE_NO_DATA), > + errmsg("Could not open log file %s.", filename))); > + } > + free(filename); > + } > + > + PG_RETURN_CSTRING(buf); > +} > Index: backend/utils/error/elog.c > =================================================================== > RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/error/elog.c,v > retrieving revision 1.140 > diff -u -r1.140 elog.c > --- backend/utils/error/elog.c 3 Jun 2004 02:08:04 -0000 1.140 > +++ backend/utils/error/elog.c 8 Jun 2004 18:07:39 -0000 > @@ -71,8 +71,10 @@ > PGErrorVerbosity Log_error_verbosity = PGERROR_VERBOSE; > char *Log_line_prefix = NULL; /* format for extra log line info */ > unsigned int Log_destination = LOG_DESTINATION_STDERR; > +char *Log_filename = NULL; > > bool in_fatal_exit = false; > +FILE *logfile = NULL; > > #ifdef HAVE_SYSLOG > char *Syslog_facility; /* openlog() parameters */ > @@ -936,6 +938,69 @@ > > > /* > + * Name of configured log file, or NULL > + * must be freed after usage > + */ > +char* > +LogFileName(void) > +{ > + if (Log_filename && (Log_destination & LOG_DESTINATION_FILE)) > + { > + if (is_absolute_path(Log_filename)) > + return strdup(Log_filename); > + else > + { > + char *buf = malloc(strlen(DataDir) + strlen(Log_filename) +2); > + if (!buf) > + ereport(FATAL, > + (errcode(ERRCODE_OUT_OF_MEMORY), > + errmsg("out of memory"))); > + > + sprintf(buf, "%s/%s", DataDir, Log_filename); > + > + return buf; > + } > + } > + return NULL; > +} > + > + > +/* > + * Open log file, if configured. > + */ > +void > +LogFileOpen(void) > +{ > + char *filename = LogFileName(); > + > + if (filename) > + { > + LogFileClose(); > + > + logfile = fopen(filename, "at"); > + > + if (!logfile) > + ereport(WARNING, > + (errcode(ERRCODE_CONFIG_FILE_ERROR), > + errmsg("could not open log file %s", filename))); > + > + free(filename); > + } > +} > + > + > +/* > + * Close log file, if open. > + */ > +void > +LogFileClose(void) > +{ > + if (logfile) > + fclose(logfile); > + logfile = NULL; > +} > + > +/* > * Initialization of error output file > */ > void > @@ -1445,6 +1510,11 @@ > if ((Log_destination & LOG_DESTINATION_STDERR) || whereToSendOutput == Debug) > { > fprintf(stderr, "%s", buf.data); > + } > + > + if (logfile && (Log_destination & LOG_DESTINATION_FILE)) > + { > + fprintf(logfile, "%s", buf.data); > } > > pfree(buf.data); > Index: backend/utils/misc/guc.c > =================================================================== > RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/misc/guc.c,v > retrieving revision 1.210 > diff -u -r1.210 guc.c > --- backend/utils/misc/guc.c 30 May 2004 23:40:38 -0000 1.210 > +++ backend/utils/misc/guc.c 8 Jun 2004 18:07:47 -0000 > @@ -76,6 +76,8 @@ > static const char *assign_log_destination(const char *value, > bool doit, GucSource source); > > +extern char *Log_filename; > + > #ifdef HAVE_SYSLOG > extern char *Syslog_facility; > extern char *Syslog_ident; > @@ -1644,13 +1646,23 @@ > { > {"log_destination", PGC_POSTMASTER, LOGGING_WHERE, > gettext_noop("Sets the target for log output."), > - gettext_noop("Valid values are combinations of stderr, syslog " > + gettext_noop("Valid values are combinations of stderr, file, syslog " > "and eventlog, depending on platform."), > GUC_LIST_INPUT | GUC_REPORT > }, > &log_destination_string, > "stderr", assign_log_destination, NULL > }, > + { > + {"log_filename", PGC_POSTMASTER, LOGGING_WHERE, > + gettext_noop("Sets the target filename for log output."), > + gettext_noop("May be specified as relative to the cluster directory " > + "or as absolute path."), > + GUC_LIST_INPUT | GUC_REPORT > + }, > + &Log_filename, > + "postgresql.log", NULL, NULL > + }, > > #ifdef HAVE_SYSLOG > { > @@ -4775,6 +4787,8 @@ > > if (pg_strcasecmp(tok,"stderr") == 0) > newlogdest |= LOG_DESTINATION_STDERR; > + else if (pg_strcasecmp(tok,"file") == 0) > + newlogdest |= LOG_DESTINATION_FILE; > #ifdef HAVE_SYSLOG > else if (pg_strcasecmp(tok,"syslog") == 0) > newlogdest |= LOG_DESTINATION_SYSLOG; > Index: backend/utils/misc/postgresql.conf.sample > =================================================================== > RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/misc/postgresql.conf.sample,v > retrieving revision 1.113 > diff -u -r1.113 postgresql.conf.sample > --- backend/utils/misc/postgresql.conf.sample 7 Apr 2004 05:05:50 -0000 1.113 > +++ backend/utils/misc/postgresql.conf.sample 8 Jun 2004 18:07:48 -0000 > @@ -147,9 +147,10 @@ > > # - Where to Log - > > -#log_destination = 'stderr' # Valid values are combinations of stderr, > +#log_destination = 'stderr' # Valid values are combinations of stderr, file, > # syslog and eventlog, depending on > # platform. > +#log_filename = 'pgsql.log' > #syslog_facility = 'LOCAL0' > #syslog_ident = 'postgres' > > Index: include/catalog/pg_proc.h > =================================================================== > RCS file: /projects/cvsroot/pgsql-server/src/include/catalog/pg_proc.h,v > retrieving revision 1.334 > diff -u -r1.334 pg_proc.h > --- include/catalog/pg_proc.h 2 Jun 2004 21:29:29 -0000 1.334 > +++ include/catalog/pg_proc.h 8 Jun 2004 18:08:03 -0000 > @@ -3588,6 +3588,12 @@ > DATA(insert OID = 2243 ( bit_or PGNSP PGUID 12 t f f f i 1 1560 "1560" _null_ aggregate_dummy- _null_)); > DESCR("bitwise-or bit aggregate"); > > +DATA(insert OID = 2550( pg_logfile_length PGNSP PGUID 12 f f f f v 0 23 "" _null_ pg_logfile_length - _null_)); > +DESCR("length of log file"); > +DATA(insert OID = 2551( pg_logfile PGNSP PGUID 12 f f f f v 2 2275 "23 23" _null_ pg_logfile -_null_ )); > +DESCR("return log file contents"); > + > + > /* > * Symbolic values for provolatile column: these indicate whether the result > * of a function is dependent *only* on the values of its explicit arguments, > Index: include/utils/builtins.h > =================================================================== > RCS file: /projects/cvsroot/pgsql-server/src/include/utils/builtins.h,v > retrieving revision 1.241 > diff -u -r1.241 builtins.h > --- include/utils/builtins.h 2 Jun 2004 21:29:29 -0000 1.241 > +++ include/utils/builtins.h 8 Jun 2004 18:08:05 -0000 > @@ -356,6 +356,8 @@ > extern Datum current_database(PG_FUNCTION_ARGS); > extern Datum pg_terminate_backend(PG_FUNCTION_ARGS); > extern Datum pg_cancel_backend(PG_FUNCTION_ARGS); > +extern Datum pg_logfile_length(PG_FUNCTION_ARGS); > +extern Datum pg_logfile(PG_FUNCTION_ARGS); > > /* not_in.c */ > extern Datum int4notin(PG_FUNCTION_ARGS); > Index: include/utils/elog.h > =================================================================== > RCS file: /projects/cvsroot/pgsql-server/src/include/utils/elog.h,v > retrieving revision 1.68 > diff -u -r1.68 elog.h > --- include/utils/elog.h 5 Apr 2004 03:02:10 -0000 1.68 > +++ include/utils/elog.h 8 Jun 2004 18:08:06 -0000 > @@ -182,8 +182,12 @@ > #define LOG_DESTINATION_STDERR 1 > #define LOG_DESTINATION_SYSLOG 2 > #define LOG_DESTINATION_EVENTLOG 4 > +#define LOG_DESTINATION_FILE 8 > > /* Other exported functions */ > extern void DebugFileOpen(void); > +extern char *LogFileName(void); > +extern void LogFileOpen(void); > +extern void LogFileClose(void); > > #endif /* ELOG_H */ > > ---------------------------(end of broadcast)--------------------------- > TIP 7: don't forget to increase your free space map settings -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073
Oh, it would need doc additions. I can do that when I apply, or you can resubmit. --------------------------------------------------------------------------- Andreas Pflug wrote: > Magnus Hagander wrote: > > >Specifically about the logs, I still think there is a lot of value to > >being able to read the logs remotely even if you can't restart > >postmaster. > > > Since I believe that retrieving the logs easily without server file > access is a feature that's welcomed by many users, here's my proposal. > > The attached diff will > - add a guc-variable log_filename > - extend log_destination to accept the keyword 'file' > - elog to that file if configured > - provide two functions pg_logfile_length() and pg_logfile to obtain the > contents. > > int4 pg_logfile_length() > cstring pg_logfile(int4 size, int4 position) > size (may be null meaning max) is the chunk size (max: currently 50000) > position (may be null meaning -size) is the start position; positive > counting from log file start, negative from end. > > > Regards, > Andreas > > Index: backend/postmaster/postmaster.c > =================================================================== > RCS file: /projects/cvsroot/pgsql-server/src/backend/postmaster/postmaster.c,v > retrieving revision 1.402 > diff -u -r1.402 postmaster.c > --- backend/postmaster/postmaster.c 3 Jun 2004 02:08:03 -0000 1.402 > +++ backend/postmaster/postmaster.c 8 Jun 2004 18:07:30 -0000 > @@ -532,6 +532,9 @@ > /* If timezone is not set, determine what the OS uses */ > pg_timezone_initialize(); > > + /* open alternate logfile, if any */ > + LogFileOpen(); > + > #ifdef EXEC_BACKEND > write_nondefault_variables(PGC_POSTMASTER); > #endif > Index: backend/storage/ipc/ipc.c > =================================================================== > RCS file: /projects/cvsroot/pgsql-server/src/backend/storage/ipc/ipc.c,v > retrieving revision 1.87 > diff -u -r1.87 ipc.c > --- backend/storage/ipc/ipc.c 12 Dec 2003 18:45:09 -0000 1.87 > +++ backend/storage/ipc/ipc.c 8 Jun 2004 18:07:31 -0000 > @@ -111,6 +111,8 @@ > on_proc_exit_list[on_proc_exit_index].arg); > > elog(DEBUG3, "exit(%d)", code); > + > + LogFileClose(); > exit(code); > } > > Index: backend/utils/adt/misc.c > =================================================================== > RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/adt/misc.c,v > retrieving revision 1.34 > diff -u -r1.34 misc.c > --- backend/utils/adt/misc.c 2 Jun 2004 21:29:29 -0000 1.34 > +++ backend/utils/adt/misc.c 8 Jun 2004 18:07:36 -0000 > @@ -103,3 +103,64 @@ > { > PG_RETURN_INT32(pg_signal_backend(PG_GETARG_INT32(0),SIGINT)); > } > + > +Datum pg_logfile_length(PG_FUNCTION_ARGS) > +{ > + extern FILE *logfile; // in elog.c > + > + if (logfile) > + PG_RETURN_INT32(ftell(logfile)); > + PG_RETURN_INT32(0); > +} > + > + > +#define MAXLOGFILECHUNK 50000 > +Datum pg_logfile(PG_FUNCTION_ARGS) > +{ > + size_t size=MAXLOGFILECHUNK; > + char *buf=0; > + size_t nbytes; > + > + char *filename = LogFileName(); > + if (filename) > + { > + if (!PG_ARGISNULL(0)) > + size = PG_GETARG_INT32(0); > + if (size > MAXLOGFILECHUNK) > + { > + size = MAXLOGFILECHUNK; > + ereport(WARNING, > + (errcode(ERRCODE_OUT_OF_MEMORY), > + errmsg("Maximum size is %d.", MAXLOGFILECHUNK))); > + } > + > + FILE *f=fopen(filename, "r"); > + if (f) > + { > + if (PG_ARGISNULL(1)) > + fseek(f, -size, SEEK_END); > + else > + { > + long pos = PG_GETARG_INT32(1); > + if (pos >= 0) > + fseek(f, pos, SEEK_SET); > + else > + fseek(f, pos, SEEK_END); > + } > + buf = palloc(size+1); > + nbytes = fread(buf, 1, size, f); > + buf[nbytes] = 0; > + > + fclose(f); > + } > + else > + { > + ereport(WARNING, > + (errcode(ERRCODE_NO_DATA), > + errmsg("Could not open log file %s.", filename))); > + } > + free(filename); > + } > + > + PG_RETURN_CSTRING(buf); > +} > Index: backend/utils/error/elog.c > =================================================================== > RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/error/elog.c,v > retrieving revision 1.140 > diff -u -r1.140 elog.c > --- backend/utils/error/elog.c 3 Jun 2004 02:08:04 -0000 1.140 > +++ backend/utils/error/elog.c 8 Jun 2004 18:07:39 -0000 > @@ -71,8 +71,10 @@ > PGErrorVerbosity Log_error_verbosity = PGERROR_VERBOSE; > char *Log_line_prefix = NULL; /* format for extra log line info */ > unsigned int Log_destination = LOG_DESTINATION_STDERR; > +char *Log_filename = NULL; > > bool in_fatal_exit = false; > +FILE *logfile = NULL; > > #ifdef HAVE_SYSLOG > char *Syslog_facility; /* openlog() parameters */ > @@ -936,6 +938,69 @@ > > > /* > + * Name of configured log file, or NULL > + * must be freed after usage > + */ > +char* > +LogFileName(void) > +{ > + if (Log_filename && (Log_destination & LOG_DESTINATION_FILE)) > + { > + if (is_absolute_path(Log_filename)) > + return strdup(Log_filename); > + else > + { > + char *buf = malloc(strlen(DataDir) + strlen(Log_filename) +2); > + if (!buf) > + ereport(FATAL, > + (errcode(ERRCODE_OUT_OF_MEMORY), > + errmsg("out of memory"))); > + > + sprintf(buf, "%s/%s", DataDir, Log_filename); > + > + return buf; > + } > + } > + return NULL; > +} > + > + > +/* > + * Open log file, if configured. > + */ > +void > +LogFileOpen(void) > +{ > + char *filename = LogFileName(); > + > + if (filename) > + { > + LogFileClose(); > + > + logfile = fopen(filename, "at"); > + > + if (!logfile) > + ereport(WARNING, > + (errcode(ERRCODE_CONFIG_FILE_ERROR), > + errmsg("could not open log file %s", filename))); > + > + free(filename); > + } > +} > + > + > +/* > + * Close log file, if open. > + */ > +void > +LogFileClose(void) > +{ > + if (logfile) > + fclose(logfile); > + logfile = NULL; > +} > + > +/* > * Initialization of error output file > */ > void > @@ -1445,6 +1510,11 @@ > if ((Log_destination & LOG_DESTINATION_STDERR) || whereToSendOutput == Debug) > { > fprintf(stderr, "%s", buf.data); > + } > + > + if (logfile && (Log_destination & LOG_DESTINATION_FILE)) > + { > + fprintf(logfile, "%s", buf.data); > } > > pfree(buf.data); > Index: backend/utils/misc/guc.c > =================================================================== > RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/misc/guc.c,v > retrieving revision 1.210 > diff -u -r1.210 guc.c > --- backend/utils/misc/guc.c 30 May 2004 23:40:38 -0000 1.210 > +++ backend/utils/misc/guc.c 8 Jun 2004 18:07:47 -0000 > @@ -76,6 +76,8 @@ > static const char *assign_log_destination(const char *value, > bool doit, GucSource source); > > +extern char *Log_filename; > + > #ifdef HAVE_SYSLOG > extern char *Syslog_facility; > extern char *Syslog_ident; > @@ -1644,13 +1646,23 @@ > { > {"log_destination", PGC_POSTMASTER, LOGGING_WHERE, > gettext_noop("Sets the target for log output."), > - gettext_noop("Valid values are combinations of stderr, syslog " > + gettext_noop("Valid values are combinations of stderr, file, syslog " > "and eventlog, depending on platform."), > GUC_LIST_INPUT | GUC_REPORT > }, > &log_destination_string, > "stderr", assign_log_destination, NULL > }, > + { > + {"log_filename", PGC_POSTMASTER, LOGGING_WHERE, > + gettext_noop("Sets the target filename for log output."), > + gettext_noop("May be specified as relative to the cluster directory " > + "or as absolute path."), > + GUC_LIST_INPUT | GUC_REPORT > + }, > + &Log_filename, > + "postgresql.log", NULL, NULL > + }, > > #ifdef HAVE_SYSLOG > { > @@ -4775,6 +4787,8 @@ > > if (pg_strcasecmp(tok,"stderr") == 0) > newlogdest |= LOG_DESTINATION_STDERR; > + else if (pg_strcasecmp(tok,"file") == 0) > + newlogdest |= LOG_DESTINATION_FILE; > #ifdef HAVE_SYSLOG > else if (pg_strcasecmp(tok,"syslog") == 0) > newlogdest |= LOG_DESTINATION_SYSLOG; > Index: backend/utils/misc/postgresql.conf.sample > =================================================================== > RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/misc/postgresql.conf.sample,v > retrieving revision 1.113 > diff -u -r1.113 postgresql.conf.sample > --- backend/utils/misc/postgresql.conf.sample 7 Apr 2004 05:05:50 -0000 1.113 > +++ backend/utils/misc/postgresql.conf.sample 8 Jun 2004 18:07:48 -0000 > @@ -147,9 +147,10 @@ > > # - Where to Log - > > -#log_destination = 'stderr' # Valid values are combinations of stderr, > +#log_destination = 'stderr' # Valid values are combinations of stderr, file, > # syslog and eventlog, depending on > # platform. > +#log_filename = 'pgsql.log' > #syslog_facility = 'LOCAL0' > #syslog_ident = 'postgres' > > Index: include/catalog/pg_proc.h > =================================================================== > RCS file: /projects/cvsroot/pgsql-server/src/include/catalog/pg_proc.h,v > retrieving revision 1.334 > diff -u -r1.334 pg_proc.h > --- include/catalog/pg_proc.h 2 Jun 2004 21:29:29 -0000 1.334 > +++ include/catalog/pg_proc.h 8 Jun 2004 18:08:03 -0000 > @@ -3588,6 +3588,12 @@ > DATA(insert OID = 2243 ( bit_or PGNSP PGUID 12 t f f f i 1 1560 "1560" _null_ aggregate_dummy- _null_)); > DESCR("bitwise-or bit aggregate"); > > +DATA(insert OID = 2550( pg_logfile_length PGNSP PGUID 12 f f f f v 0 23 "" _null_ pg_logfile_length - _null_)); > +DESCR("length of log file"); > +DATA(insert OID = 2551( pg_logfile PGNSP PGUID 12 f f f f v 2 2275 "23 23" _null_ pg_logfile -_null_ )); > +DESCR("return log file contents"); > + > + > /* > * Symbolic values for provolatile column: these indicate whether the result > * of a function is dependent *only* on the values of its explicit arguments, > Index: include/utils/builtins.h > =================================================================== > RCS file: /projects/cvsroot/pgsql-server/src/include/utils/builtins.h,v > retrieving revision 1.241 > diff -u -r1.241 builtins.h > --- include/utils/builtins.h 2 Jun 2004 21:29:29 -0000 1.241 > +++ include/utils/builtins.h 8 Jun 2004 18:08:05 -0000 > @@ -356,6 +356,8 @@ > extern Datum current_database(PG_FUNCTION_ARGS); > extern Datum pg_terminate_backend(PG_FUNCTION_ARGS); > extern Datum pg_cancel_backend(PG_FUNCTION_ARGS); > +extern Datum pg_logfile_length(PG_FUNCTION_ARGS); > +extern Datum pg_logfile(PG_FUNCTION_ARGS); > > /* not_in.c */ > extern Datum int4notin(PG_FUNCTION_ARGS); > Index: include/utils/elog.h > =================================================================== > RCS file: /projects/cvsroot/pgsql-server/src/include/utils/elog.h,v > retrieving revision 1.68 > diff -u -r1.68 elog.h > --- include/utils/elog.h 5 Apr 2004 03:02:10 -0000 1.68 > +++ include/utils/elog.h 8 Jun 2004 18:08:06 -0000 > @@ -182,8 +182,12 @@ > #define LOG_DESTINATION_STDERR 1 > #define LOG_DESTINATION_SYSLOG 2 > #define LOG_DESTINATION_EVENTLOG 4 > +#define LOG_DESTINATION_FILE 8 > > /* Other exported functions */ > extern void DebugFileOpen(void); > +extern char *LogFileName(void); > +extern void LogFileOpen(void); > +extern void LogFileClose(void); > > #endif /* ELOG_H */ > > ---------------------------(end of broadcast)--------------------------- > TIP 7: don't forget to increase your free space map settings -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073
Bruce Momjian <pgman@candle.pha.pa.us> writes: > Looks good to me. The only issue I saw was that the default file name > mentioned in postgresql.conf doesn't match the actual default. I'm really not happy with the concept that the postmaster overrides its stderr direction. regards, tom lane
Tom Lane wrote: >Bruce Momjian <pgman@candle.pha.pa.us> writes: > > >>Looks good to me. The only issue I saw was that the default file name >>mentioned in postgresql.conf doesn't match the actual default. >> >> > >I'm really not happy with the concept that the postmaster overrides >its stderr direction. > > > I agree, that's why I implemented it as *additional* log_destination. Regards, Andreas
Andreas Pflug wrote: > Tom Lane wrote: > > >Bruce Momjian <pgman@candle.pha.pa.us> writes: > > > > > >>Looks good to me. The only issue I saw was that the default file name > >>mentioned in postgresql.conf doesn't match the actual default. > >> > >> > > > >I'm really not happy with the concept that the postmaster overrides > >its stderr direction. > > > > > > > I agree, that's why I implemented it as *additional* log_destination. One idea would be to send a message to stderr when this option is used stating that everything is going to 'filename'. Also can we close/reopen the file on SIGHUP. My guess is we can't because of all the backends accessing the output file. -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073
Sorry I didn't get back on this earlier, yesterday morning my internet access was literally struck by lightning, I'm running temporary hardware now. Bruce Momjian wrote: >>>>Looks good to me. The only issue I saw was that the default file name >>>>mentioned in postgresql.conf doesn't match the actual default. >>>> >>>> I'll fix the default filename difference, postgresql.log seems best. I'll add doc too. >One idea would be to send a message to stderr when this option is used >stating that everything is going to 'filename'. > > I can ereport LogFileOpen and LogFileClose, do we need this? Currently, only open problems will be reported. >Also can we close/reopen the file on SIGHUP. My guess is we can't >because of all the backends accessing the output file. > > I'd also like it flushed in pg_logfile and pg_logfile_length, same problem; any hints welcome. Regards, Andreas
Andreas Pflug wrote: > Sorry I didn't get back on this earlier, yesterday morning my internet > access was literally struck by lightning, I'm running temporary hardware > now. > > Bruce Momjian wrote: > > >>>>Looks good to me. The only issue I saw was that the default file name > >>>>mentioned in postgresql.conf doesn't match the actual default. > >>>> > >>>> > > I'll fix the default filename difference, postgresql.log seems best. > I'll add doc too. > > >One idea would be to send a message to stderr when this option is used > >stating that everything is going to 'filename'. > > > > > I can ereport LogFileOpen and LogFileClose, do we need this? Currently, > only open problems will be reported. Actually, my idea of sending a message to stderr saying we are using a pre-configured file is so folks aren't surprised by the fact they can't see any stderr anymore. But doesn't syslog have the same issue. Maybe not, and that's why we need a message like: "All standard output and standard error are going to postgresql.conf" and send that to the processes standard error. > > >Also can we close/reopen the file on SIGHUP. My guess is we can't > >because of all the backends accessing the output file. > > > > > I'd also like it flushed in pg_logfile and pg_logfile_length, same > problem; any hints welcome. I don't understand this. I was thinking of close/reopen so log files could be rotated. -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073
Bruce Momjian <pgman@candle.pha.pa.us> writes: > Actually, my idea of sending a message to stderr saying we are using a > pre-configured file is so folks aren't surprised by the fact they can't > see any stderr anymore. Hm? I thought we'd just established that the patch wasn't going to suppress output to stderr. regards, tom lane
Tom Lane wrote: > Bruce Momjian <pgman@candle.pha.pa.us> writes: > > Actually, my idea of sending a message to stderr saying we are using a > > pre-configured file is so folks aren't surprised by the fact they can't > > see any stderr anymore. > > Hm? I thought we'd just established that the patch wasn't going to > suppress output to stderr. Oh, I didn't see that. -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073
Bruce Momjian wrote: >I was thinking of close/reopen so log files >could be rotated. > > > Log file rotation is fine, if we find a consensus quite soon how to implement it... Seems as if I might find some time to implement it until feature freeze. The attached patch has the default filename issue fixed, and documentation. Since I don't have a doc build system functional, there might be tag mismatches or other typos; please check. IMHO this should be committed without waiting for log rotation stuff. Regards, Andreas Index: doc/src/sgml/func.sgml =================================================================== RCS file: /projects/cvsroot/pgsql-server/doc/src/sgml/func.sgml,v retrieving revision 1.206 diff -u -r1.206 func.sgml --- doc/src/sgml/func.sgml 2 Jun 2004 21:34:49 -0000 1.206 +++ doc/src/sgml/func.sgml 11 Jun 2004 17:58:35 -0000 @@ -7308,6 +7308,53 @@ columns do not have OIDs of their own. </para> + <indexterm zone="functions-misc"> + <primary>pg_logfile</primary> + </indexterm> + <indexterm zone="functions-misc"> + <primary>pg_logfile_length</primary> + </indexterm> + <para> + The functions shown in <xref linkend="functions-misc-logfile"> + deal with the server log file if configured with log_destination + <quote>file</quote>. + previously stored with the <command>COMMENT</command> command. A + null value is returned if no comment could be found matching the + specified parameters. + </para> + + <table id="functions-misc-logfile"> + <title>Server Logfile Functions</title> + <tgroup cols="3"> + <thead> + <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry></row> + </thead> + + <tbody> + <row> + <entry><literal><function>pg_logfile</function>(<parameter>size_int4</parameter>, <parameter>offset_int4</parameter>)</literal></entry> + <entry><type>cstring</type></entry> + <entry>get a part of the server log file</entry> + </row> + <row> + <entry><literal><function>pg_logfile_length</function>()</literal></entry> + <entry><type>int4</type></entry> + <entry>return the current length of the server log file</entry> + </row> + </tbody> +</tgroup> +</table> +<para> +The <function>pg_logfile</function> function will return the + contents of the server log file, limited by the size + parameter. If size is NULL, a server internal limit (currently + 50000) is applied. The position parameter determines the + starting position of the server log chunk to be returned. A + positive number or 0 will be counted from the start of the file, + a negative number from the end; if NULL, -size is assumed + (i.e. the tail of the log file). +</para> + </sect1> <sect1 id="functions-array"> Index: doc/src/sgml/runtime.sgml =================================================================== RCS file: /projects/cvsroot/pgsql-server/doc/src/sgml/runtime.sgml,v retrieving revision 1.266 diff -u -r1.266 runtime.sgml --- doc/src/sgml/runtime.sgml 10 Jun 2004 22:26:17 -0000 1.266 +++ doc/src/sgml/runtime.sgml 11 Jun 2004 17:58:46 -0000 @@ -1721,14 +1721,25 @@ <listitem> <para> <productname>PostgreSQL</productname> supports several methods - for loggning, including <systemitem>stderr</systemitem> and - <systemitem>syslog</systemitem>. On Windows, - <systemitem>eventlog</systemitem> is also supported. Set this + for logging, including <systemitem>stderr</systemitem>, + <systemitem>file</systemitem> and <systemitem>syslog</systemitem>. + On Windows, <systemitem>eventlog</systemitem> is also supported. Set this option to a list of desired log destinations separated by a comma. The default is to log to <systemitem>stderr</systemitem> only. This option must be set at server start. </para> </listitem> + </varlistentry> + + <varlistentry id="guc-syslog-facility" xreflabel="log_filename"> + <term><varname>log_filename</varname> (<type>string</type>)</term> + <listitem> + <para> + This option sets the target filename for the log destination + <quote>file</quote> option. It may be specified as absolute + path or relative to the <application>cluster directory</application>. + </para> + </listitem> </varlistentry> <varlistentry id="guc-syslog-facility" xreflabel="syslog_facility"> Index: src/backend/postmaster/postmaster.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/postmaster/postmaster.c,v retrieving revision 1.403 diff -u -r1.403 postmaster.c --- src/backend/postmaster/postmaster.c 11 Jun 2004 03:54:43 -0000 1.403 +++ src/backend/postmaster/postmaster.c 11 Jun 2004 17:58:52 -0000 @@ -532,6 +532,9 @@ /* If timezone is not set, determine what the OS uses */ pg_timezone_initialize(); + /* open alternate logfile, if any */ + LogFileOpen(); + #ifdef EXEC_BACKEND write_nondefault_variables(PGC_POSTMASTER); #endif Index: src/backend/storage/ipc/ipc.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/storage/ipc/ipc.c,v retrieving revision 1.87 diff -u -r1.87 ipc.c --- src/backend/storage/ipc/ipc.c 12 Dec 2003 18:45:09 -0000 1.87 +++ src/backend/storage/ipc/ipc.c 11 Jun 2004 17:58:52 -0000 @@ -111,6 +111,8 @@ on_proc_exit_list[on_proc_exit_index].arg); elog(DEBUG3, "exit(%d)", code); + + LogFileClose(); exit(code); } Index: src/backend/utils/adt/misc.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/adt/misc.c,v retrieving revision 1.34 diff -u -r1.34 misc.c --- src/backend/utils/adt/misc.c 2 Jun 2004 21:29:29 -0000 1.34 +++ src/backend/utils/adt/misc.c 11 Jun 2004 17:58:58 -0000 @@ -103,3 +103,70 @@ { PG_RETURN_INT32(pg_signal_backend(PG_GETARG_INT32(0),SIGINT)); } + +extern FILE *logfile; // in elog.c + +Datum pg_logfile_length(PG_FUNCTION_ARGS) +{ + if (logfile) + { + fflush(logfile); + PG_RETURN_INT32(ftell(logfile)); + } + PG_RETURN_INT32(0); +} + + +#define MAXLOGFILECHUNK 50000 +Datum pg_logfile(PG_FUNCTION_ARGS) +{ + size_t size=MAXLOGFILECHUNK; + char *buf=0; + size_t nbytes; + + char *filename = LogFileName(); + if (filename) + { + if (!PG_ARGISNULL(0)) + size = PG_GETARG_INT32(0); + if (size > MAXLOGFILECHUNK) + { + size = MAXLOGFILECHUNK; + ereport(WARNING, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("Maximum size is %d.", MAXLOGFILECHUNK))); + } + + FILE *f=fopen(filename, "rb"); + if (f) + { + if (logfile) + fflush(logfile); + + if (PG_ARGISNULL(1)) + fseek(f, -size, SEEK_END); + else + { + long pos = PG_GETARG_INT32(1); + if (pos >= 0) + fseek(f, pos, SEEK_SET); + else + fseek(f, pos, SEEK_END); + } + buf = palloc(size+1); + nbytes = fread(buf, 1, size, f); + buf[nbytes] = 0; + + fclose(f); + } + else + { + ereport(WARNING, + (errcode(ERRCODE_NO_DATA), + errmsg("Could not open log file %s.", filename))); + } + free(filename); + } + + PG_RETURN_CSTRING(buf); +} Index: src/backend/utils/error/elog.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/error/elog.c,v retrieving revision 1.140 diff -u -r1.140 elog.c --- src/backend/utils/error/elog.c 3 Jun 2004 02:08:04 -0000 1.140 +++ src/backend/utils/error/elog.c 11 Jun 2004 17:59:01 -0000 @@ -71,8 +71,10 @@ PGErrorVerbosity Log_error_verbosity = PGERROR_VERBOSE; char *Log_line_prefix = NULL; /* format for extra log line info */ unsigned int Log_destination = LOG_DESTINATION_STDERR; +char *Log_filename = NULL; bool in_fatal_exit = false; +FILE *logfile = NULL; #ifdef HAVE_SYSLOG char *Syslog_facility; /* openlog() parameters */ @@ -936,6 +938,69 @@ /* + * Name of configured log file, or NULL + * must be freed after usage + */ +char* +LogFileName(void) +{ + if (Log_filename && (Log_destination & LOG_DESTINATION_FILE)) + { + if (is_absolute_path(Log_filename)) + return strdup(Log_filename); + else + { + char *buf = malloc(strlen(DataDir) + strlen(Log_filename) +2); + if (!buf) + ereport(FATAL, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + + sprintf(buf, "%s/%s", DataDir, Log_filename); + + return buf; + } + } + return NULL; +} + + +/* + * Open log file, if configured. + */ +void +LogFileOpen(void) +{ + char *filename = LogFileName(); + + if (filename) + { + LogFileClose(); + + logfile = fopen(filename, "ab"); + + if (!logfile) + ereport(WARNING, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("could not open log file %s", filename))); + + free(filename); + } +} + + +/* + * Close log file, if open. + */ +void +LogFileClose(void) +{ + if (logfile) + fclose(logfile); + logfile = NULL; +} + +/* * Initialization of error output file */ void @@ -1445,6 +1510,11 @@ if ((Log_destination & LOG_DESTINATION_STDERR) || whereToSendOutput == Debug) { fprintf(stderr, "%s", buf.data); + } + + if (logfile && (Log_destination & LOG_DESTINATION_FILE)) + { + fprintf(logfile, "%s", buf.data); } pfree(buf.data); Index: src/backend/utils/misc/guc.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/misc/guc.c,v retrieving revision 1.211 diff -u -r1.211 guc.c --- src/backend/utils/misc/guc.c 11 Jun 2004 03:54:54 -0000 1.211 +++ src/backend/utils/misc/guc.c 11 Jun 2004 17:59:09 -0000 @@ -76,6 +76,8 @@ static const char *assign_log_destination(const char *value, bool doit, GucSource source); +extern char *Log_filename; + #ifdef HAVE_SYSLOG extern char *Syslog_facility; extern char *Syslog_ident; @@ -1644,13 +1646,23 @@ { {"log_destination", PGC_POSTMASTER, LOGGING_WHERE, gettext_noop("Sets the target for log output."), - gettext_noop("Valid values are combinations of stderr, syslog " + gettext_noop("Valid values are combinations of stderr, file, syslog " "and eventlog, depending on platform."), GUC_LIST_INPUT | GUC_REPORT }, &log_destination_string, "stderr", assign_log_destination, NULL }, + { + {"log_filename", PGC_POSTMASTER, LOGGING_WHERE, + gettext_noop("Sets the target filename for log output."), + gettext_noop("May be specified as relative to the cluster directory " + "or as absolute path."), + GUC_LIST_INPUT | GUC_REPORT + }, + &Log_filename, + "postgresql.log", NULL, NULL + }, #ifdef HAVE_SYSLOG { @@ -4779,6 +4791,8 @@ if (pg_strcasecmp(tok,"stderr") == 0) newlogdest |= LOG_DESTINATION_STDERR; + else if (pg_strcasecmp(tok,"file") == 0) + newlogdest |= LOG_DESTINATION_FILE; #ifdef HAVE_SYSLOG else if (pg_strcasecmp(tok,"syslog") == 0) newlogdest |= LOG_DESTINATION_SYSLOG; Index: src/backend/utils/misc/postgresql.conf.sample =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/misc/postgresql.conf.sample,v retrieving revision 1.113 diff -u -r1.113 postgresql.conf.sample --- src/backend/utils/misc/postgresql.conf.sample 7 Apr 2004 05:05:50 -0000 1.113 +++ src/backend/utils/misc/postgresql.conf.sample 11 Jun 2004 17:59:10 -0000 @@ -147,9 +147,10 @@ # - Where to Log - -#log_destination = 'stderr' # Valid values are combinations of stderr, +#log_destination = 'stderr' # Valid values are combinations of stderr, file, # syslog and eventlog, depending on # platform. +#log_filename = 'postgresql.log' #syslog_facility = 'LOCAL0' #syslog_ident = 'postgres' Index: src/include/catalog/pg_proc.h =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/include/catalog/pg_proc.h,v retrieving revision 1.335 diff -u -r1.335 pg_proc.h --- src/include/catalog/pg_proc.h 6 Jun 2004 19:07:00 -0000 1.335 +++ src/include/catalog/pg_proc.h 11 Jun 2004 17:59:25 -0000 @@ -3588,6 +3588,15 @@ DATA(insert OID = 2243 ( bit_or PGNSP PGUID 12 t f f f i 1 1560 "1560" _null_ aggregate_dummy- _null_)); DESCR("bitwise-or bit aggregate"); +DATA(insert OID = 2546( int2array_int2vector_eq PGNSP PGUID 12 f f t f i 2 16 "1005 22" _null_ int2array_int2vector_eq- _null_ )); +DESCR("int2array int2vector equal"); + +DATA(insert OID = 2550( pg_logfile_length PGNSP PGUID 12 f f f f v 0 23 "" _null_ pg_logfile_length - _null_)); +DESCR("length of log file"); +DATA(insert OID = 2551( pg_logfile PGNSP PGUID 12 f f f f v 2 2275 "23 23" _null_ pg_logfile - _null_)); +DESCR("return log file contents"); + + /* * Symbolic values for provolatile column: these indicate whether the result * of a function is dependent *only* on the values of its explicit arguments, Index: src/include/utils/builtins.h =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/include/utils/builtins.h,v retrieving revision 1.241 diff -u -r1.241 builtins.h --- src/include/utils/builtins.h 2 Jun 2004 21:29:29 -0000 1.241 +++ src/include/utils/builtins.h 11 Jun 2004 17:59:27 -0000 @@ -356,6 +356,8 @@ extern Datum current_database(PG_FUNCTION_ARGS); extern Datum pg_terminate_backend(PG_FUNCTION_ARGS); extern Datum pg_cancel_backend(PG_FUNCTION_ARGS); +extern Datum pg_logfile_length(PG_FUNCTION_ARGS); +extern Datum pg_logfile(PG_FUNCTION_ARGS); /* not_in.c */ extern Datum int4notin(PG_FUNCTION_ARGS); Index: src/include/utils/elog.h =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/include/utils/elog.h,v retrieving revision 1.68 diff -u -r1.68 elog.h --- src/include/utils/elog.h 5 Apr 2004 03:02:10 -0000 1.68 +++ src/include/utils/elog.h 11 Jun 2004 17:59:28 -0000 @@ -182,8 +182,12 @@ #define LOG_DESTINATION_STDERR 1 #define LOG_DESTINATION_SYSLOG 2 #define LOG_DESTINATION_EVENTLOG 4 +#define LOG_DESTINATION_FILE 8 /* Other exported functions */ extern void DebugFileOpen(void); +extern char *LogFileName(void); +extern void LogFileOpen(void); +extern void LogFileClose(void); #endif /* ELOG_H */
Andreas Pflug <pgadmin@pse-consulting.de> writes: > The attached patch has the default filename issue fixed, and > documentation. Since I don't have a doc build system functional, there > might be tag mismatches or other typos; please check. IMHO this should > be committed without waiting for log rotation stuff. This has got portability issues (fopen("ab")) and I don't care for its use of malloc in preference to palloc either. Also, pg_logfile() will dump core if LogFileName returns null. The bigger issue though is whether this is useful at all, if you cannot solve the file rotation issue (and I don't think you can). As implemented, the secondary log file cannot be truncated without restarting the postmaster. I think that reduces it from a possibly useful feature to a useless toy. (The fact that pg_logfile_length returns int and not something wider is pretty silly in this connection.) My vote is not to apply until and unless something that can rotate the logfile is demonstrated ... regards, tom lane
Tom Lane wrote: > Andreas Pflug <pgadmin@pse-consulting.de> writes: > > The attached patch has the default filename issue fixed, and > > documentation. Since I don't have a doc build system functional, there > > might be tag mismatches or other typos; please check. IMHO this should > > be committed without waiting for log rotation stuff. > > This has got portability issues (fopen("ab")) and I don't care for its > use of malloc in preference to palloc either. Also, pg_logfile() will > dump core if LogFileName returns null. > > The bigger issue though is whether this is useful at all, if you cannot > solve the file rotation issue (and I don't think you can). As > implemented, the secondary log file cannot be truncated without > restarting the postmaster. I think that reduces it from a possibly > useful feature to a useless toy. (The fact that pg_logfile_length > returns int and not something wider is pretty silly in this connection.) > > My vote is not to apply until and unless something that can rotate the > logfile is demonstrated ... Agreed. Lets see where it goes. -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073
Tom Lane wrote: > >This has got portability issues (fopen("ab")) > My doc says b is ignored on ansi systems, and recommends using it. Do you have other experiences? > and I don't care for its >use of malloc in preference to palloc either. > Do we already have an applicable memory context in the postmaster at that early stage of initialization? >Also, pg_logfile() will dump core if LogFileName returns null. > > How that? char *filename=LogFileName(); if (filename) { ... free(filename); } >The bigger issue though is whether this is useful at all, if you cannot >solve the file rotation issue (and I don't think you can). As >implemented, the secondary log file cannot be truncated without >restarting the postmaster. I think that reduces it from a possibly >useful feature to a useless toy. > This patch isn't trying to be better on logfile handling than the default stderr redirection behavior, besides being able to access it through the postmaster. Seems you insist to name this a toy, many users don't. > (The fact that pg_logfile_length >returns int and not something wider is pretty silly in this connection.) > > 2GB logfile seems pretty big... Regards, Andreas
Were are we on this? --------------------------------------------------------------------------- Andreas Pflug wrote: > Tom Lane wrote: > > > > >This has got portability issues (fopen("ab")) > > > My doc says b is ignored on ansi systems, and recommends using it. Do > you have other experiences? > > > and I don't care for its > >use of malloc in preference to palloc either. > > > Do we already have an applicable memory context in the postmaster at > that early stage of initialization? > > >Also, pg_logfile() will dump core if LogFileName returns null. > > > > > How that? > > char *filename=LogFileName(); > if (filename) > { > ... > free(filename); > } > > >The bigger issue though is whether this is useful at all, if you cannot > >solve the file rotation issue (and I don't think you can). As > >implemented, the secondary log file cannot be truncated without > >restarting the postmaster. I think that reduces it from a possibly > >useful feature to a useless toy. > > > This patch isn't trying to be better on logfile handling than the > default stderr redirection behavior, besides being able to access it > through the postmaster. Seems you insist to name this a toy, many users > don't. > > > (The fact that pg_logfile_length > >returns int and not something wider is pretty silly in this connection.) > > > > > 2GB logfile seems pretty big... > > Regards, > Andreas > > > ---------------------------(end of broadcast)--------------------------- > TIP 5: Have you checked our extensive FAQ? > > http://www.postgresql.org/docs/faqs/FAQ.html > -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073