设为首页 收藏本站
查看: 1380|回复: 0

[经验分享] GlusterFS源代码解析 —— GlusterFS 日志

[复制链接]

尚未签到

发表于 2015-9-10 02:00:20 | 显示全部楼层 |阅读模式
  



Logging.c:
  

/*
Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
This file is part of GlusterFS.
This file is licensed to you under your choice of the GNU Lesser
General Public License, version 3 or any later version (LGPLv3 or
later), or the GNU General Public License, version 2 (GPLv2), in all
cases as published by the Free Software Foundation.
*/
#ifndef _CONFIG_H
#define _CONFIG_H
#include &quot;config.h&quot;
#endif
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdarg.h>
#include <time.h>
#include <locale.h>
#include <string.h>
#include <stdlib.h>
#include &quot;xlator.h&quot;
#include &quot;logging.h&quot;
#include &quot;defaults.h&quot;
#include &quot;glusterfs.h&quot;
#ifdef GF_LINUX_HOST_OS
#include <syslog.h>
#endif
#ifdef HAVE_BACKTRACE
#include <execinfo.h>
#endif
/* Ideally this should get moved to logging.h */
struct _msg_queue {
struct list_head msgs;
};
struct _log_msg {
const char *msg;
struct list_head queue;
};
void
gf_log_logrotate (int signum)
{
THIS->ctx->log.logrotate = 1;
}
void
gf_log_enable_syslog (void)
{
THIS->ctx->log.gf_log_syslog = 1;
}
void
gf_log_disable_syslog (void)
{
THIS->ctx->log.gf_log_syslog = 0;
}
gf_loglevel_t
gf_log_get_loglevel (void)
{
return THIS->ctx->log.loglevel;
}
void
gf_log_set_loglevel (gf_loglevel_t level)
{
THIS->ctx->log.loglevel = level;
}

gf_loglevel_t
gf_log_get_xl_loglevel (void *this)
{
xlator_t *xl = this;
if (!xl)
return 0;
return xl->loglevel;
}
void
gf_log_set_xl_loglevel (void *this, gf_loglevel_t level)
{
xlator_t *xl = this;
if (!xl)
return;
xl->ctx->log.gf_log_xl_log_set = 1;
xl->loglevel = level;
}
void
gf_log_fini (void)
{
pthread_mutex_destroy (&THIS->ctx->log.logfile_mutex);
}

void
gf_log_globals_init (void *data)
{
glusterfs_ctx_t *ctx = data;
pthread_mutex_init (&ctx->log.logfile_mutex, NULL);
ctx->log.loglevel         = GF_LOG_INFO;
ctx->log.gf_log_syslog    = 1;
ctx->log.sys_log_level    = GF_LOG_CRITICAL;
#ifdef GF_LINUX_HOST_OS
/* For the 'syslog' output. one can grep 'GlusterFS' in syslog
for serious logs */
openlog (&quot;GlusterFS&quot;, LOG_PID, LOG_DAEMON);
#endif
}
int
gf_log_init (void *data, const char *file)
{
glusterfs_ctx_t *ctx = NULL;
int     fd = -1;
ctx = data;
if (!file){
fprintf (stderr, &quot;ERROR: no filename specified\n&quot;);
return -1;
}
if (strcmp (file, &quot;-&quot;) == 0) {
ctx->log.gf_log_logfile = stderr;
return 0;
}
ctx->log.filename = gf_strdup (file);
if (!ctx->log.filename) {
fprintf (stderr, &quot;ERROR: updating log-filename failed: %s\n&quot;,
strerror (errno));
return -1;
}
fd = open (file, O_CREAT | O_RDONLY, S_IRUSR | S_IWUSR);
if (fd < 0) {
fprintf (stderr, &quot;ERROR: failed to create logfile \&quot;%s\&quot; (%s)\n&quot;,
file, strerror (errno));
return -1;
}
close (fd);
ctx->log.logfile = fopen (file, &quot;a&quot;);
if (!ctx->log.logfile){
fprintf (stderr, &quot;ERROR: failed to open logfile \&quot;%s\&quot; (%s)\n&quot;,
file, strerror (errno));
return -1;
}
ctx->log.gf_log_logfile = ctx->log.logfile;
return 0;
}
void
set_sys_log_level (gf_loglevel_t level)
{
THIS->ctx->log.sys_log_level = level;
}
/*
* 内存申请失败日志打印.假设日志级别较高,打印到系统日志中&quot;/var/log/message&quot;
* 不支持变參
*
* 若定义了HAVE_BACKTRACE,则打出函数调用栈
*
* @domain 模块名
*
* 假设日志文件不存在,则打印到标准错误输出
*/
int
_gf_log_nomem (const char *domain, const char *file,
const char *function, int line, gf_loglevel_t level,
size_t size)
{
const char     *basename        = NULL;
xlator_t       *this            = NULL;
struct timeval  tv              = {0,};
int             ret             = 0;
char            msg[8092]       = {0,};
char            timestr[256]    = {0,};
char            callstr[4096]   = {0,};
glusterfs_ctx_t *ctx = NULL;
this = THIS;
ctx = this->ctx;
if (ctx->log.gf_log_xl_log_set) {
if (this->loglevel && (level > this->loglevel))
goto out;
}
if (level > ctx->log.loglevel)
goto out;
static char *level_strings[] = {&quot;&quot;,  /* NONE */
&quot;M&quot;, /* EMERGENCY */
&quot;A&quot;, /* ALERT */
&quot;C&quot;, /* CRITICAL */
&quot;E&quot;, /* ERROR */
&quot;W&quot;, /* WARNING */
&quot;N&quot;, /* NOTICE */
&quot;I&quot;, /* INFO */
&quot;D&quot;, /* DEBUG */
&quot;T&quot;, /* TRACE */
&quot;&quot;};
if (!domain || !file || !function) {
fprintf (stderr,
&quot;logging: %s:%s():%d: invalid argument\n&quot;,
__FILE__, __PRETTY_FUNCTION__, __LINE__);
return -1;
}
#if HAVE_BACKTRACE
/* Print 'calling function' */
do {
void *array[5];
char **callingfn = NULL;
size_t bt_size = 0;
bt_size = backtrace (array, 5);
if (bt_size)
callingfn = backtrace_symbols (&array[2], bt_size-2);
if (!callingfn)
break;
if (bt_size == 5)
snprintf (callstr, 4096, &quot;(-->%s (-->%s (-->%s)))&quot;,
callingfn[2], callingfn[1], callingfn[0]);
if (bt_size == 4)
snprintf (callstr, 4096, &quot;(-->%s (-->%s))&quot;,
callingfn[1], callingfn[0]);
if (bt_size == 3)
snprintf (callstr, 4096, &quot;(-->%s)&quot;, callingfn[0]);
free (callingfn);
} while (0);
#endif /* HAVE_BACKTRACE */
ret = gettimeofday (&tv, NULL);
if (-1 == ret)
goto out;
gf_time_fmt (timestr, sizeof timestr, tv.tv_sec, gf_timefmt_FT);
snprintf (timestr + strlen (timestr), sizeof timestr - strlen (timestr),
&quot;.%&quot;GF_PRI_SUSECONDS, tv.tv_usec);
basename = strrchr (file, '/');
if (basename)
basename++;
else
basename = file;
ret = sprintf (msg, &quot;[%s] %s [%s:%d:%s] %s %s: no memory &quot;
&quot;available for size (%&quot;GF_PRI_SIZET&quot;)&quot;,
timestr, level_strings[level],
basename, line, function, callstr,
domain, size);
if (-1 == ret) {
goto out;
}
pthread_mutex_lock (&ctx->log.logfile_mutex);
{
if (ctx->log.logfile) {
fprintf (ctx->log.logfile, &quot;%s\n&quot;, msg);
} else {
fprintf (stderr, &quot;%s\n&quot;, msg);
}
#ifdef GF_LINUX_HOST_OS
/* We want only serious log in 'syslog', not our debug
and trace logs */
if (ctx->log.gf_log_syslog && level &&
(level <= ctx->log.sys_log_level))
syslog ((level-1), &quot;%s\n&quot;, msg);
#endif
}
pthread_mutex_unlock (&ctx->log.logfile_mutex);
out:
return ret;
}
/*
* 函数调用參数无效日志打印.假设日志级别较高,打印到系统日志中&quot;/var/log/message&quot;
* 支持变參
*
* 若定义了HAVE_BACKTRACE,则打出函数调用栈
*
* @domain 模块名
*
* 假设日志文件不存在,则打印到标准输出
*/
int
_gf_log_callingfn (const char *domain, const char *file, const char *function,
int line, gf_loglevel_t level, const char *fmt, ...)
{
const char     *basename        = NULL;
xlator_t       *this            = NULL;
char           *str1            = NULL;
char           *str2            = NULL;
char           *msg             = NULL;
char            timestr[256]    = {0,};
char            callstr[4096]   = {0,};
struct timeval  tv              = {0,};
size_t          len             = 0;
int             ret             = 0;
va_list         ap;
glusterfs_ctx_t *ctx = NULL;
this = THIS;
ctx = this->ctx;
if (ctx->log.gf_log_xl_log_set) {
if (this->loglevel && (level > this->loglevel))
goto out;
}
if (level > ctx->log.loglevel)
goto out;
static char *level_strings[] = {&quot;&quot;,  /* NONE */
&quot;M&quot;, /* EMERGENCY */
&quot;A&quot;, /* ALERT */
&quot;C&quot;, /* CRITICAL */
&quot;E&quot;, /* ERROR */
&quot;W&quot;, /* WARNING */
&quot;N&quot;, /* NOTICE */
&quot;I&quot;, /* INFO */
&quot;D&quot;, /* DEBUG */
&quot;T&quot;, /* TRACE */
&quot;&quot;};
if (!domain || !file || !function || !fmt) {
fprintf (stderr,
&quot;logging: %s:%s():%d: invalid argument\n&quot;,
__FILE__, __PRETTY_FUNCTION__, __LINE__);
return -1;
}
#if HAVE_BACKTRACE
/* Print 'calling function' */
do {
void *array[5];
char **callingfn = NULL;
size_t size = 0;
size = backtrace (array, 5);
if (size)
callingfn = backtrace_symbols (&array[2], size-2);
if (!callingfn)
break;
if (size == 5)
snprintf (callstr, 4096, &quot;(-->%s (-->%s (-->%s)))&quot;,
callingfn[2], callingfn[1], callingfn[0]);
if (size == 4)
snprintf (callstr, 4096, &quot;(-->%s (-->%s))&quot;,
callingfn[1], callingfn[0]);
if (size == 3)
snprintf (callstr, 4096, &quot;(-->%s)&quot;, callingfn[0]);
free (callingfn);
} while (0);
#endif /* HAVE_BACKTRACE */
ret = gettimeofday (&tv, NULL);
if (-1 == ret)
goto out;
va_start (ap, fmt);
gf_time_fmt (timestr, sizeof timestr, tv.tv_sec, gf_timefmt_FT);
snprintf (timestr + strlen (timestr), sizeof timestr - strlen (timestr),
&quot;.%&quot;GF_PRI_SUSECONDS, tv.tv_usec);
basename = strrchr (file, '/');
if (basename)
basename++;
else
basename = file;
ret = gf_asprintf (&str1, &quot;[%s] %s [%s:%d:%s] %s %d-%s: &quot;,
timestr, level_strings[level],
basename, line, function, callstr,
((this->graph) ? this->graph->id:0), domain);
if (-1 == ret) {
goto out;
}
ret = vasprintf (&str2, fmt, ap);
if (-1 == ret) {
goto out;
}
va_end (ap);
len = strlen (str1);
msg = GF_MALLOC (len + strlen (str2) + 1, gf_common_mt_char);
strcpy (msg, str1);
strcpy (msg + len, str2);
pthread_mutex_lock (&ctx->log.logfile_mutex);
{
if (ctx->log.logfile) {
fprintf (ctx->log.logfile, &quot;%s\n&quot;, msg);
} else {
fprintf (stderr, &quot;%s\n&quot;, msg);
}
#ifdef GF_LINUX_HOST_OS
/* We want only serious log in 'syslog', not our debug
and trace logs */
if (ctx->log.gf_log_syslog && level &&
(level <= ctx->log.sys_log_level))
syslog ((level-1), &quot;%s\n&quot;, msg);
#endif
}
pthread_mutex_unlock (&ctx->log.logfile_mutex);
out:
GF_FREE (msg);
GF_FREE (str1);
FREE (str2);
return ret;
}
/*
* 记录系统执行日志到文件
*
* 假设日志文件不存在,则打印到标准输出
*/
int
_gf_log (const char *domain, const char *file, const char *function, int line,
gf_loglevel_t level, const char *fmt, ...)
{
const char    *basename = NULL;
FILE          *new_logfile = NULL;
va_list        ap;
char           timestr[256] = {0,};
struct timeval tv = {0,};
char          *str1 = NULL;
char          *str2 = NULL;
char          *msg  = NULL;
size_t         len  = 0;
int            ret  = 0;
int            fd   = -1;
xlator_t      *this = NULL;
glusterfs_ctx_t *ctx = NULL;
this = THIS;
ctx = this->ctx;
if (ctx->log.gf_log_xl_log_set) {
if (this->loglevel && (level > this->loglevel))
goto out;
}
if (level > ctx->log.loglevel)
goto out;
static char *level_strings[] = {&quot;&quot;,  /* NONE */
&quot;M&quot;, /* EMERGENCY */
&quot;A&quot;, /* ALERT */
&quot;C&quot;, /* CRITICAL */
&quot;E&quot;, /* ERROR */
&quot;W&quot;, /* WARNING */
&quot;N&quot;, /* NOTICE */
&quot;I&quot;, /* INFO */
&quot;D&quot;, /* DEBUG */
&quot;T&quot;, /* TRACE */
&quot;&quot;};
if (!domain || !file || !function || !fmt) {
fprintf (stderr,
&quot;logging: %s:%s():%d: invalid argument\n&quot;,
__FILE__, __PRETTY_FUNCTION__, __LINE__);
return -1;
}

if (ctx->log.logrotate) {
ctx->log.logrotate = 0;
fd = open (ctx->log.filename,
O_CREAT | O_RDONLY, S_IRUSR | S_IWUSR);
if (fd < 0) {
gf_log (&quot;logrotate&quot;, GF_LOG_ERROR,
&quot;%s&quot;, strerror (errno));
return -1;
}
close (fd);
new_logfile = fopen (ctx->log.filename, &quot;a&quot;);
if (!new_logfile) {
gf_log (&quot;logrotate&quot;, GF_LOG_CRITICAL,
&quot;failed to open logfile %s (%s)&quot;,
ctx->log.filename, strerror (errno));
goto log;
}
pthread_mutex_lock (&ctx->log.logfile_mutex);
{
if (ctx->log.logfile)
fclose (ctx->log.logfile);
ctx->log.gf_log_logfile = ctx->log.logfile = new_logfile;
}
pthread_mutex_unlock (&ctx->log.logfile_mutex);
}
log:
ret = gettimeofday (&tv, NULL);
if (-1 == ret)
goto out;
va_start (ap, fmt);
gf_time_fmt (timestr, sizeof timestr, tv.tv_sec, gf_timefmt_FT);
snprintf (timestr + strlen (timestr), sizeof timestr - strlen (timestr),
&quot;.%&quot;GF_PRI_SUSECONDS, tv.tv_usec);
basename = strrchr (file, '/');
if (basename)
basename++;
else
basename = file;
ret = gf_asprintf (&str1, &quot;[%s] %s [%s:%d:%s] %d-%s: &quot;,
timestr, level_strings[level],
basename, line, function,
((this->graph)?this->graph->id:0), domain);
if (-1 == ret) {
goto err;
}
ret = vasprintf (&str2, fmt, ap);
if (-1 == ret) {
goto err;
}
va_end (ap);
len = strlen (str1);
msg = GF_MALLOC (len + strlen (str2) + 1, gf_common_mt_char);
strcpy (msg, str1);
strcpy (msg + len, str2);
pthread_mutex_lock (&ctx->log.logfile_mutex);
{
if (ctx->log.logfile) {
fprintf (ctx->log.logfile, &quot;%s\n&quot;, msg);
fflush (ctx->log.logfile);
} else {
fprintf (stderr, &quot;%s\n&quot;, msg);
fflush (stderr);
}
#ifdef GF_LINUX_HOST_OS
/* We want only serious log in 'syslog', not our debug
and trace logs */
if (ctx->log.gf_log_syslog && level &&
(level <= ctx->log.sys_log_level))
syslog ((level-1), &quot;%s\n&quot;, msg);
#endif
}
pthread_mutex_unlock (&ctx->log.logfile_mutex);
err:
GF_FREE (msg);
GF_FREE (str1);
FREE (str2);
out:
return (0);
}
int
_gf_log_eh (const char *function, const char *fmt, ...)
{
int          ret   = -1;
va_list      ap;
char         *str1 = NULL;
char         *str2 = NULL;
char         *msg  = NULL;
xlator_t     *this = NULL;
this = THIS;
ret = gf_asprintf (&str1, &quot;[%d] %s: &quot;,
((this->graph)?this->graph->id:0),
function);
if (-1 == ret) {
goto out;
}
va_start (ap, fmt);
ret = vasprintf (&str2, fmt, ap);
if (-1 == ret) {
goto out;
}
va_end (ap);
msg = GF_MALLOC (strlen (str1) + strlen (str2) + 1, gf_common_mt_char);
if (!msg) {
ret = -1;
goto out;
}
strcpy (msg, str1);
strcat (msg, str2);
ret = eh_save_history (this->history, msg);
out:
GF_FREE (str1);
/* Use FREE instead of GF_FREE since str2 was allocated by vasprintf */
if (str2)
FREE (str2);
return ret;
}
/*
* 初始化&quot;命令记录&quot;日志
*/
int
gf_cmd_log_init (const char *filename)
{
int         fd   = -1;
xlator_t   *this = NULL;
glusterfs_ctx_t *ctx = NULL;
this = THIS;
ctx  = this->ctx;
if (!filename){
gf_log (this->name, GF_LOG_CRITICAL, &quot;gf_cmd_log_init: no &quot;
&quot;filename specified\n&quot;);
return -1;
}
ctx->log.cmd_log_filename = gf_strdup (filename);
if (!ctx->log.cmd_log_filename) {
gf_log (this->name, GF_LOG_CRITICAL,
&quot;gf_cmd_log_init: strdup error\n&quot;);
return -1;
}
/* close and reopen cmdlogfile for log rotate*/
if (ctx->log.cmdlogfile) {
fclose (ctx->log.cmdlogfile);
ctx->log.cmdlogfile = NULL;
}
fd = open (ctx->log.cmd_log_filename,
O_CREAT | O_RDONLY, S_IRUSR | S_IWUSR);
if (fd < 0) {
gf_log (this->name, GF_LOG_CRITICAL,
&quot;%s&quot;, strerror (errno));
return -1;
}
close (fd);
ctx->log.cmdlogfile = fopen (ctx->log.cmd_log_filename, &quot;a&quot;);
if (!ctx->log.cmdlogfile){
gf_log (this->name, GF_LOG_CRITICAL,
&quot;gf_cmd_log_init: failed to open logfile \&quot;%s\&quot; &quot;
&quot;(%s)\n&quot;, ctx->log.cmd_log_filename, strerror (errno));
return -1;
}
return 0;
}
/*
* 记录命令日志到文件
*/
int
gf_cmd_log (const char *domain, const char *fmt, ...)
{
va_list        ap;
char           timestr[64];
struct timeval tv = {0,};
char          *str1 = NULL;
char          *str2 = NULL;
char          *msg  = NULL;
size_t         len  = 0;
int            ret  = 0;
glusterfs_ctx_t *ctx = NULL;
ctx = THIS->ctx;
if (!ctx->log.cmdlogfile)
return -1;

if (!domain || !fmt) {
gf_log (&quot;glusterd&quot;, GF_LOG_TRACE,
&quot;logging: invalid argument\n&quot;);
return -1;
}
ret = gettimeofday (&tv, NULL);
if (ret == -1)
goto out;
va_start (ap, fmt);
gf_time_fmt (timestr, sizeof timestr, tv.tv_sec, gf_timefmt_FT);
snprintf (timestr + strlen (timestr), 256 - strlen (timestr),
&quot;.%&quot;GF_PRI_SUSECONDS, tv.tv_usec);
ret = gf_asprintf (&str1, &quot;[%s] %s : &quot;,
timestr, domain);
if (ret == -1) {
goto out;
}
ret = vasprintf (&str2, fmt, ap);
if (ret == -1) {
goto out;
}
va_end (ap);
len = strlen (str1);
msg = GF_MALLOC (len + strlen (str2) + 1, gf_common_mt_char);
strcpy (msg, str1);
strcpy (msg + len, str2);
fprintf (ctx->log.cmdlogfile, &quot;%s\n&quot;, msg);
fflush (ctx->log.cmdlogfile);
out:
GF_FREE (msg);
GF_FREE (str1);
FREE (str2);
return (0);
}



  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-111603-1-1.html 上篇帖子: GlusterFS组件 下篇帖子: GlusterFS源代码解析 —— GlusterFS 简单介绍
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表