zoukankan      html  css  js  c++  java
  • C语言日志处理

    一、简介

    zlog是一个高可靠性、高性能、线程安全、灵活、概念清晰的纯C日志函数库,在效率、功能、安全性上大大超过了log4c,并且是用c写成的,具有比较好的通用性。

    二、安装

    下载

    三、实例

    参考:

    源码目录:test,包括了大量使用示例,如下:

    image

    四、系统日志

    参考:

     

    示例:

    #include <syslog.h>
    int main(int argc, char **argv)
    {
        openlog("MyMsgMARK", LOG_CONS | LOG_PID, 0);
        syslog(LOG_INFO,
               "This is a syslog test message generated by program '%s'
    ",
               argv[0]);
        closelog();
        return 0;
    }

    编译

    gcc -g -o test test.c

    运行

    1

     

    五、Apache 日志处理分析

    Apache通过调用ap_log_XXX函数进行日志记录,此处以ap_log_perror为例进行分析

    Apache启动时通过httpd/modules/core/mod_so.c:load_module函数进行DSO模块加载,加载成功后将调用ap_log_perror函数记录模块加载日志

    266     ap_log_perror(APLOG_MARK, APLOG_DEBUG, 0, cmd->pool, APLOGNO(01575)"loaded module %s from %s", modname, module_file);

    ap_log_perror函数事实上是一个宏,定义在文件:/httpd/include/http_log.h,如下:

    412 #define ap_log_perror ap_log_perror_
    而ap_log_perror_函数实现在文件:httpd/server/log.c,代码如下:
    1409 AP_DECLARE(void) ap_log_perror_(const char *file, int line, int module_index,
    1410                                 int level, apr_status_t status, apr_pool_t *p,
    1411                                 const char *fmt, ...)
    1412 {
    1413     va_list args;
    1414 
    1415     va_start(args, fmt);
    1416     log_error_core(file, line, module_index, level, status, NULL, NULL, NULL,
    1417                    p, fmt, args);
    1418     va_end(args);
    1419 }

    函数log_error_core,逻辑如下:

    1、判断请求结构r是否为NULL,若不为空则:c = r->connection

    2、判断服务器结构s是否为NULL,若为空则:logf = stderr_log,此处s为NULL

    3、填充结构日志info

    4、调用do_errorlog_default函数拼接要写入日志的内容并暂存在buf中,并返回相应长度len

    5、调用write_logline函数进行实际的日志输出

    6、运行日志钩子error_log

    static void log_error_core(const char *file, int line, int module_index,
                               int level,
                               apr_status_t status, const server_rec *s,
                               const conn_rec *c,
                               const request_rec *r, apr_pool_t *pool,
                               const char *fmt, va_list args)
    {
        char errstr[MAX_STRING_LEN];
        apr_file_t *logf = NULL;
        int level_and_mask = level & APLOG_LEVELMASK;
        const request_rec *rmain = NULL;
        core_server_config *sconf = NULL;
        ap_errorlog_info info;
    
        /* do we need to log once-per-req or once-per-conn info? */
        int log_conn_info = 0, log_req_info = 0;
        apr_array_header_t **lines = NULL;
        int done = 0;
        int line_number = 0;
    
        if (r)
        {
            AP_DEBUG_ASSERT(r->connection != NULL);
            c = r->connection;
        }
    
        if (s == NULL)
        {
            /*
             * If we are doing stderr logging (startup), don't log messages that are
             * above the default server log level unless it is a startup/shutdown
             * notice
             */
    #ifndef DEBUG
            if ((level_and_mask != APLOG_NOTICE)
                    && (level_and_mask > ap_default_loglevel))
            {
                return;
            }
    #endif
    
            logf = stderr_log;
        }
        else
        {
            int configured_level = r ? ap_get_request_module_loglevel(r, module_index)        :
                                   c ? ap_get_conn_server_module_loglevel(c, s, module_index) :
                                   ap_get_server_module_loglevel(s, module_index);
            if (s->error_log)
            {
                /*
                 * If we are doing normal logging, don't log messages that are
                 * above the module's log level unless it is a startup/shutdown notice
                 */
                if ((level_and_mask != APLOG_NOTICE)
                        && (level_and_mask > configured_level))
                {
                }
                else
                {
                    /*
                     * If we are doing syslog logging, don't log messages that are
                     * above the module's log level (including a startup/shutdown notice)
                     */
                    if (level_and_mask > configured_level)
                    {
    
                    }
                }
    
                /* the faked server_rec from mod_cgid does not have s->module_config */
    
                sconf = ap_get_core_module_config(s->module_config);
                if (c && !c->log_id)
                {
                    add_log_id(c, NULL);
                    if (sconf->error_log_conn && sconf->error_log_conn->nelts > 0)
                        log_conn_info = 1;
                }
                if (r)
                {
                    if (r->main)
                        rmain = r->main;
                    else
                        rmain = r;
    
                    if (!rmain->log_id)
                    {
                        /* XXX: do we need separate log ids for subrequests? */
                        if (sconf->error_log_req && sconf->error_log_req->nelts > 0)
                            log_req_info = 1;
                        /*
                         * XXX: potential optimization: only create log id if %L is
                         * XXX: actually used
                         */
                        add_log_id(c, rmain);
                    }
                }
            }
        }
    
        info.s             = s;
        info.c             = c;
        info.pool          = pool;
        info.file          = NULL;
        info.line          = 0;
        info.status        = 0;
        info.using_syslog  = (logf == NULL);
        info.startup       = ((level & APLOG_STARTUP) == APLOG_STARTUP);
        info.format        = fmt;
    
        while (!done)
        {
            apr_array_header_t *log_format;
            int len = 0, errstr_start = 0, errstr_end = 0;
            /* XXX: potential optimization: format common prefixes only once */
            if (log_conn_info)
            {
                /* once-per-connection info */
                if (line_number == 0)
                {
                    lines = (apr_array_header_t **)sconf->error_log_conn->elts;
                    info.r = NULL;
                    info.rmain = NULL;
                    info.level = -1;
                    info.module_index = APLOG_NO_MODULE;
                }
    
                log_format = lines[line_number++];
    
                if (line_number == sconf->error_log_conn->nelts)
                {
                    /* this is the last line of once-per-connection info */
                    line_number = 0;
                    log_conn_info = 0;
                }
            }
            else if (log_req_info)
            {
                /* once-per-request info */
                if (line_number == 0)
                {
                    lines = (apr_array_header_t **)sconf->error_log_req->elts;
                    info.r = rmain;
                    info.rmain = rmain;
                    info.level = -1;
                    info.module_index = APLOG_NO_MODULE;
                }
    
                log_format = lines[line_number++];
    
                if (line_number == sconf->error_log_req->nelts)
                {
                    /* this is the last line of once-per-request info */
                    line_number = 0;
                    log_req_info = 0;
                }
            }
            else
            {
                /* the actual error message */
                info.r            = r;
                info.rmain        = rmain;
                info.level        = level_and_mask;
                info.module_index = module_index;
                info.file         = file;
                info.line         = line;
                info.status       = status;
                log_format = sconf ? sconf->error_log_format : NULL;
                done = 1;
            }
    
            /*
             * prepare and log one line
             */
    
            if (log_format && !info.startup)
            {
                len += do_errorlog_format(log_format, &info, errstr + len,
                                          MAX_STRING_LEN - len,
                                          &errstr_start, &errstr_end, fmt, args);
            }
            else
            {
                len += do_errorlog_default(&info, errstr + len, MAX_STRING_LEN - len,
                                           &errstr_start, &errstr_end, fmt, args);
            }
    
            if (!*errstr)
            {
                /*
                 * Don't log empty lines. This can happen with once-per-conn/req
                 * info if an item with AP_ERRORLOG_FLAG_REQUIRED is NULL.
                 */
                continue;
            }
            write_logline(errstr, len, logf, level_and_mask);
    
            if (done)
            {
                /*
                 * We don't call the error_log hook for per-request/per-conn
                 * lines, and we only pass the actual log message, not the
                 * prefix and suffix.
                 */
                errstr[errstr_end] = '';
                ap_run_error_log(&info, errstr + errstr_start);
            }
    
            *errstr = '';
        }
    }

    do_errorlog_default函数拼接要写入日志的内容并暂存在buf中,并返回相应长度len,此处拼接出的日志的内容如下:

    [Sat Jun 20 22:08:19.506426 2015] [so:debug] [pid 3826] mod_so.c(266): AH01575: loaded module unixd_module from /app/HRP/lib/mod_unixd.so

    do_errorlog_default函数实现在文件:httpd/server/log.c,代码如下:

    static int do_errorlog_default(const ap_errorlog_info *info, char *buf,
                                   int buflen, int *errstr_start, int *errstr_end,
                                   const char *errstr_fmt, va_list args)
    {
        int len = 0;
        int field_start = 0;
        int item_len;
    #ifndef AP_UNSAFE_ERROR_LOG_UNESCAPED
        char scratch[MAX_STRING_LEN];
    #endif
    
        if (!info->using_syslog && !info->startup)
        {
            buf[len++] = '[';
            len += log_ctime(info, "u", buf + len, buflen - len);
            buf[len++] = ']';
            buf[len++] = ' ';
        }
    
        if (!info->startup)
        {
            buf[len++] = '[';
            len += log_module_name(info, NULL, buf + len, buflen - len);
            buf[len++] = ':';
            len += log_loglevel(info, NULL, buf + len, buflen - len);
            len += cpystrn(buf + len, "] [pid ", buflen - len);
    
            len += log_pid(info, NULL, buf + len, buflen - len);
    #if APR_HAS_THREADS
            field_start = len;
            len += cpystrn(buf + len, ":tid ", buflen - len);
            item_len = log_tid(info, NULL, buf + len, buflen - len);
            if (!item_len)
                len = field_start;
            else
                len += item_len;
    #endif
            buf[len++] = ']';
            buf[len++] = ' ';
        }
    
        if (info->level >= APLOG_DEBUG)
        {
            item_len = log_file_line(info, NULL, buf + len, buflen - len);
            if (item_len)
            {
                len += item_len;
                len += cpystrn(buf + len, ": ", buflen - len);
            }
        }
    
        if (info->status)
        {
            item_len = log_apr_status(info, NULL, buf + len, buflen - len);
            if (item_len)
            {
                len += item_len;
                len += cpystrn(buf + len, ": ", buflen - len);
            }
        }
    
        /*
         * useragent_ip/client_ip can be client or backend server. If we have
         * a scoreboard handle, it is likely a client.
         */
        if (info->r)
        {
            len += apr_snprintf(buf + len, buflen - len,
                                info->r->connection->sbh ? "[client %s:%d] " : "[remote %s:%d] ",
                                info->r->useragent_ip,
                                info->r->useragent_addr ? info->r->useragent_addr->port : 0);
        }
        else if (info->c)
        {
            len += apr_snprintf(buf + len, buflen - len,
                                info->c->sbh ? "[client %s:%d] " : "[remote %s:%d] ",
                                info->c->client_ip,
                                info->c->client_addr ? info->c->client_addr->port : 0);
        }
    
        /* the actual error message */
        *errstr_start = len;
    #ifndef AP_UNSAFE_ERROR_LOG_UNESCAPED
        if (apr_vsnprintf(scratch, MAX_STRING_LEN, errstr_fmt, args))
        {
            len += ap_escape_errorlog_item(buf + len, scratch,
                                           buflen - len);
    
        }
    #else
        len += apr_vsnprintf(buf + len, buflen - len, errstr_fmt, args);
    #endif
        *errstr_end = len;
    
        field_start = len;
        len += cpystrn(buf + len, ", referer: ", buflen - len);
        item_len = log_header(info, "Referer", buf + len, buflen - len);
        if (item_len)
            len += item_len;
        else
            len = field_start;
    
        return len;
    }

    write_logline函数实现在文件:httpd/server/log.c,代码如下:

    static void write_logline(char *errstr, apr_size_t len, apr_file_t *logf,
                              int level)
    {
        /* NULL if we are logging to syslog */
        if (logf)
        {
            /* Truncate for the terminator (as apr_snprintf does) */
            if (len > MAX_STRING_LEN - sizeof(APR_EOL_STR))
            {
                len = MAX_STRING_LEN - sizeof(APR_EOL_STR);
            }
            strcpy(errstr + len, APR_EOL_STR);
            apr_file_puts(errstr, logf);
            apr_file_flush(logf);
        }
    #ifdef HAVE_SYSLOG
        else
        {
            syslog(level < LOG_PRIMASK ? level : APLOG_DEBUG, "%.*s",
                   (int)len, errstr);
        }
    #endif
    }
  • 相关阅读:
    HDU 1813 Escape from Tetris
    BZOJ 2276 Temperature
    BZOJ 4499 线性函数
    BZOJ 3131 淘金
    HDU 5738 Eureka
    POJ 2409 Let it Bead
    POJ 1286 Necklace of Beads
    POJ 1696 Space Ant
    Fox And Jumping
    Recover the String
  • 原文地址:https://www.cnblogs.com/274914765qq/p/4589929.html
Copyright © 2011-2022 走看看