~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Nginx/http/modules/ngx_http_log_module.c

Version: ~ [ nginx-1.4.1 ] ~ [ nginx-1.5.0 ] ~

  1 
  2 /*
  3  * Copyright (C) Igor Sysoev
  4  * Copyright (C) Nginx, Inc.
  5  */
  6 
  7 
  8 #include <ngx_config.h>
  9 #include <ngx_core.h>
 10 #include <ngx_http.h>
 11 
 12 #if (NGX_ZLIB)
 13 #include <zlib.h>
 14 #endif
 15 
 16 
 17 typedef struct ngx_http_log_op_s  ngx_http_log_op_t;
 18 
 19 typedef u_char *(*ngx_http_log_op_run_pt) (ngx_http_request_t *r, u_char *buf,
 20     ngx_http_log_op_t *op);
 21 
 22 typedef size_t (*ngx_http_log_op_getlen_pt) (ngx_http_request_t *r,
 23     uintptr_t data);
 24 
 25 
 26 struct ngx_http_log_op_s {
 27     size_t                      len;
 28     ngx_http_log_op_getlen_pt   getlen;
 29     ngx_http_log_op_run_pt      run;
 30     uintptr_t                   data;
 31 };
 32 
 33 
 34 typedef struct {
 35     ngx_str_t                   name;
 36     ngx_array_t                *flushes;
 37     ngx_array_t                *ops;        /* array of ngx_http_log_op_t */
 38 } ngx_http_log_fmt_t;
 39 
 40 
 41 typedef struct {
 42     ngx_array_t                 formats;    /* array of ngx_http_log_fmt_t */
 43     ngx_uint_t                  combined_used; /* unsigned  combined_used:1 */
 44 } ngx_http_log_main_conf_t;
 45 
 46 
 47 typedef struct {
 48     u_char                     *start;
 49     u_char                     *pos;
 50     u_char                     *last;
 51 
 52     ngx_event_t                *event;
 53     ngx_msec_t                  flush;
 54     ngx_int_t                   gzip;
 55 } ngx_http_log_buf_t;
 56 
 57 
 58 typedef struct {
 59     ngx_array_t                *lengths;
 60     ngx_array_t                *values;
 61 } ngx_http_log_script_t;
 62 
 63 
 64 typedef struct {
 65     ngx_open_file_t            *file;
 66     ngx_http_log_script_t      *script;
 67     time_t                      disk_full_time;
 68     time_t                      error_log_time;
 69     ngx_http_log_fmt_t         *format;
 70 } ngx_http_log_t;
 71 
 72 
 73 typedef struct {
 74     ngx_array_t                *logs;       /* array of ngx_http_log_t */
 75 
 76     ngx_open_file_cache_t      *open_file_cache;
 77     time_t                      open_file_cache_valid;
 78     ngx_uint_t                  open_file_cache_min_uses;
 79 
 80     ngx_uint_t                  off;        /* unsigned  off:1 */
 81 } ngx_http_log_loc_conf_t;
 82 
 83 
 84 typedef struct {
 85     ngx_str_t                   name;
 86     size_t                      len;
 87     ngx_http_log_op_run_pt      run;
 88 } ngx_http_log_var_t;
 89 
 90 
 91 static void ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log,
 92     u_char *buf, size_t len);
 93 static ssize_t ngx_http_log_script_write(ngx_http_request_t *r,
 94     ngx_http_log_script_t *script, u_char **name, u_char *buf, size_t len);
 95 
 96 #if (NGX_ZLIB)
 97 static ssize_t ngx_http_log_gzip(ngx_fd_t fd, u_char *buf, size_t len,
 98     ngx_int_t level, ngx_log_t *log);
 99 
100 static void *ngx_http_log_gzip_alloc(void *opaque, u_int items, u_int size);
101 static void ngx_http_log_gzip_free(void *opaque, void *address);
102 #endif
103 
104 static void ngx_http_log_flush(ngx_open_file_t *file, ngx_log_t *log);
105 static void ngx_http_log_flush_handler(ngx_event_t *ev);
106 
107 static u_char *ngx_http_log_pipe(ngx_http_request_t *r, u_char *buf,
108     ngx_http_log_op_t *op);
109 static u_char *ngx_http_log_time(ngx_http_request_t *r, u_char *buf,
110     ngx_http_log_op_t *op);
111 static u_char *ngx_http_log_iso8601(ngx_http_request_t *r, u_char *buf,
112     ngx_http_log_op_t *op);
113 static u_char *ngx_http_log_msec(ngx_http_request_t *r, u_char *buf,
114     ngx_http_log_op_t *op);
115 static u_char *ngx_http_log_request_time(ngx_http_request_t *r, u_char *buf,
116     ngx_http_log_op_t *op);
117 static u_char *ngx_http_log_status(ngx_http_request_t *r, u_char *buf,
118     ngx_http_log_op_t *op);
119 static u_char *ngx_http_log_bytes_sent(ngx_http_request_t *r, u_char *buf,
120     ngx_http_log_op_t *op);
121 static u_char *ngx_http_log_body_bytes_sent(ngx_http_request_t *r,
122     u_char *buf, ngx_http_log_op_t *op);
123 static u_char *ngx_http_log_request_length(ngx_http_request_t *r, u_char *buf,
124     ngx_http_log_op_t *op);
125 
126 static ngx_int_t ngx_http_log_variable_compile(ngx_conf_t *cf,
127     ngx_http_log_op_t *op, ngx_str_t *value);
128 static size_t ngx_http_log_variable_getlen(ngx_http_request_t *r,
129     uintptr_t data);
130 static u_char *ngx_http_log_variable(ngx_http_request_t *r, u_char *buf,
131     ngx_http_log_op_t *op);
132 static uintptr_t ngx_http_log_escape(u_char *dst, u_char *src, size_t size);
133 
134 
135 static void *ngx_http_log_create_main_conf(ngx_conf_t *cf);
136 static void *ngx_http_log_create_loc_conf(ngx_conf_t *cf);
137 static char *ngx_http_log_merge_loc_conf(ngx_conf_t *cf, void *parent,
138     void *child);
139 static char *ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd,
140     void *conf);
141 static char *ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd,
142     void *conf);
143 static char *ngx_http_log_compile_format(ngx_conf_t *cf,
144     ngx_array_t *flushes, ngx_array_t *ops, ngx_array_t *args, ngx_uint_t s);
145 static char *ngx_http_log_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd,
146     void *conf);
147 static ngx_int_t ngx_http_log_init(ngx_conf_t *cf);
148 
149 
150 static ngx_command_t  ngx_http_log_commands[] = {
151 
152     { ngx_string("log_format"),
153       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_2MORE,
154       ngx_http_log_set_format,
155       NGX_HTTP_MAIN_CONF_OFFSET,
156       0,
157       NULL },
158 
159     { ngx_string("access_log"),
160       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
161                         |NGX_HTTP_LMT_CONF|NGX_CONF_1MORE,
162       ngx_http_log_set_log,
163       NGX_HTTP_LOC_CONF_OFFSET,
164       0,
165       NULL },
166 
167     { ngx_string("open_log_file_cache"),
168       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
169       ngx_http_log_open_file_cache,
170       NGX_HTTP_LOC_CONF_OFFSET,
171       0,
172       NULL },
173 
174       ngx_null_command
175 };
176 
177 
178 static ngx_http_module_t  ngx_http_log_module_ctx = {
179     NULL,                                  /* preconfiguration */
180     ngx_http_log_init,                     /* postconfiguration */
181 
182     ngx_http_log_create_main_conf,         /* create main configuration */
183     NULL,                                  /* init main configuration */
184 
185     NULL,                                  /* create server configuration */
186     NULL,                                  /* merge server configuration */
187 
188     ngx_http_log_create_loc_conf,          /* create location configuration */
189     ngx_http_log_merge_loc_conf            /* merge location configuration */
190 };
191 
192 
193 ngx_module_t  ngx_http_log_module = {
194     NGX_MODULE_V1,
195     &ngx_http_log_module_ctx,              /* module context */
196     ngx_http_log_commands,                 /* module directives */
197     NGX_HTTP_MODULE,                       /* module type */
198     NULL,                                  /* init master */
199     NULL,                                  /* init module */
200     NULL,                                  /* init process */
201     NULL,                                  /* init thread */
202     NULL,                                  /* exit thread */
203     NULL,                                  /* exit process */
204     NULL,                                  /* exit master */
205     NGX_MODULE_V1_PADDING
206 };
207 
208 
209 static ngx_str_t  ngx_http_access_log = ngx_string(NGX_HTTP_LOG_PATH);
210 
211 
212 static ngx_str_t  ngx_http_combined_fmt =
213     ngx_string("$remote_addr - $remote_user [$time_local] "
214                "\"$request\" $status $body_bytes_sent "
215                "\"$http_referer\" \"$http_user_agent\"");
216 
217 
218 static ngx_http_log_var_t  ngx_http_log_vars[] = {
219     { ngx_string("pipe"), 1, ngx_http_log_pipe },
220     { ngx_string("time_local"), sizeof("28/Sep/1970:12:00:00 +0600") - 1,
221                           ngx_http_log_time },
222     { ngx_string("time_iso8601"), sizeof("1970-09-28T12:00:00+06:00") - 1,
223                           ngx_http_log_iso8601 },
224     { ngx_string("msec"), NGX_TIME_T_LEN + 4, ngx_http_log_msec },
225     { ngx_string("request_time"), NGX_TIME_T_LEN + 4,
226                           ngx_http_log_request_time },
227     { ngx_string("status"), NGX_INT_T_LEN, ngx_http_log_status },
228     { ngx_string("bytes_sent"), NGX_OFF_T_LEN, ngx_http_log_bytes_sent },
229     { ngx_string("body_bytes_sent"), NGX_OFF_T_LEN,
230                           ngx_http_log_body_bytes_sent },
231     { ngx_string("request_length"), NGX_SIZE_T_LEN,
232                           ngx_http_log_request_length },
233 
234     { ngx_null_string, 0, NULL }
235 };
236 
237 
238 static ngx_int_t
239 ngx_http_log_handler(ngx_http_request_t *r)
240 {
241     u_char                   *line, *p;
242     size_t                    len;
243     ngx_uint_t                i, l;
244     ngx_http_log_t           *log;
245     ngx_http_log_op_t        *op;
246     ngx_http_log_buf_t       *buffer;
247     ngx_http_log_loc_conf_t  *lcf;
248 
249     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
250                    "http log handler");
251 
252     lcf = ngx_http_get_module_loc_conf(r, ngx_http_log_module);
253 
254     if (lcf->off) {
255         return NGX_OK;
256     }
257 
258     log = lcf->logs->elts;
259     for (l = 0; l < lcf->logs->nelts; l++) {
260 
261         if (ngx_time() == log[l].disk_full_time) {
262 
263             /*
264              * on FreeBSD writing to a full filesystem with enabled softupdates
265              * may block process for much longer time than writing to non-full
266              * filesystem, so we skip writing to a log for one second
267              */
268 
269             continue;
270         }
271 
272         ngx_http_script_flush_no_cacheable_variables(r, log[l].format->flushes);
273 
274         len = 0;
275         op = log[l].format->ops->elts;
276         for (i = 0; i < log[l].format->ops->nelts; i++) {
277             if (op[i].len == 0) {
278                 len += op[i].getlen(r, op[i].data);
279 
280             } else {
281                 len += op[i].len;
282             }
283         }
284 
285         len += NGX_LINEFEED_SIZE;
286 
287         buffer = log[l].file ? log[l].file->data : NULL;
288 
289         if (buffer) {
290 
291             if (len > (size_t) (buffer->last - buffer->pos)) {
292 
293                 ngx_http_log_write(r, &log[l], buffer->start,
294                                    buffer->pos - buffer->start);
295 
296                 buffer->pos = buffer->start;
297             }
298 
299             if (len <= (size_t) (buffer->last - buffer->pos)) {
300 
301                 p = buffer->pos;
302 
303                 if (buffer->event && p == buffer->start) {
304                     ngx_add_timer(buffer->event, buffer->flush);
305                 }
306 
307                 for (i = 0; i < log[l].format->ops->nelts; i++) {
308                     p = op[i].run(r, p, &op[i]);
309                 }
310 
311                 ngx_linefeed(p);
312 
313                 buffer->pos = p;
314 
315                 continue;
316             }
317 
318             if (buffer->event && buffer->event->timer_set) {
319                 ngx_del_timer(buffer->event);
320             }
321         }
322 
323         line = ngx_pnalloc(r->pool, len);
324         if (line == NULL) {
325             return NGX_ERROR;
326         }
327 
328         p = line;
329 
330         for (i = 0; i < log[l].format->ops->nelts; i++) {
331             p = op[i].run(r, p, &op[i]);
332         }
333 
334         ngx_linefeed(p);
335 
336         ngx_http_log_write(r, &log[l], line, p - line);
337     }
338 
339     return NGX_OK;
340 }
341 
342 
343 static void
344 ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log, u_char *buf,
345     size_t len)
346 {
347     u_char              *name;
348     time_t               now;
349     ssize_t              n;
350     ngx_err_t            err;
351 #if (NGX_ZLIB)
352     ngx_http_log_buf_t  *buffer;
353 #endif
354 
355     if (log->script == NULL) {
356         name = log->file->name.data;
357 
358 #if (NGX_ZLIB)
359         buffer = log->file->data;
360 
361         if (buffer && buffer->gzip) {
362             n = ngx_http_log_gzip(log->file->fd, buf, len, buffer->gzip,
363                                   r->connection->log);
364         } else {
365             n = ngx_write_fd(log->file->fd, buf, len);
366         }
367 #else
368         n = ngx_write_fd(log->file->fd, buf, len);
369 #endif
370 
371     } else {
372         name = NULL;
373         n = ngx_http_log_script_write(r, log->script, &name, buf, len);
374     }
375 
376     if (n == (ssize_t) len) {
377         return;
378     }
379 
380     now = ngx_time();
381 
382     if (n == -1) {
383         err = ngx_errno;
384 
385         if (err == NGX_ENOSPC) {
386             log->disk_full_time = now;
387         }
388 
389         if (now - log->error_log_time > 59) {
390             ngx_log_error(NGX_LOG_ALERT, r->connection->log, err,
391                           ngx_write_fd_n " to \"%s\" failed", name);
392 
393             log->error_log_time = now;
394         }
395 
396         return;
397     }
398 
399     if (now - log->error_log_time > 59) {
400         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
401                       ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz",
402                       name, n, len);
403 
404         log->error_log_time = now;
405     }
406 }
407 
408 
409 static ssize_t
410 ngx_http_log_script_write(ngx_http_request_t *r, ngx_http_log_script_t *script,
411     u_char **name, u_char *buf, size_t len)
412 {
413     size_t                     root;
414     ssize_t                    n;
415     ngx_str_t                  log, path;
416     ngx_open_file_info_t       of;
417     ngx_http_log_loc_conf_t   *llcf;
418     ngx_http_core_loc_conf_t  *clcf;
419 
420     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
421 
422     if (!r->root_tested) {
423 
424         /* test root directory existence */
425 
426         if (ngx_http_map_uri_to_path(r, &path, &root, 0) == NULL) {
427             /* simulate successful logging */
428             return len;
429         }
430 
431         path.data[root] = '\0';
432 
433         ngx_memzero(&of, sizeof(ngx_open_file_info_t));
434 
435         of.valid = clcf->open_file_cache_valid;
436         of.min_uses = clcf->open_file_cache_min_uses;
437         of.test_dir = 1;
438         of.test_only = 1;
439         of.errors = clcf->open_file_cache_errors;
440         of.events = clcf->open_file_cache_events;
441 
442         if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
443             /* simulate successful logging */
444             return len;
445         }
446 
447         if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
448             != NGX_OK)
449         {
450             if (of.err == 0) {
451                 /* simulate successful logging */
452                 return len;
453             }
454 
455             ngx_log_error(NGX_LOG_ERR, r->connection->log, of.err,
456                           "testing \"%s\" existence failed", path.data);
457 
458             /* simulate successful logging */
459             return len;
460         }
461 
462         if (!of.is_dir) {
463             ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_ENOTDIR,
464                           "testing \"%s\" existence failed", path.data);
465 
466             /* simulate successful logging */
467             return len;
468         }
469     }
470 
471     if (ngx_http_script_run(r, &log, script->lengths->elts, 1,
472                             script->values->elts)
473         == NULL)
474     {
475         /* simulate successful logging */
476         return len;
477     }
478 
479     log.data[log.len - 1] = '\0';
480     *name = log.data;
481 
482     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
483                    "http log \"%s\"", log.data);
484 
485     llcf = ngx_http_get_module_loc_conf(r, ngx_http_log_module);
486 
487     ngx_memzero(&of, sizeof(ngx_open_file_info_t));
488 
489     of.log = 1;
490     of.valid = llcf->open_file_cache_valid;
491     of.min_uses = llcf->open_file_cache_min_uses;
492     of.directio = NGX_OPEN_FILE_DIRECTIO_OFF;
493 
494     if (ngx_http_set_disable_symlinks(r, clcf, &log, &of) != NGX_OK) {
495         /* simulate successful logging */
496         return len;
497     }
498 
499     if (ngx_open_cached_file(llcf->open_file_cache, &log, &of, r->pool)
500         != NGX_OK)
501     {
502         ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
503                       "%s \"%s\" failed", of.failed, log.data);
504         /* simulate successful logging */
505         return len;
506     }
507 
508     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
509                    "http log #%d", of.fd);
510 
511     n = ngx_write_fd(of.fd, buf, len);
512 
513     return n;
514 }
515 
516 
517 #if (NGX_ZLIB)
518 
519 static ssize_t
520 ngx_http_log_gzip(ngx_fd_t fd, u_char *buf, size_t len, ngx_int_t level,
521     ngx_log_t *log)
522 {
523     int          rc, wbits, memlevel;
524     u_char      *out;
525     size_t       size;
526     ssize_t      n;
527     z_stream     zstream;
528     ngx_err_t    err;
529     ngx_pool_t  *pool;
530 
531     wbits = MAX_WBITS;
532     memlevel = MAX_MEM_LEVEL - 1;
533 
534     while ((ssize_t) len < ((1 << (wbits - 1)) - 262)) {
535         wbits--;
536         memlevel--;
537     }
538 
539     /*
540      * This is a formula from deflateBound() for conservative upper bound of
541      * compressed data plus 18 bytes of gzip wrapper.
542      */
543 
544     size = len + ((len + 7) >> 3) + ((len + 63) >> 6) + 5 + 18;
545 
546     ngx_memzero(&zstream, sizeof(z_stream));
547 
548     pool = ngx_create_pool(256, log);
549     if (pool == NULL) {
550         /* simulate successful logging */
551         return len;
552     }
553 
554     pool->log = log;
555 
556     zstream.zalloc = ngx_http_log_gzip_alloc;
557     zstream.zfree = ngx_http_log_gzip_free;
558     zstream.opaque = pool;
559 
560     out = ngx_pnalloc(pool, size);
561     if (out == NULL) {
562         goto done;
563     }
564 
565     zstream.next_in = buf;
566     zstream.avail_in = len;
567     zstream.next_out = out;
568     zstream.avail_out = size;
569 
570     rc = deflateInit2(&zstream, (int) level, Z_DEFLATED, wbits + 16, memlevel,
571                       Z_DEFAULT_STRATEGY);
572 
573     if (rc != Z_OK) {
574         ngx_log_error(NGX_LOG_ALERT, log, 0, "deflateInit2() failed: %d", rc);
575         goto done;
576     }
577 
578     ngx_log_debug4(NGX_LOG_DEBUG_HTTP, log, 0,
579                    "deflate in: ni:%p no:%p ai:%ud ao:%ud",
580                    zstream.next_in, zstream.next_out,
581                    zstream.avail_in, zstream.avail_out);
582 
583     rc = deflate(&zstream, Z_FINISH);
584 
585     if (rc != Z_STREAM_END) {
586         ngx_log_error(NGX_LOG_ALERT, log, 0,
587                       "deflate(Z_FINISH) failed: %d", rc);
588         goto done;
589     }
590 
591     ngx_log_debug5(NGX_LOG_DEBUG_HTTP, log, 0,
592                    "deflate out: ni:%p no:%p ai:%ud ao:%ud rc:%d",
593                    zstream.next_in, zstream.next_out,
594                    zstream.avail_in, zstream.avail_out,
595                    rc);
596 
597     size -= zstream.avail_out;
598 
599     rc = deflateEnd(&zstream);
600 
601     if (rc != Z_OK) {
602         ngx_log_error(NGX_LOG_ALERT, log, 0, "deflateEnd() failed: %d", rc);
603         goto done;
604     }
605 
606     n = ngx_write_fd(fd, out, size);
607 
608     if (n != (ssize_t) size) {
609         err = (n == -1) ? ngx_errno : 0;
610 
611         ngx_destroy_pool(pool);
612 
613         ngx_set_errno(err);
614         return -1;
615     }
616 
617 done:
618 
619     ngx_destroy_pool(pool);
620 
621     /* simulate successful logging */
622     return len;
623 }
624 
625 
626 static void *
627 ngx_http_log_gzip_alloc(void *opaque, u_int items, u_int size)
628 {
629     ngx_pool_t *pool = opaque;
630 
631     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pool->log, 0,
632                    "gzip alloc: n:%ud s:%ud", items, size);
633 
634     return ngx_palloc(pool, items * size);
635 }
636 
637 
638 static void
639 ngx_http_log_gzip_free(void *opaque, void *address)
640 {
641 #if 0
642     ngx_pool_t *pool = opaque;
643 
644     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pool->log, 0, "gzip free: %p", address);
645 #endif
646 }
647 
648 #endif
649 
650 
651 static void
652 ngx_http_log_flush(ngx_open_file_t *file, ngx_log_t *log)
653 {
654     size_t               len;
655     ssize_t              n;
656     ngx_http_log_buf_t  *buffer;
657 
658     buffer = file->data;
659 
660     len = buffer->pos - buffer->start;
661 
662     if (len == 0) {
663         return;
664     }
665 
666 #if (NGX_ZLIB)
667     if (buffer->gzip) {
668         n = ngx_http_log_gzip(file->fd, buffer->start, len, buffer->gzip, log);
669     } else {
670         n = ngx_write_fd(file->fd, buffer->start, len);
671     }
672 #else
673     n = ngx_write_fd(file->fd, buffer->start, len);
674 #endif
675 
676     if (n == -1) {
677         ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
678                       ngx_write_fd_n " to \"%s\" failed",
679                       file->name.data);
680 
681     } else if ((size_t) n != len) {
682         ngx_log_error(NGX_LOG_ALERT, log, 0,
683                       ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz",
684                       file->name.data, n, len);
685     }
686 
687     buffer->pos = buffer->start;
688 
689     if (buffer->event && buffer->event->timer_set) {
690         ngx_del_timer(buffer->event);
691     }
692 }
693 
694 
695 static void
696 ngx_http_log_flush_handler(ngx_event_t *ev)
697 {
698     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0,
699                    "http log buffer flush handler");
700 
701     ngx_http_log_flush(ev->data, ev->log);
702 }
703 
704 
705 static u_char *
706 ngx_http_log_copy_short(ngx_http_request_t *r, u_char *buf,
707     ngx_http_log_op_t *op)
708 {
709     size_t     len;
710     uintptr_t  data;
711 
712     len = op->len;
713     data = op->data;
714 
715     while (len--) {
716         *buf++ = (u_char) (data & 0xff);
717         data >>= 8;
718     }
719 
720     return buf;
721 }
722 
723 
724 static u_char *
725 ngx_http_log_copy_long(ngx_http_request_t *r, u_char *buf,
726     ngx_http_log_op_t *op)
727 {
728     return ngx_cpymem(buf, (u_char *) op->data, op->len);
729 }
730 
731 
732 static u_char *
733 ngx_http_log_pipe(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
734 {
735     if (r->pipeline) {
736         *buf = 'p';
737     } else {
738         *buf = '.';
739     }
740 
741     return buf + 1;
742 }
743 
744 
745 static u_char *
746 ngx_http_log_time(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
747 {
748     return ngx_cpymem(buf, ngx_cached_http_log_time.data,
749                       ngx_cached_http_log_time.len);
750 }
751 
752 static u_char *
753 ngx_http_log_iso8601(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
754 {
755     return ngx_cpymem(buf, ngx_cached_http_log_iso8601.data,
756                       ngx_cached_http_log_iso8601.len);
757 }
758 
759 static u_char *
760 ngx_http_log_msec(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
761 {
762     ngx_time_t  *tp;
763 
764     tp = ngx_timeofday();
765 
766     return ngx_sprintf(buf, "%T.%03M", tp->sec, tp->msec);
767 }
768 
769 
770 static u_char *
771 ngx_http_log_request_time(ngx_http_request_t *r, u_char *buf,
772     ngx_http_log_op_t *op)
773 {
774     ngx_time_t      *tp;
775     ngx_msec_int_t   ms;
776 
777     tp = ngx_timeofday();
778 
779     ms = (ngx_msec_int_t)
780              ((tp->sec - r->start_sec) * 1000 + (tp->msec - r->start_msec));
781     ms = ngx_max(ms, 0);
782 
783     return ngx_sprintf(buf, "%T.%03M", ms / 1000, ms % 1000);
784 }
785 
786 
787 static u_char *
788 ngx_http_log_status(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
789 {
790     ngx_uint_t  status;
791 
792     if (r->err_status) {
793         status = r->err_status;
794 
795     } else if (r->headers_out.status) {
796         status = r->headers_out.status;
797 
798     } else if (r->http_version == NGX_HTTP_VERSION_9) {
799         status = 9;
800 
801     } else {
802         status = 0;
803     }
804 
805     return ngx_sprintf(buf, "%03ui", status);
806 }
807 
808 
809 static u_char *
810 ngx_http_log_bytes_sent(ngx_http_request_t *r, u_char *buf,
811     ngx_http_log_op_t *op)
812 {
813     return ngx_sprintf(buf, "%O", r->connection->sent);
814 }
815 
816 
817 /*
818  * although there is a real $body_bytes_sent variable,
819  * this log operation code function is more optimized for logging
820  */
821 
822 static u_char *
823 ngx_http_log_body_bytes_sent(ngx_http_request_t *r, u_char *buf,
824     ngx_http_log_op_t *op)
825 {
826     off_t  length;
827 
828     length = r->connection->sent - r->header_size;
829 
830     if (length > 0) {
831         return ngx_sprintf(buf, "%O", length);
832     }
833 
834     *buf = '';
835 
836     return buf + 1;
837 }
838 
839 
840 static u_char *
841 ngx_http_log_request_length(ngx_http_request_t *r, u_char *buf,
842     ngx_http_log_op_t *op)
843 {
844     return ngx_sprintf(buf, "%O", r->request_length);
845 }
846 
847 
848 static ngx_int_t
849 ngx_http_log_variable_compile(ngx_conf_t *cf, ngx_http_log_op_t *op,
850     ngx_str_t *value)
851 {
852     ngx_int_t  index;
853 
854     index = ngx_http_get_variable_index(cf, value);
855     if (index == NGX_ERROR) {
856         return NGX_ERROR;
857     }
858 
859     op->len = 0;
860     op->getlen = ngx_http_log_variable_getlen;
861     op->run = ngx_http_log_variable;
862     op->data = index;
863 
864     return NGX_OK;
865 }
866 
867 
868 static size_t
869 ngx_http_log_variable_getlen(ngx_http_request_t *r, uintptr_t data)
870 {
871     uintptr_t                   len;
872     ngx_http_variable_value_t  *value;
873 
874     value = ngx_http_get_indexed_variable(r, data);
875 
876     if (value == NULL || value->not_found) {
877         return 1;
878     }
879 
880     len = ngx_http_log_escape(NULL, value->data, value->len);
881 
882     value->escape = len ? 1 : 0;
883 
884     return value->len + len * 3;
885 }
886 
887 
888 static u_char *
889 ngx_http_log_variable(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
890 {
891     ngx_http_variable_value_t  *value;
892 
893     value = ngx_http_get_indexed_variable(r, op->data);
894 
895     if (value == NULL || value->not_found) {
896         *buf = '-';
897         return buf + 1;
898     }
899 
900     if (value->escape == 0) {
901         return ngx_cpymem(buf, value->data, value->len);
902 
903     } else {
904         return (u_char *) ngx_http_log_escape(buf, value->data, value->len);
905     }
906 }
907 
908 
909 static uintptr_t
910 ngx_http_log_escape(u_char *dst, u_char *src, size_t size)
911 {
912     ngx_uint_t      n;
913     static u_char   hex[] = "0123456789ABCDEF";
914 
915     static uint32_t   escape[] = {
916         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
917 
918                     /* ?>=< ;:98 7654 3210  /.-, +*)( '&%$ #"!  */
919         0x00000004, /* 0000 0000 0000 0000  0000 0000 0000 0100 */
920 
921                     /* _^]\ [ZYX WVUT SRQP  ONML KJIH GFED CBA@ */
922         0x10000000, /* 0001 0000 0000 0000  0000 0000 0000 0000 */
923 
924                     /*  ~}| {zyx wvut srqp  onml kjih gfed cba` */
925         0x80000000, /* 1000 0000 0000 0000  0000 0000 0000 0000 */
926 
927         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
928         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
929         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
930         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
931     };
932 
933 
934     if (dst == NULL) {
935 
936         /* find the number of the characters to be escaped */
937 
938         n = 0;
939 
940         while (size) {
941             if (escape[*src >> 5] & (1 << (*src & 0x1f))) {
942                 n++;
943             }
944             src++;
945             size--;
946         }
947 
948         return (uintptr_t) n;
949     }
950 
951     while (size) {
952         if (escape[*src >> 5] & (1 << (*src & 0x1f))) {
953             *dst++ = '\\';
954             *dst++ = 'x';
955             *dst++ = hex[*src >> 4];
956             *dst++ = hex[*src & 0xf];
957             src++;
958 
959         } else {
960             *dst++ = *src++;
961         }
962         size--;
963     }
964 
965     return (uintptr_t) dst;
966 }
967 
968 
969 static void *
970 ngx_http_log_create_main_conf(ngx_conf_t *cf)
971 {
972     ngx_http_log_main_conf_t  *conf;
973 
974     ngx_http_log_fmt_t  *fmt;
975 
976     conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_main_conf_t));
977     if (conf == NULL) {
978         return NULL;
979     }
980 
981     if (ngx_array_init(&conf->formats, cf->pool, 4, sizeof(ngx_http_log_fmt_t))
982         != NGX_OK)
983     {
984         return NULL;
985     }
986 
987     fmt = ngx_array_push(&conf->formats);
988     if (fmt == NULL) {
989         return NULL;
990     }
991 
992     ngx_str_set(&fmt->name, "combined");
993 
994     fmt->flushes = NULL;
995 
996     fmt->ops = ngx_array_create(cf->pool, 16, sizeof(ngx_http_log_op_t));
997     if (fmt->ops == NULL) {
998         return NULL;
999     }
1000 
1001     return conf;
1002 }
1003 
1004 
1005 static void *
1006 ngx_http_log_create_loc_conf(ngx_conf_t *cf)
1007 {
1008     ngx_http_log_loc_conf_t  *conf;
1009 
1010     conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_loc_conf_t));
1011     if (conf == NULL) {
1012         return NULL;
1013     }
1014 
1015     conf->open_file_cache = NGX_CONF_UNSET_PTR;
1016 
1017     return conf;
1018 }
1019 
1020 
1021 static char *
1022 ngx_http_log_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
1023 {
1024     ngx_http_log_loc_conf_t *prev = parent;
1025     ngx_http_log_loc_conf_t *conf = child;
1026 
1027     ngx_http_log_t            *log;
1028     ngx_http_log_fmt_t        *fmt;
1029     ngx_http_log_main_conf_t  *lmcf;
1030 
1031     if (conf->open_file_cache == NGX_CONF_UNSET_PTR) {
1032 
1033         conf->open_file_cache = prev->open_file_cache;
1034         conf->open_file_cache_valid = prev->open_file_cache_valid;
1035         conf->open_file_cache_min_uses = prev->open_file_cache_min_uses;
1036 
1037         if (conf->open_file_cache == NGX_CONF_UNSET_PTR) {
1038             conf->open_file_cache = NULL;
1039         }
1040     }
1041 
1042     if (conf->logs || conf->off) {
1043         return NGX_CONF_OK;
1044     }
1045 
1046     conf->logs = prev->logs;
1047     conf->off = prev->off;
1048 
1049     if (conf->logs || conf->off) {
1050         return NGX_CONF_OK;
1051     }
1052 
1053     conf->logs = ngx_array_create(cf->pool, 2, sizeof(ngx_http_log_t));
1054     if (conf->logs == NULL) {
1055         return NGX_CONF_ERROR;
1056     }
1057 
1058     log = ngx_array_push(conf->logs);
1059     if (log == NULL) {
1060         return NGX_CONF_ERROR;
1061     }
1062 
1063     log->file = ngx_conf_open_file(cf->cycle, &ngx_http_access_log);
1064     if (log->file == NULL) {
1065         return NGX_CONF_ERROR;
1066     }
1067 
1068     log->script = NULL;
1069     log->disk_full_time = 0;
1070     log->error_log_time = 0;
1071 
1072     lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_log_module);
1073     fmt = lmcf->formats.elts;
1074 
1075     /* the default "combined" format */
1076     log->format = &fmt[0];
1077     lmcf->combined_used = 1;
1078 
1079     return NGX_CONF_OK;
1080 }
1081 
1082 
1083 static char *
1084 ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1085 {
1086     ngx_http_log_loc_conf_t *llcf = conf;
1087 
1088     ssize_t                     size;
1089     ngx_int_t                   gzip;
1090     ngx_uint_t                  i, n;
1091     ngx_msec_t                  flush;
1092     ngx_str_t                  *value, name, s;
1093     ngx_http_log_t             *log;
1094     ngx_http_log_buf_t         *buffer;
1095     ngx_http_log_fmt_t         *fmt;
1096     ngx_http_log_main_conf_t   *lmcf;
1097     ngx_http_script_compile_t   sc;
1098 
1099     value = cf->args->elts;
1100 
1101     if (ngx_strcmp(value[1].data, "off") == 0) {
1102         llcf->off = 1;
1103         if (cf->args->nelts == 2) {
1104             return NGX_CONF_OK;
1105         }
1106 
1107         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1108                            "invalid parameter \"%V\"", &value[2]);
1109         return NGX_CONF_ERROR;
1110     }
1111 
1112     if (llcf->logs == NULL) {
1113         llcf->logs = ngx_array_create(cf->pool, 2, sizeof(ngx_http_log_t));
1114         if (llcf->logs == NULL) {
1115             return NGX_CONF_ERROR;
1116         }
1117     }
1118 
1119     lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_log_module);
1120 
1121     log = ngx_array_push(llcf->logs);
1122     if (log == NULL) {
1123         return NGX_CONF_ERROR;
1124     }
1125 
1126     ngx_memzero(log, sizeof(ngx_http_log_t));
1127 
1128     n = ngx_http_script_variables_count(&value[1]);
1129 
1130     if (n == 0) {
1131         log->file = ngx_conf_open_file(cf->cycle, &value[1]);
1132         if (log->file == NULL) {
1133             return NGX_CONF_ERROR;
1134         }
1135 
1136     } else {
1137         if (ngx_conf_full_name(cf->cycle, &value[1], 0) != NGX_OK) {
1138             return NGX_CONF_ERROR;
1139         }
1140 
1141         log->script = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_script_t));
1142         if (log->script == NULL) {
1143             return NGX_CONF_ERROR;
1144         }
1145 
1146         ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
1147 
1148         sc.cf = cf;
1149         sc.source = &value[1];
1150         sc.lengths = &log->script->lengths;
1151         sc.values = &log->script->values;
1152         sc.variables = n;
1153         sc.complete_lengths = 1;
1154         sc.complete_values = 1;
1155 
1156         if (ngx_http_script_compile(&sc) != NGX_OK) {
1157             return NGX_CONF_ERROR;
1158         }
1159     }
1160 
1161     if (cf->args->nelts >= 3) {
1162         name = value[2];
1163 
1164         if (ngx_strcmp(name.data, "combined") == 0) {
1165             lmcf->combined_used = 1;
1166         }
1167 
1168     } else {
1169         ngx_str_set(&name, "combined");
1170         lmcf->combined_used = 1;
1171     }
1172 
1173     fmt = lmcf->formats.elts;
1174     for (i = 0; i < lmcf->formats.nelts; i++) {
1175         if (fmt[i].name.len == name.len
1176             && ngx_strcasecmp(fmt[i].name.data, name.data) == 0)
1177         {
1178             log->format = &fmt[i];
1179             break;
1180         }
1181     }
1182 
1183     if (log->format == NULL) {
1184         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1185                            "unknown log format \"%V\"", &name);
1186         return NGX_CONF_ERROR;
1187     }
1188 
1189     size = 0;
1190     flush = 0;
1191     gzip = 0;
1192 
1193     for (i = 3; i < cf->args->nelts; i++) {
1194 
1195         if (ngx_strncmp(value[i].data, "buffer=", 7) == 0) {
1196             s.len = value[i].len - 7;
1197             s.data = value[i].data + 7;
1198 
1199             size = ngx_parse_size(&s);
1200 
1201             if (size == NGX_ERROR || size == 0) {
1202                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1203                                    "invalid buffer size \"%V\"", &s);
1204                 return NGX_CONF_ERROR;
1205             }
1206 
1207             continue;
1208         }
1209 
1210         if (ngx_strncmp(value[i].data, "flush=", 6) == 0) {
1211             s.len = value[i].len - 6;
1212             s.data = value[i].data + 6;
1213 
1214             flush = ngx_parse_time(&s, 0);
1215 
1216             if (flush == (ngx_msec_t) NGX_ERROR || flush == 0) {
1217                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1218                                    "invalid flush time \"%V\"", &s);
1219                 return NGX_CONF_ERROR;
1220             }
1221 
1222             continue;
1223         }
1224 
1225         if (ngx_strncmp(value[i].data, "gzip", 4) == 0
1226             && (value[i].len == 4 || value[i].data[4] == '='))
1227         {
1228 #if (NGX_ZLIB)
1229             if (size == 0) {
1230                 size = 64 * 1024;
1231             }
1232 
1233             if (value[i].len == 4) {
1234                 gzip = Z_BEST_SPEED;
1235                 continue;
1236             }
1237 
1238             s.len = value[i].len - 5;
1239             s.data = value[i].data + 5;
1240 
1241             gzip = ngx_atoi(s.data, s.len);
1242 
1243             if (gzip < 1 || gzip > 9) {
1244                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1245                                    "invalid compression level \"%V\"", &s);
1246                 return NGX_CONF_ERROR;
1247             }
1248 
1249             continue;
1250 
1251 #else
1252             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1253                                "nginx was built without zlib support");
1254             return NGX_CONF_ERROR;
1255 #endif
1256         }
1257 
1258         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1259                            "invalid parameter \"%V\"", &value[i]);
1260         return NGX_CONF_ERROR;
1261     }
1262 
1263     if (flush && size == 0) {
1264         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1265                            "no buffer is defined for access_log \"%V\"",
1266                            &value[1]);
1267         return NGX_CONF_ERROR;
1268     }
1269 
1270     if (size) {
1271 
1272         if (log->script) {
1273             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1274                                "buffered logs cannot have variables in name");
1275             return NGX_CONF_ERROR;
1276         }
1277 
1278         if (log->file->data) {
1279             buffer = log->file->data;
1280 
1281             if (buffer->last - buffer->start != size
1282                 || buffer->flush != flush
1283                 || buffer->gzip != gzip)
1284             {
1285                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1286                                    "access_log \"%V\" already defined "
1287                                    "with conflicting parameters",
1288                                    &value[1]);
1289                 return NGX_CONF_ERROR;
1290             }
1291 
1292             return NGX_CONF_OK;
1293         }
1294 
1295         buffer = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_buf_t));
1296         if (buffer == NULL) {
1297             return NGX_CONF_ERROR;
1298         }
1299 
1300         buffer->start = ngx_pnalloc(cf->pool, size);
1301         if (buffer->start == NULL) {
1302             return NGX_CONF_ERROR;
1303         }
1304 
1305         buffer->pos = buffer->start;
1306         buffer->last = buffer->start + size;
1307 
1308         if (flush) {
1309             buffer->event = ngx_pcalloc(cf->pool, sizeof(ngx_event_t));
1310             if (buffer->event == NULL) {
1311                 return NGX_CONF_ERROR;
1312             }
1313 
1314             buffer->event->data = log->file;
1315             buffer->event->handler = ngx_http_log_flush_handler;
1316             buffer->event->log = &cf->cycle->new_log;
1317 
1318             buffer->flush = flush;
1319         }
1320 
1321         buffer->gzip = gzip;
1322 
1323         log->file->flush = ngx_http_log_flush;
1324         log->file->data = buffer;
1325     }
1326 
1327     return NGX_CONF_OK;
1328 }
1329 
1330 
1331 static char *
1332 ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1333 {
1334     ngx_http_log_main_conf_t *lmcf = conf;
1335 
1336     ngx_str_t           *value;
1337     ngx_uint_t           i;
1338     ngx_http_log_fmt_t  *fmt;
1339 
1340     if (cf->cmd_type != NGX_HTTP_MAIN_CONF) {
1341         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1342                            "the \"log_format\" directive may be used "
1343                            "only on \"http\" level");
1344     }
1345 
1346     value = cf->args->elts;
1347 
1348     fmt = lmcf->formats.elts;
1349     for (i = 0; i < lmcf->formats.nelts; i++) {
1350         if (fmt[i].name.len == value[1].len
1351             && ngx_strcmp(fmt[i].name.data, value[1].data) == 0)
1352         {
1353             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1354                                "duplicate \"log_format\" name \"%V\"",
1355                                &value[1]);
1356             return NGX_CONF_ERROR;
1357         }
1358     }
1359 
1360     fmt = ngx_array_push(&lmcf->formats);
1361     if (fmt == NULL) {
1362         return NGX_CONF_ERROR;
1363     }
1364 
1365     fmt->name = value[1];
1366 
1367     fmt->flushes = ngx_array_create(cf->pool, 4, sizeof(ngx_int_t));
1368     if (fmt->flushes == NULL) {
1369         return NGX_CONF_ERROR;
1370     }
1371 
1372     fmt->ops = ngx_array_create(cf->pool, 16, sizeof(ngx_http_log_op_t));
1373     if (fmt->ops == NULL) {
1374         return NGX_CONF_ERROR;
1375     }
1376 
1377     return ngx_http_log_compile_format(cf, fmt->flushes, fmt->ops, cf->args, 2);
1378 }
1379 
1380 
1381 static char *
1382 ngx_http_log_compile_format(ngx_conf_t *cf, ngx_array_t *flushes,
1383     ngx_array_t *ops, ngx_array_t *args, ngx_uint_t s)
1384 {
1385     u_char              *data, *p, ch;
1386     size_t               i, len;
1387     ngx_str_t           *value, var;
1388     ngx_int_t           *flush;
1389     ngx_uint_t           bracket;
1390     ngx_http_log_op_t   *op;
1391     ngx_http_log_var_t  *v;
1392 
1393     value = args->elts;
1394 
1395     for ( /* void */ ; s < args->nelts; s++) {
1396 
1397         i = 0;
1398 
1399         while (i < value[s].len) {
1400 
1401             op = ngx_array_push(ops);
1402             if (op == NULL) {
1403                 return NGX_CONF_ERROR;
1404             }
1405 
1406             data = &value[s].data[i];
1407 
1408             if (value[s].data[i] == '$') {
1409 
1410                 if (++i == value[s].len) {
1411                     goto invalid;
1412                 }
1413 
1414                 if (value[s].data[i] == '{') {
1415                     bracket = 1;
1416 
1417                     if (++i == value[s].len) {
1418                         goto invalid;
1419                     }
1420 
1421                     var.data = &value[s].data[i];
1422 
1423                 } else {
1424                     bracket = 0;
1425                     var.data = &value[s].data[i];
1426                 }
1427 
1428                 for (var.len = 0; i < value[s].len; i++, var.len++) {
1429                     ch = value[s].data[i];
1430 
1431                     if (ch == '}' && bracket) {
1432                         i++;
1433                         bracket = 0;
1434                         break;
1435                     }
1436 
1437                     if ((ch >= 'A' && ch <= 'Z')
1438                         || (ch >= 'a' && ch <= 'z')
1439                         || (ch >= '' && ch <= '9')
1440                         || ch == '_')
1441                     {
1442                         continue;
1443                     }
1444 
1445                     break;
1446                 }
1447 
1448                 if (bracket) {
1449                     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1450                                        "the closing bracket in \"%V\" "
1451                                        "variable is missing", &var);
1452                     return NGX_CONF_ERROR;
1453                 }
1454 
1455                 if (var.len == 0) {
1456                     goto invalid;
1457                 }
1458 
1459                 for (v = ngx_http_log_vars; v->name.len; v++) {
1460 
1461                     if (v->name.len == var.len
1462                         && ngx_strncmp(v->name.data, var.data, var.len) == 0)
1463                     {
1464                         op->len = v->len;
1465                         op->getlen = NULL;
1466                         op->run = v->run;
1467                         op->data = 0;
1468 
1469                         goto found;
1470                     }
1471                 }
1472 
1473                 if (ngx_http_log_variable_compile(cf, op, &var) != NGX_OK) {
1474                     return NGX_CONF_ERROR;
1475                 }
1476 
1477                 if (flushes) {
1478 
1479                     flush = ngx_array_push(flushes);
1480                     if (flush == NULL) {
1481                         return NGX_CONF_ERROR;
1482                     }
1483 
1484                     *flush = op->data; /* variable index */
1485                 }
1486 
1487             found:
1488 
1489                 continue;
1490             }
1491 
1492             i++;
1493 
1494             while (i < value[s].len && value[s].data[i] != '$') {
1495                 i++;
1496             }
1497 
1498             len = &value[s].data[i] - data;
1499 
1500             if (len) {
1501 
1502                 op->len = len;
1503                 op->getlen = NULL;
1504 
1505                 if (len <= sizeof(uintptr_t)) {
1506                     op->run = ngx_http_log_copy_short;
1507                     op->data = 0;
1508 
1509                     while (len--) {
1510                         op->data <<= 8;
1511                         op->data |= data[len];
1512                     }
1513 
1514                 } else {
1515                     op->run = ngx_http_log_copy_long;
1516 
1517                     p = ngx_pnalloc(cf->pool, len);
1518                     if (p == NULL) {
1519                         return NGX_CONF_ERROR;
1520                     }
1521 
1522                     ngx_memcpy(p, data, len);
1523                     op->data = (uintptr_t) p;
1524                 }
1525             }
1526         }
1527     }
1528 
1529     return NGX_CONF_OK;
1530 
1531 invalid:
1532 
1533     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%s\"", data);
1534 
1535     return NGX_CONF_ERROR;
1536 }
1537 
1538 
1539 static char *
1540 ngx_http_log_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1541 {
1542     ngx_http_log_loc_conf_t *llcf = conf;
1543 
1544     time_t       inactive, valid;
1545     ngx_str_t   *value, s;
1546     ngx_int_t    max, min_uses;
1547     ngx_uint_t   i;
1548 
1549     if (llcf->open_file_cache != NGX_CONF_UNSET_PTR) {
1550         return "is duplicate";
1551     }
1552 
1553     value = cf->args->elts;
1554 
1555     max = 0;
1556     inactive = 10;
1557     valid = 60;
1558     min_uses = 1;
1559 
1560     for (i = 1; i < cf->args->nelts; i++) {
1561 
1562         if (ngx_strncmp(value[i].data, "max=", 4) == 0) {
1563 
1564             max = ngx_atoi(value[i].data + 4, value[i].len - 4);
1565             if (max == NGX_ERROR) {
1566                 goto failed;
1567             }
1568 
1569             continue;
1570         }
1571 
1572         if (ngx_strncmp(value[i].data, "inactive=", 9) == 0) {
1573 
1574             s.len = value[i].len - 9;
1575             s.data = value[i].data + 9;
1576 
1577             inactive = ngx_parse_time(&s, 1);
1578             if (inactive == (time_t) NGX_ERROR) {
1579                 goto failed;
1580             }
1581 
1582             continue;
1583         }
1584 
1585         if (ngx_strncmp(value[i].data, "min_uses=", 9) == 0) {
1586 
1587             min_uses = ngx_atoi(value[i].data + 9, value[i].len - 9);
1588             if (min_uses == NGX_ERROR) {
1589                 goto failed;
1590             }
1591 
1592             continue;
1593         }
1594 
1595         if (ngx_strncmp(value[i].data, "valid=", 6) == 0) {
1596 
1597             s.len = value[i].len - 6;
1598             s.data = value[i].data + 6;
1599 
1600             valid = ngx_parse_time(&s, 1);
1601             if (valid == (time_t) NGX_ERROR) {
1602                 goto failed;
1603             }
1604 
1605             continue;
1606         }
1607 
1608         if (ngx_strcmp(value[i].data, "off") == 0) {
1609 
1610             llcf->open_file_cache = NULL;
1611 
1612             continue;
1613         }
1614 
1615     failed:
1616 
1617         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1618                            "invalid \"open_log_file_cache\" parameter \"%V\"",
1619                            &value[i]);
1620         return NGX_CONF_ERROR;
1621     }
1622 
1623     if (llcf->open_file_cache == NULL) {
1624         return NGX_CONF_OK;
1625     }
1626 
1627     if (max == 0) {
1628         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1629                         "\"open_log_file_cache\" must have \"max\" parameter");
1630         return NGX_CONF_ERROR;
1631     }
1632 
1633     llcf->open_file_cache = ngx_open_file_cache_init(cf->pool, max, inactive);
1634 
1635     if (llcf->open_file_cache) {
1636 
1637         llcf->open_file_cache_valid = valid;
1638         llcf->open_file_cache_min_uses = min_uses;
1639 
1640         return NGX_CONF_OK;
1641     }
1642 
1643     return NGX_CONF_ERROR;
1644 }
1645 
1646 
1647 static ngx_int_t
1648 ngx_http_log_init(ngx_conf_t *cf)
1649 {
1650     ngx_str_t                  *value;
1651     ngx_array_t                 a;
1652     ngx_http_handler_pt        *h;
1653     ngx_http_log_fmt_t         *fmt;
1654     ngx_http_log_main_conf_t   *lmcf;
1655     ngx_http_core_main_conf_t  *cmcf;
1656 
1657     lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_log_module);
1658 
1659     if (lmcf->combined_used) {
1660         if (ngx_array_init(&a, cf->pool, 1, sizeof(ngx_str_t)) != NGX_OK) {
1661             return NGX_ERROR;
1662         }
1663 
1664         value = ngx_array_push(&a);
1665         if (value == NULL) {
1666             return NGX_ERROR;
1667         }
1668 
1669         *value = ngx_http_combined_fmt;
1670         fmt = lmcf->formats.elts;
1671 
1672         if (ngx_http_log_compile_format(cf, NULL, fmt->ops, &a, 0)
1673             != NGX_CONF_OK)
1674         {
1675             return NGX_ERROR;
1676         }
1677     }
1678 
1679     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
1680 
1681     h = ngx_array_push(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers);
1682     if (h == NULL) {
1683         return NGX_ERROR;
1684     }
1685 
1686     *h = ngx_http_log_handler;
1687 
1688     return NGX_OK;
1689 }
1690 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.