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]