Mercurial > hg > nginx-mail
comparison src/http/modules/ngx_http_log_module.c @ 384:12defd37f578 NGINX_0_7_4
nginx 0.7.4
*) Feature: variables support in the "access_log" directive.
*) Feature: the "open_log_file_cache" directive.
*) Feature: the -g switch.
*) Feature: the "Expect" request header line support.
*) Bugfix: large SSI inclusions might be truncated.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Mon, 30 Jun 2008 00:00:00 +0400 |
parents | 984bb0b1399b |
children | 1172e6d6f40f |
comparison
equal
deleted
inserted
replaced
383:6ee3ada01457 | 384:12defd37f578 |
---|---|
38 ngx_uint_t combined_used; /* unsigned combined_used:1 */ | 38 ngx_uint_t combined_used; /* unsigned combined_used:1 */ |
39 } ngx_http_log_main_conf_t; | 39 } ngx_http_log_main_conf_t; |
40 | 40 |
41 | 41 |
42 typedef struct { | 42 typedef struct { |
43 ngx_array_t *lengths; | |
44 ngx_array_t *values; | |
45 } ngx_http_log_script_t; | |
46 | |
47 | |
48 typedef struct { | |
43 ngx_open_file_t *file; | 49 ngx_open_file_t *file; |
50 ngx_http_log_script_t *script; | |
44 time_t disk_full_time; | 51 time_t disk_full_time; |
45 time_t error_log_time; | 52 time_t error_log_time; |
46 ngx_array_t *ops; /* array of ngx_http_log_op_t */ | 53 ngx_array_t *ops; /* array of ngx_http_log_op_t */ |
47 } ngx_http_log_t; | 54 } ngx_http_log_t; |
48 | 55 |
49 | 56 |
50 typedef struct { | 57 typedef struct { |
51 ngx_array_t *logs; /* array of ngx_http_log_t */ | 58 ngx_array_t *logs; /* array of ngx_http_log_t */ |
59 | |
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; | |
63 | |
52 ngx_uint_t off; /* unsigned off:1 */ | 64 ngx_uint_t off; /* unsigned off:1 */ |
53 } ngx_http_log_loc_conf_t; | 65 } ngx_http_log_loc_conf_t; |
54 | 66 |
55 | 67 |
56 typedef struct { | 68 typedef struct { |
60 } ngx_http_log_var_t; | 72 } ngx_http_log_var_t; |
61 | 73 |
62 | 74 |
63 static void ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log, | 75 static void ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log, |
64 u_char *buf, size_t len); | 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); | |
65 | 79 |
66 static u_char *ngx_http_log_connection(ngx_http_request_t *r, u_char *buf, | 80 static u_char *ngx_http_log_connection(ngx_http_request_t *r, u_char *buf, |
67 ngx_http_log_op_t *op); | 81 ngx_http_log_op_t *op); |
68 static u_char *ngx_http_log_pipe(ngx_http_request_t *r, u_char *buf, | 82 static u_char *ngx_http_log_pipe(ngx_http_request_t *r, u_char *buf, |
69 ngx_http_log_op_t *op); | 83 ngx_http_log_op_t *op); |
99 void *conf); | 113 void *conf); |
100 static char *ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd, | 114 static char *ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd, |
101 void *conf); | 115 void *conf); |
102 static char *ngx_http_log_compile_format(ngx_conf_t *cf, | 116 static char *ngx_http_log_compile_format(ngx_conf_t *cf, |
103 ngx_array_t *ops, ngx_array_t *args, ngx_uint_t s); | 117 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, | |
119 void *conf); | |
104 static ngx_int_t ngx_http_log_init(ngx_conf_t *cf); | 120 static ngx_int_t ngx_http_log_init(ngx_conf_t *cf); |
105 | 121 |
106 | 122 |
107 static ngx_command_t ngx_http_log_commands[] = { | 123 static ngx_command_t ngx_http_log_commands[] = { |
108 | 124 |
115 | 131 |
116 { ngx_string("access_log"), | 132 { ngx_string("access_log"), |
117 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF | 133 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF |
118 |NGX_HTTP_LMT_CONF|NGX_CONF_TAKE123, | 134 |NGX_HTTP_LMT_CONF|NGX_CONF_TAKE123, |
119 ngx_http_log_set_log, | 135 ngx_http_log_set_log, |
136 NGX_HTTP_LOC_CONF_OFFSET, | |
137 0, | |
138 NULL }, | |
139 | |
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, | |
120 NGX_HTTP_LOC_CONF_OFFSET, | 143 NGX_HTTP_LOC_CONF_OFFSET, |
121 0, | 144 0, |
122 NULL }, | 145 NULL }, |
123 | 146 |
124 ngx_null_command | 147 ngx_null_command |
233 | 256 |
234 len += NGX_LINEFEED_SIZE; | 257 len += NGX_LINEFEED_SIZE; |
235 | 258 |
236 file = log[l].file; | 259 file = log[l].file; |
237 | 260 |
238 if (file->buffer) { | 261 if (file && file->buffer) { |
239 | 262 |
240 if (len > (size_t) (file->last - file->pos)) { | 263 if (len > (size_t) (file->last - file->pos)) { |
241 | 264 |
242 ngx_http_log_write(r, &log[l], file->buffer, | 265 ngx_http_log_write(r, &log[l], file->buffer, |
243 file->pos - file->buffer); | 266 file->pos - file->buffer); |
283 | 306 |
284 static void | 307 static void |
285 ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log, u_char *buf, | 308 ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log, u_char *buf, |
286 size_t len) | 309 size_t len) |
287 { | 310 { |
288 time_t now; | 311 u_char *name; |
289 ssize_t n; | 312 time_t now; |
290 ngx_err_t err; | 313 ssize_t n; |
291 | 314 ngx_err_t err; |
292 n = ngx_write_fd(log->file->fd, buf, len); | 315 |
316 if (log->script == NULL) { | |
317 name = log->file->name.data; | |
318 n = ngx_write_fd(log->file->fd, buf, len); | |
319 | |
320 } else { | |
321 name = NULL; | |
322 n = ngx_http_log_script_write(r, log->script, &name, buf, len); | |
323 } | |
293 | 324 |
294 if (n == (ssize_t) len) { | 325 if (n == (ssize_t) len) { |
295 return; | 326 return; |
296 } | 327 } |
297 | 328 |
304 log->disk_full_time = now; | 335 log->disk_full_time = now; |
305 } | 336 } |
306 | 337 |
307 if (now - log->error_log_time > 59) { | 338 if (now - log->error_log_time > 59) { |
308 ngx_log_error(NGX_LOG_ALERT, r->connection->log, err, | 339 ngx_log_error(NGX_LOG_ALERT, r->connection->log, err, |
309 ngx_write_fd_n " to \"%V\" failed", | 340 ngx_write_fd_n " to \"%s\" failed", name); |
310 &log->file->name); | |
311 | 341 |
312 log->error_log_time = now; | 342 log->error_log_time = now; |
313 } | 343 } |
314 | 344 |
315 return; | 345 return; |
316 } | 346 } |
317 | 347 |
318 if (now - log->error_log_time > 59) { | 348 if (now - log->error_log_time > 59) { |
319 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, | 349 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, |
320 ngx_write_fd_n " to \"%V\" was incomplete: %z of %uz", | 350 ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz", |
321 &log->file->name, n, len); | 351 name, n, len); |
322 | 352 |
323 log->error_log_time = now; | 353 log->error_log_time = now; |
324 } | 354 } |
355 } | |
356 | |
357 | |
358 static ssize_t | |
359 ngx_http_log_script_write(ngx_http_request_t *r, ngx_http_log_script_t *script, | |
360 u_char **name, u_char *buf, size_t len) | |
361 { | |
362 size_t root; | |
363 ssize_t n; | |
364 ngx_str_t log, path; | |
365 ngx_open_file_info_t of; | |
366 ngx_http_log_loc_conf_t *llcf; | |
367 ngx_http_core_loc_conf_t *clcf; | |
368 | |
369 if (r->err_status == NGX_HTTP_NOT_FOUND) { | |
370 | |
371 /* test root directory existance */ | |
372 | |
373 if (ngx_http_map_uri_to_path(r, &path, &root, 0) == NULL) { | |
374 /* simulate successfull logging */ | |
375 return len; | |
376 } | |
377 | |
378 path.data[root] = '\0'; | |
379 | |
380 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
381 | |
382 ngx_memzero(&of, sizeof(ngx_open_file_info_t)); | |
383 | |
384 of.valid = clcf->open_file_cache_valid; | |
385 of.min_uses = clcf->open_file_cache_min_uses; | |
386 of.errors = clcf->open_file_cache_errors; | |
387 of.events = clcf->open_file_cache_events; | |
388 | |
389 if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool) | |
390 != NGX_OK | |
391 || !of.is_dir) | |
392 { | |
393 /* no root directory: simulate successfull logging */ | |
394 return len; | |
395 } | |
396 } | |
397 | |
398 if (ngx_http_script_run(r, &log, script->lengths->elts, 1, | |
399 script->values->elts) | |
400 == NULL) | |
401 { | |
402 /* simulate successfull logging */ | |
403 return len; | |
404 } | |
405 | |
406 log.data[log.len - 1] = '\0'; | |
407 *name = log.data; | |
408 | |
409 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
410 "http log \"%s\"", log.data); | |
411 | |
412 llcf = ngx_http_get_module_loc_conf(r, ngx_http_log_module); | |
413 | |
414 ngx_memzero(&of, sizeof(ngx_open_file_info_t)); | |
415 | |
416 of.log = 1; | |
417 of.valid = llcf->open_file_cache_valid; | |
418 of.min_uses = llcf->open_file_cache_min_uses; | |
419 | |
420 if (ngx_open_cached_file(llcf->open_file_cache, &log, &of, r->pool) | |
421 != NGX_OK) | |
422 { | |
423 ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, | |
424 ngx_open_file_n " \"%s\" failed", log.data); | |
425 return -1; | |
426 } | |
427 | |
428 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
429 "http log #%d", of.fd); | |
430 | |
431 n = ngx_write_fd(of.fd, buf, len); | |
432 | |
433 return n; | |
325 } | 434 } |
326 | 435 |
327 | 436 |
328 static u_char * | 437 static u_char * |
329 ngx_http_log_copy_short(ngx_http_request_t *r, u_char *buf, | 438 ngx_http_log_copy_short(ngx_http_request_t *r, u_char *buf, |
618 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_loc_conf_t)); | 727 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_loc_conf_t)); |
619 if (conf == NULL) { | 728 if (conf == NULL) { |
620 return NGX_CONF_ERROR; | 729 return NGX_CONF_ERROR; |
621 } | 730 } |
622 | 731 |
732 conf->open_file_cache = NGX_CONF_UNSET_PTR; | |
733 | |
623 return conf; | 734 return conf; |
624 } | 735 } |
625 | 736 |
626 | 737 |
627 static char * | 738 static char * |
632 | 743 |
633 ngx_http_log_t *log; | 744 ngx_http_log_t *log; |
634 ngx_http_log_fmt_t *fmt; | 745 ngx_http_log_fmt_t *fmt; |
635 ngx_http_log_main_conf_t *lmcf; | 746 ngx_http_log_main_conf_t *lmcf; |
636 | 747 |
748 if (conf->open_file_cache == NGX_CONF_UNSET_PTR) { | |
749 | |
750 conf->open_file_cache = prev->open_file_cache; | |
751 conf->open_file_cache_valid = prev->open_file_cache_valid; | |
752 conf->open_file_cache_min_uses = prev->open_file_cache_min_uses; | |
753 | |
754 if (conf->open_file_cache == NGX_CONF_UNSET_PTR) { | |
755 conf->open_file_cache = NULL; | |
756 } | |
757 } | |
758 | |
637 if (conf->logs || conf->off) { | 759 if (conf->logs || conf->off) { |
638 return NGX_CONF_OK; | 760 return NGX_CONF_OK; |
639 } | 761 } |
640 | 762 |
641 *conf = *prev; | 763 *conf = *prev; |
676 static char * | 798 static char * |
677 ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 799 ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
678 { | 800 { |
679 ngx_http_log_loc_conf_t *llcf = conf; | 801 ngx_http_log_loc_conf_t *llcf = conf; |
680 | 802 |
681 ssize_t buf; | 803 ssize_t buf; |
682 ngx_uint_t i; | 804 ngx_uint_t i, n; |
683 ngx_str_t *value, name; | 805 ngx_str_t *value, name; |
684 ngx_http_log_t *log; | 806 ngx_http_log_t *log; |
685 ngx_http_log_fmt_t *fmt; | 807 ngx_http_log_fmt_t *fmt; |
686 ngx_http_log_main_conf_t *lmcf; | 808 ngx_http_log_main_conf_t *lmcf; |
809 ngx_http_script_compile_t sc; | |
687 | 810 |
688 value = cf->args->elts; | 811 value = cf->args->elts; |
689 | 812 |
690 if (ngx_strcmp(value[1].data, "off") == 0) { | 813 if (ngx_strcmp(value[1].data, "off") == 0) { |
691 llcf->off = 1; | 814 llcf->off = 1; |
704 log = ngx_array_push(llcf->logs); | 827 log = ngx_array_push(llcf->logs); |
705 if (log == NULL) { | 828 if (log == NULL) { |
706 return NGX_CONF_ERROR; | 829 return NGX_CONF_ERROR; |
707 } | 830 } |
708 | 831 |
709 log->file = ngx_conf_open_file(cf->cycle, &value[1]); | 832 ngx_memzero(log, sizeof(ngx_http_log_t)); |
710 if (log->file == NULL) { | 833 |
711 return NGX_CONF_ERROR; | 834 n = ngx_http_script_variables_count(&value[1]); |
712 } | 835 |
713 | 836 if (n == 0) { |
714 log->disk_full_time = 0; | 837 log->file = ngx_conf_open_file(cf->cycle, &value[1]); |
715 log->error_log_time = 0; | 838 if (log->file == NULL) { |
839 return NGX_CONF_ERROR; | |
840 } | |
841 | |
842 } else { | |
843 if (ngx_conf_full_name(cf->cycle, &value[1], 0) == NGX_ERROR) { | |
844 return NGX_CONF_ERROR; | |
845 } | |
846 | |
847 log->script = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_script_t)); | |
848 if (log->script == NULL) { | |
849 return NGX_CONF_ERROR; | |
850 } | |
851 | |
852 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); | |
853 | |
854 sc.cf = cf; | |
855 sc.source = &value[1]; | |
856 sc.lengths = &log->script->lengths; | |
857 sc.values = &log->script->values; | |
858 sc.variables = n; | |
859 sc.complete_lengths = 1; | |
860 sc.complete_values = 1; | |
861 | |
862 if (ngx_http_script_compile(&sc) != NGX_OK) { | |
863 return NGX_CONF_ERROR; | |
864 } | |
865 } | |
716 | 866 |
717 if (cf->args->nelts >= 3) { | 867 if (cf->args->nelts >= 3) { |
718 name = value[2]; | 868 name = value[2]; |
719 | 869 |
720 if (ngx_strcmp(name.data, "combined") == 0) { | 870 if (ngx_strcmp(name.data, "combined") == 0) { |
745 | 895 |
746 if (cf->args->nelts == 4) { | 896 if (cf->args->nelts == 4) { |
747 if (ngx_strncmp(value[3].data, "buffer=", 7) != 0) { | 897 if (ngx_strncmp(value[3].data, "buffer=", 7) != 0) { |
748 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | 898 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
749 "invalid parameter \"%V\"", &value[3]); | 899 "invalid parameter \"%V\"", &value[3]); |
900 return NGX_CONF_ERROR; | |
901 } | |
902 | |
903 if (log->script) { | |
904 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
905 "buffered logs can not have variables in name"); | |
750 return NGX_CONF_ERROR; | 906 return NGX_CONF_ERROR; |
751 } | 907 } |
752 | 908 |
753 name.len = value[3].len - 7; | 909 name.len = value[3].len - 7; |
754 name.data = value[3].data + 7; | 910 name.data = value[3].data + 7; |
990 | 1146 |
991 return NGX_CONF_ERROR; | 1147 return NGX_CONF_ERROR; |
992 } | 1148 } |
993 | 1149 |
994 | 1150 |
1151 static char * | |
1152 ngx_http_log_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
1153 { | |
1154 ngx_http_log_loc_conf_t *llcf = conf; | |
1155 | |
1156 time_t inactive, valid; | |
1157 ngx_str_t *value, s; | |
1158 ngx_int_t max, min_uses; | |
1159 ngx_uint_t i; | |
1160 | |
1161 if (llcf->open_file_cache != NGX_CONF_UNSET_PTR) { | |
1162 return "is duplicate"; | |
1163 } | |
1164 | |
1165 value = cf->args->elts; | |
1166 | |
1167 max = 0; | |
1168 inactive = 10; | |
1169 valid = 60; | |
1170 min_uses = 1; | |
1171 | |
1172 for (i = 1; i < cf->args->nelts; i++) { | |
1173 | |
1174 if (ngx_strncmp(value[i].data, "max=", 4) == 0) { | |
1175 | |
1176 max = ngx_atoi(value[i].data + 4, value[i].len - 4); | |
1177 if (max == NGX_ERROR) { | |
1178 goto failed; | |
1179 } | |
1180 | |
1181 continue; | |
1182 } | |
1183 | |
1184 if (ngx_strncmp(value[i].data, "inactive=", 9) == 0) { | |
1185 | |
1186 s.len = value[i].len - 9; | |
1187 s.data = value[i].data + 9; | |
1188 | |
1189 inactive = ngx_parse_time(&s, 1); | |
1190 if (inactive < 0) { | |
1191 goto failed; | |
1192 } | |
1193 | |
1194 continue; | |
1195 } | |
1196 | |
1197 if (ngx_strncmp(value[i].data, "min_uses=", 9) == 0) { | |
1198 | |
1199 min_uses = ngx_atoi(value[i].data + 9, value[i].len - 9); | |
1200 if (min_uses == NGX_ERROR) { | |
1201 goto failed; | |
1202 } | |
1203 | |
1204 continue; | |
1205 } | |
1206 | |
1207 if (ngx_strncmp(value[i].data, "valid=", 6) == 0) { | |
1208 | |
1209 s.len = value[i].len - 6; | |
1210 s.data = value[i].data + 6; | |
1211 | |
1212 valid = ngx_parse_time(&s, 1); | |
1213 if (valid < 0) { | |
1214 goto failed; | |
1215 } | |
1216 | |
1217 continue; | |
1218 } | |
1219 | |
1220 if (ngx_strcmp(value[i].data, "off") == 0) { | |
1221 | |
1222 llcf->open_file_cache = NULL; | |
1223 | |
1224 continue; | |
1225 } | |
1226 | |
1227 failed: | |
1228 | |
1229 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
1230 "invalid \"open_log_file_cache\" parameter \"%V\"", | |
1231 &value[i]); | |
1232 return NGX_CONF_ERROR; | |
1233 } | |
1234 | |
1235 if (llcf->open_file_cache == NULL) { | |
1236 return NGX_CONF_OK; | |
1237 } | |
1238 | |
1239 if (max == 0) { | |
1240 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
1241 "\"open_log_file_cache\" must have \"max\" parameter"); | |
1242 return NGX_CONF_ERROR; | |
1243 } | |
1244 | |
1245 llcf->open_file_cache = ngx_open_file_cache_init(cf->pool, max, inactive); | |
1246 | |
1247 if (llcf->open_file_cache) { | |
1248 | |
1249 llcf->open_file_cache_valid = valid; | |
1250 llcf->open_file_cache_min_uses = min_uses; | |
1251 | |
1252 return NGX_CONF_OK; | |
1253 } | |
1254 | |
1255 return NGX_CONF_ERROR; | |
1256 } | |
1257 | |
1258 | |
995 static ngx_int_t | 1259 static ngx_int_t |
996 ngx_http_log_init(ngx_conf_t *cf) | 1260 ngx_http_log_init(ngx_conf_t *cf) |
997 { | 1261 { |
998 ngx_str_t *value; | 1262 ngx_str_t *value; |
999 ngx_array_t a; | 1263 ngx_array_t a; |