# 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
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"
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"
}
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
{
_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
<listitem>
<para>
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.
</para>
<para>
See the <citetitle>DEBUG LEVELS</citetitle> section in
</varlistentry>
<varlistentry>
- <term>--logfile=<parameter>FILENAME</parameter></term>
+ <term>--logging=<parameter>STRING</parameter></term>
<listitem>
<para>
- FILENAME where ctdbd will write its log. This is usually
- <filename>/var/log/log.ctdb</filename>.
- </para>
+ STRING specifies where ctdbd will write its log. The
+ default is file:<filename>/var/log/log.ctdb</filename> or
+ similar - the prefix may differ depending on how CTDB was
+ built.
+ </para>
+ <para>
+ Valid values are:
+ </para>
+ <variablelist>
+ <varlistentry>
+ <term>file:<parameter>FILENAME</parameter></term>
+ <listitem>
+ <para>
+ FILENAME where ctdbd will write its log. This is usually
+ <filename>/var/log/log.ctdb</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>syslog</term>
+ <listitem>
+ <para>
+ CTDB will log to syslog
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
</listitem>
</varlistentry>
</varlistentry>
<varlistentry>
- <term>CTDB_LOGFILE=<parameter>FILENAME</parameter></term>
+ <term>CTDB_LOGGING=<parameter>STRING</parameter></term>
<listitem>
<para>
- Defaults to <filename>/var/log/log.ctdb</filename>.
- Corresponds to <option>--logfile</option>. See also
- <citetitle>CTDB_SYSLOG</citetitle>.
+ STRING specifies where ctdbd will write its log. The
+ default is file:<filename>/var/log/log.ctdb</filename> or
+ similar - the prefix may differ depending on how CTDB was
+ built. Corresponds to <option>--logging</option>.
</para>
+ <para>
+ Valid values are:
+ </para>
+ <variablelist>
+ <varlistentry>
+ <term>file:<parameter>FILENAME</parameter></term>
+ <listitem>
+ <para>
+ FILENAME where ctdbd will write its log. This is usually
+ <filename>/var/log/log.ctdb</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>syslog</term>
+ <listitem>
+ <para>
+ CTDB will log to syslog
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
</listitem>
</varlistentry>
</listitem>
</varlistentry>
- <varlistentry>
- <term>CTDB_SYSLOG=yes|no</term>
- <listitem>
- <para>
- Default is no. Corresponds to <option>--syslog</option>.
- </para>
- </listitem>
- </varlistentry>
-
<varlistentry>
<term>CTDB_TRANSPORT=tcp|infiniband</term>
<listitem>
CTDB_PUBLIC_ADDRESSES=/etc/ctdb/public_addresses
# Enable logging to syslog
-CTDB_SYSLOG=yes
+CTDB_LOGGING=syslog
# Default log level
CTDB_DEBUGLEVEL=NOTICE
CTDB_PUBLIC_ADDRESSES=/etc/ctdb/public_addresses
# Enable logging to syslog
-CTDB_SYSLOG=yes
+CTDB_LOGGING=syslog
# Default log level
CTDB_DEBUGLEVEL=NOTICE
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);
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_ */
#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;
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);
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. */
#include "system/filesys.h"
#include "lib/util/time_basic.h"
+#define CTDB_LOG_FILE_PREFIX "file"
+
struct file_state {
int fd;
};
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) {
return 0;
}
+
+void ctdb_log_init_file(void)
+{
+ ctdb_log_register_backend(CTDB_LOG_FILE_PREFIX, ctdb_log_setup_file);
+}
"%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);
+}
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;
const char *single_public_ip;
int valgrinding;
int nosetsched;
- int use_syslog;
int start_as_disabled;
int start_as_stopped;
int no_lmaster;
.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",
{ "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" },
{ "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 },
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);
}
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"
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"