Beispiel #1
0
void ngx_cdecl
ngx_log_stderr(ngx_err_t err, const char *fmt, ...)
{
    u_char   *p, *last;
    va_list   args;
    u_char    errstr[NGX_MAX_ERROR_STR];

    last = errstr + NGX_MAX_ERROR_STR;

    va_start(args, fmt);
    p = ngx_vslprintf(errstr, last, fmt, args);
    va_end(args);

    if (err) {
        p = ngx_log_errno(p, last, err);
    }

    if (p > last - NGX_LINEFEED_SIZE) {
        p = last - NGX_LINEFEED_SIZE;
    }

    ngx_linefeed(p);

    (void) ngx_write_console(ngx_stderr, errstr, p - errstr);
}
static ngx_int_t
ngx_rtmp_log_flush(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
                   ngx_chain_t *in)
{
    ngx_rtmp_log_app_conf_t    *lacf;
    ngx_rtmp_log_t             *log;
    ngx_rtmp_log_op_t          *op;
    ngx_uint_t                  n, i;
    u_char                     *line, *p;
    size_t                      len;

    if (s->auto_pushed || s->relay) {
        return NGX_OK;
    }

    lacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_log_module);
    if (lacf == NULL || lacf->off || lacf->logs == NULL) {
        return NGX_OK;
    }

    log = lacf->logs->elts;
    for (i = 0; i < lacf->logs->nelts; ++i, ++log) {

        if (ngx_time() == log->disk_full_time) {
            /* FreeBSD full disk protection;
             * nginx http logger does the same */
            continue;
        }

        len = 0;
        op = log->format->ops->elts;
        for (n = 0; n < log->format->ops->nelts; ++n, ++op) {
            len += op->getlen(s, op);
        }

        len += NGX_LINEFEED_SIZE;

        line = ngx_palloc(s->connection->pool, len);
        if (line == NULL) {
            return NGX_OK;
        }

        p = line;
        op = log->format->ops->elts;
        for (n = 0; n < log->format->ops->nelts; ++n, ++op) {
            p = op->getdata(s, p, op);
        }

        ngx_linefeed(p);

        ngx_rtmp_log_write(s, log, line, p - line);
    }

    return NGX_OK;
}
static void
ngx_rtmp_log_pre_write(ngx_rtmp_session_t *s, ngx_rtmp_log_t *log)
{
    ngx_rtmp_log_op_t          *op;
    u_char                      line[MAX_ACCESS_LOG_LINE_LEN], *p;
    size_t                      len;
    ngx_uint_t                  n;

    if (ngx_time() == log->disk_full_time) {
        /* FreeBSD full disk protection;
         * nginx http logger does the same */
        return;
    }

    len = 0;
    op = log->format->ops->elts;
    for (n = 0; n < log->format->ops->nelts; ++n, ++op) {
        len += op->getlen(s, op);
    }
    len += NGX_LINEFEED_SIZE;

    if (len > MAX_ACCESS_LOG_LINE_LEN) {
        ngx_log_error(NGX_LOG_ERR, s->log, 0,
                "Access line len %z greater than %d",
                len, MAX_ACCESS_LOG_LINE_LEN);
        ngx_rtmp_finalize_session(s);

        return;
    }

    p = line;
    op = log->format->ops->elts;
    for (n = 0; n < log->format->ops->nelts; ++n, ++op) {
        p = op->getdata(s, p, op);
    }

    ngx_linefeed(p);

    ngx_rtmp_log_write(s, log, line, p - line);
}
static u_char *
ngx_tcp_log_fill(ngx_tcp_session_t *s, u_char *buf) 
{
    u_char              *last;
    ngx_str_t           *name;
    ngx_connection_t    *c;
    ngx_tcp_upstream_t  *u;

    c = s->connection;

    last = ngx_cpymem(buf, ngx_cached_err_log_time.data,
            ngx_cached_err_log_time.len);

    last = ngx_sprintf(last, " [%P]", ngx_pid);
    last = ngx_sprintf(last, " %V", &c->addr_text);
    last = ngx_sprintf(last, " %V ", s->addr_text);
    last = ngx_tcp_time(last, s->start_sec);
    
    name = NULL;
    if (s->upstream) {
        u = s->upstream;
        if (u->peer.connection) {
            name = u->peer.name;
        }
    }

    if (name) {
        last = ngx_sprintf(last, " %V", name);
    }
    else {
        last = ngx_sprintf(last, " -");
    }

    last = ngx_sprintf(last, " %O", s->bytes_read);
    last = ngx_sprintf(last, " %O", s->bytes_write);

    ngx_linefeed(last);

    return last;
}
Beispiel #5
0
void
ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
    const char *fmt, va_list args)

#endif
{
#if (NGX_HAVE_VARIADIC_MACROS)
    va_list  args;
#endif
    u_char  *p, *last, *msg;
    u_char   errstr[NGX_MAX_ERROR_STR];

    if (log->file->fd == NGX_INVALID_FILE) {
        return;
    }

    last = errstr + NGX_MAX_ERROR_STR;

    p = errstr ;

    p = ngx_slprintf(p, last, " [%V] ", &err_levels[level]);

    /* pid#tid */
    p = ngx_slprintf(p, last, "%P#" NGX_TID_T_FMT ": ",
                    ngx_log_pid, ngx_log_tid);

    msg = p;

#if (NGX_HAVE_VARIADIC_MACROS)

    va_start(args, fmt);
    p = ngx_vslprintf(p, last, fmt, args);
    va_end(args);

#else

    p = ngx_vslprintf(p, last, fmt, args);

#endif

    if (err) {
        p = ngx_log_errno(p, last, err);
    }

    if (level != NGX_LOG_DEBUG && log->handler) {
        p = log->handler(log, p, last - p);
    }

    if (p > last - NGX_LINEFEED_SIZE) {
        p = last - NGX_LINEFEED_SIZE;
    }

    ngx_linefeed(p);

    (void) ngx_write_fd(log->file->fd, errstr, p - errstr);

    if (!ngx_use_stderr
        || level > NGX_LOG_WARN
        || log->file->fd == ngx_stderr)
    {
        return;
    }

    msg -= (err_levels[level].len + 4);

    (void) ngx_sprintf(msg, "[%V]: ", &err_levels[level]);

    (void) ngx_write_console(ngx_stderr, msg, p - msg);
}
Beispiel #6
0
ngx_int_t
ngx_http_log_handler(ngx_http_request_t *r)
{
    u_char                   *line, *p;
    size_t                    len;
    ngx_uint_t                i, l;
    ngx_http_log_t           *log;
    ngx_open_file_t          *file;
    ngx_http_log_op_t        *op;
    ngx_http_log_loc_conf_t  *lcf;

    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "http log handler");

    lcf = ngx_http_get_module_loc_conf(r, ngx_http_log_module);

    if (lcf->off) {
        return NGX_OK;
    }

    log = lcf->logs->elts;
    for (l = 0; l < lcf->logs->nelts; l++) {

        if (ngx_time() == log[l].disk_full_time) {

            /*
             * on FreeBSD writing to a full filesystem with enabled softupdates
             * may block process for much longer time than writing to non-full
             * filesystem, so we skip writing to a log for one second
             */

            continue;
        }

        ngx_http_script_flush_no_cacheable_variables(r, log[l].format->flushes);

        len = 0;
        op = log[l].format->ops->elts;
        for (i = 0; i < log[l].format->ops->nelts; i++) {
            if (op[i].len == 0) {
                len += op[i].getlen(r, op[i].data);

            } else {
                len += op[i].len;
            }
        }

        len += NGX_LINEFEED_SIZE;

        file = log[l].file;

        if (file && file->buffer) {

            if (len > (size_t) (file->last - file->pos)) {

                ngx_http_log_write(r, &log[l], file->buffer,
                                   file->pos - file->buffer);

                file->pos = file->buffer;
            }

            if (len <= (size_t) (file->last - file->pos)) {

                p = file->pos;

                for (i = 0; i < log[l].format->ops->nelts; i++) {
                    p = op[i].run(r, p, &op[i]);
                }

                ngx_linefeed(p);

                file->pos = p;

                continue;
            }
        }

        line = ngx_pnalloc(r->pool, len);
        if (line == NULL) {
            return NGX_ERROR;
        }

        p = line;

        for (i = 0; i < log[l].format->ops->nelts; i++) {
            p = op[i].run(r, p, &op[i]);
        }

        ngx_linefeed(p);

        ngx_http_log_write(r, &log[l], line, p - line);
    }

    return NGX_OK;
}
Beispiel #7
0
void
ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
    const char *fmt, va_list args)

#endif
{
#if (NGX_HAVE_VARIADIC_MACROS)
    va_list      args;
#endif
    u_char      *p, *last, *msg;
    u_char       errstr[NGX_MAX_ERROR_STR];
    ngx_uint_t   wrote_stderr, debug_connection;

    last = errstr + NGX_MAX_ERROR_STR;

    ngx_memcpy(errstr, ngx_cached_err_log_time.data,
               ngx_cached_err_log_time.len);

    p = errstr + ngx_cached_err_log_time.len;

    p = ngx_slprintf(p, last, " [%V] ", &err_levels[level]);

    /* pid#tid */
    p = ngx_slprintf(p, last, "%P#" NGX_TID_T_FMT ": ",
                    ngx_log_pid, ngx_log_tid);

    if (log->connection) {
        p = ngx_slprintf(p, last, "*%uA ", log->connection);
    }

    msg = p;

#if (NGX_HAVE_VARIADIC_MACROS)

    va_start(args, fmt);
    p = ngx_vslprintf(p, last, fmt, args);
    va_end(args);

#else

    p = ngx_vslprintf(p, last, fmt, args);

#endif

    if (err) {
        p = ngx_log_errno(p, last, err);
    }

    if (level != NGX_LOG_DEBUG && log->handler) {
        p = log->handler(log, p, last - p);
    }

    if (p > last - NGX_LINEFEED_SIZE) {
        p = last - NGX_LINEFEED_SIZE;
    }

    ngx_linefeed(p);

    wrote_stderr = 0;
    debug_connection = (log->log_level & NGX_LOG_DEBUG_CONNECTION) != 0;

    while (log) {

        if (log->log_level < level && !debug_connection) {
            break;
        }

        (void) ngx_write_fd(log->file->fd, errstr, p - errstr);

        if (log->file->fd == ngx_stderr) {
            wrote_stderr = 1;
        }

        log = log->next;
    }

    if (!ngx_use_stderr
        || level > NGX_LOG_WARN
        || wrote_stderr)
    {
        return;
    }

    msg -= (7 + err_levels[level].len + 3);

    (void) ngx_sprintf(msg, "nginx: [%V] ", &err_levels[level]);

    (void) ngx_write_console(ngx_stderr, msg, p - msg);
}
Beispiel #8
0
static ngx_int_t
ngx_http_log_handler(ngx_http_request_t *r)
{
    u_char                   *line, *p;
    size_t                    len;
    ngx_uint_t                i, l, bypass, threshold;
    ngx_http_log_t           *log;
    ngx_open_file_t          *file;
    ngx_http_log_op_t        *op;
    ngx_http_log_loc_conf_t  *lcf;

    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "http log handler");

    lcf = ngx_http_get_module_loc_conf(r, ngx_http_log_module);

    if (lcf->off) {
        return NGX_OK;
    }

    if (r->headers_out.status == NGX_HTTP_BAD_REQUEST && !lcf->log_empty_request
        && (r->header_in && r->header_in->last == r->header_in->start))
    {
        return NGX_OK;
    }

    log = lcf->logs->elts;
    for (l = 0; l < lcf->logs->nelts; l++) {

        if (log[l].scope != 0) {

            bypass = 1;

            if (log[l].sample_count < log[l].sample) {
                if (log[l].scatter_count++ == 0) {
                    bypass = 0;
                    ++log[l].sample_count;
                }

                threshold = log[l].scatter;
                if (log[l].sample_count >= log[l].inflexion) {
                    --threshold;
                }

                if (log[l].scatter_count == threshold) {
                    log[l].scatter_count = 0;
                }
            }

            if (++log[l].scope_count == log[l].scope) {
                log[l].scope_count = 0;
                log[l].sample_count = 0;
                log[l].scatter_count = 0;
            }

            if (bypass == 1) {
                continue;
            }
        }

        if (ngx_time() == log[l].disk_full_time) {

            /*
             * on FreeBSD writing to a full filesystem with enabled softupdates
             * may block process for much longer time than writing to non-full
             * filesystem, so we skip writing to a log for one second
             */

            continue;
        }

        ngx_http_script_flush_no_cacheable_variables(r, log[l].format->flushes);

        len = 0;
        op = log[l].format->ops->elts;
        for (i = 0; i < log[l].format->ops->nelts; i++) {
            if (op[i].len == 0) {
                len += op[i].getlen(r, op[i].data);

            } else {
                len += op[i].len;
            }
        }

        len += NGX_LINEFEED_SIZE;

        file = log[l].file;

        if (file && file->buffer) {

            if (len > (size_t) (file->last - file->pos)) {

                ngx_http_log_write(r, &log[l], file->buffer,
                                   file->pos - file->buffer);

                file->pos = file->buffer;
            }

            if (len <= (size_t) (file->last - file->pos)) {

                p = file->pos;

                for (i = 0; i < log[l].format->ops->nelts; i++) {
                    p = op[i].run(r, p, &op[i]);
                }

                ngx_linefeed(p);

                file->pos = p;

                continue;
            }
        }

        line = ngx_pnalloc(r->pool, len);
        if (line == NULL) {
            return NGX_ERROR;
        }

        p = line;

        for (i = 0; i < log[l].format->ops->nelts; i++) {
            p = op[i].run(r, p, &op[i]);
        }

        ngx_linefeed(p);

#if (NGX_SYSLOG)
        if (log[l].syslog != NULL) {
            if (!(log[l].syslog->fd == NGX_INVALID_FILE
                && ngx_cached_time->sec < log[l].syslog->next_try))
            {
                (void) ngx_write_syslog(log[l].syslog, line, p - line);
            }

            continue;
        }
#endif

        ngx_http_log_write(r, &log[l], line, p - line);
    }

    return NGX_OK;
}
void
ngx_log_error_coreall(ngx_uint_t level, ngx_log_t *log, const char* filename, int lineno, ngx_err_t err,
    const char *fmt, va_list args)

#endif

{
#if (NGX_HAVE_VARIADIC_MACROS)
    va_list      args;
#endif
    u_char      *p, *last, *msg;
    ssize_t      n;
    ngx_uint_t   wrote_stderr, debug_connection;
    u_char       errstr[NGX_MAX_ERROR_STR];
    char filebuf[52];

    last = errstr + NGX_MAX_ERROR_STR;
    
    p = ngx_cpymem(errstr, ngx_cached_err_log_time.data,
                   ngx_cached_err_log_time.len);

    snprintf(filebuf, sizeof(filebuf), "[%35s, %5d][yangyazhou @@@ test]", filename, lineno);

    p = ngx_slprintf(p, last, "%s ", filebuf);  
    
    p = ngx_slprintf(p, last, " [%V] ", &err_levels[level]);

    /* pid#tid */
    p = ngx_slprintf(p, last, "%P#" NGX_TID_T_FMT ": ", ngx_log_pid, ngx_log_tid); //进程ID和线程ID(在开启线程池的时候线程ID和进程ID不同)
    
    if (log->connection) {
        p = ngx_slprintf(p, last, "*%uA ", log->connection);
    }

    msg = p;

#if (NGX_HAVE_VARIADIC_MACROS)

    va_start(args, fmt);
    p = ngx_vslprintf(p, last, fmt, args);
    va_end(args);

#else

    p = ngx_vslprintf(p, last, fmt, args);

#endif

    if (err) {
        p = ngx_log_errno(p, last, err);
    }

    if (level != NGX_LOG_DEBUG && log->handler) {
        p = log->handler(log, p, last - p);
    }

    if (p > last - NGX_LINEFEED_SIZE) {
        p = last - NGX_LINEFEED_SIZE;
    }

    ngx_linefeed(p);

    wrote_stderr = 0;
    debug_connection = (log->log_level & NGX_LOG_DEBUG_CONNECTION) != 0;

    while (log) {

        if (log->writer) {
            log->writer(log, level, errstr, p - errstr);
            goto next;
        }

        if (ngx_time() == log->disk_full_time) {

            /*
             * on FreeBSD writing to a full filesystem with enabled softupdates
             * may block process for much longer time than writing to non-full
             * filesystem, so we skip writing to a log for one second
             */

            goto next;
        }

        n = ngx_write_fd(log->file->fd, errstr, p - errstr); //写到log文件中

        if (n == -1 && ngx_errno == NGX_ENOSPC) {
            log->disk_full_time = ngx_time();
        }

        if (log->file->fd == ngx_stderr) {
            wrote_stderr = 1;
        }

    next:

        log = log->next;
    }

    if (!ngx_use_stderr
        || level > NGX_LOG_WARN
        || wrote_stderr) /* 如果满足这些条件,则不会输出打印到前台,只会写到errlog文件中 */
    {
        return;
    }

    msg -= (7 + err_levels[level].len + 3);

    (void) ngx_sprintf(msg, "nginx: [%V] ", &err_levels[level]);
    (void) ngx_write_console(ngx_stderr, msg, p - msg);
}
static ngx_int_t
ngx_http_prelog_handler(ngx_http_request_t* r){

    ngx_http_prelog_loc_conf_t *prelog_loc_conf;
    size_t                      len;
    ssize_t                     ret;
    u_char                      *line, *p;
    ngx_http_log_op_t           *op;
    ngx_uint_t                  i;
    time_t                      now;
    ngx_err_t                   err;
    u_char                      *name;

    prelog_loc_conf = ngx_http_get_module_loc_conf(r, ngx_http_prelog_module);

    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "http prelog handler");

    if (prelog_loc_conf->enable == 0){
        return NGX_DECLINED;
    }

    if (r->internal == 1){
        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "http prelog hit internal redirect, pass");
        return NGX_DECLINED;
    }

    len = 0;
    op = prelog_loc_conf->format->ops->elts;
    for (i = 0; i < prelog_loc_conf->format->ops->nelts; i++) {
        if (op[i].len == 0) {
            len += op[i].getlen(r, op[i].data);

        } else {
            len += op[i].len;
        }
    }
    len += NGX_LINEFEED_SIZE;

    line = ngx_pnalloc(r->pool, len);
    if (line == NULL) {
        return NGX_ERROR;
    }
    p = line;

    for (i = 0; i < prelog_loc_conf->format->ops->nelts; i++) {
        p = op[i].run(r, p, &op[i]);
    }

    ngx_linefeed(p);
    ret = ngx_write_fd(prelog_loc_conf->file->fd, line, p - line);

    name = prelog_loc_conf->file->name.data;
    now = ngx_time();

    if (ret == (ssize_t)len){
        goto ok;
    }

    if (ret == -1) {
        err = ngx_errno;

        if (now - prelog_loc_conf->error_log_time > 59) {
            ngx_log_error(NGX_LOG_ALERT, r->connection->log, err,
                          ngx_write_fd_n " to \"%s\" failed", name);

            prelog_loc_conf->error_log_time = now;
        }
        goto ok;
    }

    if (now - prelog_loc_conf->error_log_time > 59) {
        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
                      ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz",
                      name, ret, len);

        prelog_loc_conf->error_log_time = now;
    }

ok:
    return NGX_DECLINED;
}
Beispiel #11
0
void
ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
    const char *fmt, va_list args)

#endif
{
#if (NGX_HAVE_VARIADIC_MACROS)
    va_list  args;
#endif
    u_char   errstr[NGX_MAX_ERROR_STR], *p, *last;

    if (log->file->fd == NGX_INVALID_FILE) {
        return;
    }

    last = errstr + NGX_MAX_ERROR_STR;

    ngx_memcpy(errstr, ngx_cached_err_log_time.data,
               ngx_cached_err_log_time.len);

    p = errstr + ngx_cached_err_log_time.len;

    p = ngx_snprintf(p, last - p, " [%s] ", err_levels[level]);

    /* pid#tid */
    p = ngx_snprintf(p, last - p, "%P#" NGX_TID_T_FMT ": ",
                    ngx_log_pid, ngx_log_tid);

    if (log->connection) {
        p = ngx_snprintf(p, last - p, "*%uA ", log->connection);
    }

#if (NGX_HAVE_VARIADIC_MACROS)

    va_start(args, fmt);
    p = ngx_vsnprintf(p, last - p, fmt, args);
    va_end(args);

#else

    p = ngx_vsnprintf(p, last - p, fmt, args);

#endif

    if (err) {

        if (p > last - 50) {

            /* leave a space for an error code */

            p = last - 50;
            *p++ = '.';
            *p++ = '.';
            *p++ = '.';
        }

#if (NGX_WIN32)

        if ((unsigned) err >= 0x80000000) {
            p = ngx_snprintf(p, last - p, " (%Xd: ", err);

        } else {
            p = ngx_snprintf(p, last - p, " (%d: ", err);
        }

#else

        p = ngx_snprintf(p, last - p, " (%d: ", err);

#endif

        p = ngx_strerror_r(err, p, last - p);

        if (p < last) {
            *p++ = ')';
        }
    }

    if (level != NGX_LOG_DEBUG && log->handler) {
        p = log->handler(log, p, last - p);
    }

    if (p > last - NGX_LINEFEED_SIZE) {
        p = last - NGX_LINEFEED_SIZE;
    }

    ngx_linefeed(p);

    (void) ngx_write_fd(log->file->fd, errstr, p - errstr);
}
Beispiel #12
0
void
ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
    const char *fmt, va_list args)

#endif
{
#if (NGX_HAVE_VARIADIC_MACROS)
    va_list      args;
#endif
    u_char      *p, *last, *msg;
    ssize_t      n;
    ngx_uint_t   wrote_stderr, debug_connection;
    u_char       errstr[NGX_MAX_ERROR_STR];

    // 错误消息的最大长度,2k字节
    last = errstr + NGX_MAX_ERROR_STR;

    // 先拷贝当前的时间
    // 格式是"1970/09/28 12:00:00"
    p = ngx_cpymem(errstr, ngx_cached_err_log_time.data,
                   ngx_cached_err_log_time.len);

    // 打印错误等级的字符串描述信息,使用关联数组err_levels
    p = ngx_slprintf(p, last, " [%V] ", &err_levels[level]);

    // 打印pid和tid
    // #define ngx_log_pid  ngx_pid
    // #define ngx_log_tid           ngx_thread_tid()
    // in os/unix

    /* pid#tid */
    p = ngx_slprintf(p, last, "%P#" NGX_TID_T_FMT ": ",
                    ngx_log_pid, ngx_log_tid);

    // 如果有连接计数则打印
    if (log->connection) {
        p = ngx_slprintf(p, last, "*%uA ", log->connection);
    }

    // 前面输出的是基本的信息:当前时间+[错误级别]+pid#tid:
    msg = p;

    // 打印可变参数
#if (NGX_HAVE_VARIADIC_MACROS)

    va_start(args, fmt);
    p = ngx_vslprintf(p, last, fmt, args);
    va_end(args);

#else

    p = ngx_vslprintf(p, last, fmt, args);

#endif

    // 如果有系统错误码,那么记录(err)
    if (err) {
        p = ngx_log_errno(p, last, err);
    }

    // 记录错误日志时可以执行的回调函数
    // 参数是消息缓冲区里剩余的空间
    // 只有高于debug才会执行
    if (level != NGX_LOG_DEBUG && log->handler) {
        p = log->handler(log, p, last - p);
    }

    // #define NGX_LINEFEED_SIZE        1
    if (p > last - NGX_LINEFEED_SIZE) {
        p = last - NGX_LINEFEED_SIZE;
    }

    // #define ngx_linefeed(p)          *p++ = LF;
    ngx_linefeed(p);

    wrote_stderr = 0;
    debug_connection = (log->log_level & NGX_LOG_DEBUG_CONNECTION) != 0;

    // 对整个日志链表执行写入操作
    while (log) {

        if (log->log_level < level && !debug_connection) {
            break;
        }

        if (log->writer) {
            log->writer(log, level, errstr, p - errstr);
            goto next;
        }

        if (ngx_time() == log->disk_full_time) {

            /*
             * on FreeBSD writing to a full filesystem with enabled softupdates
             * may block process for much longer time than writing to non-full
             * filesystem, so we skip writing to a log for one second
             */

            goto next;
        }

        // 写错误日志消息到关联的文件
        // 实际上就是系统调用write,见ngx_files.h
        n = ngx_write_fd(log->file->fd, errstr, p - errstr);

        // 写入失败,且错误是磁盘满
        if (n == -1 && ngx_errno == NGX_ENOSPC) {
            log->disk_full_time = ngx_time();
        }

        if (log->file->fd == ngx_stderr) {
            wrote_stderr = 1;
        }

    next:

        // 使用下一个日志对象记录日志
        log = log->next;
    }

    if (!ngx_use_stderr
        || level > NGX_LOG_WARN
        || wrote_stderr)
    {
        return;
    }

    msg -= (7 + err_levels[level].len + 3);

    (void) ngx_sprintf(msg, "nginx: [%V] ", &err_levels[level]);

    (void) ngx_write_console(ngx_stderr, msg, p - msg);
}
static ngx_int_t ngx_http_alog_handler(ngx_http_request_t *r)
{
        u_char *line, *p;
        ngx_str_t *computed_log;

        ngx_uint_t l, log_msg_len;
        ngx_http_alog_t *log;

        ngx_http_alog_main_conf_t *lmcf;
        ngx_http_alog_loc_conf_t *llcf;

        lmcf = ngx_http_get_module_main_conf(r, ngx_http_alog_module);
        llcf = ngx_http_get_module_loc_conf(r, ngx_http_alog_module);

        if (lmcf->log_level == NGX_CONF_UNSET || llcf->logs == NULL) {
                return NGX_OK;
        }

        log = llcf->logs->elts;

        for (l = 0; l < llcf->logs->nelts; l++) {

                /* if current log level less than log_level setting, just skip.
                 * actually, low level logs should already have been skipped befroe */
                if (log[l].level < lmcf->log_level) {
                        continue;
                }

                computed_log = NULL;

                if (log[l].script->lengths == NULL) {
                        computed_log = &(log[l].script->raw_value);
                } else {
                        computed_log = ngx_pcalloc(r->pool, sizeof(ngx_str_t));

                        if (computed_log == NULL) {
                                return NGX_HTTP_INTERNAL_SERVER_ERROR;
                        }

                        if (ngx_http_script_run(r, computed_log, log[l].script->lengths->elts, 0, log[l].script->values->elts) == NULL) {
                                return NGX_HTTP_INTERNAL_SERVER_ERROR;
                        } 
                }

                if (computed_log == NULL) {
                        return NGX_HTTP_INTERNAL_SERVER_ERROR;
                }

                log_msg_len = computed_log->len;
                log_msg_len += NGX_LINEFEED_SIZE;

                line = ngx_pcalloc(r->pool, log_msg_len);

                if (line == NULL) {
                        return NGX_HTTP_INTERNAL_SERVER_ERROR;
                }

                p = line;
                p = ngx_cpymem(line, computed_log->data, computed_log->len);
                ngx_linefeed(p);

                if (ngx_http_alog_write(r, line, log_msg_len, log[l].flush) != (ngx_int_t)log_msg_len) {
                        return NGX_HTTP_INTERNAL_SERVER_ERROR;
                }
        }

        return NGX_OK;
}
void ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, const char *fmt, ...){

#else

void ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, const char *fmt, va_list args){

#endif
#if (NGX_HAVE_VARIADIC_MACROS)
    va_list args;
#endif
    u_char *p,*last,*msg;
    ssize_t n;
    ngx_uint_t wrote_stderr,debug_connection;
    u_char errstr[NGX_MAX_ERROR_STR];
    last = errstr + NGX_MAX_ERROR_STR;
    //it seems do not set the ngx_cached_err_log_time.len value
    p = ngx_cpymem(errstr,ngx_cached_err_log_time.data,
                   ngx_cached_err_log_time.len);
    p = ngx_slprintf(p,last,"[%V]",&err_levels[level]);
   //just for making the datastructure can work correctly,comment the next function
    /* pid#tid */
    // p = ngx_slprintf(p,last,"%P#" NGX_TID_T_FMT ": ",
    // ngx_log_pid,ngx_log_tid);
    if (log->connection) {
        p = ngx_slprintf(p,last,"*%uA ",log->connection);
   }

    msg = p;

#if (NGX_HAVE_VARIADIC_MACROS)
    va_start (args,fmt);
    p = ngx_vslprintf(p,last,fmt,args);
    va_end (args);

#else
    p = ngx_vslprintf(p,last,fmt,args);
#endif

    if (err) {
        p = ngx_log_errno(p,last,err);
    }

   if (level != NGX_LOG_DEBUG && log->handler){
       p = log->handler(log,p,last  - p);
   }

   if (p > last - NGX_LINEFEED_SIZE){
       p = last - NGX_LINEFEED_SIZE;
   }

   ngx_linefeed(p);

   wrote_stderr = 0;
   debug_connection = (log->log_level & NGX_LOG_DEBUG_CONNECTION) != 0;

   while(log){
       if (log->log_level < level && !debug_connection){
           break;
       }

      if(log->writer){
          log->writer(log,level,errstr,p - errstr);
          goto next;
      }

      if (ngx_time() == log->disk_full_time){

            /*
             * on FreeBSD writing to a full filesystem with enabled softupdates
             * may block process for much longer time than writing to non-full
             * filesystem, so we skip writing to a log for one second
             */
          goto next;
      }
      n = ngx_write_fd(log->file->fd,errstr,p - errstr);

      if (n == -1 && ngx_errno == NGX_ENOSPC){
          log->disk_full_time = ngx_time();
      }

      if (log->file->fd == ngx_stderr){
          wrote_stderr = 1;
      }
next:

      log = log->next;
   }

   if (!ngx_use_stderr || level > NGX_LOG_WARN || wrote_stderr){
       return;
   }

   msg -= (7 + err_levels[level].len + 3);

   (void)ngx_sprintf(msg,"nginx: [%V]",&err_levels[level]);

   (void) ngx_write_console(ngx_stderr,msg,p - msg);
}