summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/logging.txt65
-rw-r--r--libglusterfs/src/logging.c121
-rw-r--r--libglusterfs/src/logging.h3
3 files changed, 170 insertions, 19 deletions
diff --git a/doc/logging.txt b/doc/logging.txt
new file mode 100644
index 0000000..d1e568a
--- /dev/null
+++ b/doc/logging.txt
@@ -0,0 +1,65 @@
+
+New logging framework in glusterfs is targeted for end users like
+customers, community members, testers etc. This aims to bring clear,
+understandable logs called user logs whereas the current logging are
+considered as developer logs. The new framework brings with following
+features
+
+* Each message is logged with proper well defined error code and each
+ error code has well known error message.
+* A logbook has defined error code and error messages. It helps to
+ keep track of possible causes and remedies
+* Log are sent to syslog. The syslog application can be configured to
+ pass them to centralized logging system
+* It brings
+ - Remove repeated log messages
+ - Send alerts to users on certain events
+ - Run a program on events
+ - Call home service on events
+
+
+Log book:
+=========
+A log book is a JSON formatted file error-codes.json located in top
+level of glusterfs source repository. At compile time, gen-headers.py
+generates libglusterfs/src/gf-error-codes.h using the log book and
+gf-error-codes.h.template file. libglusterfs/src/gf-error-codes.h
+consists of header definitions and helper functions to get message by
+code for given locale. Currently it has _gf_get_message() function
+returns message for locale 'en'.
+
+New entry to log book is added like
+
+{
+ "IO_ERROR": {"code": 2233,
+ "message": {"en": "I/O error occurred"}},
+ "SETUP_ERROR": {"code": 2240,
+ "message": {"en": "Setup error"}},
+}
+
+
+Logging:
+========
+The framework provides two functions
+
+void gf_openlog (const char *ident, int option, int facility);
+void gf_syslog (int error_code, int facility_priority, char *format, ...);
+
+Consumers need to call gf_openlog() prior to gf_syslog() like the way
+traditional syslog function calls. error_code is mandatory when using
+gf_syslog(). For example,
+
+gf_openlog (NULL, -1, -1);
+gf_syslog (GF_ERR_DEV, LOG_ERR, "error reading configuration file");
+
+The logs are sent in CEE format (http://cee.mitre.org/) to syslog.
+Its targeted to rsyslog syslog server.
+
+This log framework can be disabled either at compile time or run time
+
+- for compile time by passing '--disable-syslog' to ./configure or
+ '--without syslog' to rpmbuild (or)
+- for run time by having a file /var/log/glusterd/logger.conf and
+ restarting gluster services
+
+Currently all gluster logs are sent with error code GF_ERR_DEV.
diff --git a/libglusterfs/src/logging.c b/libglusterfs/src/logging.c
index b74a486..14000ee 100644
--- a/libglusterfs/src/logging.c
+++ b/libglusterfs/src/logging.c
@@ -25,11 +25,13 @@
#ifdef GF_USE_SYSLOG
#include <libintl.h>
#include <syslog.h>
+#include <sys/stat.h>
#include "gf-error-codes.h"
#define GF_JSON_MSG_LENGTH 8192
#define GF_SYSLOG_CEE_FORMAT \
"@cee: {\"msg\": \"%s\", \"gf_code\": \"%u\", \"gf_message\": \"%s\"}"
+#define GF_LOG_CONTROL_FILE "/var/lib/glusterd/logger.conf"
#endif /* GF_USE_SYSLOG */
#include "xlator.h"
@@ -324,7 +326,20 @@ gf_log_globals_init (void *data)
ctx->log.gf_log_syslog = 1;
ctx->log.sys_log_level = GF_LOG_CRITICAL;
-#ifdef GF_LINUX_HOST_OS
+#if defined(GF_USE_SYSLOG)
+ {
+ /* use default ident and option */
+ /* TODO: make FACILITY configurable than LOG_DAEMON */
+ struct stat buf;
+
+ if (stat (GF_LOG_CONTROL_FILE, &buf) == 0) {
+ ctx->log.log_control_file_found = 1; /* use gf_log */
+ } else {
+ ctx->log.log_control_file_found = 0;
+ gf_openlog (NULL, -1, LOG_DAEMON);
+ }
+ }
+#elif defined(GF_LINUX_HOST_OS)
/* For the 'syslog' output. one can grep 'GlusterFS' in syslog
for serious logs */
openlog ("GlusterFS", LOG_PID, LOG_DAEMON);
@@ -426,6 +441,12 @@ _gf_log_nomem (const char *domain, const char *file,
return -1;
}
+ basename = strrchr (file, '/');
+ if (basename)
+ basename++;
+ else
+ basename = file;
+
#if HAVE_BACKTRACE
/* Print 'calling function' */
do {
@@ -452,6 +473,25 @@ _gf_log_nomem (const char *domain, const char *file,
} while (0);
#endif /* HAVE_BACKTRACE */
+#if defined(GF_USE_SYSLOG)
+ if (!(ctx->log.log_control_file_found))
+ {
+ int priority;
+ /* treat GF_LOG_TRACE and GF_LOG_NONE as LOG_DEBUG and
+ other level as is */
+ if (GF_LOG_TRACE == level || GF_LOG_NONE == level) {
+ priority = LOG_DEBUG;
+ } else {
+ priority = level - 1;
+ }
+ gf_syslog (GF_ERR_DEV, priority,
+ "[%s:%d:%s] %s %s: no memory "
+ "available for size (%"GF_PRI_SIZET")",
+ basename, line, function, callstr, domain,
+ size);
+ goto out;
+ }
+#endif /* GF_USE_SYSLOG */
ret = gettimeofday (&tv, NULL);
if (-1 == ret)
goto out;
@@ -459,12 +499,6 @@ _gf_log_nomem (const char *domain, const char *file,
snprintf (timestr + strlen (timestr), sizeof timestr - strlen (timestr),
".%"GF_PRI_SUSECONDS, tv.tv_usec);
- basename = strrchr (file, '/');
- if (basename)
- basename++;
- else
- basename = file;
-
ret = sprintf (msg, "[%s] %s [%s:%d:%s] %s %s: no memory "
"available for size (%"GF_PRI_SIZET")",
timestr, level_strings[level],
@@ -542,6 +576,12 @@ _gf_log_callingfn (const char *domain, const char *file, const char *function,
return -1;
}
+ basename = strrchr (file, '/');
+ if (basename)
+ basename++;
+ else
+ basename = file;
+
#if HAVE_BACKTRACE
/* Print 'calling function' */
do {
@@ -568,6 +608,32 @@ _gf_log_callingfn (const char *domain, const char *file, const char *function,
} while (0);
#endif /* HAVE_BACKTRACE */
+#if defined(GF_USE_SYSLOG)
+ if (!(ctx->log.log_control_file_found))
+ {
+ int priority;
+ /* treat GF_LOG_TRACE and GF_LOG_NONE as LOG_DEBUG and
+ other level as is */
+ if (GF_LOG_TRACE == level || GF_LOG_NONE == level) {
+ priority = LOG_DEBUG;
+ } else {
+ priority = level - 1;
+ }
+
+ va_start (ap, fmt);
+ vasprintf (&str2, fmt, ap);
+ va_end (ap);
+
+ gf_syslog (GF_ERR_DEV, priority,
+ "[%s:%d:%s] %s %d-%s: %s",
+ basename, line, function,
+ callstr,
+ ((this->graph) ? this->graph->id:0), domain,
+ str2);
+
+ goto out;
+ }
+#endif /* GF_USE_SYSLOG */
ret = gettimeofday (&tv, NULL);
if (-1 == ret)
goto out;
@@ -576,12 +642,6 @@ _gf_log_callingfn (const char *domain, const char *file, const char *function,
snprintf (timestr + strlen (timestr), sizeof timestr - strlen (timestr),
".%"GF_PRI_SUSECONDS, tv.tv_usec);
- basename = strrchr (file, '/');
- if (basename)
- basename++;
- else
- basename = file;
-
ret = gf_asprintf (&str1, "[%s] %s [%s:%d:%s] %s %d-%s: ",
timestr, level_strings[level],
basename, line, function, callstr,
@@ -679,6 +739,35 @@ _gf_log (const char *domain, const char *file, const char *function, int line,
return -1;
}
+ basename = strrchr (file, '/');
+ if (basename)
+ basename++;
+ else
+ basename = file;
+
+#if defined(GF_USE_SYSLOG)
+ if (!(ctx->log.log_control_file_found))
+ {
+ int priority;
+ /* treat GF_LOG_TRACE and GF_LOG_NONE as LOG_DEBUG and
+ other level as is */
+ if (GF_LOG_TRACE == level || GF_LOG_NONE == level) {
+ priority = LOG_DEBUG;
+ } else {
+ priority = level - 1;
+ }
+
+ va_start (ap, fmt);
+ vasprintf (&str2, fmt, ap);
+ va_end (ap);
+
+ gf_syslog (GF_ERR_DEV, priority,
+ "[%s:%d:%s] %d-%s: %s",
+ basename, line, function,
+ ((this->graph) ? this->graph->id:0), domain, str2);
+ goto err;
+ }
+#endif /* GF_USE_SYSLOG */
if (ctx->log.logrotate) {
ctx->log.logrotate = 0;
@@ -720,12 +809,6 @@ log:
snprintf (timestr + strlen (timestr), sizeof timestr - strlen (timestr),
".%"GF_PRI_SUSECONDS, tv.tv_usec);
- basename = strrchr (file, '/');
- if (basename)
- basename++;
- else
- basename = file;
-
ret = gf_asprintf (&str1, "[%s] %s [%s:%d:%s] %d-%s: ",
timestr, level_strings[level],
basename, line, function,
diff --git a/libglusterfs/src/logging.h b/libglusterfs/src/logging.h
index d08f944..3c65bf4 100644
--- a/libglusterfs/src/logging.h
+++ b/libglusterfs/src/logging.h
@@ -72,6 +72,9 @@ typedef struct gf_log_handle_ {
FILE *gf_log_logfile;
char *cmd_log_filename;
FILE *cmdlogfile;
+#ifdef GF_USE_SYSLOG
+ int log_control_file_found;
+#endif /* GF_USE_SYSLOG */
} gf_log_handle_t;