3
* Copyright (C) Igor Sysoev
7
#include <ngx_config.h>
12
typedef struct ngx_http_log_op_s ngx_http_log_op_t;
14
typedef u_char *(*ngx_http_log_op_run_pt) (ngx_http_request_t *r, u_char *buf,
15
ngx_http_log_op_t *op);
17
typedef size_t (*ngx_http_log_op_getlen_pt) (ngx_http_request_t *r,
21
struct ngx_http_log_op_s {
23
ngx_http_log_op_getlen_pt getlen;
24
ngx_http_log_op_run_pt run;
32
ngx_array_t *ops; /* array of ngx_http_log_op_t */
37
ngx_array_t formats; /* array of ngx_http_log_fmt_t */
38
ngx_uint_t combined_used; /* unsigned combined_used:1 */
39
} ngx_http_log_main_conf_t;
45
} ngx_http_log_script_t;
49
ngx_open_file_t *file;
50
ngx_http_log_script_t *script;
51
time_t disk_full_time;
52
time_t error_log_time;
53
ngx_http_log_fmt_t *format;
58
ngx_array_t *logs; /* array of ngx_http_log_t */
60
ngx_open_file_cache_t *open_file_cache;
61
time_t open_file_cache_valid;
62
ngx_uint_t open_file_cache_min_uses;
64
ngx_uint_t off; /* unsigned off:1 */
65
} ngx_http_log_loc_conf_t;
71
ngx_http_log_op_run_pt run;
75
static void ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log,
76
u_char *buf, size_t len);
77
static ssize_t ngx_http_log_script_write(ngx_http_request_t *r,
78
ngx_http_log_script_t *script, u_char **name, u_char *buf, size_t len);
80
static u_char *ngx_http_log_connection(ngx_http_request_t *r, u_char *buf,
81
ngx_http_log_op_t *op);
82
static u_char *ngx_http_log_pipe(ngx_http_request_t *r, u_char *buf,
83
ngx_http_log_op_t *op);
84
static u_char *ngx_http_log_time(ngx_http_request_t *r, u_char *buf,
85
ngx_http_log_op_t *op);
86
static u_char *ngx_http_log_msec(ngx_http_request_t *r, u_char *buf,
87
ngx_http_log_op_t *op);
88
static u_char *ngx_http_log_request_time(ngx_http_request_t *r, u_char *buf,
89
ngx_http_log_op_t *op);
90
static u_char *ngx_http_log_status(ngx_http_request_t *r, u_char *buf,
91
ngx_http_log_op_t *op);
92
static u_char *ngx_http_log_bytes_sent(ngx_http_request_t *r, u_char *buf,
93
ngx_http_log_op_t *op);
94
static u_char *ngx_http_log_body_bytes_sent(ngx_http_request_t *r,
95
u_char *buf, ngx_http_log_op_t *op);
96
static u_char *ngx_http_log_request_length(ngx_http_request_t *r, u_char *buf,
97
ngx_http_log_op_t *op);
99
static ngx_int_t ngx_http_log_variable_compile(ngx_conf_t *cf,
100
ngx_http_log_op_t *op, ngx_str_t *value);
101
static size_t ngx_http_log_variable_getlen(ngx_http_request_t *r,
103
static u_char *ngx_http_log_variable(ngx_http_request_t *r, u_char *buf,
104
ngx_http_log_op_t *op);
105
static uintptr_t ngx_http_log_escape(u_char *dst, u_char *src, size_t size);
108
static void *ngx_http_log_create_main_conf(ngx_conf_t *cf);
109
static void *ngx_http_log_create_loc_conf(ngx_conf_t *cf);
110
static char *ngx_http_log_merge_loc_conf(ngx_conf_t *cf, void *parent,
112
static char *ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd,
114
static char *ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd,
116
static char *ngx_http_log_compile_format(ngx_conf_t *cf,
117
ngx_array_t *flushes, ngx_array_t *ops, ngx_array_t *args, ngx_uint_t s);
118
static char *ngx_http_log_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd,
120
static ngx_int_t ngx_http_log_init(ngx_conf_t *cf);
123
static ngx_command_t ngx_http_log_commands[] = {
125
{ ngx_string("log_format"),
126
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_2MORE,
127
ngx_http_log_set_format,
128
NGX_HTTP_MAIN_CONF_OFFSET,
132
{ ngx_string("access_log"),
133
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
134
|NGX_HTTP_LMT_CONF|NGX_CONF_TAKE123,
135
ngx_http_log_set_log,
136
NGX_HTTP_LOC_CONF_OFFSET,
140
{ ngx_string("open_log_file_cache"),
141
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
142
ngx_http_log_open_file_cache,
143
NGX_HTTP_LOC_CONF_OFFSET,
151
static ngx_http_module_t ngx_http_log_module_ctx = {
152
NULL, /* preconfiguration */
153
ngx_http_log_init, /* postconfiguration */
155
ngx_http_log_create_main_conf, /* create main configuration */
156
NULL, /* init main configuration */
158
NULL, /* create server configuration */
159
NULL, /* merge server configuration */
161
ngx_http_log_create_loc_conf, /* create location configration */
162
ngx_http_log_merge_loc_conf /* merge location configration */
166
ngx_module_t ngx_http_log_module = {
168
&ngx_http_log_module_ctx, /* module context */
169
ngx_http_log_commands, /* module directives */
170
NGX_HTTP_MODULE, /* module type */
171
NULL, /* init master */
172
NULL, /* init module */
173
NULL, /* init process */
174
NULL, /* init thread */
175
NULL, /* exit thread */
176
NULL, /* exit process */
177
NULL, /* exit master */
178
NGX_MODULE_V1_PADDING
182
static ngx_str_t ngx_http_access_log = ngx_string(NGX_HTTP_LOG_PATH);
185
static ngx_str_t ngx_http_combined_fmt =
186
ngx_string("$remote_addr - $remote_user [$time_local] "
187
"\"$request\" $status $body_bytes_sent "
188
"\"$http_referer\" \"$http_user_agent\"");
191
static ngx_http_log_var_t ngx_http_log_vars[] = {
192
{ ngx_string("connection"), NGX_ATOMIC_T_LEN, ngx_http_log_connection },
193
{ ngx_string("pipe"), 1, ngx_http_log_pipe },
194
{ ngx_string("time_local"), sizeof("28/Sep/1970:12:00:00 +0600") - 1,
196
{ ngx_string("msec"), NGX_TIME_T_LEN + 4, ngx_http_log_msec },
197
{ ngx_string("request_time"), NGX_TIME_T_LEN + 4,
198
ngx_http_log_request_time },
199
{ ngx_string("status"), 3, ngx_http_log_status },
200
{ ngx_string("bytes_sent"), NGX_OFF_T_LEN, ngx_http_log_bytes_sent },
201
{ ngx_string("body_bytes_sent"), NGX_OFF_T_LEN,
202
ngx_http_log_body_bytes_sent },
203
{ ngx_string("apache_bytes_sent"), NGX_OFF_T_LEN,
204
ngx_http_log_body_bytes_sent },
205
{ ngx_string("request_length"), NGX_SIZE_T_LEN,
206
ngx_http_log_request_length },
208
{ ngx_null_string, 0, NULL }
213
ngx_http_log_handler(ngx_http_request_t *r)
219
ngx_open_file_t *file;
220
ngx_http_log_op_t *op;
221
ngx_http_log_loc_conf_t *lcf;
223
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
226
lcf = ngx_http_get_module_loc_conf(r, ngx_http_log_module);
232
log = lcf->logs->elts;
233
for (l = 0; l < lcf->logs->nelts; l++) {
235
if (ngx_time() == log[l].disk_full_time) {
238
* on FreeBSD writing to a full filesystem with enabled softupdates
239
* may block process for much longer time than writing to non-full
240
* filesystem, so we skip writing to a log for one second
246
ngx_http_script_flush_no_cacheable_variables(r, log[l].format->flushes);
249
op = log[l].format->ops->elts;
250
for (i = 0; i < log[l].format->ops->nelts; i++) {
251
if (op[i].len == 0) {
252
len += op[i].getlen(r, op[i].data);
259
len += NGX_LINEFEED_SIZE;
263
if (file && file->buffer) {
265
if (len > (size_t) (file->last - file->pos)) {
267
ngx_http_log_write(r, &log[l], file->buffer,
268
file->pos - file->buffer);
270
file->pos = file->buffer;
273
if (len <= (size_t) (file->last - file->pos)) {
277
for (i = 0; i < log[l].format->ops->nelts; i++) {
278
p = op[i].run(r, p, &op[i]);
289
line = ngx_pnalloc(r->pool, len);
296
for (i = 0; i < log[l].format->ops->nelts; i++) {
297
p = op[i].run(r, p, &op[i]);
302
ngx_http_log_write(r, &log[l], line, p - line);
310
ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log, u_char *buf,
318
if (log->script == NULL) {
319
name = log->file->name.data;
320
n = ngx_write_fd(log->file->fd, buf, len);
324
n = ngx_http_log_script_write(r, log->script, &name, buf, len);
327
if (n == (ssize_t) len) {
336
if (err == NGX_ENOSPC) {
337
log->disk_full_time = now;
340
if (now - log->error_log_time > 59) {
341
ngx_log_error(NGX_LOG_ALERT, r->connection->log, err,
342
ngx_write_fd_n " to \"%s\" failed", name);
344
log->error_log_time = now;
350
if (now - log->error_log_time > 59) {
351
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
352
ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz",
355
log->error_log_time = now;
361
ngx_http_log_script_write(ngx_http_request_t *r, ngx_http_log_script_t *script,
362
u_char **name, u_char *buf, size_t len)
367
ngx_open_file_info_t of;
368
ngx_http_log_loc_conf_t *llcf;
369
ngx_http_core_loc_conf_t *clcf;
371
if (!r->root_tested) {
373
/* test root directory existance */
375
if (ngx_http_map_uri_to_path(r, &path, &root, 0) == NULL) {
376
/* simulate successfull logging */
380
path.data[root] = '\0';
382
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
384
ngx_memzero(&of, sizeof(ngx_open_file_info_t));
386
of.valid = clcf->open_file_cache_valid;
387
of.min_uses = clcf->open_file_cache_min_uses;
390
of.errors = clcf->open_file_cache_errors;
391
of.events = clcf->open_file_cache_events;
393
if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
397
/* simulate successfull logging */
401
ngx_log_error(NGX_LOG_ERR, r->connection->log, of.err,
402
"testing \"%s\" existence failed", path.data);
404
/* simulate successfull logging */
409
ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_ENOTDIR,
410
"testing \"%s\" existence failed", path.data);
412
/* simulate successfull logging */
417
if (ngx_http_script_run(r, &log, script->lengths->elts, 1,
418
script->values->elts)
421
/* simulate successfull logging */
425
log.data[log.len - 1] = '\0';
428
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
429
"http log \"%s\"", log.data);
431
llcf = ngx_http_get_module_loc_conf(r, ngx_http_log_module);
433
ngx_memzero(&of, sizeof(ngx_open_file_info_t));
436
of.valid = llcf->open_file_cache_valid;
437
of.min_uses = llcf->open_file_cache_min_uses;
438
of.directio = NGX_OPEN_FILE_DIRECTIO_OFF;
440
if (ngx_open_cached_file(llcf->open_file_cache, &log, &of, r->pool)
443
ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
444
"%s \"%s\" failed", of.failed, log.data);
445
/* simulate successfull logging */
449
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
450
"http log #%d", of.fd);
452
n = ngx_write_fd(of.fd, buf, len);
459
ngx_http_log_copy_short(ngx_http_request_t *r, u_char *buf,
460
ngx_http_log_op_t *op)
469
*buf++ = (u_char) (data & 0xff);
478
ngx_http_log_copy_long(ngx_http_request_t *r, u_char *buf,
479
ngx_http_log_op_t *op)
481
return ngx_cpymem(buf, (u_char *) op->data, op->len);
486
ngx_http_log_connection(ngx_http_request_t *r, u_char *buf,
487
ngx_http_log_op_t *op)
489
return ngx_sprintf(buf, "%ui", r->connection->number);
494
ngx_http_log_pipe(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
507
ngx_http_log_time(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
509
return ngx_cpymem(buf, ngx_cached_http_log_time.data,
510
ngx_cached_http_log_time.len);
515
ngx_http_log_msec(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
519
tp = ngx_timeofday();
521
return ngx_sprintf(buf, "%T.%03M", tp->sec, tp->msec);
526
ngx_http_log_request_time(ngx_http_request_t *r, u_char *buf,
527
ngx_http_log_op_t *op)
532
tp = ngx_timeofday();
534
ms = (ngx_msec_int_t)
535
((tp->sec - r->start_sec) * 1000 + (tp->msec - r->start_msec));
538
return ngx_sprintf(buf, "%T.%03M", ms / 1000, ms % 1000);
543
ngx_http_log_status(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
548
status = r->err_status;
550
} else if (r->headers_out.status) {
551
status = r->headers_out.status;
553
} else if (r->http_version == NGX_HTTP_VERSION_9) {
563
return ngx_sprintf(buf, "%ui", status);
568
ngx_http_log_bytes_sent(ngx_http_request_t *r, u_char *buf,
569
ngx_http_log_op_t *op)
571
return ngx_sprintf(buf, "%O", r->connection->sent);
576
* although there is a real $body_bytes_sent variable,
577
* this log operation code function is more optimized for logging
581
ngx_http_log_body_bytes_sent(ngx_http_request_t *r, u_char *buf,
582
ngx_http_log_op_t *op)
586
length = r->connection->sent - r->header_size;
589
return ngx_sprintf(buf, "%O", length);
599
ngx_http_log_request_length(ngx_http_request_t *r, u_char *buf,
600
ngx_http_log_op_t *op)
602
return ngx_sprintf(buf, "%O", r->request_length);
607
ngx_http_log_variable_compile(ngx_conf_t *cf, ngx_http_log_op_t *op,
612
index = ngx_http_get_variable_index(cf, value);
613
if (index == NGX_ERROR) {
618
op->getlen = ngx_http_log_variable_getlen;
619
op->run = ngx_http_log_variable;
627
ngx_http_log_variable_getlen(ngx_http_request_t *r, uintptr_t data)
630
ngx_http_variable_value_t *value;
632
value = ngx_http_get_indexed_variable(r, data);
634
if (value == NULL || value->not_found) {
638
len = ngx_http_log_escape(NULL, value->data, value->len);
640
value->escape = len ? 1 : 0;
642
return value->len + len * 3;
647
ngx_http_log_variable(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
649
ngx_http_variable_value_t *value;
651
value = ngx_http_get_indexed_variable(r, op->data);
653
if (value == NULL || value->not_found) {
658
if (value->escape == 0) {
659
return ngx_cpymem(buf, value->data, value->len);
662
return (u_char *) ngx_http_log_escape(buf, value->data, value->len);
668
ngx_http_log_escape(u_char *dst, u_char *src, size_t size)
671
static u_char hex[] = "0123456789ABCDEF";
673
static uint32_t escape[] = {
674
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
676
/* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
677
0x00000004, /* 0000 0000 0000 0000 0000 0000 0000 0100 */
679
/* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
680
0x10000000, /* 0001 0000 0000 0000 0000 0000 0000 0000 */
682
/* ~}| {zyx wvut srqp onml kjih gfed cba` */
683
0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
685
0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
686
0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
687
0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
688
0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
694
/* find the number of the characters to be escaped */
699
if (escape[*src >> 5] & (1 << (*src & 0x1f))) {
706
return (uintptr_t) n;
710
if (escape[*src >> 5] & (1 << (*src & 0x1f))) {
713
*dst++ = hex[*src >> 4];
714
*dst++ = hex[*src & 0xf];
723
return (uintptr_t) dst;
728
ngx_http_log_create_main_conf(ngx_conf_t *cf)
730
ngx_http_log_main_conf_t *conf;
732
ngx_http_log_fmt_t *fmt;
734
conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_main_conf_t));
739
if (ngx_array_init(&conf->formats, cf->pool, 4, sizeof(ngx_http_log_fmt_t))
745
fmt = ngx_array_push(&conf->formats);
750
ngx_str_set(&fmt->name, "combined");
754
fmt->ops = ngx_array_create(cf->pool, 16, sizeof(ngx_http_log_op_t));
755
if (fmt->ops == NULL) {
764
ngx_http_log_create_loc_conf(ngx_conf_t *cf)
766
ngx_http_log_loc_conf_t *conf;
768
conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_loc_conf_t));
773
conf->open_file_cache = NGX_CONF_UNSET_PTR;
780
ngx_http_log_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
782
ngx_http_log_loc_conf_t *prev = parent;
783
ngx_http_log_loc_conf_t *conf = child;
786
ngx_http_log_fmt_t *fmt;
787
ngx_http_log_main_conf_t *lmcf;
789
if (conf->open_file_cache == NGX_CONF_UNSET_PTR) {
791
conf->open_file_cache = prev->open_file_cache;
792
conf->open_file_cache_valid = prev->open_file_cache_valid;
793
conf->open_file_cache_min_uses = prev->open_file_cache_min_uses;
795
if (conf->open_file_cache == NGX_CONF_UNSET_PTR) {
796
conf->open_file_cache = NULL;
800
if (conf->logs || conf->off) {
804
conf->logs = prev->logs;
805
conf->off = prev->off;
807
if (conf->logs || conf->off) {
811
conf->logs = ngx_array_create(cf->pool, 2, sizeof(ngx_http_log_t));
812
if (conf->logs == NULL) {
813
return NGX_CONF_ERROR;
816
log = ngx_array_push(conf->logs);
818
return NGX_CONF_ERROR;
821
log->file = ngx_conf_open_file(cf->cycle, &ngx_http_access_log);
822
if (log->file == NULL) {
823
return NGX_CONF_ERROR;
827
log->disk_full_time = 0;
828
log->error_log_time = 0;
830
lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_log_module);
831
fmt = lmcf->formats.elts;
833
/* the default "combined" format */
834
log->format = &fmt[0];
835
lmcf->combined_used = 1;
842
ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
844
ngx_http_log_loc_conf_t *llcf = conf;
848
ngx_str_t *value, name;
850
ngx_http_log_fmt_t *fmt;
851
ngx_http_log_main_conf_t *lmcf;
852
ngx_http_script_compile_t sc;
854
value = cf->args->elts;
856
if (ngx_strcmp(value[1].data, "off") == 0) {
858
if (cf->args->nelts == 2) {
862
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
863
"invalid parameter \"%V\"", &value[2]);
864
return NGX_CONF_ERROR;
867
if (llcf->logs == NULL) {
868
llcf->logs = ngx_array_create(cf->pool, 2, sizeof(ngx_http_log_t));
869
if (llcf->logs == NULL) {
870
return NGX_CONF_ERROR;
874
lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_log_module);
876
log = ngx_array_push(llcf->logs);
878
return NGX_CONF_ERROR;
881
ngx_memzero(log, sizeof(ngx_http_log_t));
883
n = ngx_http_script_variables_count(&value[1]);
886
log->file = ngx_conf_open_file(cf->cycle, &value[1]);
887
if (log->file == NULL) {
888
return NGX_CONF_ERROR;
892
if (ngx_conf_full_name(cf->cycle, &value[1], 0) != NGX_OK) {
893
return NGX_CONF_ERROR;
896
log->script = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_script_t));
897
if (log->script == NULL) {
898
return NGX_CONF_ERROR;
901
ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
904
sc.source = &value[1];
905
sc.lengths = &log->script->lengths;
906
sc.values = &log->script->values;
908
sc.complete_lengths = 1;
909
sc.complete_values = 1;
911
if (ngx_http_script_compile(&sc) != NGX_OK) {
912
return NGX_CONF_ERROR;
916
if (cf->args->nelts >= 3) {
919
if (ngx_strcmp(name.data, "combined") == 0) {
920
lmcf->combined_used = 1;
924
ngx_str_set(&name, "combined");
925
lmcf->combined_used = 1;
928
fmt = lmcf->formats.elts;
929
for (i = 0; i < lmcf->formats.nelts; i++) {
930
if (fmt[i].name.len == name.len
931
&& ngx_strcasecmp(fmt[i].name.data, name.data) == 0)
933
log->format = &fmt[i];
938
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
939
"unknown log format \"%V\"", &name);
940
return NGX_CONF_ERROR;
944
if (cf->args->nelts == 4) {
945
if (ngx_strncmp(value[3].data, "buffer=", 7) != 0) {
946
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
947
"invalid parameter \"%V\"", &value[3]);
948
return NGX_CONF_ERROR;
952
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
953
"buffered logs can not have variables in name");
954
return NGX_CONF_ERROR;
957
name.len = value[3].len - 7;
958
name.data = value[3].data + 7;
960
buf = ngx_parse_size(&name);
962
if (buf == NGX_ERROR) {
963
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
964
"invalid parameter \"%V\"", &value[3]);
965
return NGX_CONF_ERROR;
968
if (log->file->buffer && log->file->last - log->file->pos != buf) {
969
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
970
"access_log \"%V\" already defined "
971
"with different buffer size", &value[1]);
972
return NGX_CONF_ERROR;
975
log->file->buffer = ngx_palloc(cf->pool, buf);
976
if (log->file->buffer == NULL) {
977
return NGX_CONF_ERROR;
980
log->file->pos = log->file->buffer;
981
log->file->last = log->file->buffer + buf;
989
ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
991
ngx_http_log_main_conf_t *lmcf = conf;
995
ngx_http_log_fmt_t *fmt;
997
value = cf->args->elts;
999
fmt = lmcf->formats.elts;
1000
for (i = 0; i < lmcf->formats.nelts; i++) {
1001
if (fmt[i].name.len == value[1].len
1002
&& ngx_strcmp(fmt[i].name.data, value[1].data) == 0)
1004
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1005
"duplicate \"log_format\" name \"%V\"",
1007
return NGX_CONF_ERROR;
1011
fmt = ngx_array_push(&lmcf->formats);
1013
return NGX_CONF_ERROR;
1016
fmt->name = value[1];
1018
fmt->flushes = ngx_array_create(cf->pool, 4, sizeof(ngx_int_t));
1019
if (fmt->flushes == NULL) {
1020
return NGX_CONF_ERROR;
1023
fmt->ops = ngx_array_create(cf->pool, 16, sizeof(ngx_http_log_op_t));
1024
if (fmt->ops == NULL) {
1025
return NGX_CONF_ERROR;
1028
return ngx_http_log_compile_format(cf, fmt->flushes, fmt->ops, cf->args, 2);
1033
ngx_http_log_compile_format(ngx_conf_t *cf, ngx_array_t *flushes,
1034
ngx_array_t *ops, ngx_array_t *args, ngx_uint_t s)
1036
u_char *data, *p, ch;
1038
ngx_str_t *value, var;
1041
ngx_http_log_op_t *op;
1042
ngx_http_log_var_t *v;
1046
for ( /* void */ ; s < args->nelts; s++) {
1048
for (i = 0; i < value[s].len; i++) {
1049
if (value[s].data[i] != '%') {
1053
ch = value[s].data[i + 1];
1055
if ((ch >= 'A' && ch <= 'Z')
1056
|| (ch >= 'a' && ch <= 'z')
1059
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1060
"the parameters in the \"%%name\" form are not supported, "
1061
"use the \"$variable\" instead");
1063
return NGX_CONF_ERROR;
1069
while (i < value[s].len) {
1071
op = ngx_array_push(ops);
1073
return NGX_CONF_ERROR;
1076
data = &value[s].data[i];
1078
if (value[s].data[i] == '$') {
1080
if (++i == value[s].len) {
1084
if (value[s].data[i] == '{') {
1087
if (++i == value[s].len) {
1091
var.data = &value[s].data[i];
1095
var.data = &value[s].data[i];
1098
for (var.len = 0; i < value[s].len; i++, var.len++) {
1099
ch = value[s].data[i];
1101
if (ch == '}' && bracket) {
1107
if ((ch >= 'A' && ch <= 'Z')
1108
|| (ch >= 'a' && ch <= 'z')
1109
|| (ch >= '0' && ch <= '9')
1119
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1120
"the closing bracket in \"%V\" "
1121
"variable is missing", &var);
1122
return NGX_CONF_ERROR;
1129
if (ngx_strncmp(var.data, "apache_bytes_sent", 17) == 0) {
1130
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1131
"use \"$body_bytes_sent\" instead of "
1132
"\"$apache_bytes_sent\"");
1135
for (v = ngx_http_log_vars; v->name.len; v++) {
1137
if (v->name.len == var.len
1138
&& ngx_strncmp(v->name.data, var.data, var.len) == 0)
1149
if (ngx_http_log_variable_compile(cf, op, &var) != NGX_OK) {
1150
return NGX_CONF_ERROR;
1155
flush = ngx_array_push(flushes);
1156
if (flush == NULL) {
1157
return NGX_CONF_ERROR;
1160
*flush = op->data; /* variable index */
1170
while (i < value[s].len && value[s].data[i] != '$') {
1174
len = &value[s].data[i] - data;
1181
if (len <= sizeof(uintptr_t)) {
1182
op->run = ngx_http_log_copy_short;
1187
op->data |= data[len];
1191
op->run = ngx_http_log_copy_long;
1193
p = ngx_pnalloc(cf->pool, len);
1195
return NGX_CONF_ERROR;
1198
ngx_memcpy(p, data, len);
1199
op->data = (uintptr_t) p;
1209
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%s\"", data);
1211
return NGX_CONF_ERROR;
1216
ngx_http_log_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1218
ngx_http_log_loc_conf_t *llcf = conf;
1220
time_t inactive, valid;
1221
ngx_str_t *value, s;
1222
ngx_int_t max, min_uses;
1225
if (llcf->open_file_cache != NGX_CONF_UNSET_PTR) {
1226
return "is duplicate";
1229
value = cf->args->elts;
1236
for (i = 1; i < cf->args->nelts; i++) {
1238
if (ngx_strncmp(value[i].data, "max=", 4) == 0) {
1240
max = ngx_atoi(value[i].data + 4, value[i].len - 4);
1241
if (max == NGX_ERROR) {
1248
if (ngx_strncmp(value[i].data, "inactive=", 9) == 0) {
1250
s.len = value[i].len - 9;
1251
s.data = value[i].data + 9;
1253
inactive = ngx_parse_time(&s, 1);
1261
if (ngx_strncmp(value[i].data, "min_uses=", 9) == 0) {
1263
min_uses = ngx_atoi(value[i].data + 9, value[i].len - 9);
1264
if (min_uses == NGX_ERROR) {
1271
if (ngx_strncmp(value[i].data, "valid=", 6) == 0) {
1273
s.len = value[i].len - 6;
1274
s.data = value[i].data + 6;
1276
valid = ngx_parse_time(&s, 1);
1284
if (ngx_strcmp(value[i].data, "off") == 0) {
1286
llcf->open_file_cache = NULL;
1293
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1294
"invalid \"open_log_file_cache\" parameter \"%V\"",
1296
return NGX_CONF_ERROR;
1299
if (llcf->open_file_cache == NULL) {
1304
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1305
"\"open_log_file_cache\" must have \"max\" parameter");
1306
return NGX_CONF_ERROR;
1309
llcf->open_file_cache = ngx_open_file_cache_init(cf->pool, max, inactive);
1311
if (llcf->open_file_cache) {
1313
llcf->open_file_cache_valid = valid;
1314
llcf->open_file_cache_min_uses = min_uses;
1319
return NGX_CONF_ERROR;
1324
ngx_http_log_init(ngx_conf_t *cf)
1328
ngx_http_handler_pt *h;
1329
ngx_http_log_fmt_t *fmt;
1330
ngx_http_log_main_conf_t *lmcf;
1331
ngx_http_core_main_conf_t *cmcf;
1333
lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_log_module);
1335
if (lmcf->combined_used) {
1336
if (ngx_array_init(&a, cf->pool, 1, sizeof(ngx_str_t)) != NGX_OK) {
1340
value = ngx_array_push(&a);
1341
if (value == NULL) {
1345
*value = ngx_http_combined_fmt;
1346
fmt = lmcf->formats.elts;
1348
if (ngx_http_log_compile_format(cf, NULL, fmt->ops, &a, 0)
1355
cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
1357
h = ngx_array_push(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers);
1362
*h = ngx_http_log_handler;