From 1d1cd04cb9b8e66e0303c362669db2c6c47fccae Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Mon, 11 Aug 2014 17:07:41 +1000 Subject: [PATCH] ctdb-logging: New option CTDB_LOGGING, remove CTDB_LOGFILE, CTDB_SYSLOG Remove --logfile and --syslog daemon options and replace with --logging. Modularise and clean up logging initialisation code. The initialisation API includes an app_name argument that is currently unused - this will be used in extensions to the syslog backend. Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs --- ctdb/config/ctdb.sysconfig | 3 +- ctdb/config/ctdbd_wrapper | 14 +++--- ctdb/config/functions | 26 +++++++---- ctdb/doc/ctdbd.1.xml | 39 +++++++++++++--- ctdb/doc/ctdbd.conf.5.xml | 40 +++++++++++------ ctdb/doc/examples/cluster.conf | 2 +- ctdb/doc/examples/natgw.conf | 2 +- ctdb/include/ctdb_client.h | 2 - ctdb/include/ctdb_logging.h | 9 +++- ctdb/server/ctdb_logging.c | 67 ++++++++++++++++++++-------- ctdb/server/ctdb_logging_file.c | 19 +++++++- ctdb/server/ctdb_logging_syslog.c | 9 +++- ctdb/server/ctdbd.c | 13 ++---- ctdb/tests/eventscripts/scripts/local.sh | 5 ++- ctdb/tests/simple/scripts/local_daemons.bash | 2 +- 15 files changed, 177 insertions(+), 75 deletions(-) diff --git a/ctdb/config/ctdb.sysconfig b/ctdb/config/ctdb.sysconfig index db34c07ef06..b44e478b937 100644 --- a/ctdb/config/ctdb.sysconfig +++ b/ctdb/config/ctdb.sysconfig @@ -23,8 +23,7 @@ CTDB_PUBLIC_ADDRESSES=/etc/ctdb/public_addresses # ulimit -n 10000 # Default is to use the log file below instead of syslog. -# CTDB_LOGFILE=/var/log/log.ctdb -# CTDB_SYSLOG=no +# CTDB_LOGGING=file:/var/log/log.ctdb # Default log level is ERR. NOTICE is a little more verbose. CTDB_DEBUGLEVEL=NOTICE diff --git a/ctdb/config/ctdbd_wrapper b/ctdb/config/ctdbd_wrapper index c2c5c1a3e6a..331ee43ba0d 100755 --- a/ctdb/config/ctdbd_wrapper +++ b/ctdb/config/ctdbd_wrapper @@ -111,7 +111,7 @@ build_ctdb_options () maybe_set "--pidfile" "$pidfile" # build up ctdb_options variable from optional parameters - maybe_set "--logfile" "$CTDB_LOGFILE" + maybe_set "--logging" "$CTDB_LOGGING" maybe_set "--nlist" "$CTDB_NODES" maybe_set "--socket" "$CTDB_SOCKET" maybe_set "--public-addresses" "$CTDB_PUBLIC_ADDRESSES" @@ -129,7 +129,6 @@ build_ctdb_options () maybe_set "--no-lmaster" "$CTDB_CAPABILITY_LMASTER" "no" maybe_set "--lvs --single-public-ip" "$CTDB_LVS_PUBLIC_IP" maybe_set "--script-log-level" "$CTDB_SCRIPT_LOG_LEVEL" - maybe_set "--syslog" "$CTDB_SYSLOG" "yes" maybe_set "--max-persistent-check-errors" "$CTDB_MAX_PERSISTENT_CHECK_ERRORS" } @@ -187,9 +186,14 @@ start() ctdb_options="${ctdb_options} --valgrinding" fi - if [ "$CTDB_SYSLOG" != "yes" ] ; then - logger -t ctdbd "CTDB is being run without syslog enabled. Logs will be in ${CTDB_LOGFILE:-/var/log/log.ctdb}" - fi + case "$CTDB_LOGGING" in + syslog) : ;; + file:*) + logger -t ctdbd "CTDB is being run without syslog enabled. Logs will be in ${CTDB_LOGGING#file:}" + ;; + *) + logger -t ctdbd "CTDB is being run without syslog enabled. Logs will be in log.ctdb" + esac eval "$ctdbd" "$ctdb_options" || return 1 diff --git a/ctdb/config/functions b/ctdb/config/functions index 3f2ccee5ee5..5c9497dc520 100755 --- a/ctdb/config/functions +++ b/ctdb/config/functions @@ -86,17 +86,25 @@ script_log () { _tag="$1" ; shift - if [ "$CTDB_SYSLOG" = "yes" ] ; then - logger -t "ctdbd: ${_tag}" $* - else - { - if [ -n "$*" ] ; then - echo "$*" + case "$CTDB_LOGGING" in + file:*|"") + if [ -n "$CTDB_LOGGING" ] ; then + _file="${CTDB_LOGGING#file:}" else - cat + _file="/var/log/log.ctdb" fi - } >>"${CTDB_LOGFILE:-/var/log/log.ctdb}" - fi + { + if [ -n "$*" ] ; then + echo "$*" + else + cat + fi + } >>"$_file" + ;; + *) + logger -t "ctdbd: ${_tag}" $* + ;; + esac } # When things are run in the background in an eventscript then logging diff --git a/ctdb/doc/ctdbd.1.xml b/ctdb/doc/ctdbd.1.xml index 20f2d8bb85b..e700bf293ee 100644 --- a/ctdb/doc/ctdbd.1.xml +++ b/ctdb/doc/ctdbd.1.xml @@ -51,9 +51,10 @@ This option sets the debug level to DEBUGLEVEL, which - controls what will be written to the logfile. The default is - 0 which will only log important events and errors. A larger - number will provide additional logging. + controls what will be written by the logging + subsystem. The default is 0 which will only log important + events and errors. A larger number will provide additional + logging. See the DEBUG LEVELS section in @@ -127,12 +128,36 @@ - --logfile=FILENAME + --logging=STRING - FILENAME where ctdbd will write its log. This is usually - /var/log/log.ctdb. - + STRING specifies where ctdbd will write its log. The + default is file:/var/log/log.ctdb or + similar - the prefix may differ depending on how CTDB was + built. + + + Valid values are: + + + + file:FILENAME + + + FILENAME where ctdbd will write its log. This is usually + /var/log/log.ctdb. + + + + + syslog + + + CTDB will log to syslog + + + + diff --git a/ctdb/doc/ctdbd.conf.5.xml b/ctdb/doc/ctdbd.conf.5.xml index e316abb4124..898688dc12c 100644 --- a/ctdb/doc/ctdbd.conf.5.xml +++ b/ctdb/doc/ctdbd.conf.5.xml @@ -220,13 +220,36 @@ - CTDB_LOGFILE=FILENAME + CTDB_LOGGING=STRING - Defaults to /var/log/log.ctdb. - Corresponds to . See also - CTDB_SYSLOG. + STRING specifies where ctdbd will write its log. The + default is file:/var/log/log.ctdb or + similar - the prefix may differ depending on how CTDB was + built. Corresponds to . + + Valid values are: + + + + file:FILENAME + + + FILENAME where ctdbd will write its log. This is usually + /var/log/log.ctdb. + + + + + syslog + + + CTDB will log to syslog + + + + @@ -354,15 +377,6 @@ - CTDB_SYSLOG=yes|no - - - Default is no. Corresponds to . - - - - - CTDB_TRANSPORT=tcp|infiniband diff --git a/ctdb/doc/examples/cluster.conf b/ctdb/doc/examples/cluster.conf index 871468e341b..8da982c53f2 100644 --- a/ctdb/doc/examples/cluster.conf +++ b/ctdb/doc/examples/cluster.conf @@ -68,7 +68,7 @@ CTDB_NODES=/etc/ctdb/nodes CTDB_PUBLIC_ADDRESSES=/etc/ctdb/public_addresses # Enable logging to syslog -CTDB_SYSLOG=yes +CTDB_LOGGING=syslog # Default log level CTDB_DEBUGLEVEL=NOTICE diff --git a/ctdb/doc/examples/natgw.conf b/ctdb/doc/examples/natgw.conf index 2e3a3ea702b..ce8f04113ef 100644 --- a/ctdb/doc/examples/natgw.conf +++ b/ctdb/doc/examples/natgw.conf @@ -70,7 +70,7 @@ CTDB_NODES=/etc/ctdb/nodes CTDB_PUBLIC_ADDRESSES=/etc/ctdb/public_addresses # Enable logging to syslog -CTDB_SYSLOG=yes +CTDB_LOGGING=syslog # Default log level CTDB_DEBUGLEVEL=NOTICE diff --git a/ctdb/include/ctdb_client.h b/ctdb/include/ctdb_client.h index ac235139e35..18b74b255fa 100644 --- a/ctdb/include/ctdb_client.h +++ b/ctdb/include/ctdb_client.h @@ -367,8 +367,6 @@ uint32_t *ctdb_get_connected_nodes(struct ctdb_context *ctdb, int ctdb_statistics_reset(struct ctdb_context *ctdb, uint32_t destnode); -int ctdb_set_logfile(TALLOC_CTX *mem_ctx, const char *logfile, bool use_syslog); - typedef int (*ctdb_traverse_func)(struct ctdb_context *, TDB_DATA, TDB_DATA, void *); int ctdb_traverse(struct ctdb_db_context *ctdb_db, ctdb_traverse_func fn, void *private_data); diff --git a/ctdb/include/ctdb_logging.h b/ctdb/include/ctdb_logging.h index 8f53c6b5e9e..c419e85d77b 100644 --- a/ctdb/include/ctdb_logging.h +++ b/ctdb/include/ctdb_logging.h @@ -43,7 +43,12 @@ const char *get_debug_by_level(int32_t level); bool parse_debug(const char *str, int32_t *level); void print_debug_levels(FILE *stream); -int ctdb_log_setup_syslog(void); -int ctdb_log_setup_file(TALLOC_CTX *mem_ctx, const char *f); +bool ctdb_logging_init(TALLOC_CTX *mem_ctx, const char *logging); +typedef int (*ctdb_log_setup_fn_t)(TALLOC_CTX *mem_ctx, + const char *logging, + const char *app_name); +void ctdb_log_register_backend(const char *prefix, ctdb_log_setup_fn_t init); +void ctdb_log_init_file(void); +void ctdb_log_init_syslog(void); #endif /* _CTDB_LOGGING_H_ */ diff --git a/ctdb/server/ctdb_logging.c b/ctdb/server/ctdb_logging.c index bc47dd273fe..85dbfcfcc00 100644 --- a/ctdb/server/ctdb_logging.c +++ b/ctdb/server/ctdb_logging.c @@ -24,6 +24,13 @@ #include "system/time.h" #include "system/filesys.h" #include "lib/util/debug.h" +#include "lib/util/dlinklist.h" + +struct ctdb_log_backend { + struct ctdb_log_backend *prev, *next; + const char *prefix; + ctdb_log_setup_fn_t setup; +}; struct ctdb_log_state { const char *prefix; @@ -32,16 +39,34 @@ struct ctdb_log_state { uint16_t buf_used; void (*logfn)(const char *, uint16_t, void *); void *logfn_private; + struct ctdb_log_backend *backends; }; -/* we need this global to keep the DEBUG() syntax */ +/* Used by ctdb_set_child_logging() */ static struct ctdb_log_state *log_state; -/* - choose the logfile location -*/ -int ctdb_set_logfile(TALLOC_CTX *mem_ctx, const char *logfile, bool use_syslog) +void ctdb_log_register_backend(const char *prefix, ctdb_log_setup_fn_t setup) { + struct ctdb_log_backend *b; + + b = talloc_zero(log_state, struct ctdb_log_backend); + if (b == NULL) { + printf("Failed to register backend \"%s\" - no memory\n", + prefix); + return; + } + + b->prefix = prefix; + b->setup = setup; + + DLIST_ADD_END(log_state->backends, b, NULL); +} + + +/* Initialise logging */ +bool ctdb_logging_init(TALLOC_CTX *mem_ctx, const char *logging) +{ + struct ctdb_log_backend *b; int ret; log_state = talloc_zero(mem_ctx, struct ctdb_log_state); @@ -50,22 +75,26 @@ int ctdb_set_logfile(TALLOC_CTX *mem_ctx, const char *logfile, bool use_syslog) abort(); } - if (use_syslog) { - ret = ctdb_log_setup_syslog(); - if (ret != 0) { - printf("Setup of syslog logging failed with \"%s\"\n", - strerror(ret)); - abort(); - } - } else { - ret = ctdb_log_setup_file(mem_ctx, logfile); - if (ret != 0) { - printf("Setup of file logging failed with \"%s\"\n", - strerror(ret)); - abort(); + ctdb_log_init_file(); + ctdb_log_init_syslog(); + + for (b = log_state->backends; b != NULL; b = b->next) { + size_t l = strlen(b->prefix); + /* Exact match with prefix or prefix followed by ':' */ + if (strncmp(b->prefix, logging, l) == 0 && + (logging[l] == '\0' || logging[l] == ':')) { + ret = b->setup(mem_ctx, logging, "ctdbd"); + if (ret == 0) { + return true; + } + printf("Log init for \"%s\" failed with \"%s\"\n", + logging, strerror(ret)); + return false; } } - return 0; + + printf("Unable to find log backend for \"%s\"\n", logging); + return false; } /* Note that do_debug always uses the global log state. */ diff --git a/ctdb/server/ctdb_logging_file.c b/ctdb/server/ctdb_logging_file.c index 28b72231d9d..f931b4a8b83 100644 --- a/ctdb/server/ctdb_logging_file.c +++ b/ctdb/server/ctdb_logging_file.c @@ -24,6 +24,8 @@ #include "system/filesys.h" #include "lib/util/time_basic.h" +#define CTDB_LOG_FILE_PREFIX "file" + struct file_state { int fd; }; @@ -64,9 +66,19 @@ static int file_state_destructor(struct file_state *state) return 0; } -int ctdb_log_setup_file(TALLOC_CTX *mem_ctx, const char *logfile) +static int ctdb_log_setup_file(TALLOC_CTX *mem_ctx, + const char *logging, + const char *app_name) { struct file_state *state; + const char *logfile; + size_t l; + + l = strlen(CTDB_LOG_FILE_PREFIX); + if (logging[l] != ':') { + return EINVAL; + } + logfile = &logging[0] + l + 1; state = talloc_zero(mem_ctx, struct file_state); if (state == NULL) { @@ -94,3 +106,8 @@ int ctdb_log_setup_file(TALLOC_CTX *mem_ctx, const char *logfile) return 0; } + +void ctdb_log_init_file(void) +{ + ctdb_log_register_backend(CTDB_LOG_FILE_PREFIX, ctdb_log_setup_file); +} diff --git a/ctdb/server/ctdb_logging_syslog.c b/ctdb/server/ctdb_logging_syslog.c index 382c7916e5a..58093375f2d 100644 --- a/ctdb/server/ctdb_logging_syslog.c +++ b/ctdb/server/ctdb_logging_syslog.c @@ -54,8 +54,15 @@ static void ctdb_log_to_syslog(void *private_ptr, int dbglevel, const char *s) "%s%s", debug_extra, s); } -int ctdb_log_setup_syslog(void) +static int ctdb_log_setup_syslog(TALLOC_CTX *mem_ctx, + const char *logging, + const char *app_name) { debug_set_callback(NULL, ctdb_log_to_syslog); return 0; } + +void ctdb_log_init_syslog(void) +{ + ctdb_log_register_backend("syslog", ctdb_log_setup_syslog); +} diff --git a/ctdb/server/ctdbd.c b/ctdb/server/ctdbd.c index 16a647ac48c..ec285c043cc 100644 --- a/ctdb/server/ctdbd.c +++ b/ctdb/server/ctdbd.c @@ -33,7 +33,7 @@ static struct { const char *public_address_list; const char *event_script_dir; const char *notification_script; - const char *logfile; + const char *logging; const char *recovery_lock_file; const char *db_dir; const char *db_dir_persistent; @@ -42,7 +42,6 @@ static struct { const char *single_public_ip; int valgrinding; int nosetsched; - int use_syslog; int start_as_disabled; int start_as_stopped; int no_lmaster; @@ -56,7 +55,7 @@ static struct { .public_address_list = NULL, .transport = "tcp", .event_script_dir = NULL, - .logfile = LOGDIR "/log.ctdb", + .logging = "file:" LOGDIR "/log.ctdb", .db_dir = CTDB_VARDIR, .db_dir_persistent = CTDB_VARDIR "/persistent", .db_dir_state = CTDB_VARDIR "/state", @@ -111,7 +110,7 @@ int main(int argc, const char *argv[]) { "public-interface", 0, POPT_ARG_STRING, &options.public_interface, 0, "public interface", "interface"}, { "single-public-ip", 0, POPT_ARG_STRING, &options.single_public_ip, 0, "single public ip", "ip-address"}, { "event-script-dir", 0, POPT_ARG_STRING, &options.event_script_dir, 0, "event script directory", "dirname" }, - { "logfile", 0, POPT_ARG_STRING, &options.logfile, 0, "log file location", "filename" }, + { "logging", 0, POPT_ARG_STRING, &options.logging, 0, "logging method to be used", NULL }, { "nlist", 0, POPT_ARG_STRING, &options.nlist, 0, "node list file", "filename" }, { "notification-script", 0, POPT_ARG_STRING, &options.notification_script, 0, "notification script", "filename" }, { "listen", 0, POPT_ARG_STRING, &options.myaddress, 0, "address to listen on", "address" }, @@ -123,7 +122,6 @@ int main(int argc, const char *argv[]) { "pidfile", 0, POPT_ARG_STRING, &ctdbd_pidfile, 0, "location of PID file", "filename" }, { "valgrinding", 0, POPT_ARG_NONE, &options.valgrinding, 0, "disable setscheduler SCHED_FIFO call, use mmap for tdbs", NULL }, { "nosetsched", 0, POPT_ARG_NONE, &options.nosetsched, 0, "disable setscheduler SCHED_FIFO call, use mmap for tdbs", NULL }, - { "syslog", 0, POPT_ARG_NONE, &options.use_syslog, 0, "log messages to syslog", NULL }, { "start-as-disabled", 0, POPT_ARG_NONE, &options.start_as_disabled, 0, "Node starts in disabled state", NULL }, { "start-as-stopped", 0, POPT_ARG_NONE, &options.start_as_stopped, 0, "Node starts in stopped state", NULL }, { "no-lmaster", 0, POPT_ARG_NONE, &options.no_lmaster, 0, "disable lmaster role on this node", NULL }, @@ -175,10 +173,7 @@ int main(int argc, const char *argv[]) script_log_level = options.script_log_level; - ret = ctdb_set_logfile(ctdb, options.logfile, options.use_syslog); - if (ret == -1) { - printf("ctdb_set_logfile to %s failed - %s\n", - options.use_syslog?"syslog":options.logfile, ctdb_errstr(ctdb)); + if (!ctdb_logging_init(ctdb, options.logging)) { exit(1); } diff --git a/ctdb/tests/eventscripts/scripts/local.sh b/ctdb/tests/eventscripts/scripts/local.sh index 8f31154c021..d14e42ec847 100644 --- a/ctdb/tests/eventscripts/scripts/local.sh +++ b/ctdb/tests/eventscripts/scripts/local.sh @@ -23,8 +23,9 @@ fi mkdir -p "$EVENTSCRIPTS_TESTS_VAR_DIR" export CTDB_VARDIR="$EVENTSCRIPTS_TESTS_VAR_DIR/ctdb" -export CTDB_LOGFILE="${EVENTSCRIPTS_TESTS_VAR_DIR}/log.ctdb" -touch "$CTDB_LOGFILE" || die "Unable to create CTDB_LOGFILE=$CTDB_LOGFILE" +export CTDB_LOGGING="file:${EVENTSCRIPTS_TESTS_VAR_DIR}/log.ctdb" +touch "${CTDB_LOGGING#file:}" || \ + die "Unable to setup logging for \"$CTDB_LOGGING\"" if [ -d "${TEST_SUBDIR}/etc" ] ; then cp -a "${TEST_SUBDIR}/etc" "$EVENTSCRIPTS_TESTS_VAR_DIR" diff --git a/ctdb/tests/simple/scripts/local_daemons.bash b/ctdb/tests/simple/scripts/local_daemons.bash index a227a5d1f27..58d679a5c7e 100644 --- a/ctdb/tests/simple/scripts/local_daemons.bash +++ b/ctdb/tests/simple/scripts/local_daemons.bash @@ -97,7 +97,7 @@ daemons_start_1 () fi local node_ip=$(sed -n -e "$(($pnn + 1))p" "$CTDB_NODES") - local ctdb_options="--sloppy-start --reclock=${TEST_VAR_DIR}/rec.lock --nlist $CTDB_NODES --nopublicipcheck --listen=${node_ip} --event-script-dir=${TEST_VAR_DIR}/events.d --logfile=${TEST_VAR_DIR}/daemon.${pnn}.log -d 3 --dbdir=${TEST_VAR_DIR}/test.db --dbdir-persistent=${TEST_VAR_DIR}/test.db/persistent --dbdir-state=${TEST_VAR_DIR}/test.db/state --nosetsched" + local ctdb_options="--sloppy-start --reclock=${TEST_VAR_DIR}/rec.lock --nlist $CTDB_NODES --nopublicipcheck --listen=${node_ip} --event-script-dir=${TEST_VAR_DIR}/events.d --logging=file:${TEST_VAR_DIR}/daemon.${pnn}.log -d 3 --dbdir=${TEST_VAR_DIR}/test.db --dbdir-persistent=${TEST_VAR_DIR}/test.db/persistent --dbdir-state=${TEST_VAR_DIR}/test.db/state --nosetsched" if [ $pnn -eq $no_public_ips ] ; then ctdb_options="$ctdb_options --public-addresses=/dev/null" -- 2.11.4.GIT