log: send current gf_log to syslog conditionally
When compile time option GF_USE_SYSLOG is enabled (which is default), generated logs are sent to syslog with error code ERR_DEV. User can opt to use traditional log at run time by creating /var/log/glusterd/logger.conf file and restarting respective gluster services. Change-Id: I9837d0f99da1afc2189d7ecd214c4293ec53715a BUG: 928648 Signed-off-by: Bala.FA <barumuga@redhat.com> Reviewed-on: http://review.gluster.org/5002 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Vijay Bellur <vbellur@redhat.com>
This commit is contained in:
parent
040319d8bc
commit
41b721baee
65
doc/logging.txt
Normal file
65
doc/logging.txt
Normal file
@ -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.
|
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user