pgpool2.git / summary / log / commit / refs
commit edffd9c6c43bd1718d0e1f80311784ff4b36e7d1
Author: Tatsuo Ishii <ishii at sraoss.co.jp>
Date: Thu Dec 30 00:47:05 2010 +0000
Add syslog support. Patch contributed by Gilles Darold.
Review and editing by Guillaume Lelarge.
main.c | 11 ++++
pgpool.conf.sample | 11 +++-
pgpool.conf.sample-master-slave | 11 +++-
pgpool.conf.sample-replication | 11 +++-
pgpool.conf.sample-stream | 11 +++-
pool.h | 5 ++
pool_auth.c | 26 ++++++++
pool_config.c | 131 +++++++++++++++++++++++++++++++++++++++-
pool_config.h | 7 +++
pool_config.l | 117 +++++++++++++++++++++++++++++++++++
pool_error.c | 21 +++++++
pool_process_reporting.c | 17 +++++-
pool_shmem.c | 2 +
13 files changed, 373 insertions(+), 8 deletions(-)
diff --git a/main.c b/main.c
index ec289c777..1074a3e7b 100644
--- a/main.c
+++ b/main.c
@@ -313,6 +313,17 @@ int main(int argc, char **argv)
exit(1);
}
+ /*
+ * Open syslog connection if required
+ */
+ if (!strcmp(pool_config->log_destination, "syslog")) {
+ openlog(pool_config->syslog_ident, LOG_PID|LOG_NDELAY|LOG_NOWAIT, pool_config->syslog_facility);
+ /* set a flag to allow pool_error.c to begin writing to syslog
+ instead of stdout now that pool_get_config() is done */
+ pool_config->logsyslog = 1;
+ }
+
+
/*
* Locate pool_passwd
*/
diff --git a/pgpool.conf.sample b/pgpool.conf.sample
index e3ac4f0bd..1e1616d5f 100644
--- a/pgpool.conf.sample
+++ b/pgpool.conf.sample
@@ -53,9 +53,18 @@ client_idle_limit = 0
# 0 means no timeout.
authentication_timeout = 60
-# Logging directory
+# PgPool status file logging directory
logdir = '/tmp'
+# Where to Log. Valid values are stderr and syslog. Default to stderr.
+log_destination = 'stderr'
+
+# Select syslog local facility for logging. Default: LOCAL0
+syslog_facility = 'LOCAL0'
+
+# Set the syslog program ident string. Default to 'pgpool'
+syslog_ident = 'pgpool'
+
# pid file name
pid_file_name = '/var/run/pgpool/pgpool.pid'
diff --git a/pgpool.conf.sample-master-slave b/pgpool.conf.sample-master-slave
index 8c2c4488a..3fecffc41 100644
--- a/pgpool.conf.sample-master-slave
+++ b/pgpool.conf.sample-master-slave
@@ -53,9 +53,18 @@ client_idle_limit = 0
# 0 means no timeout.
authentication_timeout = 60
-# Logging directory
+# PgPool status file logging directory
logdir = '/tmp'
+# Where to Log. Valid values are stderr and syslog. Default to stderr.
+log_destination = 'stderr'
+
+# Select syslog local facility for logging. Default: LOCAL0
+syslog_facility = 'LOCAL0'
+
+# Set the syslog program ident string. Default to 'pgpool'
+syslog_ident = 'pgpool'
+
# pid file name
pid_file_name = '/var/run/pgpool/pgpool.pid'
diff --git a/pgpool.conf.sample-replication b/pgpool.conf.sample-replication
index 26267a934..6b08eb24c 100644
--- a/pgpool.conf.sample-replication
+++ b/pgpool.conf.sample-replication
@@ -53,9 +53,18 @@ client_idle_limit = 0
# 0 means no timeout.
authentication_timeout = 60
-# Logging directory
+# PgPool status file logging directory
logdir = '/tmp'
+# Where to Log. Valid values are stderr and syslog. Default to stderr.
+log_destination = 'stderr'
+
+# Select syslog local facility for logging. Default: LOCAL0
+syslog_facility = 'LOCAL0'
+
+# Set the syslog program ident string. Default to 'pgpool'
+syslog_ident = 'pgpool'
+
# pid file name
pid_file_name = '/var/run/pgpool/pgpool.pid'
diff --git a/pgpool.conf.sample-stream b/pgpool.conf.sample-stream
index c746bf68b..5388388a4 100644
--- a/pgpool.conf.sample-stream
+++ b/pgpool.conf.sample-stream
@@ -53,9 +53,18 @@ client_idle_limit = 0
# 0 means no timeout.
authentication_timeout = 60
-# Logging directory
+# PgPool status file logging directory
logdir = '/tmp'
+# Where to Log. Valid values are stderr and syslog. Default to stderr.
+log_destination = 'stderr'
+
+# Select syslog local facility for logging. Default: LOCAL0
+syslog_facility = 'LOCAL0'
+
+# Set the syslog program ident string. Default to 'pgpool'
+syslog_ident = 'pgpool'
+
# pid file name
pid_file_name = '/var/run/pgpool/pgpool.pid'
diff --git a/pool.h b/pool.h
index 8773e9c6a..ad55ecb88 100644
--- a/pool.h
+++ b/pool.h
@@ -43,6 +43,8 @@
#include <openssl/err.h>
#endif
+#include <syslog.h>
+
/* undef this if you have problems with non blocking accept() */
#define NONE_BLOCK
@@ -69,6 +71,9 @@
/* status file name */
#define STATUS_FILE_NAME "pgpool_status"
+/* default string used to identify pgpool on syslog output */
+#define DEFAULT_SYSLOG_IDENT "pgpool"
+
typedef enum {
POOL_CONTINUE = 0,
POOL_IDLE,
diff --git a/pool_auth.c b/pool_auth.c
index 2d93d12fc..69671f001 100644
--- a/pool_auth.c
+++ b/pool_auth.c
@@ -248,6 +248,8 @@ from pool_read_message_length and recheck the pg_hba.conf settings.");
*/
for (;;)
{
+ char *message;
+
kind = pool_read_kind(cp);
if (kind < 0)
{
@@ -269,6 +271,10 @@ from pool_read_message_length and recheck the pg_hba.conf settings.");
break;
case 'N':
+ if (pool_extract_error_message(true, MASTER(cp), protoMajor, true, &message) == 1)
+ {
+ pool_log("pool_do_auth: notice message from backend:%s", message);
+ }
/* process notice message */
if (SimpleForwardToFrontend(kind, frontend, cp))
return -1;
@@ -277,6 +283,10 @@ from pool_read_message_length and recheck the pg_hba.conf settings.");
/* process error message */
case 'E':
+ if (pool_extract_error_message(true, MASTER(cp), protoMajor, true, &message) == 1)
+ {
+ pool_log("pool_do_auth: error message from backend:%s", message);
+ }
SimpleForwardToFrontend(kind, frontend, cp);
pool_flush(frontend);
return -1;
@@ -1296,8 +1306,24 @@ signed char pool_read_kind(POOL_CONNECTION_POOL *cp)
{
if (kind != kind0)
{
+ char *message;
+
pool_error("pool_read_kind: kind does not match between master(%x) slot[%d] (%x)",
kind0, i, kind);
+ if (kind0 == 'E')
+ {
+ if (pool_extract_error_message(false, MASTER(cp), MAJOR(cp), true, &message) == 1)
+ {
+ pool_log("pool_read_kind: error message from master backend:%s", message);
+ }
+ }
+ else if (kind == 'E')
+ {
+ if (pool_extract_error_message(false, CONNECTION(cp, i), MAJOR(cp), true, &message) == 1)
+ {
+ pool_log("pool_read_kind: error message from %d th backend:%s", i, message);
+ }
+ }
return -1;
}
}
diff --git a/pool_config.c b/pool_config.c
index 1d540cbad..8f008eff6 100644
--- a/pool_config.c
+++ b/pool_config.c
@@ -1871,6 +1871,10 @@ int pool_init_config(void)
pool_config->child_max_connections = 0;
pool_config->authentication_timeout = 60;
pool_config->logdir = DEFAULT_LOGDIR;
+ pool_config->logsyslog = 0;
+ pool_config->log_destination = "stderr";
+ pool_config->syslog_facility = LOG_LOCAL0;
+ pool_config->syslog_ident = "pgpool";
pool_config->pid_file_name = DEFAULT_PID_FILE_NAME;
pool_config->log_statement = 0;
pool_config->log_per_node_statement = 0;
@@ -1926,9 +1930,9 @@ int pool_init_config(void)
pool_config->ssl_ca_cert = "";
pool_config->ssl_ca_cert_dir = "";
pool_config->debug_level = 0;
- pool_config->lists_patterns = NULL;
- pool_config->pattc = 0;
- pool_config->current_pattern_size = 0;
+ pool_config->lists_patterns = NULL;
+ pool_config->pattc = 0;
+ pool_config->current_pattern_size = 0;
res = gethostname(localhostname,sizeof(localhostname));
if(res !=0 )
@@ -2043,6 +2047,7 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context)
char key[1024];
double total_weight;
int i;
+ bool log_destination_changed = false;
#define PARSE_ERROR() pool_error("pool_config: parse error at line %d '%s'", Lineno, yytext)
@@ -2303,6 +2308,64 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context)
}
pool_config->logdir = str;
}
+ else if (!strcmp(key, "log_destination") &&
+ CHECK_CONTEXT(INIT_CONFIG|RELOAD_CONFIG, context))
+ {
+ char *str;
+
+ if (token != POOL_STRING && token != POOL_UNQUOTED_STRING && token != POOL_KEY)
+ {
+ PARSE_ERROR();
+ fclose(fd);
+ return(-1);
+ }
+ str = extract_string(yytext, token);
+ if (str == NULL)
+ {
+ fclose(fd);
+ return(-1);
+ }
+ log_destination_changed = pool_config->log_destination != str;
+ pool_config->log_destination = str;
+ }
+ else if (!strcmp(key, "syslog_facility") && CHECK_CONTEXT(INIT_CONFIG|RELOAD_CONFIG, context))
+ {
+ char *str;
+
+ if (token != POOL_STRING && token != POOL_UNQUOTED_STRING && token != POOL_KEY)
+ {
+ PARSE_ERROR();
+ fclose(fd);
+ return(-1);
+ }
+ str = extract_string(yytext, token);
+ if (str == NULL)
+ {
+ fclose(fd);
+ return(-1);
+ }
+ pool_config->syslog_facility = set_syslog_facility(str);
+ }
+ else if (!strcmp(key, "syslog_ident") &&
+ CHECK_CONTEXT(INIT_CONFIG|RELOAD_CONFIG, context))
+ {
+ char *str;
+
+ if (token != POOL_STRING && token != POOL_UNQUOTED_STRING && token != POOL_KEY)
+ {
+ PARSE_ERROR();
+ fclose(fd);
+ return(-1);
+ }
+ str = extract_string(yytext, token);
+ if (str == NULL)
+ {
+ fclose(fd);
+ return(-1);
+ }
+ log_destination_changed = log_destination_changed || pool_config->syslog_ident != str;
+ pool_config->syslog_ident = str;
+ }
else if (!strcmp(key, "pid_file_name") && CHECK_CONTEXT(INIT_CONFIG, context))
{
char *str;
@@ -2521,6 +2584,10 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context)
fclose(fd);
return(-1);
}
+ for (i=0;i<pool_config->num_white_function_list;i++)
+ {
+ add_regex_pattern("white_function_list", pool_config->white_function_list[i]);
+ }
}
else if (!strcmp(key, "black_function_list") &&
@@ -2548,6 +2615,10 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context)
fclose(fd);
return(-1);
}
+ for (i=0;i<pool_config->num_black_function_list;i++)
+ {
+ add_regex_pattern("black_function_list", pool_config->black_function_list[i]);
+ }
}
else if (!strcmp(key, "print_timestamp") && CHECK_CONTEXT(INIT_CONFIG, context))
@@ -3332,6 +3403,21 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context)
fclose(fd);
+ if (log_destination_changed)
+ {
+ // log_destination has changed, we need to open syslog or close it
+ if (!strcmp(pool_config->log_destination, "stderr"))
+ {
+ closelog();
+ pool_config->logsyslog = 0;
+ }
+ else
+ {
+ openlog(pool_config->syslog_ident, LOG_PID|LOG_NDELAY|LOG_NOWAIT, pool_config->syslog_facility);
+ pool_config->logsyslog = 1;
+ }
+ }
+
pool_config->backend_desc->num_backends = 0;
total_weight = 0.0;
@@ -3634,4 +3720,43 @@ static void print_host_entry(int slot)
}
#endif
+/* Use to set the syslog facility level if logsyslog is activated */
+int set_syslog_facility(char *value)
+{
+ int facility = LOG_LOCAL0;
+
+ if (value == NULL)
+ return facility;
+
+ if (strncmp(value, "LOCAL", 5) == 0 && strlen(value) == 6) {
+ switch (value[5]) {
+ case '0':
+ facility = LOG_LOCAL0;
+ break;
+ case '1':
+ facility = LOG_LOCAL1;
+ break;
+ case '2':
+ facility = LOG_LOCAL2;
+ break;
+ case '3':
+ facility = LOG_LOCAL3;
+ break;
+ case '4':
+ facility = LOG_LOCAL4;
+ break;
+ case '5':
+ facility = LOG_LOCAL5;
+ break;
+ case '6':
+ facility = LOG_LOCAL6;
+ break;
+ case '7':
+ facility = LOG_LOCAL7;
+ break;
+ }
+ }
+ return facility;
+}
+
diff --git a/pool_config.h b/pool_config.h
index 2dcb73b86..97f512932 100644
--- a/pool_config.h
+++ b/pool_config.h
@@ -66,6 +66,9 @@ typedef struct {
int authentication_timeout; /* maximum time in seconds to complete client authentication */
int max_pool; /* max # of connection pool per child */
char *logdir; /* logging directory */
+ char *log_destination; /* log destination: stderr or syslog */
+ int syslog_facility; /* syslog facility: LOCAL0, LOCAL1, ... */
+ char *syslog_ident; /* syslog ident string: pgpool */
char *pid_file_name; /* pid file name */
char *backend_socket_dir; /* Unix domain socket directory for the PostgreSQL server */
int replication_mode; /* replication mode */
@@ -157,6 +160,7 @@ typedef struct {
int num_reset_queries; /* number of queries in reset_query_list */
int num_white_function_list; /* number of functions in white_function_list */
int num_black_function_list; /* number of functions in black_function_list */
+ int logsyslog; /* flag used to start logging to syslog */
/* ssl configuration */
int ssl; /* if non 0, activate ssl support (frontend+backend) */
@@ -182,6 +186,9 @@ extern int pool_init_config(void);
extern int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context);
extern int eval_logical(char *str);
+/* method use for syslog support */
+extern int set_syslog_facility (char *);
+
/* methods used for regexp support */
extern int add_regex_pattern(char *type, char *s);
extern int growPatternArray (RegPattern item);
diff --git a/pool_config.l b/pool_config.l
index ba07de1b1..7fc2710d8 100644
--- a/pool_config.l
+++ b/pool_config.l
@@ -146,6 +146,10 @@ int pool_init_config(void)
pool_config->child_max_connections = 0;
pool_config->authentication_timeout = 60;
pool_config->logdir = DEFAULT_LOGDIR;
+ pool_config->logsyslog = 0;
+ pool_config->log_destination = "stderr";
+ pool_config->syslog_facility = LOG_LOCAL0;
+ pool_config->syslog_ident = "pgpool";
pool_config->pid_file_name = DEFAULT_PID_FILE_NAME;
pool_config->log_statement = 0;
pool_config->log_per_node_statement = 0;
@@ -318,6 +322,7 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context)
char key[1024];
double total_weight;
int i;
+ bool log_destination_changed = false;
#define PARSE_ERROR() pool_error("pool_config: parse error at line %d '%s'", Lineno, yytext)
@@ -578,6 +583,64 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context)
}
pool_config->logdir = str;
}
+ else if (!strcmp(key, "log_destination") &&
+ CHECK_CONTEXT(INIT_CONFIG|RELOAD_CONFIG, context))
+ {
+ char *str;
+
+ if (token != POOL_STRING && token != POOL_UNQUOTED_STRING && token != POOL_KEY)
+ {
+ PARSE_ERROR();
+ fclose(fd);
+ return(-1);
+ }
+ str = extract_string(yytext, token);
+ if (str == NULL)
+ {
+ fclose(fd);
+ return(-1);
+ }
+ log_destination_changed = pool_config->log_destination != str;
+ pool_config->log_destination = str;
+ }
+ else if (!strcmp(key, "syslog_facility") && CHECK_CONTEXT(INIT_CONFIG|RELOAD_CONFIG, context))
+ {
+ char *str;
+
+ if (token != POOL_STRING && token != POOL_UNQUOTED_STRING && token != POOL_KEY)
+ {
+ PARSE_ERROR();
+ fclose(fd);
+ return(-1);
+ }
+ str = extract_string(yytext, token);
+ if (str == NULL)
+ {
+ fclose(fd);
+ return(-1);
+ }
+ pool_config->syslog_facility = set_syslog_facility(str);
+ }
+ else if (!strcmp(key, "syslog_ident") &&
+ CHECK_CONTEXT(INIT_CONFIG|RELOAD_CONFIG, context))
+ {
+ char *str;
+
+ if (token != POOL_STRING && token != POOL_UNQUOTED_STRING && token != POOL_KEY)
+ {
+ PARSE_ERROR();
+ fclose(fd);
+ return(-1);
+ }
+ str = extract_string(yytext, token);
+ if (str == NULL)
+ {
+ fclose(fd);
+ return(-1);
+ }
+ log_destination_changed = log_destination_changed || pool_config->syslog_ident != str;
+ pool_config->syslog_ident = str;
+ }
else if (!strcmp(key, "pid_file_name") && CHECK_CONTEXT(INIT_CONFIG, context))
{
char *str;
@@ -1615,6 +1678,21 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context)
fclose(fd);
+ if (log_destination_changed)
+ {
+ // log_destination has changed, we need to open syslog or close it
+ if (!strcmp(pool_config->log_destination, "stderr"))
+ {
+ closelog();
+ pool_config->logsyslog = 0;
+ }
+ else
+ {
+ openlog(pool_config->syslog_ident, LOG_PID|LOG_NDELAY|LOG_NOWAIT, pool_config->syslog_facility);
+ pool_config->logsyslog = 1;
+ }
+ }
+
pool_config->backend_desc->num_backends = 0;
total_weight = 0.0;
@@ -1917,3 +1995,42 @@ static void print_host_entry(int slot)
}
#endif
+/* Use to set the syslog facility level if logsyslog is activated */
+int set_syslog_facility(char *value)
+{
+ int facility = LOG_LOCAL0;
+
+ if (value == NULL)
+ return facility;
+
+ if (strncmp(value, "LOCAL", 5) == 0 && strlen(value) == 6) {
+ switch (value[5]) {
+ case '0':
+ facility = LOG_LOCAL0;
+ break;
+ case '1':
+ facility = LOG_LOCAL1;
+ break;
+ case '2':
+ facility = LOG_LOCAL2;
+ break;
+ case '3':
+ facility = LOG_LOCAL3;
+ break;
+ case '4':
+ facility = LOG_LOCAL4;
+ break;
+ case '5':
+ facility = LOG_LOCAL5;
+ break;
+ case '6':
+ facility = LOG_LOCAL6;
+ break;
+ case '7':
+ facility = LOG_LOCAL7;
+ break;
+ }
+ }
+ return facility;
+}
+
diff --git a/pool_error.c b/pool_error.c
index 220edc64f..d0f4f7c76 100644
--- a/pool_error.c
+++ b/pool_error.c
@@ -50,6 +50,13 @@ void pool_error(const char *fmt,...)
#else
int oldmask;
#endif
+ /* Write error message to syslog */
+ if (pool_config->logsyslog == 1) {
+ va_start(ap, fmt);
+ vsyslog(pool_config->syslog_facility | LOG_ERR, fmt, ap);
+ va_end(ap);
+ return;
+ }
POOL_SETMASK2(&BlockSig, &oldmask);
@@ -105,6 +112,13 @@ void pool_debug(const char *fmt,...)
if (pool_config->debug_level <= 0)
return;
}
+ /* Write debug message to syslog */
+ if (pool_config->logsyslog == 1) {
+ va_start(ap, fmt);
+ vsyslog(pool_config->syslog_facility | LOG_DEBUG, fmt, ap);
+ va_end(ap);
+ return;
+ }
POOL_SETMASK2(&BlockSig, &oldmask);
@@ -149,6 +163,13 @@ void pool_log(const char *fmt,...)
#else
int oldmask;
#endif
+ /* Write log message to syslog */
+ if (pool_config->logsyslog == 1) {
+ va_start(ap, fmt);
+ vsyslog(pool_config->syslog_facility | LOG_NOTICE, fmt, ap);
+ va_end(ap);
+ return;
+ }
POOL_SETMASK2(&BlockSig, &oldmask);
diff --git a/pool_process_reporting.c b/pool_process_reporting.c
index 6a7c2e5c7..2ca65359f 100644
--- a/pool_process_reporting.c
+++ b/pool_process_reporting.c
@@ -173,7 +173,22 @@ void config_reporting(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend)
strncpy(status[i].name, "logdir", POOLCONFIG_MAXNAMELEN);
snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->logdir);
- strncpy(status[i].desc, "logging directory", POOLCONFIG_MAXDESCLEN);
+ strncpy(status[i].desc, "PgPool status file logging directory", POOLCONFIG_MAXDESCLEN);
+ i++;
+
+ strncpy(status[i].name, "log_destination", POOLCONFIG_MAXNAMELEN);
+ snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->log_destination);
+ strncpy(status[i].desc, "logging destination", POOLCONFIG_MAXDESCLEN);
+ i++;
+
+ strncpy(status[i].name, "syslog_facility", POOLCONFIG_MAXNAMELEN);
+ snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "LOCAL%d", (pool_config->syslog_facility/8) - 16);
+ strncpy(status[i].desc, "syslog local faclity", POOLCONFIG_MAXDESCLEN);
+ i++;
+
+ strncpy(status[i].name, "syslog_ident", POOLCONFIG_MAXNAMELEN);
+ snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->syslog_ident);
+ strncpy(status[i].desc, "syslog program ident string", POOLCONFIG_MAXDESCLEN);
i++;
strncpy(status[i].name, "pid_file_name", POOLCONFIG_MAXNAMELEN);
diff --git a/pool_shmem.c b/pool_shmem.c
index fc9694b79..1ff173898 100644
--- a/pool_shmem.c
+++ b/pool_shmem.c
@@ -127,6 +127,8 @@ void
pool_shmem_exit(int code)
{
shmem_exit(code);
+ /* Close syslog connection here as this function is always called on exit */
+ closelog();
}
/*
[parent: 0148b4004ed4]