|
Packit Service |
e080da |
/*
|
|
Packit Service |
e080da |
Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
|
|
Packit Service |
e080da |
This file is part of GlusterFS.
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
This file is licensed to you under your choice of the GNU Lesser
|
|
Packit Service |
e080da |
General Public License, version 3 or any later version (LGPLv3 or
|
|
Packit Service |
e080da |
later), or the GNU General Public License, version 2 (GPLv2), in all
|
|
Packit Service |
e080da |
cases as published by the Free Software Foundation.
|
|
Packit Service |
e080da |
*/
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
#include <errno.h>
|
|
Packit Service |
e080da |
#include <pthread.h>
|
|
Packit Service |
e080da |
#include <stdio.h>
|
|
Packit Service |
e080da |
#include <stdarg.h>
|
|
Packit Service |
e080da |
#include <time.h>
|
|
Packit Service |
e080da |
#include <locale.h>
|
|
Packit Service |
e080da |
#include <string.h>
|
|
Packit Service |
e080da |
#include <stdlib.h>
|
|
Packit Service |
e080da |
#include <syslog.h>
|
|
Packit Service |
173fb3 |
#include <sys/resource.h>
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
#ifdef HAVE_BACKTRACE
|
|
Packit Service |
e080da |
#include <execinfo.h>
|
|
Packit Service |
e080da |
#else
|
|
Packit Service |
e080da |
#include "execinfo_compat.h"
|
|
Packit Service |
e080da |
#endif
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
#include <sys/stat.h>
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
#include "glusterfs/syscall.h"
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
#define GF_JSON_MSG_LENGTH 8192
|
|
Packit Service |
e080da |
#define GF_SYSLOG_CEE_FORMAT \
|
|
Packit Service |
e080da |
"@cee: {\"msg\": \"%s\", \"gf_code\": \"%u\", \"gf_message\": \"%s\"}"
|
|
Packit Service |
e080da |
#define GF_LOG_CONTROL_FILE "/etc/glusterfs/logger.conf"
|
|
Packit Service |
e080da |
#define GF_LOG_BACKTRACE_DEPTH 5
|
|
Packit Service |
e080da |
#define GF_LOG_BACKTRACE_SIZE 4096
|
|
Packit Service |
e080da |
#define GF_LOG_TIMESTR_SIZE 256
|
|
Packit Service |
e080da |
#define GF_MAX_SLOG_PAIR_COUNT 100
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
#include "glusterfs/xlator.h"
|
|
Packit Service |
e080da |
#include "glusterfs/logging.h"
|
|
Packit Service |
e080da |
#include "glusterfs/defaults.h"
|
|
Packit Service |
e080da |
#include "glusterfs/glusterfs.h"
|
|
Packit Service |
e080da |
#include "glusterfs/timer.h"
|
|
Packit Service |
e080da |
#include "glusterfs/libglusterfs-messages.h"
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* Do not replace gf_log in TEST_LOG with gf_msg, as there is a slight chance
|
|
Packit Service |
e080da |
* that it could lead to an infinite recursion.*/
|
|
Packit Service |
e080da |
#define TEST_LOG(__msg, __args...) \
|
|
Packit Service |
e080da |
gf_log("logging-infra", GF_LOG_DEBUG, __msg, ##__args);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
void
|
|
Packit Service |
e080da |
gf_log_flush_timeout_cbk(void *data);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
int
|
|
Packit Service |
e080da |
gf_log_inject_timer_event(glusterfs_ctx_t *ctx);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
static void
|
|
Packit Service |
e080da |
gf_log_flush_extra_msgs(glusterfs_ctx_t *ctx, uint32_t new);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
static char *gf_level_strings[] = {"", /* NONE */
|
|
Packit Service |
e080da |
"M", /* EMERGENCY */
|
|
Packit Service |
e080da |
"A", /* ALERT */
|
|
Packit Service |
e080da |
"C", /* CRITICAL */
|
|
Packit Service |
e080da |
"E", /* ERROR */
|
|
Packit Service |
e080da |
"W", /* WARNING */
|
|
Packit Service |
e080da |
"N", /* NOTICE */
|
|
Packit Service |
e080da |
"I", /* INFO */
|
|
Packit Service |
e080da |
"D", /* DEBUG */
|
|
Packit Service |
e080da |
"T", /* TRACE */
|
|
Packit Service |
e080da |
""};
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* Ideally this should get moved to logging.h */
|
|
Packit Service |
e080da |
struct _msg_queue {
|
|
Packit Service |
e080da |
struct list_head msgs;
|
|
Packit Service |
e080da |
};
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
struct _log_msg {
|
|
Packit Service |
e080da |
const char *msg;
|
|
Packit Service |
e080da |
struct list_head queue;
|
|
Packit Service |
e080da |
};
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
void
|
|
Packit Service |
e080da |
gf_log_logrotate(int signum)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
glusterfs_ctx_t *ctx = NULL;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ctx = THIS->ctx;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (ctx) {
|
|
Packit Service |
e080da |
ctx->log.logrotate = 1;
|
|
Packit Service |
e080da |
ctx->log.cmd_history_logrotate = 1;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
void
|
|
Packit Service |
e080da |
gf_log_enable_syslog(void)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
glusterfs_ctx_t *ctx = NULL;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ctx = THIS->ctx;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (ctx)
|
|
Packit Service |
e080da |
ctx->log.gf_log_syslog = 1;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
void
|
|
Packit Service |
e080da |
gf_log_disable_syslog(void)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
glusterfs_ctx_t *ctx = NULL;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ctx = THIS->ctx;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (ctx)
|
|
Packit Service |
e080da |
ctx->log.gf_log_syslog = 0;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
gf_loglevel_t
|
|
Packit Service |
e080da |
gf_log_get_loglevel(void)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
glusterfs_ctx_t *ctx = NULL;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ctx = THIS->ctx;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (ctx)
|
|
Packit Service |
e080da |
return ctx->log.loglevel;
|
|
Packit Service |
e080da |
else
|
|
Packit Service |
e080da |
/* return global defaults (see gf_log_globals_init) */
|
|
Packit Service |
e080da |
return GF_LOG_INFO;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
void
|
|
Packit Service |
e080da |
gf_log_set_loglevel(glusterfs_ctx_t *ctx, gf_loglevel_t level)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
if (ctx)
|
|
Packit Service |
e080da |
ctx->log.loglevel = level;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
int
|
|
Packit Service |
e080da |
gf_log_get_localtime(void)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
glusterfs_ctx_t *ctx = NULL;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ctx = THIS->ctx;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (ctx)
|
|
Packit Service |
e080da |
return ctx->log.localtime;
|
|
Packit Service |
e080da |
else
|
|
Packit Service |
e080da |
/* return global defaults (see gf_log_globals_init) */
|
|
Packit Service |
e080da |
return 0;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
void
|
|
Packit Service |
e080da |
gf_log_set_localtime(int on_off)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
glusterfs_ctx_t *ctx = NULL;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ctx = THIS->ctx;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (ctx)
|
|
Packit Service |
e080da |
ctx->log.localtime = on_off;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
void
|
|
Packit Service |
e080da |
gf_log_flush(void)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
xlator_t *this = NULL;
|
|
Packit Service |
e080da |
glusterfs_ctx_t *ctx = NULL;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
this = THIS;
|
|
Packit Service |
e080da |
ctx = this->ctx;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (ctx && ctx->log.logger == gf_logger_glusterlog) {
|
|
Packit Service |
e080da |
pthread_mutex_lock(&ctx->log.logfile_mutex);
|
|
Packit Service |
e080da |
fflush(ctx->log.gf_log_logfile);
|
|
Packit Service |
e080da |
pthread_mutex_unlock(&ctx->log.logfile_mutex);
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
return;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
void
|
|
Packit Service |
e080da |
gf_log_set_xl_loglevel(void *this, gf_loglevel_t level)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
xlator_t *xl = this;
|
|
Packit Service |
e080da |
if (!xl)
|
|
Packit Service |
e080da |
return;
|
|
Packit Service |
e080da |
xl->loglevel = level;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* TODO: The following get/set functions are yet not invoked from anywhere
|
|
Packit Service |
e080da |
* in the code. The _intention_ is to pass CLI arguments to various daemons
|
|
Packit Service |
e080da |
* that are started, which would then invoke these set APIs as required.
|
|
Packit Service |
e080da |
*
|
|
Packit Service |
e080da |
* glusterd would read the defaults from its .vol file configuration shipped
|
|
Packit Service |
e080da |
* as a part of the packages distributed.
|
|
Packit Service |
e080da |
*
|
|
Packit Service |
e080da |
* For any gluster* daemon that is started the shipped configuration becomes the
|
|
Packit Service |
e080da |
* default, if a volume has to change its logging format or logger, then a
|
|
Packit Service |
e080da |
* gluster CLI is invoked to set this property for the volume in question.
|
|
Packit Service |
e080da |
*
|
|
Packit Service |
e080da |
* The property is maintained by glusterd, and passed to the daemon as a CLI
|
|
Packit Service |
e080da |
* option, IOW persistence of the option is maintained by glusterd persistent
|
|
Packit Service |
e080da |
* storage (i.e .vol file) only
|
|
Packit Service |
e080da |
*
|
|
Packit Service |
e080da |
* care needs to be taken to configure and start daemons based on the versions
|
|
Packit Service |
e080da |
* that supports these features */
|
|
Packit Service |
e080da |
gf_log_format_t
|
|
Packit Service |
e080da |
gf_log_get_logformat(void)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
glusterfs_ctx_t *ctx = NULL;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ctx = THIS->ctx;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (ctx)
|
|
Packit Service |
e080da |
return ctx->log.logformat;
|
|
Packit Service |
e080da |
else
|
|
Packit Service |
e080da |
/* return global defaluts (see gf_log_globals_init) */
|
|
Packit Service |
e080da |
return gf_logformat_withmsgid;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
void
|
|
Packit Service |
e080da |
gf_log_set_logformat(gf_log_format_t format)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
glusterfs_ctx_t *ctx = NULL;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ctx = THIS->ctx;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (ctx)
|
|
Packit Service |
e080da |
ctx->log.logformat = format;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
gf_log_logger_t
|
|
Packit Service |
e080da |
gf_log_get_logger(void)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
glusterfs_ctx_t *ctx = NULL;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ctx = THIS->ctx;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (ctx)
|
|
Packit Service |
e080da |
return ctx->log.logger;
|
|
Packit Service |
e080da |
else
|
|
Packit Service |
e080da |
/* return global defaluts (see gf_log_globals_init) */
|
|
Packit Service |
e080da |
return gf_logger_glusterlog;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
void
|
|
Packit Service |
e080da |
gf_log_set_logger(gf_log_logger_t logger)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
glusterfs_ctx_t *ctx = NULL;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ctx = THIS->ctx;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (ctx)
|
|
Packit Service |
e080da |
ctx->log.logger = logger;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
gf_loglevel_t
|
|
Packit Service |
e080da |
gf_log_get_xl_loglevel(void *this)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
xlator_t *xl = this;
|
|
Packit Service |
e080da |
if (!xl)
|
|
Packit Service |
e080da |
return 0;
|
|
Packit Service |
e080da |
return xl->loglevel;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
void
|
|
Packit Service |
e080da |
gf_log_set_log_buf_size(uint32_t buf_size)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
uint32_t old = 0;
|
|
Packit Service |
e080da |
glusterfs_ctx_t *ctx = THIS->ctx;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
pthread_mutex_lock(&ctx->log.log_buf_lock);
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
old = ctx->log.lru_size;
|
|
Packit Service |
e080da |
ctx->log.lru_size = buf_size;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
pthread_mutex_unlock(&ctx->log.log_buf_lock);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* If the old size is less than/equal to the new size, then do nothing.
|
|
Packit Service |
e080da |
*
|
|
Packit Service |
e080da |
* But if the new size is less than the old size, then
|
|
Packit Service |
e080da |
* a. If the cur size of the buf is less than or equal the new size,
|
|
Packit Service |
e080da |
* then do nothing.
|
|
Packit Service |
e080da |
* b. But if the current size of the buf is greater than the new size,
|
|
Packit Service |
e080da |
* then flush the least recently used (cur size - new_size) msgs
|
|
Packit Service |
e080da |
* to disk.
|
|
Packit Service |
e080da |
*/
|
|
Packit Service |
e080da |
if (buf_size < old)
|
|
Packit Service |
e080da |
gf_log_flush_extra_msgs(ctx, buf_size);
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
void
|
|
Packit Service |
e080da |
gf_log_set_log_flush_timeout(uint32_t timeout)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
THIS->ctx->log.timeout = timeout;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
log_buf_t *
|
|
Packit Service |
e080da |
log_buf_new()
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
log_buf_t *buf = NULL;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
buf = mem_get0(THIS->ctx->logbuf_pool);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
return buf;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* If log_buf_init() fails (indicated by a return value of -1),
|
|
Packit Service |
e080da |
* call log_buf_destroy() to clean up memory allocated in heap and to return
|
|
Packit Service |
e080da |
* the log_buf_t object back to its memory pool.
|
|
Packit Service |
e080da |
*/
|
|
Packit Service |
e080da |
int
|
|
Packit Service |
e080da |
log_buf_init(log_buf_t *buf, const char *domain, const char *file,
|
|
Packit Service |
e080da |
const char *function, int32_t line, gf_loglevel_t level,
|
|
Packit Service |
e080da |
int errnum, uint64_t msgid, char **appmsgstr, int graph_id)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
int ret = -1;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (!buf || !domain || !file || !function || !appmsgstr || !*appmsgstr)
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
buf->msg = gf_strdup(*appmsgstr);
|
|
Packit Service |
e080da |
if (!buf->msg)
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
buf->msg_id = msgid;
|
|
Packit Service |
e080da |
buf->errnum = errnum;
|
|
Packit Service |
e080da |
buf->domain = gf_strdup(domain);
|
|
Packit Service |
e080da |
if (!buf->domain)
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
buf->file = gf_strdup(file);
|
|
Packit Service |
e080da |
if (!buf->file)
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
buf->function = gf_strdup(function);
|
|
Packit Service |
e080da |
if (!buf->function)
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
buf->line = line;
|
|
Packit Service |
e080da |
buf->level = level;
|
|
Packit Service |
e080da |
buf->refcount = 0;
|
|
Packit Service |
e080da |
buf->graph_id = graph_id;
|
|
Packit Service |
e080da |
INIT_LIST_HEAD(&buf->msg_list);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ret = 0;
|
|
Packit Service |
e080da |
out:
|
|
Packit Service |
e080da |
return ret;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
int
|
|
Packit Service |
e080da |
log_buf_destroy(log_buf_t *buf)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
if (!buf)
|
|
Packit Service |
e080da |
return -1;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
GF_FREE(buf->msg);
|
|
Packit Service |
e080da |
GF_FREE(buf->domain);
|
|
Packit Service |
e080da |
GF_FREE(buf->file);
|
|
Packit Service |
e080da |
GF_FREE(buf->function);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
mem_put(buf);
|
|
Packit Service |
e080da |
return 0;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
static void
|
|
Packit Service |
e080da |
gf_log_rotate(glusterfs_ctx_t *ctx)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
int fd = -1;
|
|
Packit Service |
e080da |
FILE *new_logfile = NULL;
|
|
Packit Service |
e080da |
FILE *old_logfile = NULL;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* not involving locks on initial check to speed it up */
|
|
Packit Service |
e080da |
if (ctx->log.logrotate) {
|
|
Packit Service |
e080da |
/* let only one winner through on races */
|
|
Packit Service |
e080da |
pthread_mutex_lock(&ctx->log.logfile_mutex);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (!ctx->log.logrotate) {
|
|
Packit Service |
e080da |
pthread_mutex_unlock(&ctx->log.logfile_mutex);
|
|
Packit Service |
e080da |
return;
|
|
Packit Service |
e080da |
} else {
|
|
Packit Service |
e080da |
ctx->log.logrotate = 0;
|
|
Packit Service |
e080da |
pthread_mutex_unlock(&ctx->log.logfile_mutex);
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
fd = sys_open(ctx->log.filename, O_CREAT | O_WRONLY | O_APPEND,
|
|
Packit Service |
e080da |
S_IRUSR | S_IWUSR);
|
|
Packit Service |
e080da |
if (fd < 0) {
|
|
Packit Service |
e080da |
gf_msg("logrotate", GF_LOG_ERROR, errno, LG_MSG_FILE_OP_FAILED,
|
|
Packit Service |
e080da |
"failed to open "
|
|
Packit Service |
e080da |
"logfile");
|
|
Packit Service |
e080da |
return;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
new_logfile = fdopen(fd, "a");
|
|
Packit Service |
e080da |
if (!new_logfile) {
|
|
Packit Service |
e080da |
gf_msg("logrotate", GF_LOG_CRITICAL, errno, LG_MSG_FILE_OP_FAILED,
|
|
Packit Service |
e080da |
"failed to open logfile"
|
|
Packit Service |
e080da |
" %s",
|
|
Packit Service |
e080da |
ctx->log.filename);
|
|
Packit Service |
e080da |
sys_close(fd);
|
|
Packit Service |
e080da |
return;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
pthread_mutex_lock(&ctx->log.logfile_mutex);
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
if (ctx->log.logfile)
|
|
Packit Service |
e080da |
old_logfile = ctx->log.logfile;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ctx->log.gf_log_logfile = ctx->log.logfile = new_logfile;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
pthread_mutex_unlock(&ctx->log.logfile_mutex);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (old_logfile != NULL)
|
|
Packit Service |
e080da |
fclose(old_logfile);
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
return;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
void
|
|
Packit Service |
e080da |
gf_log_globals_fini(void)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
/* TODO: Nobody is invoking the fini, but cleanup needs to happen here,
|
|
Packit Service |
e080da |
* needs cleanup for, log.ident, log.filename, closelog, log file close
|
|
Packit Service |
e080da |
* rotate state, possibly under a lock */
|
|
Packit Service |
e080da |
pthread_mutex_destroy(&THIS->ctx->log.logfile_mutex);
|
|
Packit Service |
e080da |
pthread_mutex_destroy(&THIS->ctx->log.log_buf_lock);
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
void
|
|
Packit Service |
e080da |
gf_log_disable_suppression_before_exit(glusterfs_ctx_t *ctx)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
/*
|
|
Packit Service |
e080da |
* First set log buf size to 0. This would ensure two things:
|
|
Packit Service |
e080da |
* i. that all outstanding log messages are flushed to disk, and
|
|
Packit Service |
e080da |
* ii. all subsequent calls to gf_msg will result in the logs getting
|
|
Packit Service |
e080da |
* directly flushed to disk without being buffered.
|
|
Packit Service |
e080da |
*
|
|
Packit Service |
e080da |
* Then, cancel the current log timer event.
|
|
Packit Service |
e080da |
*/
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
gf_log_set_log_buf_size(0);
|
|
Packit Service |
e080da |
pthread_mutex_lock(&ctx->log.log_buf_lock);
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
if (ctx->log.log_flush_timer) {
|
|
Packit Service |
e080da |
gf_timer_call_cancel(ctx, ctx->log.log_flush_timer);
|
|
Packit Service |
e080da |
ctx->log.log_flush_timer = NULL;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
pthread_mutex_unlock(&ctx->log.log_buf_lock);
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/** gf_log_fini - function to perform the cleanup of the log information
|
|
Packit Service |
e080da |
* @data - glusterfs context
|
|
Packit Service |
e080da |
* @return: success: 0
|
|
Packit Service |
e080da |
* failure: -1
|
|
Packit Service |
e080da |
*/
|
|
Packit Service |
e080da |
int
|
|
Packit Service |
e080da |
gf_log_fini(void *data)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
glusterfs_ctx_t *ctx = data;
|
|
Packit Service |
e080da |
int ret = 0;
|
|
Packit Service |
e080da |
FILE *old_logfile = NULL;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (ctx == NULL) {
|
|
Packit Service |
e080da |
ret = -1;
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
gf_log_disable_suppression_before_exit(ctx);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
pthread_mutex_lock(&ctx->log.logfile_mutex);
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
if (ctx->log.logfile) {
|
|
Packit Service |
e080da |
old_logfile = ctx->log.logfile;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* Logfile needs to be set to NULL, so that any
|
|
Packit Service |
e080da |
call to gf_log after calling gf_log_fini, will
|
|
Packit Service |
e080da |
log the message to stderr.
|
|
Packit Service |
e080da |
*/
|
|
Packit Service |
e080da |
ctx->log.loglevel = GF_LOG_NONE;
|
|
Packit Service |
e080da |
ctx->log.logfile = NULL;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
pthread_mutex_unlock(&ctx->log.logfile_mutex);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (old_logfile && (fclose(old_logfile) != 0))
|
|
Packit Service |
e080da |
ret = -1;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
GF_FREE(ctx->log.ident);
|
|
Packit Service |
e080da |
GF_FREE(ctx->log.filename);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
out:
|
|
Packit Service |
e080da |
return ret;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/**
|
|
Packit Service |
e080da |
* gf_openlog -function to open syslog specific to gluster based on
|
|
Packit Service |
e080da |
* existence of file /etc/glusterfs/logger.conf
|
|
Packit Service |
e080da |
* @ident: optional identification string similar to openlog()
|
|
Packit Service |
e080da |
* @option: optional value to option to openlog(). Passing -1 uses
|
|
Packit Service |
e080da |
* 'LOG_PID | LOG_NDELAY' as default
|
|
Packit Service |
e080da |
* @facility: optional facility code similar to openlog(). Passing -1
|
|
Packit Service |
e080da |
* uses LOG_DAEMON as default
|
|
Packit Service |
e080da |
*
|
|
Packit Service |
e080da |
* @return: void
|
|
Packit Service |
e080da |
*/
|
|
Packit Service |
e080da |
void
|
|
Packit Service |
e080da |
gf_openlog(const char *ident, int option, int facility)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
int _option = option;
|
|
Packit Service |
e080da |
int _facility = facility;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (-1 == _option) {
|
|
Packit Service |
e080da |
_option = LOG_PID | LOG_NDELAY;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
if (-1 == _facility) {
|
|
Packit Service |
e080da |
_facility = LOG_LOCAL1;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* TODO: Should check for errors here and return appropriately */
|
|
Packit Service |
e080da |
setlocale(LC_ALL, "");
|
|
Packit Service |
e080da |
setlocale(LC_NUMERIC, "C"); /* C-locale for strtod, ... */
|
|
Packit Service |
e080da |
/* close the previous syslog if open as we are changing settings */
|
|
Packit Service |
e080da |
closelog();
|
|
Packit Service |
e080da |
openlog(ident, _option, _facility);
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/**
|
|
Packit Service |
e080da |
* _json_escape -function to convert string to json encoded string
|
|
Packit Service |
e080da |
* @str: input string
|
|
Packit Service |
e080da |
* @buf: buffer to store encoded string
|
|
Packit Service |
e080da |
* @len: length of @buf
|
|
Packit Service |
e080da |
*
|
|
Packit Service |
e080da |
* @return: success: last unprocessed character position by pointer in @str
|
|
Packit Service |
e080da |
* failure: NULL
|
|
Packit Service |
e080da |
*
|
|
Packit Service |
e080da |
* Internal function. Heavily inspired by _ul_str_escape() function in
|
|
Packit Service |
e080da |
* libumberlog
|
|
Packit Service |
e080da |
*
|
|
Packit Service |
e080da |
* Sample output:
|
|
Packit Service |
e080da |
* [1] str = "devel error"
|
|
Packit Service |
e080da |
* buf = "devel error"
|
|
Packit Service |
e080da |
* [2] str = "devel error"
|
|
Packit Service |
e080da |
* buf = "devel\terror"
|
|
Packit Service |
e080da |
* [3] str = "I/O error on "/tmp/foo" file"
|
|
Packit Service |
e080da |
* buf = "I/O error on \"/tmp/foo\" file"
|
|
Packit Service |
e080da |
* [4] str = "I/O error?on /tmp/bar file"
|
|
Packit Service |
e080da |
* buf = "I/O error\u001bon /tmp/bar file"
|
|
Packit Service |
e080da |
*
|
|
Packit Service |
e080da |
*/
|
|
Packit Service |
e080da |
char *
|
|
Packit Service |
e080da |
_json_escape(const char *str, char *buf, size_t len)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
static const unsigned char json_exceptions[UCHAR_MAX + 1] = {
|
|
Packit Service |
e080da |
[0x01] = 1, [0x02] = 1, [0x03] = 1, [0x04] = 1, [0x05] = 1, [0x06] = 1,
|
|
Packit Service |
e080da |
[0x07] = 1, [0x08] = 1, [0x09] = 1, [0x0a] = 1, [0x0b] = 1, [0x0c] = 1,
|
|
Packit Service |
e080da |
[0x0d] = 1, [0x0e] = 1, [0x0f] = 1, [0x10] = 1, [0x11] = 1, [0x12] = 1,
|
|
Packit Service |
e080da |
[0x13] = 1, [0x14] = 1, [0x15] = 1, [0x16] = 1, [0x17] = 1, [0x18] = 1,
|
|
Packit Service |
e080da |
[0x19] = 1, [0x1a] = 1, [0x1b] = 1, [0x1c] = 1, [0x1d] = 1, [0x1e] = 1,
|
|
Packit Service |
e080da |
[0x1f] = 1, ['\\'] = 1, ['"'] = 1};
|
|
Packit Service |
e080da |
static const char json_hex_chars[16] = "0123456789abcdef";
|
|
Packit Service |
e080da |
unsigned char *p = NULL;
|
|
Packit Service |
e080da |
size_t pos = 0;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (!str || !buf || len <= 0) {
|
|
Packit Service |
e080da |
return NULL;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
for (p = (unsigned char *)str; *p && (pos + 1) < len; p++) {
|
|
Packit Service |
e080da |
if (json_exceptions[*p] == 0) {
|
|
Packit Service |
e080da |
buf[pos++] = *p;
|
|
Packit Service |
e080da |
continue;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if ((pos + 2) >= len) {
|
|
Packit Service |
e080da |
break;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
switch (*p) {
|
|
Packit Service |
e080da |
case '\b':
|
|
Packit Service |
e080da |
buf[pos++] = '\\';
|
|
Packit Service |
e080da |
buf[pos++] = 'b';
|
|
Packit Service |
e080da |
break;
|
|
Packit Service |
e080da |
case '\n':
|
|
Packit Service |
e080da |
buf[pos++] = '\\';
|
|
Packit Service |
e080da |
buf[pos++] = 'n';
|
|
Packit Service |
e080da |
break;
|
|
Packit Service |
e080da |
case '\r':
|
|
Packit Service |
e080da |
buf[pos++] = '\\';
|
|
Packit Service |
e080da |
buf[pos++] = 'r';
|
|
Packit Service |
e080da |
break;
|
|
Packit Service |
e080da |
case '\t':
|
|
Packit Service |
e080da |
buf[pos++] = '\\';
|
|
Packit Service |
e080da |
buf[pos++] = 't';
|
|
Packit Service |
e080da |
break;
|
|
Packit Service |
e080da |
case '\\':
|
|
Packit Service |
e080da |
buf[pos++] = '\\';
|
|
Packit Service |
e080da |
buf[pos++] = '\\';
|
|
Packit Service |
e080da |
break;
|
|
Packit Service |
e080da |
case '"':
|
|
Packit Service |
e080da |
buf[pos++] = '\\';
|
|
Packit Service |
e080da |
buf[pos++] = '"';
|
|
Packit Service |
e080da |
break;
|
|
Packit Service |
e080da |
default:
|
|
Packit Service |
e080da |
if ((pos + 6) >= len) {
|
|
Packit Service |
e080da |
buf[pos] = '\0';
|
|
Packit Service |
e080da |
return (char *)p;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
buf[pos++] = '\\';
|
|
Packit Service |
e080da |
buf[pos++] = 'u';
|
|
Packit Service |
e080da |
buf[pos++] = '0';
|
|
Packit Service |
e080da |
buf[pos++] = '0';
|
|
Packit Service |
e080da |
buf[pos++] = json_hex_chars[(*p) >> 4];
|
|
Packit Service |
e080da |
buf[pos++] = json_hex_chars[(*p) & 0xf];
|
|
Packit Service |
e080da |
break;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
buf[pos] = '\0';
|
|
Packit Service |
e080da |
return (char *)p;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/**
|
|
Packit Service |
e080da |
* gf_syslog -function to submit message to syslog specific to gluster
|
|
Packit Service |
e080da |
* @facility_priority: facility_priority of syslog()
|
|
Packit Service |
e080da |
* @format: optional format string to syslog()
|
|
Packit Service |
e080da |
*
|
|
Packit Service |
e080da |
* @return: void
|
|
Packit Service |
e080da |
*/
|
|
Packit Service |
e080da |
void
|
|
Packit Service |
e080da |
gf_syslog(int facility_priority, char *format, ...)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
char *msg = NULL;
|
|
Packit Service |
e080da |
char json_msg[GF_JSON_MSG_LENGTH];
|
|
Packit Service |
e080da |
GF_UNUSED char *p = NULL;
|
|
Packit Service |
e080da |
va_list ap;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
GF_ASSERT(format);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
va_start(ap, format);
|
|
Packit Service |
e080da |
if (vasprintf(&msg, format, ap) != -1) {
|
|
Packit Service |
e080da |
p = _json_escape(msg, json_msg, GF_JSON_MSG_LENGTH);
|
|
Packit Service |
e080da |
syslog(facility_priority, "%s", msg);
|
|
Packit Service |
e080da |
free(msg);
|
|
Packit Service |
e080da |
} else
|
|
Packit Service |
e080da |
syslog(GF_LOG_CRITICAL, "vasprintf() failed, out of memory?");
|
|
Packit Service |
e080da |
va_end(ap);
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
void
|
|
Packit Service |
e080da |
gf_log_globals_init(void *data, gf_loglevel_t level)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
glusterfs_ctx_t *ctx = data;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
pthread_mutex_init(&ctx->log.logfile_mutex, NULL);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ctx->log.loglevel = level;
|
|
Packit Service |
e080da |
ctx->log.gf_log_syslog = 1;
|
|
Packit Service |
e080da |
ctx->log.sys_log_level = GF_LOG_CRITICAL;
|
|
Packit Service |
e080da |
ctx->log.logger = gf_logger_glusterlog;
|
|
Packit Service |
e080da |
ctx->log.logformat = gf_logformat_withmsgid;
|
|
Packit Service |
e080da |
ctx->log.lru_size = GF_LOG_LRU_BUFSIZE_DEFAULT;
|
|
Packit Service |
e080da |
ctx->log.timeout = GF_LOG_FLUSH_TIMEOUT_DEFAULT;
|
|
Packit Service |
e080da |
ctx->log.localtime = GF_LOG_LOCALTIME_DEFAULT;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
pthread_mutex_init(&ctx->log.log_buf_lock, NULL);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
INIT_LIST_HEAD(&ctx->log.lru_queue);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
#ifdef GF_LINUX_HOST_OS
|
|
Packit Service |
e080da |
/* For the 'syslog' output. one can grep 'GlusterFS' in syslog
|
|
Packit Service |
e080da |
for serious logs */
|
|
Packit Service |
e080da |
openlog("GlusterFS", LOG_PID, LOG_DAEMON);
|
|
Packit Service |
e080da |
#endif
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
int
|
|
Packit Service |
e080da |
gf_log_init(void *data, const char *file, const char *ident)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
glusterfs_ctx_t *ctx = NULL;
|
|
Packit Service |
e080da |
int fd = -1;
|
|
Packit Service |
e080da |
struct stat buf;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ctx = data;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (ctx == NULL) {
|
|
Packit Service |
e080da |
fprintf(stderr, "ERROR: ctx is NULL\n");
|
|
Packit Service |
e080da |
return -1;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
if (ident) {
|
|
Packit Service |
e080da |
GF_FREE(ctx->log.ident);
|
|
Packit Service |
e080da |
ctx->log.ident = gf_strdup(ident);
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* we keep the files and the syslog open, so that on logger change, we
|
|
Packit Service |
e080da |
* are ready to log anywhere, that the new value specifies */
|
|
Packit Service |
e080da |
if (ctx->log.ident) {
|
|
Packit Service |
e080da |
gf_openlog(ctx->log.ident, -1, LOG_DAEMON);
|
|
Packit Service |
e080da |
} else {
|
|
Packit Service |
e080da |
gf_openlog(NULL, -1, LOG_DAEMON);
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
/* TODO: make FACILITY configurable than LOG_DAEMON */
|
|
Packit Service |
e080da |
if (sys_stat(GF_LOG_CONTROL_FILE, &buf) == 0) {
|
|
Packit Service |
e080da |
/* use syslog logging */
|
|
Packit Service |
e080da |
ctx->log.log_control_file_found = 1;
|
|
Packit Service |
e080da |
} else {
|
|
Packit Service |
e080da |
/* use old style logging */
|
|
Packit Service |
e080da |
ctx->log.log_control_file_found = 0;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (!file) {
|
|
Packit Service |
e080da |
fprintf(stderr, "ERROR: no filename specified\n");
|
|
Packit Service |
e080da |
return -1;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* free the (possible) previous filename */
|
|
Packit Service |
e080da |
GF_FREE(ctx->log.filename);
|
|
Packit Service |
e080da |
ctx->log.filename = NULL;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* close and reopen logfile for log rotate */
|
|
Packit Service |
e080da |
if (ctx->log.logfile) {
|
|
Packit Service |
e080da |
fclose(ctx->log.logfile);
|
|
Packit Service |
e080da |
ctx->log.logfile = NULL;
|
|
Packit Service |
e080da |
ctx->log.gf_log_logfile = NULL;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (strcmp(file, "-") == 0) {
|
|
Packit Service |
e080da |
int dupfd = -1;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ctx->log.filename = gf_strdup("/dev/stderr");
|
|
Packit Service |
e080da |
if (!ctx->log.filename) {
|
|
Packit Service |
e080da |
fprintf(stderr, "ERROR: strdup failed\n");
|
|
Packit Service |
e080da |
return -1;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
dupfd = dup(fileno(stderr));
|
|
Packit Service |
e080da |
if (dupfd == -1) {
|
|
Packit Service |
e080da |
fprintf(stderr, "ERROR: could not dup %d (%s)\n", fileno(stderr),
|
|
Packit Service |
e080da |
strerror(errno));
|
|
Packit Service |
e080da |
return -1;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ctx->log.logfile = fdopen(dupfd, "a");
|
|
Packit Service |
e080da |
if (!ctx->log.logfile) {
|
|
Packit Service |
e080da |
fprintf(stderr, "ERROR: could not fdopen on %d (%s)\n", dupfd,
|
|
Packit Service |
e080da |
strerror(errno));
|
|
Packit Service |
e080da |
sys_close(dupfd);
|
|
Packit Service |
e080da |
return -1;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
} else {
|
|
Packit Service |
e080da |
/* Also create parent dir */
|
|
Packit Service |
e080da |
char *logdir = gf_strdup(file);
|
|
Packit Service |
e080da |
if (!logdir) {
|
|
Packit Service |
e080da |
return -1;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
char *tmp_index = rindex(logdir, '/');
|
|
Packit Service |
e080da |
if (tmp_index) {
|
|
Packit Service |
e080da |
tmp_index[0] = '\0';
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
if (mkdir_p(logdir, 0755, true)) {
|
|
Packit Service |
e080da |
/* EEXIST is handled in mkdir_p() itself */
|
|
Packit Service |
e080da |
gf_msg("logging", GF_LOG_ERROR, 0, LG_MSG_STRDUP_ERROR,
|
|
Packit Service |
e080da |
"failed to create metrics dir %s (%s)", logdir,
|
|
Packit Service |
e080da |
strerror(errno));
|
|
Packit Service |
e080da |
GF_FREE(logdir);
|
|
Packit Service |
e080da |
return -1;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
/* no need of this variable */
|
|
Packit Service |
e080da |
GF_FREE(logdir);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ctx->log.filename = gf_strdup(file);
|
|
Packit Service |
e080da |
if (!ctx->log.filename) {
|
|
Packit Service |
e080da |
fprintf(stderr,
|
|
Packit Service |
e080da |
"ERROR: updating log-filename failed: "
|
|
Packit Service |
e080da |
"%s\n",
|
|
Packit Service |
e080da |
strerror(errno));
|
|
Packit Service |
e080da |
return -1;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
fd = sys_open(file, O_CREAT | O_WRONLY | O_APPEND, S_IRUSR | S_IWUSR);
|
|
Packit Service |
e080da |
if (fd < 0) {
|
|
Packit Service |
e080da |
fprintf(stderr,
|
|
Packit Service |
e080da |
"ERROR: failed to create logfile"
|
|
Packit Service |
e080da |
" \"%s\" (%s)\n",
|
|
Packit Service |
e080da |
file, strerror(errno));
|
|
Packit Service |
e080da |
return -1;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ctx->log.logfile = fdopen(fd, "a");
|
|
Packit Service |
e080da |
if (!ctx->log.logfile) {
|
|
Packit Service |
e080da |
fprintf(stderr,
|
|
Packit Service |
e080da |
"ERROR: failed to open logfile \"%s\" "
|
|
Packit Service |
e080da |
"(%s)\n",
|
|
Packit Service |
e080da |
file, strerror(errno));
|
|
Packit Service |
e080da |
sys_close(fd);
|
|
Packit Service |
e080da |
return -1;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ctx->log.gf_log_logfile = ctx->log.logfile;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
return 0;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
void
|
|
Packit Service |
e080da |
set_sys_log_level(gf_loglevel_t level)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
glusterfs_ctx_t *ctx = NULL;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ctx = THIS->ctx;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (ctx)
|
|
Packit Service |
e080da |
ctx->log.sys_log_level = level;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* Check if we should be logging
|
|
Packit Service |
e080da |
* Return value: _gf_false : Print the log
|
|
Packit Service |
e080da |
* _gf_true : Do not Print the log
|
|
Packit Service |
e080da |
*/
|
|
Packit Service |
e080da |
static gf_boolean_t
|
|
Packit Service |
e080da |
skip_logging(xlator_t *this, gf_loglevel_t level)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
gf_boolean_t ret = _gf_false;
|
|
Packit Service |
e080da |
gf_loglevel_t existing_level = GF_LOG_NONE;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (level == GF_LOG_NONE) {
|
|
Packit Service |
e080da |
ret = _gf_true;
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
existing_level = this->loglevel ? this->loglevel : this->ctx->log.loglevel;
|
|
Packit Service |
e080da |
if (level > existing_level) {
|
|
Packit Service |
e080da |
ret = _gf_true;
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
out:
|
|
Packit Service |
e080da |
return ret;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
int
|
|
Packit Service |
e080da |
_gf_log_callingfn(const char *domain, const char *file, const char *function,
|
|
Packit Service |
e080da |
int line, gf_loglevel_t level, const char *fmt, ...)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
const char *basename = NULL;
|
|
Packit Service |
e080da |
xlator_t *this = NULL;
|
|
Packit Service |
e080da |
char *logline = NULL;
|
|
Packit Service |
e080da |
char *msg = NULL;
|
|
Packit Service |
e080da |
char timestr[256] = {
|
|
Packit Service |
e080da |
0,
|
|
Packit Service |
e080da |
};
|
|
Packit Service |
e080da |
char *callstr = NULL;
|
|
Packit Service |
e080da |
struct timeval tv = {
|
|
Packit Service |
e080da |
0,
|
|
Packit Service |
e080da |
};
|
|
Packit Service |
e080da |
int ret = 0;
|
|
Packit Service |
e080da |
va_list ap;
|
|
Packit Service |
e080da |
glusterfs_ctx_t *ctx = NULL;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
this = THIS;
|
|
Packit Service |
e080da |
ctx = this->ctx;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (!ctx)
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (skip_logging(this, level))
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
static char *level_strings[] = {"", /* NONE */
|
|
Packit Service |
e080da |
"M", /* EMERGENCY */
|
|
Packit Service |
e080da |
"A", /* ALERT */
|
|
Packit Service |
e080da |
"C", /* CRITICAL */
|
|
Packit Service |
e080da |
"E", /* ERROR */
|
|
Packit Service |
e080da |
"W", /* WARNING */
|
|
Packit Service |
e080da |
"N", /* NOTICE */
|
|
Packit Service |
e080da |
"I", /* INFO */
|
|
Packit Service |
e080da |
"D", /* DEBUG */
|
|
Packit Service |
e080da |
"T", /* TRACE */
|
|
Packit Service |
e080da |
""};
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (!domain || !file || !function || !fmt) {
|
|
Packit Service |
e080da |
fprintf(stderr, "logging: %s:%s():%d: invalid argument\n", __FILE__,
|
|
Packit Service |
e080da |
__PRETTY_FUNCTION__, __LINE__);
|
|
Packit Service |
e080da |
return -1;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
basename = strrchr(file, '/');
|
|
Packit Service |
e080da |
if (basename)
|
|
Packit Service |
e080da |
basename++;
|
|
Packit Service |
e080da |
else
|
|
Packit Service |
e080da |
basename = file;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/*Saving the backtrace to pre-allocated ctx->btbuf
|
|
Packit Service |
e080da |
* to avoid allocating memory from the heap*/
|
|
Packit Service |
e080da |
callstr = gf_backtrace_save(NULL);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
va_start(ap, fmt);
|
|
Packit Service |
e080da |
ret = vasprintf(&msg, fmt, ap);
|
|
Packit Service |
e080da |
va_end(ap);
|
|
Packit Service |
e080da |
if (-1 == ret) {
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (ctx->log.log_control_file_found) {
|
|
Packit Service |
e080da |
int priority;
|
|
Packit Service |
e080da |
/* treat GF_LOG_TRACE and GF_LOG_NONE as LOG_DEBUG and
|
|
Packit Service |
e080da |
other level as is */
|
|
Packit Service |
e080da |
if (GF_LOG_TRACE == level || GF_LOG_NONE == level) {
|
|
Packit Service |
e080da |
priority = LOG_DEBUG;
|
|
Packit Service |
e080da |
} else {
|
|
Packit Service |
e080da |
priority = level - 1;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
gf_syslog(priority, "[%s:%d:%s] %s %d-%s: %s", basename, line, function,
|
|
Packit Service |
e080da |
callstr, ((this->graph) ? this->graph->id : 0), domain, msg);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ret = gettimeofday(&tv, NULL);
|
|
Packit Service |
e080da |
if (-1 == ret)
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
gf_time_fmt(timestr, sizeof timestr, tv.tv_sec, gf_timefmt_FT);
|
|
Packit Service |
e080da |
snprintf(timestr + strlen(timestr), sizeof timestr - strlen(timestr),
|
|
Packit Service |
e080da |
".%" GF_PRI_SUSECONDS, tv.tv_usec);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ret = gf_asprintf(&logline, "[%s] %s [%s:%d:%s] %s %d-%s: %s", timestr,
|
|
Packit Service |
e080da |
level_strings[level], basename, line, function, callstr,
|
|
Packit Service |
e080da |
((this->graph) ? this->graph->id : 0), domain, msg);
|
|
Packit Service |
e080da |
if (-1 == ret) {
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
pthread_mutex_lock(&ctx->log.logfile_mutex);
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
if (ctx->log.logfile) {
|
|
Packit Service |
e080da |
fprintf(ctx->log.logfile, "%s\n", logline);
|
|
Packit Service |
e080da |
fflush(ctx->log.logfile);
|
|
Packit Service |
e080da |
} else if (ctx->log.loglevel >= level) {
|
|
Packit Service |
e080da |
fprintf(stderr, "%s\n", logline);
|
|
Packit Service |
e080da |
fflush(stderr);
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
#ifdef GF_LINUX_HOST_OS
|
|
Packit Service |
e080da |
/* We want only serious log in 'syslog', not our debug
|
|
Packit Service |
e080da |
and trace logs */
|
|
Packit Service |
e080da |
if (ctx->log.gf_log_syslog && level &&
|
|
Packit Service |
e080da |
(level <= ctx->log.sys_log_level))
|
|
Packit Service |
e080da |
syslog((level - 1), "%s\n", logline);
|
|
Packit Service |
e080da |
#endif
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
pthread_mutex_unlock(&ctx->log.logfile_mutex);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
out:
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
GF_FREE(logline);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
FREE(msg);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
return ret;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
int
|
|
Packit Service |
e080da |
_gf_msg_plain_internal(gf_loglevel_t level, const char *msg)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
xlator_t *this = NULL;
|
|
Packit Service |
e080da |
glusterfs_ctx_t *ctx = NULL;
|
|
Packit Service |
e080da |
int priority;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
this = THIS;
|
|
Packit Service |
e080da |
ctx = this->ctx;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* log to the configured logging service */
|
|
Packit Service |
e080da |
switch (ctx->log.logger) {
|
|
Packit Service |
e080da |
case gf_logger_syslog:
|
|
Packit Service |
e080da |
if (ctx->log.log_control_file_found && ctx->log.gf_log_syslog) {
|
|
Packit Service |
e080da |
SET_LOG_PRIO(level, priority);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
syslog(priority, "%s", msg);
|
|
Packit Service |
e080da |
break;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
/* NOTE: If syslog control file is absent, which is another
|
|
Packit Service |
e080da |
* way to control logging to syslog, then we will fall through
|
|
Packit Service |
e080da |
* to the gluster log. The ideal way to do things would be to
|
|
Packit Service |
e080da |
* not have the extra control file check */
|
|
Packit Service |
e080da |
case gf_logger_glusterlog:
|
|
Packit Service |
e080da |
pthread_mutex_lock(&ctx->log.logfile_mutex);
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
if (ctx->log.logfile) {
|
|
Packit Service |
e080da |
fprintf(ctx->log.logfile, "%s\n", msg);
|
|
Packit Service |
e080da |
fflush(ctx->log.logfile);
|
|
Packit Service |
e080da |
} else {
|
|
Packit Service |
e080da |
fprintf(stderr, "%s\n", msg);
|
|
Packit Service |
e080da |
fflush(stderr);
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
#ifdef GF_LINUX_HOST_OS
|
|
Packit Service |
e080da |
/* We want only serious logs in 'syslog', not our debug
|
|
Packit Service |
e080da |
* and trace logs */
|
|
Packit Service |
e080da |
if (ctx->log.gf_log_syslog && level &&
|
|
Packit Service |
e080da |
(level <= ctx->log.sys_log_level))
|
|
Packit Service |
e080da |
syslog((level - 1), "%s\n", msg);
|
|
Packit Service |
e080da |
#endif
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
pthread_mutex_unlock(&ctx->log.logfile_mutex);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
break;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
return 0;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
int
|
|
Packit Service |
e080da |
_gf_msg_plain(gf_loglevel_t level, const char *fmt, ...)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
xlator_t *this = NULL;
|
|
Packit Service |
e080da |
int ret = 0;
|
|
Packit Service |
e080da |
va_list ap;
|
|
Packit Service |
e080da |
char *msg = NULL;
|
|
Packit Service |
e080da |
glusterfs_ctx_t *ctx = NULL;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
this = THIS;
|
|
Packit Service |
e080da |
ctx = this->ctx;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (!ctx)
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (skip_logging(this, level))
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
va_start(ap, fmt);
|
|
Packit Service |
e080da |
ret = vasprintf(&msg, fmt, ap);
|
|
Packit Service |
e080da |
va_end(ap);
|
|
Packit Service |
e080da |
if (-1 == ret) {
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ret = _gf_msg_plain_internal(level, msg);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
FREE(msg);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
out:
|
|
Packit Service |
e080da |
return ret;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
int
|
|
Packit Service |
e080da |
_gf_msg_vplain(gf_loglevel_t level, const char *fmt, va_list ap)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
xlator_t *this = NULL;
|
|
Packit Service |
e080da |
int ret = 0;
|
|
Packit Service |
e080da |
char *msg = NULL;
|
|
Packit Service |
e080da |
glusterfs_ctx_t *ctx = NULL;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
this = THIS;
|
|
Packit Service |
e080da |
ctx = this->ctx;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (!ctx)
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (skip_logging(this, level))
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ret = vasprintf(&msg, fmt, ap);
|
|
Packit Service |
e080da |
if (-1 == ret) {
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ret = _gf_msg_plain_internal(level, msg);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
FREE(msg);
|
|
Packit Service |
e080da |
out:
|
|
Packit Service |
e080da |
return ret;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
int
|
|
Packit Service |
e080da |
_gf_msg_plain_nomem(gf_loglevel_t level, const char *msg)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
xlator_t *this = NULL;
|
|
Packit Service |
e080da |
int ret = 0;
|
|
Packit Service |
e080da |
glusterfs_ctx_t *ctx = NULL;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
this = THIS;
|
|
Packit Service |
e080da |
ctx = this->ctx;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (!ctx)
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (skip_logging(this, level))
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ret = _gf_msg_plain_internal(level, msg);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
out:
|
|
Packit Service |
e080da |
return ret;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
void
|
|
Packit Service |
e080da |
_gf_msg_backtrace_nomem(gf_loglevel_t level, int stacksize)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
xlator_t *this = NULL;
|
|
Packit Service |
e080da |
glusterfs_ctx_t *ctx = NULL;
|
|
Packit Service |
e080da |
void *array[200];
|
|
Packit Service |
e080da |
size_t bt_size = 0;
|
|
Packit Service |
e080da |
int fd = -1;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
this = THIS;
|
|
Packit Service |
e080da |
ctx = this->ctx;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (!ctx)
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* syslog does not have fd support, hence no no-mem variant */
|
|
Packit Service |
e080da |
if (ctx->log.logger != gf_logger_glusterlog)
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (skip_logging(this, level))
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
bt_size = backtrace(array, ((stacksize <= 200) ? stacksize : 200));
|
|
Packit Service |
e080da |
pthread_mutex_lock(&ctx->log.logfile_mutex);
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
fd = ctx->log.logfile ? fileno(ctx->log.logfile) : fileno(stderr);
|
|
Packit Service |
e080da |
if (bt_size && (fd != -1)) {
|
|
Packit Service |
e080da |
/* print to the file fd, to prevent any
|
|
Packit Service |
e080da |
allocations from backtrace_symbols
|
|
Packit Service |
e080da |
*/
|
|
Packit Service |
e080da |
backtrace_symbols_fd(&array[0], bt_size, fd);
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
pthread_mutex_unlock(&ctx->log.logfile_mutex);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
out:
|
|
Packit Service |
e080da |
return;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
int
|
|
Packit Service |
e080da |
_gf_msg_backtrace(int stacksize, char *callstr, size_t strsize)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
int ret = -1;
|
|
Packit Service |
e080da |
int i = 0;
|
|
Packit Service |
e080da |
int size = 0;
|
|
Packit Service |
e080da |
int savstrsize = strsize;
|
|
Packit Service |
e080da |
void *array[200];
|
|
Packit Service |
e080da |
char **callingfn = NULL;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* We chop off last 2 anyway, so if request is less than tolerance
|
|
Packit Service |
e080da |
* nothing to do */
|
|
Packit Service |
e080da |
if (stacksize < 3)
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
size = backtrace(array, ((stacksize <= 200) ? stacksize : 200));
|
|
Packit Service |
e080da |
if ((size - 3) < 0)
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
if (size)
|
|
Packit Service |
e080da |
callingfn = backtrace_symbols(&array[2], size - 2);
|
|
Packit Service |
e080da |
if (!callingfn)
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ret = snprintf(callstr, strsize, "(");
|
|
Packit Service |
e080da |
PRINT_SIZE_CHECK(ret, out, strsize);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
for ((i = size - 3); i >= 0; i--) {
|
|
Packit Service |
e080da |
ret = snprintf(callstr + savstrsize - strsize, strsize, "-->%s ",
|
|
Packit Service |
e080da |
callingfn[i]);
|
|
Packit Service |
e080da |
PRINT_SIZE_CHECK(ret, out, strsize);
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ret = snprintf(callstr + savstrsize - strsize, strsize, ")");
|
|
Packit Service |
e080da |
PRINT_SIZE_CHECK(ret, out, strsize);
|
|
Packit Service |
e080da |
out:
|
|
Packit Service |
e080da |
FREE(callingfn);
|
|
Packit Service |
e080da |
return ret;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
int
|
|
Packit Service |
e080da |
_gf_msg_nomem(const char *domain, const char *file, const char *function,
|
|
Packit Service |
e080da |
int line, gf_loglevel_t level, size_t size)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
const char *basename = NULL;
|
|
Packit Service |
e080da |
xlator_t *this = NULL;
|
|
Packit Service |
e080da |
struct timeval tv = {
|
|
Packit Service |
e080da |
0,
|
|
Packit Service |
e080da |
};
|
|
Packit Service |
e080da |
int ret = 0;
|
|
Packit Service |
e080da |
int fd = -1;
|
|
Packit Service |
e080da |
char msg[2048] = {
|
|
Packit Service |
e080da |
0,
|
|
Packit Service |
e080da |
};
|
|
Packit Service |
e080da |
char timestr[GF_LOG_TIMESTR_SIZE] = {
|
|
Packit Service |
e080da |
0,
|
|
Packit Service |
e080da |
};
|
|
Packit Service |
e080da |
glusterfs_ctx_t *ctx = NULL;
|
|
Packit Service |
e080da |
int wlen = 0;
|
|
Packit Service |
e080da |
int priority;
|
|
Packit Service |
173fb3 |
struct rusage r_usage;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
this = THIS;
|
|
Packit Service |
e080da |
ctx = this->ctx;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (!ctx)
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (skip_logging(this, level))
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (!domain || !file || !function) {
|
|
Packit Service |
e080da |
fprintf(stderr, "logging: %s:%s():%d: invalid argument\n", __FILE__,
|
|
Packit Service |
e080da |
__PRETTY_FUNCTION__, __LINE__);
|
|
Packit Service |
e080da |
return -1;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
GET_FILE_NAME_TO_LOG(file, basename);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ret = gettimeofday(&tv, NULL);
|
|
Packit Service |
e080da |
if (-1 == ret)
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
gf_time_fmt(timestr, sizeof timestr, tv.tv_sec, gf_timefmt_FT);
|
|
Packit Service |
e080da |
ret = snprintf(timestr + strlen(timestr), sizeof timestr - strlen(timestr),
|
|
Packit Service |
e080da |
".%" GF_PRI_SUSECONDS, tv.tv_usec);
|
|
Packit Service |
e080da |
if (-1 == ret) {
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* TODO: Currently we print in the enhanced format, with a message ID
|
|
Packit Service |
e080da |
* of 0. Need to enhance this to support format as configured */
|
|
Packit Service |
e080da |
ret = snprintf(msg, sizeof msg,
|
|
Packit Service |
e080da |
"[%s] %s [MSGID: %" PRIu64
|
|
Packit Service |
e080da |
"]"
|
|
Packit Service |
e080da |
" [%s:%d:%s] %s: no memory "
|
|
Packit Service |
e080da |
"available for size (%" GF_PRI_SIZET
|
|
Packit Service |
173fb3 |
") current memory usage in kilobytes %ld"
|
|
Packit Service |
e080da |
" [call stack follows]\n",
|
|
Packit Service |
e080da |
timestr, gf_level_strings[level], (uint64_t)0, basename,
|
|
Packit Service |
173fb3 |
line, function, domain, size,
|
|
Packit Service |
173fb3 |
(!getrusage(RUSAGE_SELF, &r_usage) ? r_usage.ru_maxrss : 0));
|
|
Packit Service |
e080da |
if (-1 == ret) {
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* log to the configured logging service */
|
|
Packit Service |
e080da |
switch (ctx->log.logger) {
|
|
Packit Service |
e080da |
case gf_logger_syslog:
|
|
Packit Service |
e080da |
if (ctx->log.log_control_file_found && ctx->log.gf_log_syslog) {
|
|
Packit Service |
e080da |
SET_LOG_PRIO(level, priority);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* if syslog allocates, then this may fail, but we
|
|
Packit Service |
e080da |
* cannot do much about it at the moment */
|
|
Packit Service |
e080da |
/* There is no fd for syslog, hence no stack printed */
|
|
Packit Service |
e080da |
syslog(priority, "%s", msg);
|
|
Packit Service |
e080da |
break;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
/* NOTE: If syslog control file is absent, which is another
|
|
Packit Service |
e080da |
* way to control logging to syslog, then we will fall through
|
|
Packit Service |
e080da |
* to the gluster log. The ideal way to do things would be to
|
|
Packit Service |
e080da |
* not have the extra control file check */
|
|
Packit Service |
e080da |
case gf_logger_glusterlog:
|
|
Packit Service |
e080da |
pthread_mutex_lock(&ctx->log.logfile_mutex);
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
fd = ctx->log.logfile ? fileno(ctx->log.logfile)
|
|
Packit Service |
e080da |
: fileno(stderr);
|
|
Packit Service |
e080da |
if (fd == -1) {
|
|
Packit Service |
e080da |
pthread_mutex_unlock(&ctx->log.logfile_mutex);
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
wlen = strlen(msg);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* write directly to the fd to prevent out of order
|
|
Packit Service |
e080da |
* message and stack */
|
|
Packit Service |
e080da |
ret = sys_write(fd, msg, wlen);
|
|
Packit Service |
e080da |
if (ret == -1) {
|
|
Packit Service |
e080da |
pthread_mutex_unlock(&ctx->log.logfile_mutex);
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
#ifdef GF_LINUX_HOST_OS
|
|
Packit Service |
e080da |
/* We want only serious log in 'syslog', not our debug
|
|
Packit Service |
e080da |
* and trace logs */
|
|
Packit Service |
e080da |
if (ctx->log.gf_log_syslog && level &&
|
|
Packit Service |
e080da |
(level <= ctx->log.sys_log_level))
|
|
Packit Service |
e080da |
syslog((level - 1), "%s\n", msg);
|
|
Packit Service |
e080da |
#endif
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
pthread_mutex_unlock(&ctx->log.logfile_mutex);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
_gf_msg_backtrace_nomem(level, GF_LOG_BACKTRACE_DEPTH);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
break;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
out:
|
|
Packit Service |
e080da |
return ret;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
static int
|
|
Packit Service |
e080da |
gf_log_syslog(glusterfs_ctx_t *ctx, const char *domain, const char *file,
|
|
Packit Service |
e080da |
const char *function, int32_t line, gf_loglevel_t level,
|
|
Packit Service |
e080da |
int errnum, uint64_t msgid, char **appmsgstr, char *callstr,
|
|
Packit Service |
e080da |
int graph_id, gf_log_format_t fmt)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
int priority;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
SET_LOG_PRIO(level, priority);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* log with appropriate format */
|
|
Packit Service |
e080da |
switch (fmt) {
|
|
Packit Service |
e080da |
case gf_logformat_traditional:
|
|
Packit Service |
e080da |
if (!callstr) {
|
|
Packit Service |
e080da |
if (errnum)
|
|
Packit Service |
e080da |
syslog(priority, "[%s:%d:%s] %d-%s: %s [%s]", file, line,
|
|
Packit Service |
e080da |
function, graph_id, domain, *appmsgstr,
|
|
Packit Service |
e080da |
strerror(errnum));
|
|
Packit Service |
e080da |
else
|
|
Packit Service |
e080da |
syslog(priority, "[%s:%d:%s] %d-%s: %s", file, line,
|
|
Packit Service |
e080da |
function, graph_id, domain, *appmsgstr);
|
|
Packit Service |
e080da |
} else {
|
|
Packit Service |
e080da |
if (errnum)
|
|
Packit Service |
e080da |
syslog(priority,
|
|
Packit Service |
e080da |
"[%s:%d:%s] %s %d-%s:"
|
|
Packit Service |
e080da |
" %s [%s]",
|
|
Packit Service |
e080da |
file, line, function, callstr, graph_id, domain,
|
|
Packit Service |
e080da |
*appmsgstr, strerror(errnum));
|
|
Packit Service |
e080da |
else
|
|
Packit Service |
e080da |
syslog(priority, "[%s:%d:%s] %s %d-%s: %s", file, line,
|
|
Packit Service |
e080da |
function, callstr, graph_id, domain, *appmsgstr);
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
break;
|
|
Packit Service |
e080da |
case gf_logformat_withmsgid:
|
|
Packit Service |
e080da |
if (!callstr) {
|
|
Packit Service |
e080da |
if (errnum)
|
|
Packit Service |
e080da |
syslog(priority,
|
|
Packit Service |
e080da |
"[MSGID: %" PRIu64
|
|
Packit Service |
e080da |
"]"
|
|
Packit Service |
e080da |
" [%s:%d:%s] %d-%s: %s [%s]",
|
|
Packit Service |
e080da |
msgid, file, line, function, graph_id, domain,
|
|
Packit Service |
e080da |
*appmsgstr, strerror(errnum));
|
|
Packit Service |
e080da |
else
|
|
Packit Service |
e080da |
syslog(priority,
|
|
Packit Service |
e080da |
"[MSGID: %" PRIu64
|
|
Packit Service |
e080da |
"]"
|
|
Packit Service |
e080da |
" [%s:%d:%s] %d-%s: %s",
|
|
Packit Service |
e080da |
msgid, file, line, function, graph_id, domain,
|
|
Packit Service |
e080da |
*appmsgstr);
|
|
Packit Service |
e080da |
} else {
|
|
Packit Service |
e080da |
if (errnum)
|
|
Packit Service |
e080da |
syslog(priority,
|
|
Packit Service |
e080da |
"[MSGID: %" PRIu64
|
|
Packit Service |
e080da |
"]"
|
|
Packit Service |
e080da |
" [%s:%d:%s] %s %d-%s: %s [%s]",
|
|
Packit Service |
e080da |
msgid, file, line, function, callstr, graph_id,
|
|
Packit Service |
e080da |
domain, *appmsgstr, strerror(errnum));
|
|
Packit Service |
e080da |
else
|
|
Packit Service |
e080da |
syslog(priority,
|
|
Packit Service |
e080da |
"[MSGID: %" PRIu64
|
|
Packit Service |
e080da |
"]"
|
|
Packit Service |
e080da |
" [%s:%d:%s] %s %d-%s: %s",
|
|
Packit Service |
e080da |
msgid, file, line, function, callstr, graph_id,
|
|
Packit Service |
e080da |
domain, *appmsgstr);
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
break;
|
|
Packit Service |
e080da |
case gf_logformat_cee:
|
|
Packit Service |
e080da |
/* TODO: Enhance CEE with additional parameters */
|
|
Packit Service |
e080da |
gf_syslog(priority, "[%s:%d:%s] %d-%s: %s", file, line, function,
|
|
Packit Service |
e080da |
graph_id, domain, *appmsgstr);
|
|
Packit Service |
e080da |
break;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
default:
|
|
Packit Service |
e080da |
/* NOTE: should not get here without logging */
|
|
Packit Service |
e080da |
break;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* TODO: There can be no errors from gf_syslog? */
|
|
Packit Service |
e080da |
return 0;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
static int
|
|
Packit Service |
e080da |
gf_log_glusterlog(glusterfs_ctx_t *ctx, const char *domain, const char *file,
|
|
Packit Service |
e080da |
const char *function, int32_t line, gf_loglevel_t level,
|
|
Packit Service |
e080da |
int errnum, uint64_t msgid, char **appmsgstr, char *callstr,
|
|
Packit Service |
e080da |
struct timeval tv, int graph_id, gf_log_format_t fmt)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
char timestr[GF_LOG_TIMESTR_SIZE] = {
|
|
Packit Service |
e080da |
0,
|
|
Packit Service |
e080da |
};
|
|
Packit Service |
e080da |
char *header = NULL;
|
|
Packit Service |
e080da |
char *footer = NULL;
|
|
Packit Service |
e080da |
char *msg = NULL;
|
|
Packit Service |
e080da |
size_t hlen = 0, flen = 0, mlen = 0;
|
|
Packit Service |
e080da |
int ret = 0;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* rotate if required */
|
|
Packit Service |
e080da |
gf_log_rotate(ctx);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* format the time stamp */
|
|
Packit Service |
e080da |
gf_time_fmt(timestr, sizeof timestr, tv.tv_sec, gf_timefmt_FT);
|
|
Packit Service |
e080da |
snprintf(timestr + strlen(timestr), sizeof timestr - strlen(timestr),
|
|
Packit Service |
e080da |
".%" GF_PRI_SUSECONDS, tv.tv_usec);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* generate header and footer */
|
|
Packit Service |
e080da |
if (fmt == gf_logformat_traditional) {
|
|
Packit Service |
e080da |
if (!callstr) {
|
|
Packit Service |
e080da |
ret = gf_asprintf(&header,
|
|
Packit Service |
e080da |
"[%s] %s [%s:%d:%s]"
|
|
Packit Service |
e080da |
" %d-%s: ",
|
|
Packit Service |
e080da |
timestr, gf_level_strings[level], file, line,
|
|
Packit Service |
e080da |
function, graph_id, domain);
|
|
Packit Service |
e080da |
} else {
|
|
Packit Service |
e080da |
ret = gf_asprintf(&header,
|
|
Packit Service |
e080da |
"[%s] %s [%s:%d:%s] %s"
|
|
Packit Service |
e080da |
" %d-%s: ",
|
|
Packit Service |
e080da |
timestr, gf_level_strings[level], file, line,
|
|
Packit Service |
e080da |
function, callstr, graph_id, domain);
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
if (-1 == ret) {
|
|
Packit Service |
e080da |
goto err;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
} else { /* gf_logformat_withmsgid */
|
|
Packit Service |
e080da |
/* CEE log format unsupported in logger_glusterlog, so just
|
|
Packit Service |
e080da |
* print enhanced log format */
|
|
Packit Service |
e080da |
if (!callstr) {
|
|
Packit Service |
e080da |
ret = gf_asprintf(&header,
|
|
Packit Service |
e080da |
"[%s] %s [MSGID: %" PRIu64
|
|
Packit Service |
e080da |
"]"
|
|
Packit Service |
e080da |
" [%s:%d:%s] %d-%s: ",
|
|
Packit Service |
e080da |
timestr, gf_level_strings[level], msgid, file,
|
|
Packit Service |
e080da |
line, function, graph_id, domain);
|
|
Packit Service |
e080da |
} else {
|
|
Packit Service |
e080da |
ret = gf_asprintf(&header,
|
|
Packit Service |
e080da |
"[%s] %s [MSGID: %" PRIu64
|
|
Packit Service |
e080da |
"]"
|
|
Packit Service |
e080da |
" [%s:%d:%s] %s %d-%s: ",
|
|
Packit Service |
e080da |
timestr, gf_level_strings[level], msgid, file,
|
|
Packit Service |
e080da |
line, function, callstr, graph_id, domain);
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
if (-1 == ret) {
|
|
Packit Service |
e080da |
goto err;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (errnum) {
|
|
Packit Service |
e080da |
ret = gf_asprintf(&footer, " [%s]", strerror(errnum));
|
|
Packit Service |
e080da |
if (-1 == ret) {
|
|
Packit Service |
e080da |
goto err;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* generate the full message to log */
|
|
Packit Service |
e080da |
hlen = strlen(header);
|
|
Packit Service |
e080da |
flen = footer ? strlen(footer) : 0;
|
|
Packit Service |
e080da |
mlen = strlen(*appmsgstr);
|
|
Packit Service |
e080da |
msg = GF_MALLOC(hlen + flen + mlen + 1, gf_common_mt_char);
|
|
Packit Service |
e080da |
if (!msg) {
|
|
Packit Service |
e080da |
ret = -1;
|
|
Packit Service |
e080da |
goto err;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
strcpy(msg, header);
|
|
Packit Service |
e080da |
strcpy(msg + hlen, *appmsgstr);
|
|
Packit Service |
e080da |
if (footer)
|
|
Packit Service |
e080da |
strcpy(msg + hlen + mlen, footer);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
pthread_mutex_lock(&ctx->log.logfile_mutex);
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
if (ctx->log.logfile) {
|
|
Packit Service |
e080da |
fprintf(ctx->log.logfile, "%s\n", msg);
|
|
Packit Service |
e080da |
fflush(ctx->log.logfile);
|
|
Packit Service |
e080da |
} else if (ctx->log.loglevel >= level) {
|
|
Packit Service |
e080da |
fprintf(stderr, "%s\n", msg);
|
|
Packit Service |
e080da |
fflush(stderr);
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
#ifdef GF_LINUX_HOST_OS
|
|
Packit Service |
e080da |
/* We want only serious logs in 'syslog', not our debug
|
|
Packit Service |
e080da |
* and trace logs */
|
|
Packit Service |
e080da |
if (ctx->log.gf_log_syslog && level &&
|
|
Packit Service |
e080da |
(level <= ctx->log.sys_log_level))
|
|
Packit Service |
e080da |
syslog((level - 1), "%s\n", msg);
|
|
Packit Service |
e080da |
#endif
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* TODO: Plugin in memory log buffer retention here. For logs not
|
|
Packit Service |
e080da |
* flushed during cores, it would be useful to retain some of the last
|
|
Packit Service |
e080da |
* few messages in memory */
|
|
Packit Service |
e080da |
pthread_mutex_unlock(&ctx->log.logfile_mutex);
|
|
Packit Service |
e080da |
ret = 0;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
err:
|
|
Packit Service |
e080da |
GF_FREE(msg);
|
|
Packit Service |
e080da |
GF_FREE(header);
|
|
Packit Service |
e080da |
GF_FREE(footer);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
return ret;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
static int
|
|
Packit Service |
e080da |
gf_syslog_log_repetitions(const char *domain, const char *file,
|
|
Packit Service |
e080da |
const char *function, int32_t line,
|
|
Packit Service |
e080da |
gf_loglevel_t level, int errnum, uint64_t msgid,
|
|
Packit Service |
e080da |
char **appmsgstr, char *callstr, int refcount,
|
|
Packit Service |
e080da |
struct timeval oldest, struct timeval latest,
|
|
Packit Service |
e080da |
int graph_id)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
int priority;
|
|
Packit Service |
e080da |
char timestr_latest[256] = {
|
|
Packit Service |
e080da |
0,
|
|
Packit Service |
e080da |
};
|
|
Packit Service |
e080da |
char timestr_oldest[256] = {
|
|
Packit Service |
e080da |
0,
|
|
Packit Service |
e080da |
};
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
SET_LOG_PRIO(level, priority);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
gf_time_fmt(timestr_latest, sizeof timestr_latest, latest.tv_sec,
|
|
Packit Service |
e080da |
gf_timefmt_FT);
|
|
Packit Service |
e080da |
snprintf(timestr_latest + strlen(timestr_latest),
|
|
Packit Service |
e080da |
sizeof(timestr_latest) - strlen(timestr_latest),
|
|
Packit Service |
e080da |
".%" GF_PRI_SUSECONDS, latest.tv_usec);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
gf_time_fmt(timestr_oldest, sizeof timestr_oldest, oldest.tv_sec,
|
|
Packit Service |
e080da |
gf_timefmt_FT);
|
|
Packit Service |
e080da |
snprintf(timestr_oldest + strlen(timestr_oldest),
|
|
Packit Service |
e080da |
sizeof(timestr_oldest) - strlen(timestr_oldest),
|
|
Packit Service |
e080da |
".%" GF_PRI_SUSECONDS, oldest.tv_usec);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (errnum) {
|
|
Packit Service |
e080da |
syslog(priority,
|
|
Packit Service |
e080da |
"The message \"[MSGID: %" PRIu64
|
|
Packit Service |
e080da |
"] [%s:%d:%s] "
|
|
Packit Service |
e080da |
"%d-%s: %s [%s] \" repeated %d times between %s and %s",
|
|
Packit Service |
e080da |
msgid, file, line, function, graph_id, domain, *appmsgstr,
|
|
Packit Service |
e080da |
strerror(errnum), refcount, timestr_oldest, timestr_latest);
|
|
Packit Service |
e080da |
} else {
|
|
Packit Service |
e080da |
syslog(priority,
|
|
Packit Service |
e080da |
"The message \"[MSGID: %" PRIu64
|
|
Packit Service |
e080da |
"] [%s:%d:%s] "
|
|
Packit Service |
e080da |
"%d-%s: %s \" repeated %d times between %s and %s",
|
|
Packit Service |
e080da |
msgid, file, line, function, graph_id, domain, *appmsgstr,
|
|
Packit Service |
e080da |
refcount, timestr_oldest, timestr_latest);
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
return 0;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
static int
|
|
Packit Service |
e080da |
gf_glusterlog_log_repetitions(glusterfs_ctx_t *ctx, const char *domain,
|
|
Packit Service |
e080da |
const char *file, const char *function,
|
|
Packit Service |
e080da |
int32_t line, gf_loglevel_t level, int errnum,
|
|
Packit Service |
e080da |
uint64_t msgid, char **appmsgstr, char *callstr,
|
|
Packit Service |
e080da |
int refcount, struct timeval oldest,
|
|
Packit Service |
e080da |
struct timeval latest, int graph_id)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
int ret = 0;
|
|
Packit Service |
e080da |
size_t hlen = 0;
|
|
Packit Service |
e080da |
size_t flen = 0;
|
|
Packit Service |
e080da |
size_t mlen = 0;
|
|
Packit Service |
e080da |
char timestr_latest[256] = {
|
|
Packit Service |
e080da |
0,
|
|
Packit Service |
e080da |
};
|
|
Packit Service |
e080da |
char timestr_oldest[256] = {
|
|
Packit Service |
e080da |
0,
|
|
Packit Service |
e080da |
};
|
|
Packit Service |
e080da |
char errstr[256] = {
|
|
Packit Service |
e080da |
0,
|
|
Packit Service |
e080da |
};
|
|
Packit Service |
e080da |
char *header = NULL;
|
|
Packit Service |
e080da |
char *footer = NULL;
|
|
Packit Service |
e080da |
char *msg = NULL;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (!ctx)
|
|
Packit Service |
e080da |
goto err;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
gf_log_rotate(ctx);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
gf_time_fmt(timestr_latest, sizeof timestr_latest, latest.tv_sec,
|
|
Packit Service |
e080da |
gf_timefmt_FT);
|
|
Packit Service |
e080da |
snprintf(timestr_latest + strlen(timestr_latest),
|
|
Packit Service |
e080da |
sizeof(timestr_latest) - strlen(timestr_latest),
|
|
Packit Service |
e080da |
".%" GF_PRI_SUSECONDS, latest.tv_usec);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
gf_time_fmt(timestr_oldest, sizeof timestr_oldest, oldest.tv_sec,
|
|
Packit Service |
e080da |
gf_timefmt_FT);
|
|
Packit Service |
e080da |
snprintf(timestr_oldest + strlen(timestr_oldest),
|
|
Packit Service |
e080da |
sizeof(timestr_oldest) - strlen(timestr_oldest),
|
|
Packit Service |
e080da |
".%" GF_PRI_SUSECONDS, oldest.tv_usec);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ret = gf_asprintf(&header,
|
|
Packit Service |
e080da |
"The message \"%s [MSGID: %" PRIu64
|
|
Packit Service |
e080da |
"]"
|
|
Packit Service |
e080da |
" [%s:%d:%s] %d-%s: ",
|
|
Packit Service |
e080da |
gf_level_strings[level], msgid, file, line, function,
|
|
Packit Service |
e080da |
graph_id, domain);
|
|
Packit Service |
e080da |
if (-1 == ret)
|
|
Packit Service |
e080da |
goto err;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (errnum)
|
|
Packit Service |
e080da |
snprintf(errstr, sizeof(errstr) - 1, " [%s]", strerror(errnum));
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ret = gf_asprintf(&footer,
|
|
Packit Service |
e080da |
"%s\" repeated %d times between"
|
|
Packit Service |
e080da |
" [%s] and [%s]",
|
|
Packit Service |
e080da |
errstr, refcount, timestr_oldest, timestr_latest);
|
|
Packit Service |
e080da |
if (-1 == ret)
|
|
Packit Service |
e080da |
goto err;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* generate the full message to log */
|
|
Packit Service |
e080da |
hlen = strlen(header);
|
|
Packit Service |
e080da |
flen = strlen(footer);
|
|
Packit Service |
e080da |
mlen = strlen(*appmsgstr);
|
|
Packit Service |
e080da |
msg = GF_MALLOC(hlen + flen + mlen + 1, gf_common_mt_char);
|
|
Packit Service |
e080da |
if (!msg) {
|
|
Packit Service |
e080da |
ret = -1;
|
|
Packit Service |
e080da |
goto err;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
strcpy(msg, header);
|
|
Packit Service |
e080da |
strcpy(msg + hlen, *appmsgstr);
|
|
Packit Service |
e080da |
strcpy(msg + hlen + mlen, footer);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
pthread_mutex_lock(&ctx->log.logfile_mutex);
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
if (ctx->log.logfile) {
|
|
Packit Service |
e080da |
fprintf(ctx->log.logfile, "%s\n", msg);
|
|
Packit Service |
e080da |
fflush(ctx->log.logfile);
|
|
Packit Service |
e080da |
} else if (ctx->log.loglevel >= level) {
|
|
Packit Service |
e080da |
fprintf(stderr, "%s\n", msg);
|
|
Packit Service |
e080da |
fflush(stderr);
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
#ifdef GF_LINUX_HOST_OS
|
|
Packit Service |
e080da |
/* We want only serious logs in 'syslog', not our debug
|
|
Packit Service |
e080da |
* and trace logs */
|
|
Packit Service |
e080da |
if (ctx->log.gf_log_syslog && level &&
|
|
Packit Service |
e080da |
(level <= ctx->log.sys_log_level))
|
|
Packit Service |
e080da |
syslog((level - 1), "%s\n", msg);
|
|
Packit Service |
e080da |
#endif
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* TODO: Plugin in memory log buffer retention here. For logs not
|
|
Packit Service |
e080da |
* flushed during cores, it would be useful to retain some of the last
|
|
Packit Service |
e080da |
* few messages in memory */
|
|
Packit Service |
e080da |
pthread_mutex_unlock(&ctx->log.logfile_mutex);
|
|
Packit Service |
e080da |
ret = 0;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
err:
|
|
Packit Service |
e080da |
GF_FREE(msg);
|
|
Packit Service |
e080da |
GF_FREE(header);
|
|
Packit Service |
e080da |
GF_FREE(footer);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
return ret;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
static int
|
|
Packit Service |
e080da |
gf_log_print_with_repetitions(glusterfs_ctx_t *ctx, const char *domain,
|
|
Packit Service |
e080da |
const char *file, const char *function,
|
|
Packit Service |
e080da |
int32_t line, gf_loglevel_t level, int errnum,
|
|
Packit Service |
e080da |
uint64_t msgid, char **appmsgstr, char *callstr,
|
|
Packit Service |
e080da |
int refcount, struct timeval oldest,
|
|
Packit Service |
e080da |
struct timeval latest, int graph_id)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
int ret = -1;
|
|
Packit Service |
e080da |
gf_log_logger_t logger = 0;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
logger = ctx->log.logger;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
switch (logger) {
|
|
Packit Service |
e080da |
case gf_logger_syslog:
|
|
Packit Service |
e080da |
if (ctx->log.log_control_file_found && ctx->log.gf_log_syslog) {
|
|
Packit Service |
e080da |
ret = gf_syslog_log_repetitions(
|
|
Packit Service |
e080da |
domain, file, function, line, level, errnum, msgid,
|
|
Packit Service |
e080da |
appmsgstr, callstr, refcount, oldest, latest, graph_id);
|
|
Packit Service |
e080da |
break;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
case gf_logger_glusterlog:
|
|
Packit Service |
e080da |
ret = gf_glusterlog_log_repetitions(
|
|
Packit Service |
e080da |
ctx, domain, file, function, line, level, errnum, msgid,
|
|
Packit Service |
e080da |
appmsgstr, callstr, refcount, oldest, latest, graph_id);
|
|
Packit Service |
e080da |
break;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
return ret;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
static int
|
|
Packit Service |
e080da |
gf_log_print_plain_fmt(glusterfs_ctx_t *ctx, const char *domain,
|
|
Packit Service |
e080da |
const char *file, const char *function, int32_t line,
|
|
Packit Service |
e080da |
gf_loglevel_t level, int errnum, uint64_t msgid,
|
|
Packit Service |
e080da |
char **appmsgstr, char *callstr, struct timeval tv,
|
|
Packit Service |
e080da |
int graph_id, gf_log_format_t fmt)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
int ret = -1;
|
|
Packit Service |
e080da |
gf_log_logger_t logger = 0;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
logger = ctx->log.logger;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* log to the configured logging service */
|
|
Packit Service |
e080da |
switch (logger) {
|
|
Packit Service |
e080da |
case gf_logger_syslog:
|
|
Packit Service |
e080da |
if (ctx->log.log_control_file_found && ctx->log.gf_log_syslog) {
|
|
Packit Service |
e080da |
ret = gf_log_syslog(ctx, domain, file, function, line, level,
|
|
Packit Service |
e080da |
errnum, msgid, appmsgstr, callstr, graph_id,
|
|
Packit Service |
e080da |
fmt);
|
|
Packit Service |
e080da |
break;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
/* NOTE: If syslog control file is absent, which is another
|
|
Packit Service |
e080da |
* way to control logging to syslog, then we will fall through
|
|
Packit Service |
e080da |
* to the gluster log. The ideal way to do things would be to
|
|
Packit Service |
e080da |
* not have the extra control file check */
|
|
Packit Service |
e080da |
case gf_logger_glusterlog:
|
|
Packit Service |
e080da |
ret = gf_log_glusterlog(ctx, domain, file, function, line, level,
|
|
Packit Service |
e080da |
errnum, msgid, appmsgstr, callstr, tv,
|
|
Packit Service |
e080da |
graph_id, fmt);
|
|
Packit Service |
e080da |
break;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
return ret;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
void
|
|
Packit Service |
e080da |
gf_log_flush_message(log_buf_t *buf, glusterfs_ctx_t *ctx)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
if (buf->refcount == 1) {
|
|
Packit Service |
e080da |
(void)gf_log_print_plain_fmt(ctx, buf->domain, buf->file, buf->function,
|
|
Packit Service |
e080da |
buf->line, buf->level, buf->errnum,
|
|
Packit Service |
e080da |
buf->msg_id, &buf->msg, NULL, buf->latest,
|
|
Packit Service |
e080da |
buf->graph_id, gf_logformat_withmsgid);
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (buf->refcount > 1) {
|
|
Packit Service |
e080da |
gf_log_print_with_repetitions(
|
|
Packit Service |
e080da |
ctx, buf->domain, buf->file, buf->function, buf->line, buf->level,
|
|
Packit Service |
e080da |
buf->errnum, buf->msg_id, &buf->msg, NULL, buf->refcount,
|
|
Packit Service |
e080da |
buf->oldest, buf->latest, buf->graph_id);
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
return;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
static void
|
|
Packit Service |
e080da |
gf_log_flush_list(struct list_head *copy, glusterfs_ctx_t *ctx)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
log_buf_t *iter = NULL;
|
|
Packit Service |
e080da |
log_buf_t *tmp = NULL;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
list_for_each_entry_safe(iter, tmp, copy, msg_list)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
gf_log_flush_message(iter, ctx);
|
|
Packit Service |
e080da |
list_del_init(&iter->msg_list);
|
|
Packit Service |
e080da |
log_buf_destroy(iter);
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
void
|
|
Packit Service |
e080da |
gf_log_flush_msgs(glusterfs_ctx_t *ctx)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
struct list_head copy;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
INIT_LIST_HEAD(©);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
pthread_mutex_lock(&ctx->log.log_buf_lock);
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
list_splice_init(&ctx->log.lru_queue, ©);
|
|
Packit Service |
e080da |
ctx->log.lru_cur_size = 0;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
pthread_mutex_unlock(&ctx->log.log_buf_lock);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
gf_log_flush_list(©, ctx);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
return;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
static void
|
|
Packit Service |
e080da |
gf_log_flush_extra_msgs(glusterfs_ctx_t *ctx, uint32_t new)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
int count = 0;
|
|
Packit Service |
e080da |
int i = 0;
|
|
Packit Service |
e080da |
log_buf_t *iter = NULL;
|
|
Packit Service |
e080da |
log_buf_t *tmp = NULL;
|
|
Packit Service |
e080da |
struct list_head copy;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
INIT_LIST_HEAD(©);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* If the number of outstanding log messages does not cause list
|
|
Packit Service |
e080da |
* overflow even after reducing the size of the list, then do nothing.
|
|
Packit Service |
e080da |
* Otherwise (that is if there are more items in the list than there
|
|
Packit Service |
e080da |
* need to be after reducing its size), move the least recently used
|
|
Packit Service |
e080da |
* 'diff' elements to be flushed into a separate list...
|
|
Packit Service |
e080da |
*/
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
pthread_mutex_lock(&ctx->log.log_buf_lock);
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
if (ctx->log.lru_cur_size <= new)
|
|
Packit Service |
e080da |
goto unlock;
|
|
Packit Service |
e080da |
count = ctx->log.lru_cur_size - new;
|
|
Packit Service |
e080da |
list_for_each_entry_safe(iter, tmp, &ctx->log.lru_queue, msg_list)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
if (i == count)
|
|
Packit Service |
e080da |
break;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
list_del_init(&iter->msg_list);
|
|
Packit Service |
e080da |
list_add_tail(&iter->msg_list, ©);
|
|
Packit Service |
e080da |
i++;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
ctx->log.lru_cur_size = ctx->log.lru_cur_size - count;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
// ... quickly unlock ...
|
|
Packit Service |
e080da |
unlock:
|
|
Packit Service |
e080da |
pthread_mutex_unlock(&ctx->log.log_buf_lock);
|
|
Packit Service |
e080da |
if (list_empty(©))
|
|
Packit Service |
e080da |
return;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
TEST_LOG(
|
|
Packit Service |
e080da |
"Log buffer size reduced. About to flush %d extra log "
|
|
Packit Service |
e080da |
"messages",
|
|
Packit Service |
e080da |
count);
|
|
Packit Service |
e080da |
// ... and then flush them outside the lock.
|
|
Packit Service |
e080da |
gf_log_flush_list(©, ctx);
|
|
Packit Service |
e080da |
TEST_LOG("Just flushed %d extra log messages", count);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
return;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
static int
|
|
Packit Service |
e080da |
__gf_log_inject_timer_event(glusterfs_ctx_t *ctx)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
int ret = -1;
|
|
Packit Service |
e080da |
struct timespec timeout = {
|
|
Packit Service |
e080da |
0,
|
|
Packit Service |
e080da |
};
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (!ctx)
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (ctx->log.log_flush_timer) {
|
|
Packit Service |
e080da |
gf_timer_call_cancel(ctx, ctx->log.log_flush_timer);
|
|
Packit Service |
e080da |
ctx->log.log_flush_timer = NULL;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
timeout.tv_sec = ctx->log.timeout;
|
|
Packit Service |
e080da |
timeout.tv_nsec = 0;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
TEST_LOG("Starting timer now. Timeout = %u, current buf size = %d",
|
|
Packit Service |
e080da |
ctx->log.timeout, ctx->log.lru_size);
|
|
Packit Service |
e080da |
ctx->log.log_flush_timer = gf_timer_call_after(
|
|
Packit Service |
e080da |
ctx, timeout, gf_log_flush_timeout_cbk, (void *)ctx);
|
|
Packit Service |
e080da |
if (!ctx->log.log_flush_timer)
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ret = 0;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
out:
|
|
Packit Service |
e080da |
return ret;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
int
|
|
Packit Service |
e080da |
gf_log_inject_timer_event(glusterfs_ctx_t *ctx)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
int ret = -1;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (!ctx)
|
|
Packit Service |
e080da |
return -1;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
pthread_mutex_lock(&ctx->log.log_buf_lock);
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
ret = __gf_log_inject_timer_event(ctx);
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
pthread_mutex_unlock(&ctx->log.log_buf_lock);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
return ret;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
void
|
|
Packit Service |
e080da |
gf_log_flush_timeout_cbk(void *data)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
glusterfs_ctx_t *ctx = NULL;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ctx = (glusterfs_ctx_t *)data;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
TEST_LOG(
|
|
Packit Service |
e080da |
"Log timer timed out. About to flush outstanding messages if "
|
|
Packit Service |
e080da |
"present");
|
|
Packit Service |
e080da |
gf_log_flush_msgs(ctx);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
(void)gf_log_inject_timer_event(ctx);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
return;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
static int
|
|
Packit Service |
e080da |
_gf_msg_internal(const char *domain, const char *file, const char *function,
|
|
Packit Service |
e080da |
int32_t line, gf_loglevel_t level, int errnum, uint64_t msgid,
|
|
Packit Service |
e080da |
char **appmsgstr, char *callstr, int graph_id)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
int ret = -1;
|
|
Packit Service |
e080da |
uint32_t size = 0;
|
|
Packit Service |
e080da |
const char *basename = NULL;
|
|
Packit Service |
e080da |
xlator_t *this = NULL;
|
|
Packit Service |
e080da |
glusterfs_ctx_t *ctx = NULL;
|
|
Packit Service |
e080da |
log_buf_t *iter = NULL;
|
|
Packit Service |
e080da |
log_buf_t *buf_tmp = NULL;
|
|
Packit Service |
e080da |
log_buf_t *buf_new = NULL;
|
|
Packit Service |
e080da |
log_buf_t *first = NULL;
|
|
Packit Service |
e080da |
struct timeval tv = {
|
|
Packit Service |
e080da |
0,
|
|
Packit Service |
e080da |
};
|
|
Packit Service |
e080da |
gf_boolean_t found = _gf_false;
|
|
Packit Service |
e080da |
gf_boolean_t flush_lru = _gf_false;
|
|
Packit Service |
e080da |
gf_boolean_t flush_logged_msg = _gf_false;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
this = THIS;
|
|
Packit Service |
e080da |
ctx = this->ctx;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (!ctx)
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
GET_FILE_NAME_TO_LOG(file, basename);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ret = gettimeofday(&tv, NULL);
|
|
Packit Service |
e080da |
if (ret)
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* If this function is called via _gf_msg_callingfn () (indicated by a
|
|
Packit Service |
e080da |
* non-NULL callstr), or if the logformat is traditional, flush the
|
|
Packit Service |
e080da |
* message directly to disk.
|
|
Packit Service |
e080da |
*/
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if ((callstr) || (ctx->log.logformat == gf_logformat_traditional)) {
|
|
Packit Service |
e080da |
ret = gf_log_print_plain_fmt(ctx, domain, basename, function, line,
|
|
Packit Service |
e080da |
level, errnum, msgid, appmsgstr, callstr,
|
|
Packit Service |
e080da |
tv, graph_id, gf_logformat_traditional);
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
pthread_mutex_lock(&ctx->log.log_buf_lock);
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
/* Check if the msg being logged is already part of the list */
|
|
Packit Service |
e080da |
list_for_each_entry_safe_reverse(iter, buf_tmp, &ctx->log.lru_queue,
|
|
Packit Service |
e080da |
msg_list)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
if (first == NULL)
|
|
Packit Service |
e080da |
// Remember the first (lru) element in first ptr
|
|
Packit Service |
e080da |
first = iter;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* Try to fail the search early on by doing the less
|
|
Packit Service |
e080da |
* expensive integer comparisons and continue to string
|
|
Packit Service |
e080da |
* parameter comparisons only after all int parameters
|
|
Packit Service |
e080da |
* are found to be matching.
|
|
Packit Service |
e080da |
*/
|
|
Packit Service |
e080da |
if (line != iter->line)
|
|
Packit Service |
e080da |
continue;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (errnum != iter->errnum)
|
|
Packit Service |
e080da |
continue;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (msgid != iter->msg_id)
|
|
Packit Service |
e080da |
continue;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (level != iter->level)
|
|
Packit Service |
e080da |
continue;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (graph_id != iter->graph_id)
|
|
Packit Service |
e080da |
continue;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (strcmp(domain, iter->domain))
|
|
Packit Service |
e080da |
continue;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (strcmp(basename, iter->file))
|
|
Packit Service |
e080da |
continue;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (strcmp(function, iter->function))
|
|
Packit Service |
e080da |
continue;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (strcmp(*appmsgstr, iter->msg))
|
|
Packit Service |
e080da |
continue;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
// Ah! Found a match!
|
|
Packit Service |
e080da |
list_move_tail(&iter->msg_list, &ctx->log.lru_queue);
|
|
Packit Service |
e080da |
iter->refcount++;
|
|
Packit Service |
e080da |
found = _gf_true;
|
|
Packit Service |
e080da |
// Update the 'latest' timestamp.
|
|
Packit Service |
e080da |
memcpy((void *)&(iter->latest), (void *)&tv,
|
|
Packit Service |
e080da |
sizeof(struct timeval));
|
|
Packit Service |
e080da |
break;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
if (found) {
|
|
Packit Service |
e080da |
ret = 0;
|
|
Packit Service |
e080da |
goto unlock;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
// else ...
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
size = ctx->log.lru_size;
|
|
Packit Service |
e080da |
/* If the upper limit on the log buf size is 0, flush the msg to
|
|
Packit Service |
e080da |
* disk directly after unlock. There's no need to buffer the
|
|
Packit Service |
e080da |
* msg here.
|
|
Packit Service |
e080da |
*/
|
|
Packit Service |
e080da |
if (size == 0) {
|
|
Packit Service |
e080da |
flush_logged_msg = _gf_true;
|
|
Packit Service |
e080da |
goto unlock;
|
|
Packit Service |
e080da |
} else if ((ctx->log.lru_cur_size + 1) > size) {
|
|
Packit Service |
e080da |
/* If the list is full, flush the lru msg to disk and also
|
|
Packit Service |
e080da |
* release it after unlock, and ...
|
|
Packit Service |
e080da |
* */
|
|
Packit Service |
e080da |
if (first->refcount >= 1)
|
|
Packit Service |
e080da |
TEST_LOG(
|
|
Packit Service |
e080da |
"Buffer overflow of a buffer whose size limit "
|
|
Packit Service |
e080da |
"is %d. About to flush least recently used log"
|
|
Packit Service |
e080da |
" message to disk",
|
|
Packit Service |
e080da |
size);
|
|
Packit Service |
e080da |
list_del_init(&first->msg_list);
|
|
Packit Service |
e080da |
ctx->log.lru_cur_size--;
|
|
Packit Service |
e080da |
flush_lru = _gf_true;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
/* create a new list element, initialise and enqueue it.
|
|
Packit Service |
e080da |
* Additionally, this being the first occurrence of the msg,
|
|
Packit Service |
e080da |
* log it directly to disk after unlock. */
|
|
Packit Service |
e080da |
buf_new = log_buf_new();
|
|
Packit Service |
e080da |
if (!buf_new) {
|
|
Packit Service |
e080da |
ret = -1;
|
|
Packit Service |
e080da |
goto unlock;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
ret = log_buf_init(buf_new, domain, basename, function, line, level,
|
|
Packit Service |
e080da |
errnum, msgid, appmsgstr, graph_id);
|
|
Packit Service |
e080da |
if (ret) {
|
|
Packit Service |
e080da |
log_buf_destroy(buf_new);
|
|
Packit Service |
e080da |
goto unlock;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
memcpy((void *)&(buf_new->latest), (void *)&tv, sizeof(struct timeval));
|
|
Packit Service |
e080da |
memcpy((void *)&(buf_new->oldest), (void *)&tv, sizeof(struct timeval));
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
list_add_tail(&buf_new->msg_list, &ctx->log.lru_queue);
|
|
Packit Service |
e080da |
ctx->log.lru_cur_size++;
|
|
Packit Service |
e080da |
flush_logged_msg = _gf_true;
|
|
Packit Service |
e080da |
ret = 0;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
unlock:
|
|
Packit Service |
e080da |
pthread_mutex_unlock(&ctx->log.log_buf_lock);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* Value of @ret is a don't-care below since irrespective of success or
|
|
Packit Service |
e080da |
* failure post setting of @flush_lru, @first must be flushed and freed.
|
|
Packit Service |
e080da |
*/
|
|
Packit Service |
e080da |
if (flush_lru) {
|
|
Packit Service |
e080da |
gf_log_flush_message(first, ctx);
|
|
Packit Service |
e080da |
log_buf_destroy(first);
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
/* Similarly, irrespective of whether all operations since setting of
|
|
Packit Service |
e080da |
* @flush_logged_msg were successful or not, flush the message being
|
|
Packit Service |
e080da |
* logged to disk in the plain format.
|
|
Packit Service |
e080da |
*/
|
|
Packit Service |
e080da |
if (flush_logged_msg) {
|
|
Packit Service |
e080da |
ret = gf_log_print_plain_fmt(ctx, domain, basename, function, line,
|
|
Packit Service |
e080da |
level, errnum, msgid, appmsgstr, callstr,
|
|
Packit Service |
e080da |
tv, graph_id, gf_logformat_withmsgid);
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
out:
|
|
Packit Service |
e080da |
return ret;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
int
|
|
Packit Service |
e080da |
_gf_msg(const char *domain, const char *file, const char *function,
|
|
Packit Service |
e080da |
int32_t line, gf_loglevel_t level, int errnum, int trace,
|
|
Packit Service |
e080da |
uint64_t msgid, const char *fmt, ...)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
int ret = 0;
|
|
Packit Service |
e080da |
char *msgstr = NULL;
|
|
Packit Service |
e080da |
va_list ap;
|
|
Packit Service |
e080da |
xlator_t *this = NULL;
|
|
Packit Service |
e080da |
glusterfs_ctx_t *ctx = NULL;
|
|
Packit Service |
e080da |
char callstr[GF_LOG_BACKTRACE_SIZE] = {
|
|
Packit Service |
e080da |
0,
|
|
Packit Service |
e080da |
};
|
|
Packit Service |
e080da |
int passcallstr = 0;
|
|
Packit Service |
e080da |
int log_inited = 0;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* in args check */
|
|
Packit Service |
e080da |
if (!domain || !file || !function || !fmt) {
|
|
Packit Service |
e080da |
fprintf(stderr, "logging: %s:%s():%d: invalid argument\n", __FILE__,
|
|
Packit Service |
e080da |
__PRETTY_FUNCTION__, __LINE__);
|
|
Packit Service |
e080da |
return -1;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
this = THIS;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (this == NULL)
|
|
Packit Service |
e080da |
return -1;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ctx = this->ctx;
|
|
Packit Service |
e080da |
if (ctx == NULL) {
|
|
Packit Service |
e080da |
/* messages before context initialization are ignored */
|
|
Packit Service |
e080da |
return -1;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* check if we should be logging */
|
|
Packit Service |
e080da |
if (skip_logging(this, level))
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (trace) {
|
|
Packit Service |
e080da |
ret = _gf_msg_backtrace(GF_LOG_BACKTRACE_DEPTH, callstr,
|
|
Packit Service |
e080da |
GF_LOG_BACKTRACE_SIZE);
|
|
Packit Service |
e080da |
if (ret >= 0)
|
|
Packit Service |
e080da |
passcallstr = 1;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
pthread_mutex_lock(&ctx->log.logfile_mutex);
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
if (ctx->log.logfile) {
|
|
Packit Service |
e080da |
log_inited = 1;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
pthread_mutex_unlock(&ctx->log.logfile_mutex);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* form the message */
|
|
Packit Service |
e080da |
va_start(ap, fmt);
|
|
Packit Service |
e080da |
ret = vasprintf(&msgstr, fmt, ap);
|
|
Packit Service |
e080da |
va_end(ap);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* log */
|
|
Packit Service |
e080da |
if (ret != -1) {
|
|
Packit Service |
e080da |
if (!log_inited && ctx->log.gf_log_syslog) {
|
|
Packit Service |
e080da |
ret = gf_log_syslog(
|
|
Packit Service |
e080da |
ctx, domain, file, function, line, level, errnum, msgid,
|
|
Packit Service |
e080da |
&msgstr, (passcallstr ? callstr : NULL),
|
|
Packit Service |
e080da |
(this->graph) ? this->graph->id : 0, gf_logformat_traditional);
|
|
Packit Service |
e080da |
} else {
|
|
Packit Service |
e080da |
ret = _gf_msg_internal(domain, file, function, line, level, errnum,
|
|
Packit Service |
e080da |
msgid, &msgstr,
|
|
Packit Service |
e080da |
(passcallstr ? callstr : NULL),
|
|
Packit Service |
e080da |
(this->graph) ? this->graph->id : 0);
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
} else {
|
|
Packit Service |
e080da |
/* man (3) vasprintf states on error strp contents
|
|
Packit Service |
e080da |
* are undefined, be safe */
|
|
Packit Service |
e080da |
msgstr = NULL;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
FREE(msgstr);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
out:
|
|
Packit Service |
e080da |
return ret;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* TODO: Deprecate (delete) _gf_log, _gf_log_callingfn,
|
|
Packit Service |
e080da |
* once messages are changed to use _gf_msgXXX APIs for logging */
|
|
Packit Service |
e080da |
int
|
|
Packit Service |
e080da |
_gf_log(const char *domain, const char *file, const char *function, int line,
|
|
Packit Service |
e080da |
gf_loglevel_t level, const char *fmt, ...)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
const char *basename = NULL;
|
|
Packit Service |
e080da |
FILE *new_logfile = NULL;
|
|
Packit Service |
e080da |
va_list ap;
|
|
Packit Service |
e080da |
char timestr[GF_LOG_TIMESTR_SIZE] = {
|
|
Packit Service |
e080da |
0,
|
|
Packit Service |
e080da |
};
|
|
Packit Service |
e080da |
struct timeval tv = {
|
|
Packit Service |
e080da |
0,
|
|
Packit Service |
e080da |
};
|
|
Packit Service |
e080da |
char *logline = NULL;
|
|
Packit Service |
e080da |
char *msg = NULL;
|
|
Packit Service |
e080da |
int ret = 0;
|
|
Packit Service |
e080da |
int fd = -1;
|
|
Packit Service |
e080da |
xlator_t *this = NULL;
|
|
Packit Service |
e080da |
glusterfs_ctx_t *ctx = NULL;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
this = THIS;
|
|
Packit Service |
e080da |
ctx = this->ctx;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (!ctx)
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (skip_logging(this, level))
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
static char *level_strings[] = {"", /* NONE */
|
|
Packit Service |
e080da |
"M", /* EMERGENCY */
|
|
Packit Service |
e080da |
"A", /* ALERT */
|
|
Packit Service |
e080da |
"C", /* CRITICAL */
|
|
Packit Service |
e080da |
"E", /* ERROR */
|
|
Packit Service |
e080da |
"W", /* WARNING */
|
|
Packit Service |
e080da |
"N", /* NOTICE */
|
|
Packit Service |
e080da |
"I", /* INFO */
|
|
Packit Service |
e080da |
"D", /* DEBUG */
|
|
Packit Service |
e080da |
"T", /* TRACE */
|
|
Packit Service |
e080da |
""};
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (!domain || !file || !function || !fmt) {
|
|
Packit Service |
e080da |
fprintf(stderr, "logging: %s:%s():%d: invalid argument\n", __FILE__,
|
|
Packit Service |
e080da |
__PRETTY_FUNCTION__, __LINE__);
|
|
Packit Service |
e080da |
return -1;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
basename = strrchr(file, '/');
|
|
Packit Service |
e080da |
if (basename)
|
|
Packit Service |
e080da |
basename++;
|
|
Packit Service |
e080da |
else
|
|
Packit Service |
e080da |
basename = file;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
va_start(ap, fmt);
|
|
Packit Service |
e080da |
ret = vasprintf(&msg, fmt, ap);
|
|
Packit Service |
e080da |
va_end(ap);
|
|
Packit Service |
e080da |
if (-1 == ret) {
|
|
Packit Service |
e080da |
goto err;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (ctx->log.log_control_file_found) {
|
|
Packit Service |
e080da |
int priority;
|
|
Packit Service |
e080da |
/* treat GF_LOG_TRACE and GF_LOG_NONE as LOG_DEBUG and
|
|
Packit Service |
e080da |
other level as is */
|
|
Packit Service |
e080da |
if (GF_LOG_TRACE == level || GF_LOG_NONE == level) {
|
|
Packit Service |
e080da |
priority = LOG_DEBUG;
|
|
Packit Service |
e080da |
} else {
|
|
Packit Service |
e080da |
priority = level - 1;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
gf_syslog(priority, "[%s:%d:%s] %d-%s: %s", basename, line, function,
|
|
Packit Service |
e080da |
((this->graph) ? this->graph->id : 0), domain, msg);
|
|
Packit Service |
e080da |
goto err;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (ctx->log.logrotate) {
|
|
Packit Service |
e080da |
ctx->log.logrotate = 0;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
fd = sys_open(ctx->log.filename, O_CREAT | O_RDONLY, S_IRUSR | S_IWUSR);
|
|
Packit Service |
e080da |
if (fd < 0) {
|
|
Packit Service |
e080da |
gf_msg("logrotate", GF_LOG_ERROR, errno, LG_MSG_FILE_OP_FAILED,
|
|
Packit Service |
e080da |
"failed to open logfile");
|
|
Packit Service |
e080da |
return -1;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
sys_close(fd);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
new_logfile = fopen(ctx->log.filename, "a");
|
|
Packit Service |
e080da |
if (!new_logfile) {
|
|
Packit Service |
e080da |
gf_msg("logrotate", GF_LOG_CRITICAL, errno, LG_MSG_FILE_OP_FAILED,
|
|
Packit Service |
e080da |
"failed to open logfile %s", ctx->log.filename);
|
|
Packit Service |
e080da |
goto log;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
pthread_mutex_lock(&ctx->log.logfile_mutex);
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
if (ctx->log.logfile)
|
|
Packit Service |
e080da |
fclose(ctx->log.logfile);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ctx->log.gf_log_logfile = ctx->log.logfile = new_logfile;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
pthread_mutex_unlock(&ctx->log.logfile_mutex);
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
log:
|
|
Packit Service |
e080da |
ret = gettimeofday(&tv, NULL);
|
|
Packit Service |
e080da |
if (-1 == ret)
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
gf_time_fmt(timestr, sizeof timestr, tv.tv_sec, gf_timefmt_FT);
|
|
Packit Service |
e080da |
snprintf(timestr + strlen(timestr), sizeof timestr - strlen(timestr),
|
|
Packit Service |
e080da |
".%" GF_PRI_SUSECONDS, tv.tv_usec);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ret = gf_asprintf(&logline, "[%s] %s [%s:%d:%s] %d-%s: %s", timestr,
|
|
Packit Service |
e080da |
level_strings[level], basename, line, function,
|
|
Packit Service |
e080da |
((this->graph) ? this->graph->id : 0), domain, msg);
|
|
Packit Service |
e080da |
if (-1 == ret) {
|
|
Packit Service |
e080da |
goto err;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
pthread_mutex_lock(&ctx->log.logfile_mutex);
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
if (ctx->log.logfile) {
|
|
Packit Service |
e080da |
fprintf(ctx->log.logfile, "%s\n", logline);
|
|
Packit Service |
e080da |
fflush(ctx->log.logfile);
|
|
Packit Service |
e080da |
} else if (ctx->log.loglevel >= level) {
|
|
Packit Service |
e080da |
fprintf(stderr, "%s\n", logline);
|
|
Packit Service |
e080da |
fflush(stderr);
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
#ifdef GF_LINUX_HOST_OS
|
|
Packit Service |
e080da |
/* We want only serious log in 'syslog', not our debug
|
|
Packit Service |
e080da |
and trace logs */
|
|
Packit Service |
e080da |
if (ctx->log.gf_log_syslog && level &&
|
|
Packit Service |
e080da |
(level <= ctx->log.sys_log_level))
|
|
Packit Service |
e080da |
syslog((level - 1), "%s\n", logline);
|
|
Packit Service |
e080da |
#endif
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
pthread_mutex_unlock(&ctx->log.logfile_mutex);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
err:
|
|
Packit Service |
e080da |
GF_FREE(logline);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
FREE(msg);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
out:
|
|
Packit Service |
e080da |
return (0);
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
int
|
|
Packit Service |
e080da |
_gf_log_eh(const char *function, const char *fmt, ...)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
int ret = -1;
|
|
Packit Service |
e080da |
va_list ap;
|
|
Packit Service |
e080da |
char *logline = NULL;
|
|
Packit Service |
e080da |
char *msg = NULL;
|
|
Packit Service |
e080da |
xlator_t *this = NULL;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
this = THIS;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
va_start(ap, fmt);
|
|
Packit Service |
e080da |
ret = vasprintf(&msg, fmt, ap);
|
|
Packit Service |
e080da |
va_end(ap);
|
|
Packit Service |
e080da |
if (-1 == ret) {
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ret = gf_asprintf(&logline, "[%d] %s: %s",
|
|
Packit Service |
e080da |
((this->graph) ? this->graph->id : 0), function, msg);
|
|
Packit Service |
e080da |
if (-1 == ret) {
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ret = eh_save_history(this->history, logline);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
out:
|
|
Packit Service |
e080da |
GF_FREE(logline);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
FREE(msg);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
return ret;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
int
|
|
Packit Service |
e080da |
gf_cmd_log_init(const char *filename)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
int fd = -1;
|
|
Packit Service |
e080da |
xlator_t *this = NULL;
|
|
Packit Service |
e080da |
glusterfs_ctx_t *ctx = NULL;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
this = THIS;
|
|
Packit Service |
e080da |
ctx = this->ctx;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (!ctx)
|
|
Packit Service |
e080da |
return -1;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (!filename) {
|
|
Packit Service |
e080da |
gf_msg(this->name, GF_LOG_CRITICAL, 0, LG_MSG_INVALID_ENTRY,
|
|
Packit Service |
e080da |
"gf_cmd_log_init: no filename specified\n");
|
|
Packit Service |
e080da |
return -1;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ctx->log.cmd_log_filename = gf_strdup(filename);
|
|
Packit Service |
e080da |
if (!ctx->log.cmd_log_filename) {
|
|
Packit Service |
e080da |
return -1;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
/* close and reopen cmdlogfile for log rotate*/
|
|
Packit Service |
e080da |
if (ctx->log.cmdlogfile) {
|
|
Packit Service |
e080da |
fclose(ctx->log.cmdlogfile);
|
|
Packit Service |
e080da |
ctx->log.cmdlogfile = NULL;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
fd = sys_open(ctx->log.cmd_log_filename, O_CREAT | O_WRONLY | O_APPEND,
|
|
Packit Service |
e080da |
S_IRUSR | S_IWUSR);
|
|
Packit Service |
e080da |
if (fd < 0) {
|
|
Packit Service |
e080da |
gf_msg(this->name, GF_LOG_CRITICAL, errno, LG_MSG_FILE_OP_FAILED,
|
|
Packit Service |
e080da |
"failed to open cmd_log_file");
|
|
Packit Service |
e080da |
return -1;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ctx->log.cmdlogfile = fdopen(fd, "a");
|
|
Packit Service |
e080da |
if (!ctx->log.cmdlogfile) {
|
|
Packit Service |
e080da |
gf_msg(this->name, GF_LOG_CRITICAL, errno, LG_MSG_FILE_OP_FAILED,
|
|
Packit Service |
e080da |
"gf_cmd_log_init: failed to open logfile \"%s\" "
|
|
Packit Service |
e080da |
"\n",
|
|
Packit Service |
e080da |
ctx->log.cmd_log_filename);
|
|
Packit Service |
e080da |
sys_close(fd);
|
|
Packit Service |
e080da |
return -1;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
return 0;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
int
|
|
Packit Service |
e080da |
gf_cmd_log(const char *domain, const char *fmt, ...)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
va_list ap;
|
|
Packit Service |
e080da |
char timestr[64];
|
|
Packit Service |
e080da |
struct timeval tv = {
|
|
Packit Service |
e080da |
0,
|
|
Packit Service |
e080da |
};
|
|
Packit Service |
e080da |
char *logline = NULL;
|
|
Packit Service |
e080da |
char *msg = NULL;
|
|
Packit Service |
e080da |
int ret = 0;
|
|
Packit Service |
e080da |
int fd = -1;
|
|
Packit Service |
e080da |
glusterfs_ctx_t *ctx = NULL;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ctx = THIS->ctx;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (!ctx)
|
|
Packit Service |
e080da |
return -1;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (!ctx->log.cmdlogfile)
|
|
Packit Service |
e080da |
return -1;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (!domain || !fmt) {
|
|
Packit Service |
e080da |
gf_msg_trace("glusterd", 0, "logging: invalid argument\n");
|
|
Packit Service |
e080da |
return -1;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ret = gettimeofday(&tv, NULL);
|
|
Packit Service |
e080da |
if (ret == -1)
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
va_start(ap, fmt);
|
|
Packit Service |
e080da |
ret = vasprintf(&msg, fmt, ap);
|
|
Packit Service |
e080da |
va_end(ap);
|
|
Packit Service |
e080da |
if (ret == -1) {
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
gf_time_fmt(timestr, sizeof timestr, tv.tv_sec, gf_timefmt_FT);
|
|
Packit Service |
e080da |
snprintf(timestr + strlen(timestr), GF_LOG_TIMESTR_SIZE - strlen(timestr),
|
|
Packit Service |
e080da |
".%" GF_PRI_SUSECONDS, tv.tv_usec);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ret = gf_asprintf(&logline, "[%s] %s : %s", timestr, domain, msg);
|
|
Packit Service |
e080da |
if (ret == -1) {
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* close and reopen cmdlogfile fd for in case of log rotate*/
|
|
Packit Service |
e080da |
if (ctx->log.cmd_history_logrotate) {
|
|
Packit Service |
e080da |
ctx->log.cmd_history_logrotate = 0;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (ctx->log.cmdlogfile) {
|
|
Packit Service |
e080da |
fclose(ctx->log.cmdlogfile);
|
|
Packit Service |
e080da |
ctx->log.cmdlogfile = NULL;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
fd = sys_open(ctx->log.cmd_log_filename, O_CREAT | O_WRONLY | O_APPEND,
|
|
Packit Service |
e080da |
S_IRUSR | S_IWUSR);
|
|
Packit Service |
e080da |
if (fd < 0) {
|
|
Packit Service |
e080da |
gf_msg(THIS->name, GF_LOG_CRITICAL, errno, LG_MSG_FILE_OP_FAILED,
|
|
Packit Service |
e080da |
"failed to open "
|
|
Packit Service |
e080da |
"logfile \"%s\" \n",
|
|
Packit Service |
e080da |
ctx->log.cmd_log_filename);
|
|
Packit Service |
e080da |
ret = -1;
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ctx->log.cmdlogfile = fdopen(fd, "a");
|
|
Packit Service |
e080da |
if (!ctx->log.cmdlogfile) {
|
|
Packit Service |
e080da |
gf_msg(THIS->name, GF_LOG_CRITICAL, errno, LG_MSG_FILE_OP_FAILED,
|
|
Packit Service |
e080da |
"failed to open logfile \"%s\""
|
|
Packit Service |
e080da |
" \n",
|
|
Packit Service |
e080da |
ctx->log.cmd_log_filename);
|
|
Packit Service |
e080da |
ret = -1;
|
|
Packit Service |
e080da |
sys_close(fd);
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
fprintf(ctx->log.cmdlogfile, "%s\n", logline);
|
|
Packit Service |
e080da |
fflush(ctx->log.cmdlogfile);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
out:
|
|
Packit Service |
e080da |
GF_FREE(logline);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
FREE(msg);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
return ret;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
static int
|
|
Packit Service |
e080da |
_do_slog_format(const char *event, va_list inp, char **msg)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
va_list valist_tmp;
|
|
Packit Service |
e080da |
int i = 0;
|
|
Packit Service |
e080da |
int j = 0;
|
|
Packit Service |
e080da |
int k = 0;
|
|
Packit Service |
e080da |
int ret = 0;
|
|
Packit Service |
e080da |
char *fmt = NULL;
|
|
Packit Service |
e080da |
char *buffer = NULL;
|
|
Packit Service |
e080da |
int num_format_chars = 0;
|
|
Packit Service |
e080da |
char format_char = '%';
|
|
Packit Service |
e080da |
char *tmp1 = NULL;
|
|
Packit Service |
e080da |
char *tmp2 = NULL;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ret = gf_asprintf(&tmp2, "%s", event);
|
|
Packit Service |
e080da |
if (ret == -1)
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* Hardcoded value for max key value pairs, exits early */
|
|
Packit Service |
e080da |
/* from loop if found NULL */
|
|
Packit Service |
e080da |
for (i = 0; i < GF_MAX_SLOG_PAIR_COUNT; i++) {
|
|
Packit Service |
e080da |
fmt = va_arg(inp, char *);
|
|
Packit Service |
e080da |
if (fmt == NULL) {
|
|
Packit Service |
e080da |
break;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
/* Get number of times % is used in input for formatting, */
|
|
Packit Service |
e080da |
/* this count will be used to skip those many args from the */
|
|
Packit Service |
e080da |
/* main list and will be used to format inner format */
|
|
Packit Service |
e080da |
num_format_chars = 0;
|
|
Packit Service |
e080da |
for (k = 0; fmt[k] != '\0'; k++) {
|
|
Packit Service |
e080da |
/* If %% is used then that is escaped */
|
|
Packit Service |
e080da |
if (fmt[k] == format_char && fmt[k + 1] == format_char) {
|
|
Packit Service |
e080da |
k++;
|
|
Packit Service |
e080da |
} else if (fmt[k] == format_char) {
|
|
Packit Service |
e080da |
num_format_chars++;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
tmp1 = gf_strdup(tmp2);
|
|
Packit Service |
e080da |
if (!tmp1) {
|
|
Packit Service |
e080da |
ret = -1;
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
GF_FREE(tmp2);
|
|
Packit Service |
e080da |
tmp2 = NULL;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (num_format_chars > 0) {
|
|
Packit Service |
e080da |
/* Make separate valist and format the string */
|
|
Packit Service |
e080da |
va_copy(valist_tmp, inp);
|
|
Packit Service |
e080da |
ret = gf_vasprintf(&buffer, fmt, valist_tmp);
|
|
Packit Service |
e080da |
if (ret < 0) {
|
|
Packit Service |
e080da |
va_end(valist_tmp);
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
va_end(valist_tmp);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
for (j = 0; j < num_format_chars; j++) {
|
|
Packit Service |
e080da |
/* Skip the va_arg value since these values
|
|
Packit Service |
e080da |
are already used for internal formatting */
|
|
Packit Service |
e080da |
(void)va_arg(inp, void *);
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ret = gf_asprintf(&tmp2, "%s\t%s", tmp1, buffer);
|
|
Packit Service |
e080da |
if (ret < 0)
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
GF_FREE(buffer);
|
|
Packit Service |
e080da |
buffer = NULL;
|
|
Packit Service |
e080da |
} else {
|
|
Packit Service |
e080da |
ret = gf_asprintf(&tmp2, "%s\t%s", tmp1, fmt);
|
|
Packit Service |
e080da |
if (ret < 0)
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
GF_FREE(tmp1);
|
|
Packit Service |
e080da |
tmp1 = NULL;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
*msg = gf_strdup(tmp2);
|
|
Packit Service |
e080da |
if (!*msg)
|
|
Packit Service |
e080da |
ret = -1;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
out:
|
|
Packit Service |
e080da |
if (buffer)
|
|
Packit Service |
e080da |
GF_FREE(buffer);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (tmp1)
|
|
Packit Service |
e080da |
GF_FREE(tmp1);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
if (tmp2)
|
|
Packit Service |
e080da |
GF_FREE(tmp2);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
return ret;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
int
|
|
Packit Service |
e080da |
_gf_smsg(const char *domain, const char *file, const char *function,
|
|
Packit Service |
e080da |
int32_t line, gf_loglevel_t level, int errnum, int trace,
|
|
Packit Service |
e080da |
uint64_t msgid, const char *event, ...)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
va_list valist;
|
|
Packit Service |
e080da |
char *msg = NULL;
|
|
Packit Service |
e080da |
int ret = 0;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
va_start(valist, event);
|
|
Packit Service |
e080da |
ret = _do_slog_format(event, valist, &msg;;
|
|
Packit Service |
e080da |
if (ret == -1)
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ret = _gf_msg(domain, file, function, line, level, errnum, trace, msgid,
|
|
Packit Service |
e080da |
"%s", msg);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
out:
|
|
Packit Service |
e080da |
va_end(valist);
|
|
Packit Service |
e080da |
if (msg)
|
|
Packit Service |
e080da |
GF_FREE(msg);
|
|
Packit Service |
e080da |
return ret;
|
|
Packit Service |
e080da |
}
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
int
|
|
Packit Service |
e080da |
_gf_slog(const char *domain, const char *file, const char *function, int line,
|
|
Packit Service |
e080da |
gf_loglevel_t level, const char *event, ...)
|
|
Packit Service |
e080da |
{
|
|
Packit Service |
e080da |
va_list valist;
|
|
Packit Service |
e080da |
char *msg = NULL;
|
|
Packit Service |
e080da |
int ret = 0;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
va_start(valist, event);
|
|
Packit Service |
e080da |
ret = _do_slog_format(event, valist, &msg;;
|
|
Packit Service |
e080da |
if (ret == -1)
|
|
Packit Service |
e080da |
goto out;
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
ret = _gf_log(domain, file, function, line, level, "%s", msg);
|
|
Packit Service |
e080da |
|
|
Packit Service |
e080da |
out:
|
|
Packit Service |
e080da |
va_end(valist);
|
|
Packit Service |
e080da |
if (msg)
|
|
Packit Service |
e080da |
GF_FREE(msg);
|
|
Packit Service |
e080da |
return ret;
|
|
Packit Service |
e080da |
}
|