src/core/ngx_log.c - nginx-1.7.10

Global variables defined

Functions defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>


  7. static char *ngx_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
  8. static char *ngx_log_set_levels(ngx_conf_t *cf, ngx_log_t *log);
  9. static void ngx_log_insert(ngx_log_t *log, ngx_log_t *new_log);


  10. static ngx_command_t  ngx_errlog_commands[] = {

  11.     {ngx_string("error_log"),
  12.      NGX_MAIN_CONF|NGX_CONF_1MORE,
  13.      ngx_error_log,
  14.      0,
  15.      0,
  16.      NULL},

  17.     ngx_null_command
  18. };


  19. static ngx_core_module_t  ngx_errlog_module_ctx = {
  20.     ngx_string("errlog"),
  21.     NULL,
  22.     NULL
  23. };


  24. ngx_module_t  ngx_errlog_module = {
  25.     NGX_MODULE_V1,
  26.     &ngx_errlog_module_ctx,                /* module context */
  27.     ngx_errlog_commands,                   /* module directives */
  28.     NGX_CORE_MODULE,                       /* module type */
  29.     NULL,                                  /* init master */
  30.     NULL,                                  /* init module */
  31.     NULL,                                  /* init process */
  32.     NULL,                                  /* init thread */
  33.     NULL,                                  /* exit thread */
  34.     NULL,                                  /* exit process */
  35.     NULL,                                  /* exit master */
  36.     NGX_MODULE_V1_PADDING
  37. };


  38. static ngx_log_t        ngx_log;
  39. static ngx_open_file_t  ngx_log_file;
  40. ngx_uint_t              ngx_use_stderr = 1;


  41. static ngx_str_t err_levels[] = {
  42.     ngx_null_string,
  43.     ngx_string("emerg"),
  44.     ngx_string("alert"),
  45.     ngx_string("crit"),
  46.     ngx_string("error"),
  47.     ngx_string("warn"),
  48.     ngx_string("notice"),
  49.     ngx_string("info"),
  50.     ngx_string("debug")
  51. };

  52. static const char *debug_levels[] = {
  53.     "debug_core", "debug_alloc", "debug_mutex", "debug_event",
  54.     "debug_http", "debug_mail", "debug_mysql"
  55. };


  56. #if (NGX_HAVE_VARIADIC_MACROS)

  57. void
  58. ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
  59.     const char *fmt, ...)

  60. #else

  61. void
  62. ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
  63.     const char *fmt, va_list args)

  64. #endif
  65. {
  66. #if (NGX_HAVE_VARIADIC_MACROS)
  67.     va_list      args;
  68. #endif
  69.     u_char      *p, *last, *msg;
  70.     ssize_t      n;
  71.     ngx_uint_t   wrote_stderr, debug_connection;
  72.     u_char       errstr[NGX_MAX_ERROR_STR];

  73.     last = errstr + NGX_MAX_ERROR_STR;

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

  76.     p = errstr + ngx_cached_err_log_time.len;

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

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

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

  84.     msg = p;

  85. #if (NGX_HAVE_VARIADIC_MACROS)

  86.     va_start(args, fmt);
  87.     p = ngx_vslprintf(p, last, fmt, args);
  88.     va_end(args);

  89. #else

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

  91. #endif

  92.     if (err) {
  93.         p = ngx_log_errno(p, last, err);
  94.     }

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

  98.     if (p > last - NGX_LINEFEED_SIZE) {
  99.         p = last - NGX_LINEFEED_SIZE;
  100.     }

  101.     ngx_linefeed(p);

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

  104.     while (log) {

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

  108.         if (log->writer) {
  109.             log->writer(log, level, errstr, p - errstr);
  110.             goto next;
  111.         }

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

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

  118.             goto next;
  119.         }

  120.         n = ngx_write_fd(log->file->fd, errstr, p - errstr);

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

  124.         if (log->file->fd == ngx_stderr) {
  125.             wrote_stderr = 1;
  126.         }

  127.     next:

  128.         log = log->next;
  129.     }

  130.     if (!ngx_use_stderr
  131.         || level > NGX_LOG_WARN
  132.         || wrote_stderr)
  133.     {
  134.         return;
  135.     }

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

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

  138.     (void) ngx_write_console(ngx_stderr, msg, p - msg);
  139. }


  140. #if !(NGX_HAVE_VARIADIC_MACROS)

  141. void ngx_cdecl
  142. ngx_log_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
  143.     const char *fmt, ...)
  144. {
  145.     va_list  args;

  146.     if (log->log_level >= level) {
  147.         va_start(args, fmt);
  148.         ngx_log_error_core(level, log, err, fmt, args);
  149.         va_end(args);
  150.     }
  151. }


  152. void ngx_cdecl
  153. ngx_log_debug_core(ngx_log_t *log, ngx_err_t err, const char *fmt, ...)
  154. {
  155.     va_list  args;

  156.     va_start(args, fmt);
  157.     ngx_log_error_core(NGX_LOG_DEBUG, log, err, fmt, args);
  158.     va_end(args);
  159. }

  160. #endif


  161. void ngx_cdecl
  162. ngx_log_abort(ngx_err_t err, const char *fmt, ...)
  163. {
  164.     u_char   *p;
  165.     va_list   args;
  166.     u_char    errstr[NGX_MAX_CONF_ERRSTR];

  167.     va_start(args, fmt);
  168.     p = ngx_vsnprintf(errstr, sizeof(errstr) - 1, fmt, args);
  169.     va_end(args);

  170.     ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, err,
  171.                   "%*s", p - errstr, errstr);
  172. }


  173. void ngx_cdecl
  174. ngx_log_stderr(ngx_err_t err, const char *fmt, ...)
  175. {
  176.     u_char   *p, *last;
  177.     va_list   args;
  178.     u_char    errstr[NGX_MAX_ERROR_STR];

  179.     last = errstr + NGX_MAX_ERROR_STR;
  180.     p = errstr + 7;

  181.     ngx_memcpy(errstr, "nginx: ", 7);

  182.     va_start(args, fmt);
  183.     p = ngx_vslprintf(p, last, fmt, args);
  184.     va_end(args);

  185.     if (err) {
  186.         p = ngx_log_errno(p, last, err);
  187.     }

  188.     if (p > last - NGX_LINEFEED_SIZE) {
  189.         p = last - NGX_LINEFEED_SIZE;
  190.     }

  191.     ngx_linefeed(p);

  192.     (void) ngx_write_console(ngx_stderr, errstr, p - errstr);
  193. }


  194. u_char *
  195. ngx_log_errno(u_char *buf, u_char *last, ngx_err_t err)
  196. {
  197.     if (buf > last - 50) {

  198.         /* leave a space for an error code */

  199.         buf = last - 50;
  200.         *buf++ = '.';
  201.         *buf++ = '.';
  202.         *buf++ = '.';
  203.     }

  204. #if (NGX_WIN32)
  205.     buf = ngx_slprintf(buf, last, ((unsigned) err < 0x80000000)
  206.                                        ? " (%d: " : " (%Xd: ", err);
  207. #else
  208.     buf = ngx_slprintf(buf, last, " (%d: ", err);
  209. #endif

  210.     buf = ngx_strerror(err, buf, last - buf);

  211.     if (buf < last) {
  212.         *buf++ = ')';
  213.     }

  214.     return buf;
  215. }


  216. ngx_log_t *
  217. ngx_log_init(u_char *prefix)
  218. {
  219.     u_char  *p, *name;
  220.     size_t   nlen, plen;

  221.     ngx_log.file = &ngx_log_file;
  222.     ngx_log.log_level = NGX_LOG_NOTICE;

  223.     name = (u_char *) NGX_ERROR_LOG_PATH;

  224.     /*
  225.      * we use ngx_strlen() here since BCC warns about
  226.      * condition is always false and unreachable code
  227.      */

  228.     nlen = ngx_strlen(name);

  229.     if (nlen == 0) {
  230.         ngx_log_file.fd = ngx_stderr;
  231.         return &ngx_log;
  232.     }

  233.     p = NULL;

  234. #if (NGX_WIN32)
  235.     if (name[1] != ':') {
  236. #else
  237.     if (name[0] != '/') {
  238. #endif

  239.         if (prefix) {
  240.             plen = ngx_strlen(prefix);

  241.         } else {
  242. #ifdef NGX_PREFIX
  243.             prefix = (u_char *) NGX_PREFIX;
  244.             plen = ngx_strlen(prefix);
  245. #else
  246.             plen = 0;
  247. #endif
  248.         }

  249.         if (plen) {
  250.             name = malloc(plen + nlen + 2);
  251.             if (name == NULL) {
  252.                 return NULL;
  253.             }

  254.             p = ngx_cpymem(name, prefix, plen);

  255.             if (!ngx_path_separator(*(p - 1))) {
  256.                 *p++ = '/';
  257.             }

  258.             ngx_cpystrn(p, (u_char *) NGX_ERROR_LOG_PATH, nlen + 1);

  259.             p = name;
  260.         }
  261.     }

  262.     ngx_log_file.fd = ngx_open_file(name, NGX_FILE_APPEND,
  263.                                     NGX_FILE_CREATE_OR_OPEN,
  264.                                     NGX_FILE_DEFAULT_ACCESS);

  265.     if (ngx_log_file.fd == NGX_INVALID_FILE) {
  266.         ngx_log_stderr(ngx_errno,
  267.                        "[alert] could not open error log file: "
  268.                        ngx_open_file_n " \"%s\" failed", name);
  269. #if (NGX_WIN32)
  270.         ngx_event_log(ngx_errno,
  271.                        "could not open error log file: "
  272.                        ngx_open_file_n " \"%s\" failed", name);
  273. #endif

  274.         ngx_log_file.fd = ngx_stderr;
  275.     }

  276.     if (p) {
  277.         ngx_free(p);
  278.     }

  279.     return &ngx_log;
  280. }


  281. ngx_int_t
  282. ngx_log_open_default(ngx_cycle_t *cycle)
  283. {
  284.     ngx_log_t         *log;
  285.     static ngx_str_t   error_log = ngx_string(NGX_ERROR_LOG_PATH);

  286.     if (ngx_log_get_file_log(&cycle->new_log) != NULL) {
  287.         return NGX_OK;
  288.     }

  289.     if (cycle->new_log.log_level != 0) {
  290.         /* there are some error logs, but no files */

  291.         log = ngx_pcalloc(cycle->pool, sizeof(ngx_log_t));
  292.         if (log == NULL) {
  293.             return NGX_ERROR;
  294.         }

  295.     } else {
  296.         /* no error logs at all */
  297.         log = &cycle->new_log;
  298.     }

  299.     log->log_level = NGX_LOG_ERR;

  300.     log->file = ngx_conf_open_file(cycle, &error_log);
  301.     if (log->file == NULL) {
  302.         return NGX_ERROR;
  303.     }

  304.     if (log != &cycle->new_log) {
  305.         ngx_log_insert(&cycle->new_log, log);
  306.     }

  307.     return NGX_OK;
  308. }


  309. ngx_int_t
  310. ngx_log_redirect_stderr(ngx_cycle_t *cycle)
  311. {
  312.     ngx_fd_t  fd;

  313.     if (cycle->log_use_stderr) {
  314.         return NGX_OK;
  315.     }

  316.     /* file log always exists when we are called */
  317.     fd = ngx_log_get_file_log(cycle->log)->file->fd;

  318.     if (fd != ngx_stderr) {
  319.         if (ngx_set_stderr(fd) == NGX_FILE_ERROR) {
  320.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  321.                           ngx_set_stderr_n " failed");

  322.             return NGX_ERROR;
  323.         }
  324.     }

  325.     return NGX_OK;
  326. }


  327. ngx_log_t *
  328. ngx_log_get_file_log(ngx_log_t *head)
  329. {
  330.     ngx_log_t  *log;

  331.     for (log = head; log; log = log->next) {
  332.         if (log->file != NULL) {
  333.             return log;
  334.         }
  335.     }

  336.     return NULL;
  337. }


  338. static char *
  339. ngx_log_set_levels(ngx_conf_t *cf, ngx_log_t *log)
  340. {
  341.     ngx_uint_t   i, n, d, found;
  342.     ngx_str_t   *value;

  343.     if (cf->args->nelts == 2) {
  344.         log->log_level = NGX_LOG_ERR;
  345.         return NGX_CONF_OK;
  346.     }

  347.     value = cf->args->elts;

  348.     for (i = 2; i < cf->args->nelts; i++) {
  349.         found = 0;

  350.         for (n = 1; n <= NGX_LOG_DEBUG; n++) {
  351.             if (ngx_strcmp(value[i].data, err_levels[n].data) == 0) {

  352.                 if (log->log_level != 0) {
  353.                     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  354.                                        "duplicate log level \"%V\"",
  355.                                        &value[i]);
  356.                     return NGX_CONF_ERROR;
  357.                 }

  358.                 log->log_level = n;
  359.                 found = 1;
  360.                 break;
  361.             }
  362.         }

  363.         for (n = 0, d = NGX_LOG_DEBUG_FIRST; d <= NGX_LOG_DEBUG_LAST; d <<= 1) {
  364.             if (ngx_strcmp(value[i].data, debug_levels[n++]) == 0) {
  365.                 if (log->log_level & ~NGX_LOG_DEBUG_ALL) {
  366.                     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  367.                                        "invalid log level \"%V\"",
  368.                                        &value[i]);
  369.                     return NGX_CONF_ERROR;
  370.                 }

  371.                 log->log_level |= d;
  372.                 found = 1;
  373.                 break;
  374.             }
  375.         }


  376.         if (!found) {
  377.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  378.                                "invalid log level \"%V\"", &value[i]);
  379.             return NGX_CONF_ERROR;
  380.         }
  381.     }

  382.     if (log->log_level == NGX_LOG_DEBUG) {
  383.         log->log_level = NGX_LOG_DEBUG_ALL;
  384.     }

  385.     return NGX_CONF_OK;
  386. }


  387. static char *
  388. ngx_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  389. {
  390.     ngx_log_t  *dummy;

  391.     dummy = &cf->cycle->new_log;

  392.     return ngx_log_set_log(cf, &dummy);
  393. }


  394. char *
  395. ngx_log_set_log(ngx_conf_t *cf, ngx_log_t **head)
  396. {
  397.     ngx_log_t          *new_log;
  398.     ngx_str_t          *value, name;
  399.     ngx_syslog_peer_t  *peer;

  400.     if (*head != NULL && (*head)->log_level == 0) {
  401.         new_log = *head;

  402.     } else {

  403.         new_log = ngx_pcalloc(cf->pool, sizeof(ngx_log_t));
  404.         if (new_log == NULL) {
  405.             return NGX_CONF_ERROR;
  406.         }

  407.         if (*head == NULL) {
  408.             *head = new_log;
  409.         }
  410.     }

  411.     value = cf->args->elts;

  412.     if (ngx_strcmp(value[1].data, "stderr") == 0) {
  413.         ngx_str_null(&name);
  414.         cf->cycle->log_use_stderr = 1;

  415.         new_log->file = ngx_conf_open_file(cf->cycle, &name);
  416.         if (new_log->file == NULL) {
  417.             return NGX_CONF_ERROR;
  418.         }


  419.      } else if (ngx_strncmp(value[1].data, "syslog:", 7) == 0) {
  420.         peer = ngx_pcalloc(cf->pool, sizeof(ngx_syslog_peer_t));
  421.         if (peer == NULL) {
  422.             return NGX_CONF_ERROR;
  423.         }

  424.         if (ngx_syslog_process_conf(cf, peer) != NGX_CONF_OK) {
  425.             return NGX_CONF_ERROR;
  426.         }

  427.         new_log->writer = ngx_syslog_writer;
  428.         new_log->wdata = peer;

  429.     } else {
  430.         new_log->file = ngx_conf_open_file(cf->cycle, &value[1]);
  431.         if (new_log->file == NULL) {
  432.             return NGX_CONF_ERROR;
  433.         }
  434.     }

  435.     if (ngx_log_set_levels(cf, new_log) != NGX_CONF_OK) {
  436.         return NGX_CONF_ERROR;
  437.     }

  438.     if (*head != new_log) {
  439.         ngx_log_insert(*head, new_log);
  440.     }

  441.     return NGX_CONF_OK;
  442. }


  443. static void
  444. ngx_log_insert(ngx_log_t *log, ngx_log_t *new_log)
  445. {
  446.     ngx_log_t  tmp;

  447.     if (new_log->log_level > log->log_level) {

  448.         /*
  449.          * list head address is permanent, insert new log after
  450.          * head and swap its contents with head
  451.          */

  452.         tmp = *log;
  453.         *log = *new_log;
  454.         *new_log = tmp;

  455.         log->next = new_log;
  456.         return;
  457.     }

  458.     while (log->next) {
  459.         if (new_log->log_level > log->next->log_level) {
  460.             new_log->next = log->next;
  461.             log->next = new_log;
  462.             return;
  463.         }

  464.         log = log->next;
  465.     }

  466.     log->next = new_log;
  467. }