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;