1 /*-------------------------------------------------------------------------
5 * Conditional trace ans logging functions.
7 * Massimo Dal Zotto <dz@cs.unitn.it>
9 *-------------------------------------------------------------------------
18 #include <sys/types.h>
27 #include "miscadmin.h"
28 #include "utils/trace.h"
29 #include "libpq/pqsignal.h"
33 * Global option to control the use of syslog(3) for logging:
35 * 0 stdout/stderr only
36 * 1 stdout/stderr + syslog
39 #define UseSyslog pg_options[OPT_SYSLOG]
40 #define PG_LOG_FACILITY LOG_LOCAL0
41 #define PG_LOG_IDENT "postgres"
47 * Trace option names, must match the constants in trace_opts[].
49 static char *opt_names[] = {
59 "shortlocks", /* currently unused but needed, see lock.c */
68 "lock_read_priority", /* lock priority, see lock.c */
69 "deadlock_timeout", /* deadlock timeout, see proc.c */
70 "syslog", /* use syslog for error messages */
71 "hostlookup", /* enable hostname lookup in ps_status */
72 "showportnumber", /* show port number in ps_status */
73 "notifyunlock", /* enable unlock of pg_listener after
75 "notifyhack" /* enable notify hack to remove duplicate
80 * Array of trace flags which can be set or reset independently.
82 int pg_options[NUM_PG_OPTIONS] = {0};
84 static int openlog_done = 0;
87 * Print a timestamp and a message to stdout if the trace flag
88 * indexed by the flag value is set.
91 tprintf(int flag, const char *fmt,...)
94 char line[ELOG_MAXLEN + TIMESTAMP_SIZE + 1];
101 if ((flag == TRACE_ALL) || (pg_options[TRACE_ALL] > 0))
103 /* uconditional trace or trace all option set */
105 else if (pg_options[TRACE_ALL] == 0)
107 if ((flag < 0) || (flag >= NUM_PG_OPTIONS) || (!pg_options[flag]))
110 else if (pg_options[TRACE_ALL] < 0)
114 #ifdef ELOG_TIMESTAMPS
115 strcpy(line, tprintf_timestamp());
117 vsprintf(line + TIMESTAMP_SIZE, fmt, ap);
121 log_level = ((flag == TRACE_ALL) ? LOG_INFO : LOG_DEBUG);
122 write_syslog(log_level, line + TIMESTAMP_SIZE);
135 * Print a timestamp and a message to stderr.
138 eprintf(const char *fmt,...)
141 char line[ELOG_MAXLEN + TIMESTAMP_SIZE + 1];
144 #ifdef ELOG_TIMESTAMPS
145 strcpy(line, tprintf_timestamp());
147 vsprintf(line + TIMESTAMP_SIZE, fmt, ap);
151 write_syslog(LOG_ERR, line + TIMESTAMP_SIZE);
166 * Write a message line to syslog if the syslog option is set.
169 write_syslog(int level, char *line)
176 openlog(PG_LOG_IDENT, LOG_PID | LOG_NDELAY, PG_LOG_FACILITY);
178 syslog(level, "%s", line);
184 #ifdef ELOG_TIMESTAMPS
186 * Return a timestamp string like "980119.17:25:59.902 [21974] "
194 static char timestamp[32],
197 gettimeofday(&tv, DST_NONE);
199 time = localtime(&tm);
201 sprintf(pid, "[%d]", MyProcPid);
202 sprintf(timestamp, "%02d%02d%02d.%02d:%02d:%02d.%03d %7s ",
203 time->tm_year, time->tm_mon + 1, time->tm_mday,
204 time->tm_hour, time->tm_min, time->tm_sec,
205 tv.tv_usec / 1000, pid);
213 option_flag(int flag)
215 if ((flag < 0) || (flag >= NUM_PG_OPTIONS))
217 return pg_options[flag];
221 set_option_flag(int flag, int value)
223 if ((flag < 0) || (flag >= NUM_PG_OPTIONS))
226 pg_options[flag] = value;
231 * Parse an option string like "name,name+,name-,name=value".
232 * Single options are delimited by ',',space,tab,newline or cr.
235 parse_options(char *str)
244 Assert((sizeof(opt_names) / sizeof(char *)) == NUM_PG_OPTIONS);
261 val = strtol(s, &s, 10);
293 for (i = 0; i < NUM_PG_OPTIONS; i++)
295 if (strncmp(name, opt_names[i], len) == 0)
301 if (!is_comment && (i >= NUM_PG_OPTIONS))
302 fprintf(stderr, "invalid option: %s\n", name);
307 #define BUF_SIZE 4096
310 read_pg_options(SIGNAL_ARGS)
315 char buffer[BUF_SIZE];
320 sprintf(buffer, "%s/%s", DataDir, "pg_options");
321 if ((fd = open(buffer, O_RDONLY)) < 0)
324 if ((n = read(fd, buffer, BUF_SIZE - 1)) > 0)
326 /* collpse buffer in place removing comments and spaces */
327 for (s = buffer, p = buffer, c = '\0'; s < (buffer + n);)
332 while ((s < (buffer + n)) && (*s++ != '\n'));
350 verbose = pg_options[TRACE_VERBOSE];
351 parse_options(buffer);
352 verbose |= pg_options[TRACE_VERBOSE];
353 if (verbose || postgres_signal_arg == SIGHUP)
354 tprintf(TRACE_ALL, "read_pg_options: %s", buffer);