3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
8 #include <ngx_config.h>
17 typedef struct ngx_http_log_op_s ngx_http_log_op_t
;
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
);
22 typedef size_t (*ngx_http_log_op_getlen_pt
) (ngx_http_request_t
*r
,
26 struct ngx_http_log_op_s
{
28 ngx_http_log_op_getlen_pt getlen
;
29 ngx_http_log_op_run_pt run
;
37 ngx_array_t
*ops
; /* array of ngx_http_log_op_t */
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
;
61 } ngx_http_log_script_t
;
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
;
74 ngx_array_t
*logs
; /* array of ngx_http_log_t */
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
;
80 ngx_uint_t off
; /* unsigned off:1 */
81 } ngx_http_log_loc_conf_t
;
87 ngx_http_log_op_run_pt run
;
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
);
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
);
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
);
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
);
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
);
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
,
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
);
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
,
139 static char *ngx_http_log_set_log(ngx_conf_t
*cf
, ngx_command_t
*cmd
,
141 static char *ngx_http_log_set_format(ngx_conf_t
*cf
, ngx_command_t
*cmd
,
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
,
147 static ngx_int_t
ngx_http_log_init(ngx_conf_t
*cf
);
150 static ngx_command_t ngx_http_log_commands
[] = {
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
,
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
,
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
,
178 static ngx_http_module_t ngx_http_log_module_ctx
= {
179 NULL
, /* preconfiguration */
180 ngx_http_log_init
, /* postconfiguration */
182 ngx_http_log_create_main_conf
, /* create main configuration */
183 NULL
, /* init main configuration */
185 NULL
, /* create server configuration */
186 NULL
, /* merge server configuration */
188 ngx_http_log_create_loc_conf
, /* create location configuration */
189 ngx_http_log_merge_loc_conf
/* merge location configuration */
193 ngx_module_t ngx_http_log_module
= {
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
209 static ngx_str_t ngx_http_access_log
= ngx_string(NGX_HTTP_LOG_PATH
);
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\"");
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,
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
},
234 { ngx_null_string
, 0, NULL
}
239 ngx_http_log_handler(ngx_http_request_t
*r
)
245 ngx_http_log_op_t
*op
;
246 ngx_http_log_buf_t
*buffer
;
247 ngx_http_log_loc_conf_t
*lcf
;
249 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
252 lcf
= ngx_http_get_module_loc_conf(r
, ngx_http_log_module
);
258 log
= lcf
->logs
->elts
;
259 for (l
= 0; l
< lcf
->logs
->nelts
; l
++) {
261 if (ngx_time() == log
[l
].disk_full_time
) {
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
272 ngx_http_script_flush_no_cacheable_variables(r
, log
[l
].format
->flushes
);
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
);
285 len
+= NGX_LINEFEED_SIZE
;
287 buffer
= log
[l
].file
? log
[l
].file
->data
: NULL
;
291 if (len
> (size_t) (buffer
->last
- buffer
->pos
)) {
293 ngx_http_log_write(r
, &log
[l
], buffer
->start
,
294 buffer
->pos
- buffer
->start
);
296 buffer
->pos
= buffer
->start
;
299 if (len
<= (size_t) (buffer
->last
- buffer
->pos
)) {
303 if (buffer
->event
&& p
== buffer
->start
) {
304 ngx_add_timer(buffer
->event
, buffer
->flush
);
307 for (i
= 0; i
< log
[l
].format
->ops
->nelts
; i
++) {
308 p
= op
[i
].run(r
, p
, &op
[i
]);
318 if (buffer
->event
&& buffer
->event
->timer_set
) {
319 ngx_del_timer(buffer
->event
);
323 line
= ngx_pnalloc(r
->pool
, len
);
330 for (i
= 0; i
< log
[l
].format
->ops
->nelts
; i
++) {
331 p
= op
[i
].run(r
, p
, &op
[i
]);
336 ngx_http_log_write(r
, &log
[l
], line
, p
- line
);
344 ngx_http_log_write(ngx_http_request_t
*r
, ngx_http_log_t
*log
, u_char
*buf
,
352 ngx_http_log_buf_t
*buffer
;
355 if (log
->script
== NULL
) {
356 name
= log
->file
->name
.data
;
359 buffer
= log
->file
->data
;
361 if (buffer
&& buffer
->gzip
) {
362 n
= ngx_http_log_gzip(log
->file
->fd
, buf
, len
, buffer
->gzip
,
365 n
= ngx_write_fd(log
->file
->fd
, buf
, len
);
368 n
= ngx_write_fd(log
->file
->fd
, buf
, len
);
373 n
= ngx_http_log_script_write(r
, log
->script
, &name
, buf
, len
);
376 if (n
== (ssize_t
) len
) {
385 if (err
== NGX_ENOSPC
) {
386 log
->disk_full_time
= now
;
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
);
393 log
->error_log_time
= now
;
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",
404 log
->error_log_time
= now
;
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
)
416 ngx_open_file_info_t of
;
417 ngx_http_log_loc_conf_t
*llcf
;
418 ngx_http_core_loc_conf_t
*clcf
;
420 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
422 if (!r
->root_tested
) {
424 /* test root directory existence */
426 if (ngx_http_map_uri_to_path(r
, &path
, &root
, 0) == NULL
) {
427 /* simulate successful logging */
431 path
.data
[root
] = '\0';
433 ngx_memzero(&of
, sizeof(ngx_open_file_info_t
));
435 of
.valid
= clcf
->open_file_cache_valid
;
436 of
.min_uses
= clcf
->open_file_cache_min_uses
;
439 of
.errors
= clcf
->open_file_cache_errors
;
440 of
.events
= clcf
->open_file_cache_events
;
442 if (ngx_http_set_disable_symlinks(r
, clcf
, &path
, &of
) != NGX_OK
) {
443 /* simulate successful logging */
447 if (ngx_open_cached_file(clcf
->open_file_cache
, &path
, &of
, r
->pool
)
451 /* simulate successful logging */
455 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, of
.err
,
456 "testing \"%s\" existence failed", path
.data
);
458 /* simulate successful logging */
463 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, NGX_ENOTDIR
,
464 "testing \"%s\" existence failed", path
.data
);
466 /* simulate successful logging */
471 if (ngx_http_script_run(r
, &log
, script
->lengths
->elts
, 1,
472 script
->values
->elts
)
475 /* simulate successful logging */
479 log
.data
[log
.len
- 1] = '\0';
482 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
483 "http log \"%s\"", log
.data
);
485 llcf
= ngx_http_get_module_loc_conf(r
, ngx_http_log_module
);
487 ngx_memzero(&of
, sizeof(ngx_open_file_info_t
));
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
;
494 if (ngx_http_set_disable_symlinks(r
, clcf
, &log
, &of
) != NGX_OK
) {
495 /* simulate successful logging */
499 if (ngx_open_cached_file(llcf
->open_file_cache
, &log
, &of
, r
->pool
)
502 ngx_log_error(NGX_LOG_CRIT
, r
->connection
->log
, ngx_errno
,
503 "%s \"%s\" failed", of
.failed
, log
.data
);
504 /* simulate successful logging */
508 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
509 "http log #%d", of
.fd
);
511 n
= ngx_write_fd(of
.fd
, buf
, len
);
520 ngx_http_log_gzip(ngx_fd_t fd
, u_char
*buf
, size_t len
, ngx_int_t level
,
523 int rc
, wbits
, memlevel
;
532 memlevel
= MAX_MEM_LEVEL
- 1;
534 while ((ssize_t
) len
< ((1 << (wbits
- 1)) - 262)) {
540 * This is a formula from deflateBound() for conservative upper bound of
541 * compressed data plus 18 bytes of gzip wrapper.
544 size
= len
+ ((len
+ 7) >> 3) + ((len
+ 63) >> 6) + 5 + 18;
546 ngx_memzero(&zstream
, sizeof(z_stream
));
548 pool
= ngx_create_pool(256, log
);
550 /* simulate successful logging */
556 zstream
.zalloc
= ngx_http_log_gzip_alloc
;
557 zstream
.zfree
= ngx_http_log_gzip_free
;
558 zstream
.opaque
= pool
;
560 out
= ngx_pnalloc(pool
, size
);
565 zstream
.next_in
= buf
;
566 zstream
.avail_in
= len
;
567 zstream
.next_out
= out
;
568 zstream
.avail_out
= size
;
570 rc
= deflateInit2(&zstream
, (int) level
, Z_DEFLATED
, wbits
+ 16, memlevel
,
574 ngx_log_error(NGX_LOG_ALERT
, log
, 0, "deflateInit2() failed: %d", rc
);
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
);
583 rc
= deflate(&zstream
, Z_FINISH
);
585 if (rc
!= Z_STREAM_END
) {
586 ngx_log_error(NGX_LOG_ALERT
, log
, 0,
587 "deflate(Z_FINISH) failed: %d", rc
);
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
,
597 size
-= zstream
.avail_out
;
599 rc
= deflateEnd(&zstream
);
602 ngx_log_error(NGX_LOG_ALERT
, log
, 0, "deflateEnd() failed: %d", rc
);
606 n
= ngx_write_fd(fd
, out
, size
);
608 if (n
!= (ssize_t
) size
) {
609 err
= (n
== -1) ? ngx_errno
: 0;
611 ngx_destroy_pool(pool
);
619 ngx_destroy_pool(pool
);
621 /* simulate successful logging */
627 ngx_http_log_gzip_alloc(void *opaque
, u_int items
, u_int size
)
629 ngx_pool_t
*pool
= opaque
;
631 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, pool
->log
, 0,
632 "gzip alloc: n:%ud s:%ud", items
, size
);
634 return ngx_palloc(pool
, items
* size
);
639 ngx_http_log_gzip_free(void *opaque
, void *address
)
642 ngx_pool_t
*pool
= opaque
;
644 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, pool
->log
, 0, "gzip free: %p", address
);
652 ngx_http_log_flush(ngx_open_file_t
*file
, ngx_log_t
*log
)
656 ngx_http_log_buf_t
*buffer
;
660 len
= buffer
->pos
- buffer
->start
;
668 n
= ngx_http_log_gzip(file
->fd
, buffer
->start
, len
, buffer
->gzip
, log
);
670 n
= ngx_write_fd(file
->fd
, buffer
->start
, len
);
673 n
= ngx_write_fd(file
->fd
, buffer
->start
, len
);
677 ngx_log_error(NGX_LOG_ALERT
, log
, ngx_errno
,
678 ngx_write_fd_n
" to \"%s\" failed",
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
);
687 buffer
->pos
= buffer
->start
;
689 if (buffer
->event
&& buffer
->event
->timer_set
) {
690 ngx_del_timer(buffer
->event
);
696 ngx_http_log_flush_handler(ngx_event_t
*ev
)
698 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, ev
->log
, 0,
699 "http log buffer flush handler");
701 ngx_http_log_flush(ev
->data
, ev
->log
);
706 ngx_http_log_copy_short(ngx_http_request_t
*r
, u_char
*buf
,
707 ngx_http_log_op_t
*op
)
716 *buf
++ = (u_char
) (data
& 0xff);
725 ngx_http_log_copy_long(ngx_http_request_t
*r
, u_char
*buf
,
726 ngx_http_log_op_t
*op
)
728 return ngx_cpymem(buf
, (u_char
*) op
->data
, op
->len
);
733 ngx_http_log_pipe(ngx_http_request_t
*r
, u_char
*buf
, ngx_http_log_op_t
*op
)
746 ngx_http_log_time(ngx_http_request_t
*r
, u_char
*buf
, ngx_http_log_op_t
*op
)
748 return ngx_cpymem(buf
, ngx_cached_http_log_time
.data
,
749 ngx_cached_http_log_time
.len
);
753 ngx_http_log_iso8601(ngx_http_request_t
*r
, u_char
*buf
, ngx_http_log_op_t
*op
)
755 return ngx_cpymem(buf
, ngx_cached_http_log_iso8601
.data
,
756 ngx_cached_http_log_iso8601
.len
);
760 ngx_http_log_msec(ngx_http_request_t
*r
, u_char
*buf
, ngx_http_log_op_t
*op
)
764 tp
= ngx_timeofday();
766 return ngx_sprintf(buf
, "%T.%03M", tp
->sec
, tp
->msec
);
771 ngx_http_log_request_time(ngx_http_request_t
*r
, u_char
*buf
,
772 ngx_http_log_op_t
*op
)
777 tp
= ngx_timeofday();
779 ms
= (ngx_msec_int_t
)
780 ((tp
->sec
- r
->start_sec
) * 1000 + (tp
->msec
- r
->start_msec
));
783 return ngx_sprintf(buf
, "%T.%03M", ms
/ 1000, ms
% 1000);
788 ngx_http_log_status(ngx_http_request_t
*r
, u_char
*buf
, ngx_http_log_op_t
*op
)
793 status
= r
->err_status
;
795 } else if (r
->headers_out
.status
) {
796 status
= r
->headers_out
.status
;
798 } else if (r
->http_version
== NGX_HTTP_VERSION_9
) {
805 return ngx_sprintf(buf
, "%03ui", status
);
810 ngx_http_log_bytes_sent(ngx_http_request_t
*r
, u_char
*buf
,
811 ngx_http_log_op_t
*op
)
813 return ngx_sprintf(buf
, "%O", r
->connection
->sent
);
818 * although there is a real $body_bytes_sent variable,
819 * this log operation code function is more optimized for logging
823 ngx_http_log_body_bytes_sent(ngx_http_request_t
*r
, u_char
*buf
,
824 ngx_http_log_op_t
*op
)
828 length
= r
->connection
->sent
- r
->header_size
;
831 return ngx_sprintf(buf
, "%O", length
);
841 ngx_http_log_request_length(ngx_http_request_t
*r
, u_char
*buf
,
842 ngx_http_log_op_t
*op
)
844 return ngx_sprintf(buf
, "%O", r
->request_length
);
849 ngx_http_log_variable_compile(ngx_conf_t
*cf
, ngx_http_log_op_t
*op
,
854 index
= ngx_http_get_variable_index(cf
, value
);
855 if (index
== NGX_ERROR
) {
860 op
->getlen
= ngx_http_log_variable_getlen
;
861 op
->run
= ngx_http_log_variable
;
869 ngx_http_log_variable_getlen(ngx_http_request_t
*r
, uintptr_t data
)
872 ngx_http_variable_value_t
*value
;
874 value
= ngx_http_get_indexed_variable(r
, data
);
876 if (value
== NULL
|| value
->not_found
) {
880 len
= ngx_http_log_escape(NULL
, value
->data
, value
->len
);
882 value
->escape
= len
? 1 : 0;
884 return value
->len
+ len
* 3;
889 ngx_http_log_variable(ngx_http_request_t
*r
, u_char
*buf
, ngx_http_log_op_t
*op
)
891 ngx_http_variable_value_t
*value
;
893 value
= ngx_http_get_indexed_variable(r
, op
->data
);
895 if (value
== NULL
|| value
->not_found
) {
900 if (value
->escape
== 0) {
901 return ngx_cpymem(buf
, value
->data
, value
->len
);
904 return (u_char
*) ngx_http_log_escape(buf
, value
->data
, value
->len
);
910 ngx_http_log_escape(u_char
*dst
, u_char
*src
, size_t size
)
913 static u_char hex
[] = "0123456789ABCDEF";
915 static uint32_t escape
[] = {
916 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
918 /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
919 0x00000004, /* 0000 0000 0000 0000 0000 0000 0000 0100 */
921 /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
922 0x10000000, /* 0001 0000 0000 0000 0000 0000 0000 0000 */
924 /* ~}| {zyx wvut srqp onml kjih gfed cba` */
925 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */
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 */
936 /* find the number of the characters to be escaped */
941 if (escape
[*src
>> 5] & (1 << (*src
& 0x1f))) {
948 return (uintptr_t) n
;
952 if (escape
[*src
>> 5] & (1 << (*src
& 0x1f))) {
955 *dst
++ = hex
[*src
>> 4];
956 *dst
++ = hex
[*src
& 0xf];
965 return (uintptr_t) dst
;
970 ngx_http_log_create_main_conf(ngx_conf_t
*cf
)
972 ngx_http_log_main_conf_t
*conf
;
974 ngx_http_log_fmt_t
*fmt
;
976 conf
= ngx_pcalloc(cf
->pool
, sizeof(ngx_http_log_main_conf_t
));
981 if (ngx_array_init(&conf
->formats
, cf
->pool
, 4, sizeof(ngx_http_log_fmt_t
))
987 fmt
= ngx_array_push(&conf
->formats
);
992 ngx_str_set(&fmt
->name
, "combined");
996 fmt
->ops
= ngx_array_create(cf
->pool
, 16, sizeof(ngx_http_log_op_t
));
997 if (fmt
->ops
== NULL
) {
1006 ngx_http_log_create_loc_conf(ngx_conf_t
*cf
)
1008 ngx_http_log_loc_conf_t
*conf
;
1010 conf
= ngx_pcalloc(cf
->pool
, sizeof(ngx_http_log_loc_conf_t
));
1015 conf
->open_file_cache
= NGX_CONF_UNSET_PTR
;
1022 ngx_http_log_merge_loc_conf(ngx_conf_t
*cf
, void *parent
, void *child
)
1024 ngx_http_log_loc_conf_t
*prev
= parent
;
1025 ngx_http_log_loc_conf_t
*conf
= child
;
1027 ngx_http_log_t
*log
;
1028 ngx_http_log_fmt_t
*fmt
;
1029 ngx_http_log_main_conf_t
*lmcf
;
1031 if (conf
->open_file_cache
== NGX_CONF_UNSET_PTR
) {
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
;
1037 if (conf
->open_file_cache
== NGX_CONF_UNSET_PTR
) {
1038 conf
->open_file_cache
= NULL
;
1042 if (conf
->logs
|| conf
->off
) {
1046 conf
->logs
= prev
->logs
;
1047 conf
->off
= prev
->off
;
1049 if (conf
->logs
|| conf
->off
) {
1053 conf
->logs
= ngx_array_create(cf
->pool
, 2, sizeof(ngx_http_log_t
));
1054 if (conf
->logs
== NULL
) {
1055 return NGX_CONF_ERROR
;
1058 log
= ngx_array_push(conf
->logs
);
1060 return NGX_CONF_ERROR
;
1063 log
->file
= ngx_conf_open_file(cf
->cycle
, &ngx_http_access_log
);
1064 if (log
->file
== NULL
) {
1065 return NGX_CONF_ERROR
;
1069 log
->disk_full_time
= 0;
1070 log
->error_log_time
= 0;
1072 lmcf
= ngx_http_conf_get_module_main_conf(cf
, ngx_http_log_module
);
1073 fmt
= lmcf
->formats
.elts
;
1075 /* the default "combined" format */
1076 log
->format
= &fmt
[0];
1077 lmcf
->combined_used
= 1;
1084 ngx_http_log_set_log(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
1086 ngx_http_log_loc_conf_t
*llcf
= conf
;
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
;
1099 value
= cf
->args
->elts
;
1101 if (ngx_strcmp(value
[1].data
, "off") == 0) {
1103 if (cf
->args
->nelts
== 2) {
1107 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
1108 "invalid parameter \"%V\"", &value
[2]);
1109 return NGX_CONF_ERROR
;
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
;
1119 lmcf
= ngx_http_conf_get_module_main_conf(cf
, ngx_http_log_module
);
1121 log
= ngx_array_push(llcf
->logs
);
1123 return NGX_CONF_ERROR
;
1126 ngx_memzero(log
, sizeof(ngx_http_log_t
));
1128 n
= ngx_http_script_variables_count(&value
[1]);
1131 log
->file
= ngx_conf_open_file(cf
->cycle
, &value
[1]);
1132 if (log
->file
== NULL
) {
1133 return NGX_CONF_ERROR
;
1137 if (ngx_conf_full_name(cf
->cycle
, &value
[1], 0) != NGX_OK
) {
1138 return NGX_CONF_ERROR
;
1141 log
->script
= ngx_pcalloc(cf
->pool
, sizeof(ngx_http_log_script_t
));
1142 if (log
->script
== NULL
) {
1143 return NGX_CONF_ERROR
;
1146 ngx_memzero(&sc
, sizeof(ngx_http_script_compile_t
));
1149 sc
.source
= &value
[1];
1150 sc
.lengths
= &log
->script
->lengths
;
1151 sc
.values
= &log
->script
->values
;
1153 sc
.complete_lengths
= 1;
1154 sc
.complete_values
= 1;
1156 if (ngx_http_script_compile(&sc
) != NGX_OK
) {
1157 return NGX_CONF_ERROR
;
1161 if (cf
->args
->nelts
>= 3) {
1164 if (ngx_strcmp(name
.data
, "combined") == 0) {
1165 lmcf
->combined_used
= 1;
1169 ngx_str_set(&name
, "combined");
1170 lmcf
->combined_used
= 1;
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)
1178 log
->format
= &fmt
[i
];
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
;
1193 for (i
= 3; i
< cf
->args
->nelts
; i
++) {
1195 if (ngx_strncmp(value
[i
].data
, "buffer=", 7) == 0) {
1196 s
.len
= value
[i
].len
- 7;
1197 s
.data
= value
[i
].data
+ 7;
1199 size
= ngx_parse_size(&s
);
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
;
1210 if (ngx_strncmp(value
[i
].data
, "flush=", 6) == 0) {
1211 s
.len
= value
[i
].len
- 6;
1212 s
.data
= value
[i
].data
+ 6;
1214 flush
= ngx_parse_time(&s
, 0);
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
;
1225 if (ngx_strncmp(value
[i
].data
, "gzip", 4) == 0
1226 && (value
[i
].len
== 4 || value
[i
].data
[4] == '='))
1233 if (value
[i
].len
== 4) {
1234 gzip
= Z_BEST_SPEED
;
1238 s
.len
= value
[i
].len
- 5;
1239 s
.data
= value
[i
].data
+ 5;
1241 gzip
= ngx_atoi(s
.data
, s
.len
);
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
;
1252 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
1253 "nginx was built without zlib support");
1254 return NGX_CONF_ERROR
;
1258 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
1259 "invalid parameter \"%V\"", &value
[i
]);
1260 return NGX_CONF_ERROR
;
1263 if (flush
&& size
== 0) {
1264 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
1265 "no buffer is defined for access_log \"%V\"",
1267 return NGX_CONF_ERROR
;
1273 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
1274 "buffered logs cannot have variables in name");
1275 return NGX_CONF_ERROR
;
1278 if (log
->file
->data
) {
1279 buffer
= log
->file
->data
;
1281 if (buffer
->last
- buffer
->start
!= size
1282 || buffer
->flush
!= flush
1283 || buffer
->gzip
!= gzip
)
1285 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
1286 "access_log \"%V\" already defined "
1287 "with conflicting parameters",
1289 return NGX_CONF_ERROR
;
1295 buffer
= ngx_pcalloc(cf
->pool
, sizeof(ngx_http_log_buf_t
));
1296 if (buffer
== NULL
) {
1297 return NGX_CONF_ERROR
;
1300 buffer
->start
= ngx_pnalloc(cf
->pool
, size
);
1301 if (buffer
->start
== NULL
) {
1302 return NGX_CONF_ERROR
;
1305 buffer
->pos
= buffer
->start
;
1306 buffer
->last
= buffer
->start
+ size
;
1309 buffer
->event
= ngx_pcalloc(cf
->pool
, sizeof(ngx_event_t
));
1310 if (buffer
->event
== NULL
) {
1311 return NGX_CONF_ERROR
;
1314 buffer
->event
->data
= log
->file
;
1315 buffer
->event
->handler
= ngx_http_log_flush_handler
;
1316 buffer
->event
->log
= &cf
->cycle
->new_log
;
1318 buffer
->flush
= flush
;
1321 buffer
->gzip
= gzip
;
1323 log
->file
->flush
= ngx_http_log_flush
;
1324 log
->file
->data
= buffer
;
1332 ngx_http_log_set_format(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
1334 ngx_http_log_main_conf_t
*lmcf
= conf
;
1338 ngx_http_log_fmt_t
*fmt
;
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");
1346 value
= cf
->args
->elts
;
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)
1353 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
1354 "duplicate \"log_format\" name \"%V\"",
1356 return NGX_CONF_ERROR
;
1360 fmt
= ngx_array_push(&lmcf
->formats
);
1362 return NGX_CONF_ERROR
;
1365 fmt
->name
= value
[1];
1367 fmt
->flushes
= ngx_array_create(cf
->pool
, 4, sizeof(ngx_int_t
));
1368 if (fmt
->flushes
== NULL
) {
1369 return NGX_CONF_ERROR
;
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
;
1377 return ngx_http_log_compile_format(cf
, fmt
->flushes
, fmt
->ops
, cf
->args
, 2);
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
)
1385 u_char
*data
, *p
, ch
;
1387 ngx_str_t
*value
, var
;
1390 ngx_http_log_op_t
*op
;
1391 ngx_http_log_var_t
*v
;
1395 for ( /* void */ ; s
< args
->nelts
; s
++) {
1399 while (i
< value
[s
].len
) {
1401 op
= ngx_array_push(ops
);
1403 return NGX_CONF_ERROR
;
1406 data
= &value
[s
].data
[i
];
1408 if (value
[s
].data
[i
] == '$') {
1410 if (++i
== value
[s
].len
) {
1414 if (value
[s
].data
[i
] == '{') {
1417 if (++i
== value
[s
].len
) {
1421 var
.data
= &value
[s
].data
[i
];
1425 var
.data
= &value
[s
].data
[i
];
1428 for (var
.len
= 0; i
< value
[s
].len
; i
++, var
.len
++) {
1429 ch
= value
[s
].data
[i
];
1431 if (ch
== '}' && bracket
) {
1437 if ((ch
>= 'A' && ch
<= 'Z')
1438 || (ch
>= 'a' && ch
<= 'z')
1439 || (ch
>= '0' && ch
<= '9')
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
;
1459 for (v
= ngx_http_log_vars
; v
->name
.len
; v
++) {
1461 if (v
->name
.len
== var
.len
1462 && ngx_strncmp(v
->name
.data
, var
.data
, var
.len
) == 0)
1473 if (ngx_http_log_variable_compile(cf
, op
, &var
) != NGX_OK
) {
1474 return NGX_CONF_ERROR
;
1479 flush
= ngx_array_push(flushes
);
1480 if (flush
== NULL
) {
1481 return NGX_CONF_ERROR
;
1484 *flush
= op
->data
; /* variable index */
1494 while (i
< value
[s
].len
&& value
[s
].data
[i
] != '$') {
1498 len
= &value
[s
].data
[i
] - data
;
1505 if (len
<= sizeof(uintptr_t)) {
1506 op
->run
= ngx_http_log_copy_short
;
1511 op
->data
|= data
[len
];
1515 op
->run
= ngx_http_log_copy_long
;
1517 p
= ngx_pnalloc(cf
->pool
, len
);
1519 return NGX_CONF_ERROR
;
1522 ngx_memcpy(p
, data
, len
);
1523 op
->data
= (uintptr_t) p
;
1533 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0, "invalid parameter \"%s\"", data
);
1535 return NGX_CONF_ERROR
;
1540 ngx_http_log_open_file_cache(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
1542 ngx_http_log_loc_conf_t
*llcf
= conf
;
1544 time_t inactive
, valid
;
1545 ngx_str_t
*value
, s
;
1546 ngx_int_t max
, min_uses
;
1549 if (llcf
->open_file_cache
!= NGX_CONF_UNSET_PTR
) {
1550 return "is duplicate";
1553 value
= cf
->args
->elts
;
1560 for (i
= 1; i
< cf
->args
->nelts
; i
++) {
1562 if (ngx_strncmp(value
[i
].data
, "max=", 4) == 0) {
1564 max
= ngx_atoi(value
[i
].data
+ 4, value
[i
].len
- 4);
1565 if (max
== NGX_ERROR
) {
1572 if (ngx_strncmp(value
[i
].data
, "inactive=", 9) == 0) {
1574 s
.len
= value
[i
].len
- 9;
1575 s
.data
= value
[i
].data
+ 9;
1577 inactive
= ngx_parse_time(&s
, 1);
1578 if (inactive
== (time_t) NGX_ERROR
) {
1585 if (ngx_strncmp(value
[i
].data
, "min_uses=", 9) == 0) {
1587 min_uses
= ngx_atoi(value
[i
].data
+ 9, value
[i
].len
- 9);
1588 if (min_uses
== NGX_ERROR
) {
1595 if (ngx_strncmp(value
[i
].data
, "valid=", 6) == 0) {
1597 s
.len
= value
[i
].len
- 6;
1598 s
.data
= value
[i
].data
+ 6;
1600 valid
= ngx_parse_time(&s
, 1);
1601 if (valid
== (time_t) NGX_ERROR
) {
1608 if (ngx_strcmp(value
[i
].data
, "off") == 0) {
1610 llcf
->open_file_cache
= NULL
;
1617 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
1618 "invalid \"open_log_file_cache\" parameter \"%V\"",
1620 return NGX_CONF_ERROR
;
1623 if (llcf
->open_file_cache
== NULL
) {
1628 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
1629 "\"open_log_file_cache\" must have \"max\" parameter");
1630 return NGX_CONF_ERROR
;
1633 llcf
->open_file_cache
= ngx_open_file_cache_init(cf
->pool
, max
, inactive
);
1635 if (llcf
->open_file_cache
) {
1637 llcf
->open_file_cache_valid
= valid
;
1638 llcf
->open_file_cache_min_uses
= min_uses
;
1643 return NGX_CONF_ERROR
;
1648 ngx_http_log_init(ngx_conf_t
*cf
)
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
;
1657 lmcf
= ngx_http_conf_get_module_main_conf(cf
, ngx_http_log_module
);
1659 if (lmcf
->combined_used
) {
1660 if (ngx_array_init(&a
, cf
->pool
, 1, sizeof(ngx_str_t
)) != NGX_OK
) {
1664 value
= ngx_array_push(&a
);
1665 if (value
== NULL
) {
1669 *value
= ngx_http_combined_fmt
;
1670 fmt
= lmcf
->formats
.elts
;
1672 if (ngx_http_log_compile_format(cf
, NULL
, fmt
->ops
, &a
, 0)
1679 cmcf
= ngx_http_conf_get_module_main_conf(cf
, ngx_http_core_module
);
1681 h
= ngx_array_push(&cmcf
->phases
[NGX_HTTP_LOG_PHASE
].handlers
);
1686 *h
= ngx_http_log_handler
;