1 /*-------------------------------------------------------------------------
5 * Conditional trace and logging functions.
7 * Massimo Dal Zotto <dz@cs.unitn.it>
9 *-------------------------------------------------------------------------
17 #include <sys/types.h>
24 #include "miscadmin.h"
25 #include "utils/trace.h"
28 * We could support trace messages of indefinite length, as elog() does,
29 * but it's probably not worth the trouble. Instead limit trace message
32 #define TRACEMSG_MAXLEN 1024
36 * Global option to control the use of syslog(3) for logging:
38 * 0 stdout/stderr only
39 * 1 stdout/stderr + syslog
42 #define UseSyslog pg_options[OPT_SYSLOG]
43 #define PG_LOG_FACILITY LOG_LOCAL0
44 #define PG_LOG_IDENT "postgres"
50 * Trace option names, must match the constants in trace_opts[].
52 static char *opt_names[] = {
53 "all", /* 0=trace some, 1=trace all, -1=trace none */
65 "shortlocks", /* currently unused but needed, see lock.c */
74 "lock_read_priority", /* lock priority, see lock.c */
75 "deadlock_timeout", /* deadlock timeout, see proc.c */
76 "nofsync", /* turn fsync off */
77 "syslog", /* use syslog for error messages */
78 "hostlookup", /* enable hostname lookup in ps_status */
79 "showportnumber", /* show port number in ps_status */
81 /* NUM_PG_OPTIONS */ /* must be the last item of enum */
85 * Array of trace flags which can be set or reset independently.
87 int pg_options[NUM_PG_OPTIONS] = {0};
90 * Print a timestamp and a message to stdout if the trace flag
91 * indexed by the flag value is set.
94 tprintf(int flag, const char *fmt,...)
97 char line[TRACEMSG_MAXLEN + TIMESTAMP_SIZE + 1];
102 if ((flag == TRACE_ALL) || (pg_options[TRACE_ALL] > 0))
104 /* unconditional trace or trace all option set */
106 else if (pg_options[TRACE_ALL] == 0)
108 if ((flag < 0) || (flag >= NUM_PG_OPTIONS) || (!pg_options[flag]))
111 else if (pg_options[TRACE_ALL] < 0)
114 #ifdef ELOG_TIMESTAMPS
115 strcpy(line, tprintf_timestamp());
118 vsnprintf(line + TIMESTAMP_SIZE, TRACEMSG_MAXLEN, fmt, ap);
122 log_level = ((flag == TRACE_ALL) ? LOG_INFO : LOG_DEBUG);
123 write_syslog(log_level, line + TIMESTAMP_SIZE);
136 * Print a timestamp and a message to stdout or to syslog.
140 tprintf1(const char *fmt,...)
143 char line[TRACEMSG_MAXLEN + TIMESTAMP_SIZE + 1];
145 #ifdef ELOG_TIMESTAMPS
146 strcpy(line, tprintf_timestamp());
149 vsnprintf(line + TIMESTAMP_SIZE, TRACEMSG_MAXLEN, fmt, ap);
153 write_syslog(LOG_INFO, line + TIMESTAMP_SIZE);
167 * Print a timestamp and a message to stderr.
170 eprintf(const char *fmt,...)
173 char line[TRACEMSG_MAXLEN + TIMESTAMP_SIZE + 1];
175 #ifdef ELOG_TIMESTAMPS
176 strcpy(line, tprintf_timestamp());
179 vsnprintf(line + TIMESTAMP_SIZE, TRACEMSG_MAXLEN, fmt, ap);
183 write_syslog(LOG_ERR, line + TIMESTAMP_SIZE);
198 * Write a message line to syslog if the syslog option is set.
201 write_syslog(int level, char *line)
203 static int openlog_done = 0;
210 openlog(PG_LOG_IDENT, LOG_PID | LOG_NDELAY, PG_LOG_FACILITY);
212 syslog(level, "%s", line);
217 #ifdef ELOG_TIMESTAMPS
219 * Return a timestamp string like "980119.17:25:59.902 [21974] "
225 struct timezone tz = { 0, 0 };
228 static char timestamp[32],
231 gettimeofday(&tv, &tz);
233 time = localtime(&tm);
235 sprintf(pid, "[%d]", MyProcPid);
236 sprintf(timestamp, "%02d%02d%02d.%02d:%02d:%02d.%03d %7s ",
237 time->tm_year, time->tm_mon + 1, time->tm_mday,
238 time->tm_hour, time->tm_min, time->tm_sec,
239 (int) (tv.tv_usec/1000), pid);
247 option_flag(int flag)
249 if ((flag < 0) || (flag >= NUM_PG_OPTIONS))
251 return pg_options[flag];
255 set_option_flag(int flag, int value)
257 if ((flag < 0) || (flag >= NUM_PG_OPTIONS))
260 pg_options[flag] = value;
266 * Parse an option string like "name,name+,name-,name=value".
267 * Single options are delimited by ',',space,tab,newline or cr.
269 * If 'secure' is false, the option string came from a remote client via
270 * connection "debug options" field --- do not obey any requests that
271 * might potentially be security loopholes.
274 parse_options(char *str, bool secure)
283 Assert((sizeof(opt_names) / sizeof(char *)) == NUM_PG_OPTIONS);
300 val = strtol(s, &s, 10);
332 for (i = 0; i < NUM_PG_OPTIONS; i++)
334 if (strncmp(name, opt_names[i], len) == 0)
340 if (!is_comment && (i >= NUM_PG_OPTIONS))
341 fprintf(stderr, "invalid option: %s\n", name);
346 #define BUF_SIZE 4096
349 read_pg_options(SIGNAL_ARGS)
354 char buffer[BUF_SIZE];
361 fprintf(stderr, "read_pg_options: DataDir not defined\n");
365 snprintf(buffer, BUF_SIZE - 1, "%s/%s", DataDir, "pg_options");
367 if ((fd = open(buffer, O_RDONLY)) < 0)
369 if ((fd = open(buffer, O_RDONLY | O_BINARY)) < 0)
373 if ((n = read(fd, buffer, BUF_SIZE - 1)) > 0)
375 /* collpse buffer in place removing comments and spaces */
376 for (s = buffer, p = buffer, c = '\0'; s < (buffer + n);)
381 while ((s < (buffer + n)) && (*s++ != '\n'));
399 verbose = pg_options[TRACE_VERBOSE];
400 parse_options(buffer, true);
401 verbose |= pg_options[TRACE_VERBOSE];
402 if (verbose || postgres_signal_arg == SIGHUP)
403 tprintf(TRACE_ALL, "read_pg_options: %s", buffer);
414 for (i=0; i<NUM_PG_OPTIONS; i++) {
415 elog(NOTICE, "%s=%d", opt_names[i], pg_options[i]);