comparison src/http/modules/ngx_http_log_module.c @ 4986:3efc49b156d9

Access log: the "flush" parameter of the "access_log" directive.
author Valentin Bartenev <vbart@nginx.com>
date Sun, 23 Dec 2012 15:51:47 +0000
parents a0599b56e748
children 3849bb380605
comparison
equal deleted inserted replaced
4985:a0599b56e748 4986:3efc49b156d9
42 42
43 typedef struct { 43 typedef struct {
44 u_char *start; 44 u_char *start;
45 u_char *pos; 45 u_char *pos;
46 u_char *last; 46 u_char *last;
47
48 ngx_event_t *event;
49 ngx_msec_t flush;
47 } ngx_http_log_buf_t; 50 } ngx_http_log_buf_t;
48 51
49 52
50 typedef struct { 53 typedef struct {
51 ngx_array_t *lengths; 54 ngx_array_t *lengths;
84 u_char *buf, size_t len); 87 u_char *buf, size_t len);
85 static ssize_t ngx_http_log_script_write(ngx_http_request_t *r, 88 static ssize_t ngx_http_log_script_write(ngx_http_request_t *r,
86 ngx_http_log_script_t *script, u_char **name, u_char *buf, size_t len); 89 ngx_http_log_script_t *script, u_char **name, u_char *buf, size_t len);
87 90
88 static void ngx_http_log_flush(ngx_open_file_t *file, ngx_log_t *log); 91 static void ngx_http_log_flush(ngx_open_file_t *file, ngx_log_t *log);
92 static void ngx_http_log_flush_handler(ngx_event_t *ev);
89 93
90 static u_char *ngx_http_log_pipe(ngx_http_request_t *r, u_char *buf, 94 static u_char *ngx_http_log_pipe(ngx_http_request_t *r, u_char *buf,
91 ngx_http_log_op_t *op); 95 ngx_http_log_op_t *op);
92 static u_char *ngx_http_log_time(ngx_http_request_t *r, u_char *buf, 96 static u_char *ngx_http_log_time(ngx_http_request_t *r, u_char *buf,
93 ngx_http_log_op_t *op); 97 ngx_http_log_op_t *op);
139 0, 143 0,
140 NULL }, 144 NULL },
141 145
142 { ngx_string("access_log"), 146 { ngx_string("access_log"),
143 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF 147 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
144 |NGX_HTTP_LMT_CONF|NGX_CONF_TAKE123, 148 |NGX_HTTP_LMT_CONF|NGX_CONF_1MORE,
145 ngx_http_log_set_log, 149 ngx_http_log_set_log,
146 NGX_HTTP_LOC_CONF_OFFSET, 150 NGX_HTTP_LOC_CONF_OFFSET,
147 0, 151 0,
148 NULL }, 152 NULL },
149 153
281 285
282 if (len <= (size_t) (buffer->last - buffer->pos)) { 286 if (len <= (size_t) (buffer->last - buffer->pos)) {
283 287
284 p = buffer->pos; 288 p = buffer->pos;
285 289
290 if (buffer->event && p == buffer->start) {
291 ngx_add_timer(buffer->event, buffer->flush);
292 }
293
286 for (i = 0; i < log[l].format->ops->nelts; i++) { 294 for (i = 0; i < log[l].format->ops->nelts; i++) {
287 p = op[i].run(r, p, &op[i]); 295 p = op[i].run(r, p, &op[i]);
288 } 296 }
289 297
290 ngx_linefeed(p); 298 ngx_linefeed(p);
291 299
292 buffer->pos = p; 300 buffer->pos = p;
293 301
294 continue; 302 continue;
303 }
304
305 if (buffer->event && buffer->event->timer_set) {
306 ngx_del_timer(buffer->event);
295 } 307 }
296 } 308 }
297 309
298 line = ngx_pnalloc(r->pool, len); 310 line = ngx_pnalloc(r->pool, len);
299 if (line == NULL) { 311 if (line == NULL) {
501 ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz", 513 ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz",
502 file->name.data, n, len); 514 file->name.data, n, len);
503 } 515 }
504 516
505 buffer->pos = buffer->start; 517 buffer->pos = buffer->start;
518
519 if (buffer->event && buffer->event->timer_set) {
520 ngx_del_timer(buffer->event);
521 }
522 }
523
524
525 static void
526 ngx_http_log_flush_handler(ngx_event_t *ev)
527 {
528 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0,
529 "http log buffer flush handler");
530
531 ngx_http_log_flush(ev->data, ev->log);
506 } 532 }
507 533
508 534
509 static u_char * 535 static u_char *
510 ngx_http_log_copy_short(ngx_http_request_t *r, u_char *buf, 536 ngx_http_log_copy_short(ngx_http_request_t *r, u_char *buf,
889 { 915 {
890 ngx_http_log_loc_conf_t *llcf = conf; 916 ngx_http_log_loc_conf_t *llcf = conf;
891 917
892 ssize_t size; 918 ssize_t size;
893 ngx_uint_t i, n; 919 ngx_uint_t i, n;
894 ngx_str_t *value, name; 920 ngx_msec_t flush;
921 ngx_str_t *value, name, s;
895 ngx_http_log_t *log; 922 ngx_http_log_t *log;
896 ngx_http_log_buf_t *buffer; 923 ngx_http_log_buf_t *buffer;
897 ngx_http_log_fmt_t *fmt; 924 ngx_http_log_fmt_t *fmt;
898 ngx_http_log_main_conf_t *lmcf; 925 ngx_http_log_main_conf_t *lmcf;
899 ngx_http_script_compile_t sc; 926 ngx_http_script_compile_t sc;
976 for (i = 0; i < lmcf->formats.nelts; i++) { 1003 for (i = 0; i < lmcf->formats.nelts; i++) {
977 if (fmt[i].name.len == name.len 1004 if (fmt[i].name.len == name.len
978 && ngx_strcasecmp(fmt[i].name.data, name.data) == 0) 1005 && ngx_strcasecmp(fmt[i].name.data, name.data) == 0)
979 { 1006 {
980 log->format = &fmt[i]; 1007 log->format = &fmt[i];
981 goto buffer; 1008 break;
982 } 1009 }
983 } 1010 }
984 1011
985 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 1012 if (log->format == NULL) {
986 "unknown log format \"%V\"", &name); 1013 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
987 return NGX_CONF_ERROR; 1014 "unknown log format \"%V\"", &name);
988 1015 return NGX_CONF_ERROR;
989 buffer: 1016 }
990 1017
991 if (cf->args->nelts == 4) { 1018 size = 0;
992 if (ngx_strncmp(value[3].data, "buffer=", 7) != 0) { 1019 flush = 0;
993 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 1020
994 "invalid parameter \"%V\"", &value[3]); 1021 for (i = 3; i < cf->args->nelts; i++) {
995 return NGX_CONF_ERROR; 1022
996 } 1023 if (ngx_strncmp(value[i].data, "buffer=", 7) == 0) {
1024 s.len = value[i].len - 7;
1025 s.data = value[i].data + 7;
1026
1027 size = ngx_parse_size(&s);
1028
1029 if (size == NGX_ERROR || size == 0) {
1030 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1031 "invalid buffer size \"%V\"", &s);
1032 return NGX_CONF_ERROR;
1033 }
1034
1035 continue;
1036 }
1037
1038 if (ngx_strncmp(value[i].data, "flush=", 6) == 0) {
1039 s.len = value[i].len - 6;
1040 s.data = value[i].data + 6;
1041
1042 flush = ngx_parse_time(&s, 0);
1043
1044 if (flush == (ngx_msec_t) NGX_ERROR || flush == 0) {
1045 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1046 "invalid flush time \"%V\"", &s);
1047 return NGX_CONF_ERROR;
1048 }
1049
1050 continue;
1051 }
1052
1053 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1054 "invalid parameter \"%V\"", &value[i]);
1055 return NGX_CONF_ERROR;
1056 }
1057
1058 if (flush && size == 0) {
1059 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1060 "no buffer is defined for access_log \"%V\"",
1061 &value[1]);
1062 return NGX_CONF_ERROR;
1063 }
1064
1065 if (size) {
997 1066
998 if (log->script) { 1067 if (log->script) {
999 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 1068 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1000 "buffered logs cannot have variables in name"); 1069 "buffered logs cannot have variables in name");
1001 return NGX_CONF_ERROR; 1070 return NGX_CONF_ERROR;
1002 } 1071 }
1003 1072
1004 name.len = value[3].len - 7;
1005 name.data = value[3].data + 7;
1006
1007 size = ngx_parse_size(&name);
1008
1009 if (size == NGX_ERROR) {
1010 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1011 "invalid buffer value \"%V\"", &name);
1012 return NGX_CONF_ERROR;
1013 }
1014
1015 if (log->file->data) { 1073 if (log->file->data) {
1016 buffer = log->file->data; 1074 buffer = log->file->data;
1017 1075
1018 if (buffer->last - buffer->start != size) { 1076 if (buffer->last - buffer->start != size
1077 || buffer->flush != flush)
1078 {
1019 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 1079 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1020 "access_log \"%V\" already defined " 1080 "access_log \"%V\" already defined "
1021 "with different buffer size", &value[1]); 1081 "with conflicting parameters",
1082 &value[1]);
1022 return NGX_CONF_ERROR; 1083 return NGX_CONF_ERROR;
1023 } 1084 }
1024 1085
1025 return NGX_CONF_OK; 1086 return NGX_CONF_OK;
1026 } 1087 }
1035 return NGX_CONF_ERROR; 1096 return NGX_CONF_ERROR;
1036 } 1097 }
1037 1098
1038 buffer->pos = buffer->start; 1099 buffer->pos = buffer->start;
1039 buffer->last = buffer->start + size; 1100 buffer->last = buffer->start + size;
1101
1102 if (flush) {
1103 buffer->event = ngx_pcalloc(cf->pool, sizeof(ngx_event_t));
1104 if (buffer->event == NULL) {
1105 return NGX_CONF_ERROR;
1106 }
1107
1108 buffer->event->data = log->file;
1109 buffer->event->handler = ngx_http_log_flush_handler;
1110 buffer->event->log = &cf->cycle->new_log;
1111
1112 buffer->flush = flush;
1113 }
1040 1114
1041 log->file->flush = ngx_http_log_flush; 1115 log->file->flush = ngx_http_log_flush;
1042 log->file->data = buffer; 1116 log->file->data = buffer;
1043 } 1117 }
1044 1118