Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 1 | |
Igor Sysoev | d90282d | 2004-09-28 08:34:51 +0000 | [diff] [blame] | 2 | /* |
Igor Sysoev | ff8da91 | 2004-09-29 16:00:49 +0000 | [diff] [blame] | 3 | * Copyright (C) Igor Sysoev |
Igor Sysoev | d90282d | 2004-09-28 08:34:51 +0000 | [diff] [blame] | 4 | */ |
| 5 | |
| 6 | |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 7 | #include <ngx_config.h> |
| 8 | #include <ngx_core.h> |
| 9 | #include <ngx_http.h> |
| 10 | #include <nginx.h> |
| 11 | |
| 12 | |
Igor Sysoev | a8c54c0 | 2006-11-27 14:46:15 +0000 | [diff] [blame] | 13 | typedef struct ngx_http_log_op_s ngx_http_log_op_t; |
| 14 | |
| 15 | typedef u_char *(*ngx_http_log_op_run_pt) (ngx_http_request_t *r, u_char *buf, |
| 16 | ngx_http_log_op_t *op); |
| 17 | |
| 18 | typedef size_t (*ngx_http_log_op_getlen_pt) (ngx_http_request_t *r, |
| 19 | uintptr_t data); |
| 20 | |
| 21 | |
| 22 | struct ngx_http_log_op_s { |
| 23 | size_t len; |
| 24 | ngx_http_log_op_getlen_pt getlen; |
| 25 | ngx_http_log_op_run_pt run; |
| 26 | uintptr_t data; |
| 27 | }; |
| 28 | |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 29 | |
| 30 | typedef struct { |
| 31 | ngx_str_t name; |
| 32 | ngx_array_t *ops; /* array of ngx_http_log_op_t */ |
| 33 | } ngx_http_log_fmt_t; |
| 34 | |
Igor Sysoev | ef809b8 | 2006-06-28 16:00:26 +0000 | [diff] [blame] | 35 | |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 36 | typedef struct { |
| 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; |
| 40 | |
Igor Sysoev | ef809b8 | 2006-06-28 16:00:26 +0000 | [diff] [blame] | 41 | |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 42 | typedef struct { |
| 43 | ngx_open_file_t *file; |
Igor Sysoev | 8a2b2fb | 2006-04-14 09:53:38 +0000 | [diff] [blame] | 44 | time_t disk_full_time; |
Igor Sysoev | d0863c1 | 2007-01-21 19:01:01 +0000 | [diff] [blame] | 45 | time_t error_log_time; |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 46 | ngx_array_t *ops; /* array of ngx_http_log_op_t */ |
| 47 | } ngx_http_log_t; |
| 48 | |
Igor Sysoev | ef809b8 | 2006-06-28 16:00:26 +0000 | [diff] [blame] | 49 | |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 50 | typedef struct { |
| 51 | ngx_array_t *logs; /* array of ngx_http_log_t */ |
| 52 | ngx_uint_t off; /* unsigned off:1 */ |
| 53 | } ngx_http_log_loc_conf_t; |
| 54 | |
| 55 | |
| 56 | typedef struct { |
| 57 | ngx_str_t name; |
| 58 | size_t len; |
| 59 | ngx_http_log_op_run_pt run; |
| 60 | } ngx_http_log_var_t; |
| 61 | |
| 62 | |
Igor Sysoev | d0863c1 | 2007-01-21 19:01:01 +0000 | [diff] [blame] | 63 | static void ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log, |
| 64 | u_char *buf, size_t len); |
| 65 | |
Igor Sysoev | 10a543a | 2004-03-16 07:10:12 +0000 | [diff] [blame] | 66 | static u_char *ngx_http_log_connection(ngx_http_request_t *r, u_char *buf, |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 67 | ngx_http_log_op_t *op); |
Igor Sysoev | 10a543a | 2004-03-16 07:10:12 +0000 | [diff] [blame] | 68 | static u_char *ngx_http_log_pipe(ngx_http_request_t *r, u_char *buf, |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 69 | ngx_http_log_op_t *op); |
Igor Sysoev | 10a543a | 2004-03-16 07:10:12 +0000 | [diff] [blame] | 70 | static u_char *ngx_http_log_time(ngx_http_request_t *r, u_char *buf, |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 71 | ngx_http_log_op_t *op); |
Igor Sysoev | a7c4a2a | 2004-08-29 03:55:41 +0000 | [diff] [blame] | 72 | static u_char *ngx_http_log_msec(ngx_http_request_t *r, u_char *buf, |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 73 | ngx_http_log_op_t *op); |
| 74 | static u_char *ngx_http_log_request_time(ngx_http_request_t *r, u_char *buf, |
| 75 | ngx_http_log_op_t *op); |
Igor Sysoev | 10a543a | 2004-03-16 07:10:12 +0000 | [diff] [blame] | 76 | static u_char *ngx_http_log_status(ngx_http_request_t *r, u_char *buf, |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 77 | ngx_http_log_op_t *op); |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 78 | static u_char *ngx_http_log_bytes_sent(ngx_http_request_t *r, u_char *buf, |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 79 | ngx_http_log_op_t *op); |
Igor Sysoev | 0e5dc5c | 2005-11-15 13:30:52 +0000 | [diff] [blame] | 80 | static u_char *ngx_http_log_body_bytes_sent(ngx_http_request_t *r, |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 81 | u_char *buf, ngx_http_log_op_t *op); |
Igor Sysoev | 6a12fc9 | 2004-12-06 14:45:08 +0000 | [diff] [blame] | 82 | static u_char *ngx_http_log_request_length(ngx_http_request_t *r, u_char *buf, |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 83 | ngx_http_log_op_t *op); |
Igor Sysoev | 02025fd | 2005-01-18 13:03:58 +0000 | [diff] [blame] | 84 | |
Igor Sysoev | c157172 | 2005-03-19 12:38:37 +0000 | [diff] [blame] | 85 | static ngx_int_t ngx_http_log_variable_compile(ngx_conf_t *cf, |
| 86 | ngx_http_log_op_t *op, ngx_str_t *value); |
| 87 | static size_t ngx_http_log_variable_getlen(ngx_http_request_t *r, |
| 88 | uintptr_t data); |
| 89 | static u_char *ngx_http_log_variable(ngx_http_request_t *r, u_char *buf, |
| 90 | ngx_http_log_op_t *op); |
| 91 | |
| 92 | |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 93 | static void *ngx_http_log_create_main_conf(ngx_conf_t *cf); |
| 94 | static void *ngx_http_log_create_loc_conf(ngx_conf_t *cf); |
| 95 | static char *ngx_http_log_merge_loc_conf(ngx_conf_t *cf, void *parent, |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 96 | void *child); |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 97 | static char *ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd, |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 98 | void *conf); |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 99 | static char *ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd, |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 100 | void *conf); |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 101 | static char *ngx_http_log_compile_format(ngx_conf_t *cf, |
| 102 | ngx_array_t *ops, ngx_array_t *args, ngx_uint_t s); |
| 103 | static ngx_int_t ngx_http_log_init(ngx_conf_t *cf); |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 104 | |
| 105 | |
| 106 | static ngx_command_t ngx_http_log_commands[] = { |
| 107 | |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 108 | { ngx_string("log_format"), |
| 109 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_2MORE, |
| 110 | ngx_http_log_set_format, |
| 111 | NGX_HTTP_MAIN_CONF_OFFSET, |
| 112 | 0, |
| 113 | NULL }, |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 114 | |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 115 | { ngx_string("access_log"), |
Igor Sysoev | ac72bd1 | 2006-05-04 15:32:46 +0000 | [diff] [blame] | 116 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF |
| 117 | |NGX_CONF_TAKE123, |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 118 | ngx_http_log_set_log, |
| 119 | NGX_HTTP_LOC_CONF_OFFSET, |
| 120 | 0, |
| 121 | NULL }, |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 122 | |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 123 | ngx_null_command |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 124 | }; |
| 125 | |
| 126 | |
Igor Sysoev | 8f12558 | 2006-07-28 15:16:17 +0000 | [diff] [blame] | 127 | static ngx_http_module_t ngx_http_log_module_ctx = { |
Igor Sysoev | a8c54c0 | 2006-11-27 14:46:15 +0000 | [diff] [blame] | 128 | NULL, /* preconfiguration */ |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 129 | ngx_http_log_init, /* postconfiguration */ |
Igor Sysoev | 7832933 | 2003-11-10 17:17:31 +0000 | [diff] [blame] | 130 | |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 131 | ngx_http_log_create_main_conf, /* create main configuration */ |
| 132 | NULL, /* init main configuration */ |
| 133 | |
| 134 | NULL, /* create server configuration */ |
| 135 | NULL, /* merge server configuration */ |
| 136 | |
| 137 | ngx_http_log_create_loc_conf, /* create location configration */ |
| 138 | ngx_http_log_merge_loc_conf /* merge location configration */ |
| 139 | }; |
| 140 | |
| 141 | |
| 142 | ngx_module_t ngx_http_log_module = { |
Igor Sysoev | 899b44e | 2005-05-12 14:58:06 +0000 | [diff] [blame] | 143 | NGX_MODULE_V1, |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 144 | &ngx_http_log_module_ctx, /* module context */ |
| 145 | ngx_http_log_commands, /* module directives */ |
| 146 | NGX_HTTP_MODULE, /* module type */ |
Igor Sysoev | e573380 | 2005-09-08 14:36:09 +0000 | [diff] [blame] | 147 | NULL, /* init master */ |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 148 | NULL, /* init module */ |
Igor Sysoev | e573380 | 2005-09-08 14:36:09 +0000 | [diff] [blame] | 149 | NULL, /* init process */ |
| 150 | NULL, /* init thread */ |
| 151 | NULL, /* exit thread */ |
| 152 | NULL, /* exit process */ |
| 153 | NULL, /* exit master */ |
| 154 | NGX_MODULE_V1_PADDING |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 155 | }; |
| 156 | |
| 157 | |
Igor Sysoev | 3a58cc9 | 2007-01-24 09:15:25 +0000 | [diff] [blame] | 158 | static ngx_str_t ngx_http_access_log = ngx_string(NGX_HTTP_LOG_PATH); |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 159 | |
| 160 | |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 161 | static ngx_str_t ngx_http_combined_fmt = |
Igor Sysoev | c31a9bb | 2005-11-26 10:11:11 +0000 | [diff] [blame] | 162 | ngx_string("$remote_addr - $remote_user [$time_local] " |
Igor Sysoev | 0e5dc5c | 2005-11-15 13:30:52 +0000 | [diff] [blame] | 163 | "\"$request\" $status $body_bytes_sent " |
Igor Sysoev | 9ac946b | 2005-10-24 15:09:41 +0000 | [diff] [blame] | 164 | "\"$http_referer\" \"$http_user_agent\""); |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 165 | |
| 166 | |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 167 | static ngx_http_log_var_t ngx_http_log_vars[] = { |
| 168 | { ngx_string("connection"), NGX_ATOMIC_T_LEN, ngx_http_log_connection }, |
| 169 | { ngx_string("pipe"), 1, ngx_http_log_pipe }, |
Igor Sysoev | c31a9bb | 2005-11-26 10:11:11 +0000 | [diff] [blame] | 170 | { ngx_string("time_local"), sizeof("28/Sep/1970:12:00:00 +0600") - 1, |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 171 | ngx_http_log_time }, |
| 172 | { ngx_string("msec"), NGX_TIME_T_LEN + 4, ngx_http_log_msec }, |
| 173 | { ngx_string("request_time"), NGX_TIME_T_LEN, ngx_http_log_request_time }, |
| 174 | { ngx_string("status"), 3, ngx_http_log_status }, |
| 175 | { ngx_string("bytes_sent"), NGX_OFF_T_LEN, ngx_http_log_bytes_sent }, |
Igor Sysoev | 0e5dc5c | 2005-11-15 13:30:52 +0000 | [diff] [blame] | 176 | { ngx_string("body_bytes_sent"), NGX_OFF_T_LEN, |
| 177 | ngx_http_log_body_bytes_sent }, |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 178 | { ngx_string("apache_bytes_sent"), NGX_OFF_T_LEN, |
Igor Sysoev | 0e5dc5c | 2005-11-15 13:30:52 +0000 | [diff] [blame] | 179 | ngx_http_log_body_bytes_sent }, |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 180 | { ngx_string("request_length"), NGX_SIZE_T_LEN, |
| 181 | ngx_http_log_request_length }, |
| 182 | |
| 183 | { ngx_null_string, 0, NULL } |
| 184 | }; |
| 185 | |
| 186 | |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 187 | ngx_int_t |
| 188 | ngx_http_log_handler(ngx_http_request_t *r) |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 189 | { |
Igor Sysoev | 10a543a | 2004-03-16 07:10:12 +0000 | [diff] [blame] | 190 | u_char *line, *p; |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 191 | size_t len; |
Igor Sysoev | d0863c1 | 2007-01-21 19:01:01 +0000 | [diff] [blame] | 192 | ngx_uint_t i, l; |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 193 | ngx_http_log_t *log; |
Igor Sysoev | 697d1ae | 2005-10-27 15:46:13 +0000 | [diff] [blame] | 194 | ngx_open_file_t *file; |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 195 | ngx_http_log_op_t *op; |
| 196 | ngx_http_log_loc_conf_t *lcf; |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 197 | |
Igor Sysoev | dc867cd | 2003-12-14 20:10:27 +0000 | [diff] [blame] | 198 | ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
| 199 | "http log handler"); |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 200 | |
| 201 | lcf = ngx_http_get_module_loc_conf(r, ngx_http_log_module); |
| 202 | |
Igor Sysoev | 85cccfb | 2004-09-15 16:00:43 +0000 | [diff] [blame] | 203 | if (lcf->off) { |
| 204 | return NGX_OK; |
| 205 | } |
| 206 | |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 207 | log = lcf->logs->elts; |
| 208 | for (l = 0; l < lcf->logs->nelts; l++) { |
| 209 | |
Igor Sysoev | 8a2b2fb | 2006-04-14 09:53:38 +0000 | [diff] [blame] | 210 | if (ngx_time() == log[l].disk_full_time) { |
| 211 | |
| 212 | /* |
Igor Sysoev | d0863c1 | 2007-01-21 19:01:01 +0000 | [diff] [blame] | 213 | * on FreeBSD writing to a full filesystem with enabled softupdates |
Igor Sysoev | 8a2b2fb | 2006-04-14 09:53:38 +0000 | [diff] [blame] | 214 | * may block process for much longer time than writing to non-full |
Igor Sysoev | d0863c1 | 2007-01-21 19:01:01 +0000 | [diff] [blame] | 215 | * filesystem, so we skip writing to a log for one second |
Igor Sysoev | 8a2b2fb | 2006-04-14 09:53:38 +0000 | [diff] [blame] | 216 | */ |
| 217 | |
| 218 | continue; |
| 219 | } |
| 220 | |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 221 | len = 0; |
| 222 | op = log[l].ops->elts; |
| 223 | for (i = 0; i < log[l].ops->nelts; i++) { |
| 224 | if (op[i].len == 0) { |
Igor Sysoev | 02025fd | 2005-01-18 13:03:58 +0000 | [diff] [blame] | 225 | len += op[i].getlen(r, op[i].data); |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 226 | |
| 227 | } else { |
| 228 | len += op[i].len; |
| 229 | } |
| 230 | } |
| 231 | |
Igor Sysoev | 697d1ae | 2005-10-27 15:46:13 +0000 | [diff] [blame] | 232 | len += NGX_LINEFEED_SIZE; |
| 233 | |
| 234 | file = log[l].file; |
| 235 | |
| 236 | if (file->buffer) { |
| 237 | |
| 238 | if (len > (size_t) (file->last - file->pos)) { |
| 239 | |
Igor Sysoev | d0863c1 | 2007-01-21 19:01:01 +0000 | [diff] [blame] | 240 | ngx_http_log_write(r, &log[l], file->buffer, |
| 241 | file->pos - file->buffer); |
Igor Sysoev | 697d1ae | 2005-10-27 15:46:13 +0000 | [diff] [blame] | 242 | |
| 243 | file->pos = file->buffer; |
| 244 | } |
| 245 | |
| 246 | if (len <= (size_t) (file->last - file->pos)) { |
| 247 | |
| 248 | p = file->pos; |
| 249 | |
| 250 | for (i = 0; i < log[l].ops->nelts; i++) { |
| 251 | p = op[i].run(r, p, &op[i]); |
| 252 | } |
| 253 | |
| 254 | ngx_linefeed(p); |
| 255 | |
| 256 | file->pos = p; |
| 257 | |
| 258 | continue; |
| 259 | } |
| 260 | } |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 261 | |
Igor Sysoev | c157172 | 2005-03-19 12:38:37 +0000 | [diff] [blame] | 262 | line = ngx_palloc(r->pool, len); |
| 263 | if (line == NULL) { |
Igor Sysoev | 42b12b3 | 2004-12-02 18:40:46 +0000 | [diff] [blame] | 264 | return NGX_ERROR; |
| 265 | } |
| 266 | |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 267 | p = line; |
| 268 | |
| 269 | for (i = 0; i < log[l].ops->nelts; i++) { |
Igor Sysoev | 02025fd | 2005-01-18 13:03:58 +0000 | [diff] [blame] | 270 | p = op[i].run(r, p, &op[i]); |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 271 | } |
| 272 | |
Igor Sysoev | 697d1ae | 2005-10-27 15:46:13 +0000 | [diff] [blame] | 273 | ngx_linefeed(p); |
| 274 | |
Igor Sysoev | d0863c1 | 2007-01-21 19:01:01 +0000 | [diff] [blame] | 275 | ngx_http_log_write(r, &log[l], line, p - line); |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 276 | } |
| 277 | |
| 278 | return NGX_OK; |
| 279 | } |
| 280 | |
| 281 | |
Igor Sysoev | d0863c1 | 2007-01-21 19:01:01 +0000 | [diff] [blame] | 282 | static void |
| 283 | ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log, u_char *buf, |
| 284 | size_t len) |
| 285 | { |
| 286 | time_t now; |
| 287 | ssize_t n; |
| 288 | ngx_err_t err; |
| 289 | |
| 290 | n = ngx_write_fd(log->file->fd, buf, len); |
| 291 | |
| 292 | if (n == (ssize_t) len) { |
| 293 | return; |
| 294 | } |
| 295 | |
| 296 | now = ngx_time(); |
| 297 | |
| 298 | if (n == -1) { |
| 299 | err = ngx_errno; |
| 300 | |
| 301 | if (err == NGX_ENOSPC) { |
| 302 | log->disk_full_time = now; |
| 303 | } |
| 304 | |
| 305 | if (now - log->error_log_time > 60) { |
| 306 | ngx_log_error(NGX_LOG_ALERT, r->connection->log, err, |
| 307 | ngx_write_fd_n " to \"%V\" failed", |
| 308 | &log->file->name); |
| 309 | |
| 310 | log->error_log_time = now; |
| 311 | } |
| 312 | |
| 313 | return; |
| 314 | } |
| 315 | |
| 316 | if (now - log->error_log_time > 60) { |
| 317 | ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, |
| 318 | ngx_write_fd_n " to \"%V\" was incomplete: %z of %uz", |
| 319 | &log->file->name, n, len); |
| 320 | |
| 321 | log->error_log_time = now; |
| 322 | } |
| 323 | } |
| 324 | |
| 325 | |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 326 | static u_char * |
| 327 | ngx_http_log_copy_short(ngx_http_request_t *r, u_char *buf, |
| 328 | ngx_http_log_op_t *op) |
Igor Sysoev | 02025fd | 2005-01-18 13:03:58 +0000 | [diff] [blame] | 329 | { |
| 330 | size_t len; |
| 331 | uintptr_t data; |
| 332 | |
| 333 | len = op->len; |
| 334 | data = op->data; |
| 335 | |
| 336 | while (len--) { |
| 337 | *buf++ = (u_char) (data & 0xff); |
| 338 | data >>= 8; |
| 339 | } |
| 340 | |
| 341 | return buf; |
| 342 | } |
| 343 | |
| 344 | |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 345 | static u_char * |
| 346 | ngx_http_log_copy_long(ngx_http_request_t *r, u_char *buf, |
| 347 | ngx_http_log_op_t *op) |
Igor Sysoev | 02025fd | 2005-01-18 13:03:58 +0000 | [diff] [blame] | 348 | { |
| 349 | return ngx_cpymem(buf, (u_char *) op->data, op->len); |
| 350 | } |
| 351 | |
| 352 | |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 353 | static u_char * |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 354 | ngx_http_log_connection(ngx_http_request_t *r, u_char *buf, |
| 355 | ngx_http_log_op_t *op) |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 356 | { |
Igor Sysoev | c0edbcc | 2004-10-21 15:34:38 +0000 | [diff] [blame] | 357 | return ngx_sprintf(buf, "%ui", r->connection->number); |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 358 | } |
| 359 | |
| 360 | |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 361 | static u_char * |
| 362 | ngx_http_log_pipe(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op) |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 363 | { |
| 364 | if (r->pipeline) { |
| 365 | *buf = 'p'; |
| 366 | } else { |
| 367 | *buf = '.'; |
| 368 | } |
| 369 | |
| 370 | return buf + 1; |
| 371 | } |
| 372 | |
| 373 | |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 374 | static u_char * |
| 375 | ngx_http_log_time(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op) |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 376 | { |
Igor Sysoev | d59a047 | 2003-11-10 21:09:22 +0000 | [diff] [blame] | 377 | return ngx_cpymem(buf, ngx_cached_http_log_time.data, |
| 378 | ngx_cached_http_log_time.len); |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 379 | } |
| 380 | |
| 381 | |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 382 | static u_char * |
| 383 | ngx_http_log_msec(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op) |
Igor Sysoev | a7c4a2a | 2004-08-29 03:55:41 +0000 | [diff] [blame] | 384 | { |
Igor Sysoev | c2068d0 | 2005-10-19 12:33:58 +0000 | [diff] [blame] | 385 | ngx_time_t *tp; |
Igor Sysoev | a7c4a2a | 2004-08-29 03:55:41 +0000 | [diff] [blame] | 386 | |
Igor Sysoev | c2068d0 | 2005-10-19 12:33:58 +0000 | [diff] [blame] | 387 | tp = ngx_timeofday(); |
Igor Sysoev | a7c4a2a | 2004-08-29 03:55:41 +0000 | [diff] [blame] | 388 | |
Igor Sysoev | c2068d0 | 2005-10-19 12:33:58 +0000 | [diff] [blame] | 389 | return ngx_sprintf(buf, "%T.%03M", tp->sec, tp->msec); |
Igor Sysoev | a7c4a2a | 2004-08-29 03:55:41 +0000 | [diff] [blame] | 390 | } |
| 391 | |
| 392 | |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 393 | static u_char * |
| 394 | ngx_http_log_request_time(ngx_http_request_t *r, u_char *buf, |
| 395 | ngx_http_log_op_t *op) |
| 396 | { |
| 397 | time_t elapsed; |
| 398 | |
| 399 | elapsed = ngx_time() - r->start_time; |
| 400 | |
| 401 | return ngx_sprintf(buf, "%T", elapsed); |
| 402 | } |
| 403 | |
| 404 | |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 405 | static u_char * |
| 406 | ngx_http_log_status(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op) |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 407 | { |
Igor Sysoev | c0edbcc | 2004-10-21 15:34:38 +0000 | [diff] [blame] | 408 | return ngx_sprintf(buf, "%ui", |
| 409 | r->err_status ? r->err_status : r->headers_out.status); |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 410 | } |
| 411 | |
| 412 | |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 413 | static u_char * |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 414 | ngx_http_log_bytes_sent(ngx_http_request_t *r, u_char *buf, |
| 415 | ngx_http_log_op_t *op) |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 416 | { |
Igor Sysoev | c0edbcc | 2004-10-21 15:34:38 +0000 | [diff] [blame] | 417 | return ngx_sprintf(buf, "%O", r->connection->sent); |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 418 | } |
| 419 | |
| 420 | |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 421 | static u_char * |
Igor Sysoev | 0e5dc5c | 2005-11-15 13:30:52 +0000 | [diff] [blame] | 422 | ngx_http_log_body_bytes_sent(ngx_http_request_t *r, u_char *buf, |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 423 | ngx_http_log_op_t *op) |
Igor Sysoev | dc867cd | 2003-12-14 20:10:27 +0000 | [diff] [blame] | 424 | { |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 425 | off_t length; |
| 426 | |
| 427 | length = r->connection->sent - r->header_size; |
| 428 | |
| 429 | if (length > 0) { |
| 430 | return ngx_sprintf(buf, "%O", length); |
| 431 | } |
| 432 | |
| 433 | *buf = '0'; |
| 434 | |
| 435 | return buf + 1; |
Igor Sysoev | dc867cd | 2003-12-14 20:10:27 +0000 | [diff] [blame] | 436 | } |
| 437 | |
| 438 | |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 439 | static u_char * |
| 440 | ngx_http_log_request_length(ngx_http_request_t *r, u_char *buf, |
| 441 | ngx_http_log_op_t *op) |
Igor Sysoev | 6a12fc9 | 2004-12-06 14:45:08 +0000 | [diff] [blame] | 442 | { |
Igor Sysoev | 1765f47 | 2006-07-07 16:33:19 +0000 | [diff] [blame] | 443 | return ngx_sprintf(buf, "%O", r->request_length); |
Igor Sysoev | 6a12fc9 | 2004-12-06 14:45:08 +0000 | [diff] [blame] | 444 | } |
| 445 | |
| 446 | |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 447 | static ngx_int_t |
Igor Sysoev | c157172 | 2005-03-19 12:38:37 +0000 | [diff] [blame] | 448 | ngx_http_log_variable_compile(ngx_conf_t *cf, ngx_http_log_op_t *op, |
| 449 | ngx_str_t *value) |
| 450 | { |
Igor Sysoev | 899b44e | 2005-05-12 14:58:06 +0000 | [diff] [blame] | 451 | ngx_int_t index; |
Igor Sysoev | c157172 | 2005-03-19 12:38:37 +0000 | [diff] [blame] | 452 | |
Igor Sysoev | 899b44e | 2005-05-12 14:58:06 +0000 | [diff] [blame] | 453 | index = ngx_http_get_variable_index(cf, value); |
| 454 | if (index == NGX_ERROR) { |
Igor Sysoev | c157172 | 2005-03-19 12:38:37 +0000 | [diff] [blame] | 455 | return NGX_ERROR; |
| 456 | } |
| 457 | |
| 458 | op->len = 0; |
| 459 | op->getlen = ngx_http_log_variable_getlen; |
| 460 | op->run = ngx_http_log_variable; |
Igor Sysoev | 899b44e | 2005-05-12 14:58:06 +0000 | [diff] [blame] | 461 | op->data = index; |
Igor Sysoev | c157172 | 2005-03-19 12:38:37 +0000 | [diff] [blame] | 462 | |
| 463 | return NGX_OK; |
| 464 | } |
| 465 | |
| 466 | |
| 467 | static size_t |
| 468 | ngx_http_log_variable_getlen(ngx_http_request_t *r, uintptr_t data) |
| 469 | { |
| 470 | ngx_http_variable_value_t *value; |
| 471 | |
| 472 | value = ngx_http_get_indexed_variable(r, data); |
| 473 | |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 474 | if (value == NULL || value->not_found) { |
Igor Sysoev | c157172 | 2005-03-19 12:38:37 +0000 | [diff] [blame] | 475 | return 1; |
| 476 | } |
| 477 | |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 478 | return value->len; |
Igor Sysoev | c157172 | 2005-03-19 12:38:37 +0000 | [diff] [blame] | 479 | } |
| 480 | |
| 481 | |
| 482 | static u_char * |
| 483 | ngx_http_log_variable(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op) |
| 484 | { |
| 485 | ngx_http_variable_value_t *value; |
| 486 | |
| 487 | value = ngx_http_get_indexed_variable(r, op->data); |
| 488 | |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 489 | if (value == NULL || value->not_found) { |
Igor Sysoev | c157172 | 2005-03-19 12:38:37 +0000 | [diff] [blame] | 490 | *buf = '-'; |
| 491 | return buf + 1; |
| 492 | } |
| 493 | |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 494 | return ngx_cpymem(buf, value->data, value->len); |
Igor Sysoev | c157172 | 2005-03-19 12:38:37 +0000 | [diff] [blame] | 495 | } |
| 496 | |
| 497 | |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 498 | static void * |
| 499 | ngx_http_log_create_main_conf(ngx_conf_t *cf) |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 500 | { |
| 501 | ngx_http_log_main_conf_t *conf; |
| 502 | |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 503 | ngx_http_log_fmt_t *fmt; |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 504 | |
Igor Sysoev | c157172 | 2005-03-19 12:38:37 +0000 | [diff] [blame] | 505 | conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_main_conf_t)); |
| 506 | if (conf == NULL) { |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 507 | return NGX_CONF_ERROR; |
| 508 | } |
| 509 | |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 510 | if (ngx_array_init(&conf->formats, cf->pool, 4, sizeof(ngx_http_log_fmt_t)) |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 511 | != NGX_OK) |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 512 | { |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 513 | return NGX_CONF_ERROR; |
| 514 | } |
| 515 | |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 516 | fmt = ngx_array_push(&conf->formats); |
| 517 | if (fmt == NULL) { |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 518 | return NGX_CONF_ERROR; |
| 519 | } |
| 520 | |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 521 | fmt->name.len = sizeof("combined") - 1; |
| 522 | fmt->name.data = (u_char *) "combined"; |
Igor Sysoev | 9ac946b | 2005-10-24 15:09:41 +0000 | [diff] [blame] | 523 | |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 524 | fmt->ops = ngx_array_create(cf->pool, 16, sizeof(ngx_http_log_op_t)); |
| 525 | if (fmt->ops == NULL) { |
Igor Sysoev | 9ac946b | 2005-10-24 15:09:41 +0000 | [diff] [blame] | 526 | return NGX_CONF_ERROR; |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 527 | } |
| 528 | |
| 529 | return conf; |
| 530 | } |
| 531 | |
| 532 | |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 533 | static void * |
| 534 | ngx_http_log_create_loc_conf(ngx_conf_t *cf) |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 535 | { |
| 536 | ngx_http_log_loc_conf_t *conf; |
| 537 | |
Igor Sysoev | c157172 | 2005-03-19 12:38:37 +0000 | [diff] [blame] | 538 | conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_loc_conf_t)); |
| 539 | if (conf == NULL) { |
Igor Sysoev | 85cccfb | 2004-09-15 16:00:43 +0000 | [diff] [blame] | 540 | return NGX_CONF_ERROR; |
| 541 | } |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 542 | |
| 543 | return conf; |
| 544 | } |
| 545 | |
| 546 | |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 547 | static char * |
| 548 | ngx_http_log_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 549 | { |
| 550 | ngx_http_log_loc_conf_t *prev = parent; |
| 551 | ngx_http_log_loc_conf_t *conf = child; |
| 552 | |
| 553 | ngx_http_log_t *log; |
| 554 | ngx_http_log_fmt_t *fmt; |
| 555 | ngx_http_log_main_conf_t *lmcf; |
| 556 | |
Igor Sysoev | 3a58cc9 | 2007-01-24 09:15:25 +0000 | [diff] [blame] | 557 | if (conf->logs || conf->off) { |
| 558 | return NGX_CONF_OK; |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 559 | } |
| 560 | |
Igor Sysoev | 3a58cc9 | 2007-01-24 09:15:25 +0000 | [diff] [blame] | 561 | *conf = *prev; |
| 562 | |
| 563 | if (conf->logs || conf->off) { |
| 564 | return NGX_CONF_OK; |
| 565 | } |
| 566 | |
| 567 | conf->logs = ngx_array_create(cf->pool, 2, sizeof(ngx_http_log_t)); |
| 568 | if (conf->logs == NULL) { |
| 569 | return NGX_CONF_ERROR; |
| 570 | } |
| 571 | |
| 572 | log = ngx_array_push(conf->logs); |
| 573 | if (log == NULL) { |
| 574 | return NGX_CONF_ERROR; |
| 575 | } |
| 576 | |
| 577 | log->file = ngx_conf_open_file(cf->cycle, &ngx_http_access_log); |
| 578 | if (log->file == NULL) { |
| 579 | return NGX_CONF_ERROR; |
| 580 | } |
| 581 | |
| 582 | log->disk_full_time = 0; |
| 583 | log->error_log_time = 0; |
| 584 | |
| 585 | lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_log_module); |
| 586 | fmt = lmcf->formats.elts; |
| 587 | |
| 588 | /* the default "combined" format */ |
| 589 | log->ops = fmt[0].ops; |
| 590 | lmcf->combined_used = 1; |
| 591 | |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 592 | return NGX_CONF_OK; |
| 593 | } |
| 594 | |
| 595 | |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 596 | static char * |
| 597 | ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 598 | { |
| 599 | ngx_http_log_loc_conf_t *llcf = conf; |
| 600 | |
Igor Sysoev | 697d1ae | 2005-10-27 15:46:13 +0000 | [diff] [blame] | 601 | ssize_t buf; |
Igor Sysoev | 10a543a | 2004-03-16 07:10:12 +0000 | [diff] [blame] | 602 | ngx_uint_t i; |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 603 | ngx_str_t *value, name; |
| 604 | ngx_http_log_t *log; |
| 605 | ngx_http_log_fmt_t *fmt; |
| 606 | ngx_http_log_main_conf_t *lmcf; |
| 607 | |
Igor Sysoev | 85cccfb | 2004-09-15 16:00:43 +0000 | [diff] [blame] | 608 | value = cf->args->elts; |
| 609 | |
| 610 | if (ngx_strcmp(value[1].data, "off") == 0) { |
| 611 | llcf->off = 1; |
| 612 | return NGX_CONF_OK; |
| 613 | } |
| 614 | |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 615 | if (llcf->logs == NULL) { |
Igor Sysoev | 85cccfb | 2004-09-15 16:00:43 +0000 | [diff] [blame] | 616 | llcf->logs = ngx_array_create(cf->pool, 2, sizeof(ngx_http_log_t)); |
| 617 | if (llcf->logs == NULL) { |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 618 | return NGX_CONF_ERROR; |
| 619 | } |
| 620 | } |
| 621 | |
Igor Sysoev | 1c3567e | 2004-07-15 16:35:51 +0000 | [diff] [blame] | 622 | lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_log_module); |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 623 | |
Igor Sysoev | c157172 | 2005-03-19 12:38:37 +0000 | [diff] [blame] | 624 | log = ngx_array_push(llcf->logs); |
| 625 | if (log == NULL) { |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 626 | return NGX_CONF_ERROR; |
| 627 | } |
| 628 | |
Igor Sysoev | c157172 | 2005-03-19 12:38:37 +0000 | [diff] [blame] | 629 | log->file = ngx_conf_open_file(cf->cycle, &value[1]); |
| 630 | if (log->file == NULL) { |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 631 | return NGX_CONF_ERROR; |
| 632 | } |
| 633 | |
Igor Sysoev | 8a2b2fb | 2006-04-14 09:53:38 +0000 | [diff] [blame] | 634 | log->disk_full_time = 0; |
Igor Sysoev | d0863c1 | 2007-01-21 19:01:01 +0000 | [diff] [blame] | 635 | log->error_log_time = 0; |
Igor Sysoev | 8a2b2fb | 2006-04-14 09:53:38 +0000 | [diff] [blame] | 636 | |
Igor Sysoev | 697d1ae | 2005-10-27 15:46:13 +0000 | [diff] [blame] | 637 | if (cf->args->nelts >= 3) { |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 638 | name = value[2]; |
Igor Sysoev | c31a9bb | 2005-11-26 10:11:11 +0000 | [diff] [blame] | 639 | |
| 640 | if (ngx_strcmp(name.data, "combined") == 0) { |
| 641 | lmcf->combined_used = 1; |
| 642 | } |
| 643 | |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 644 | } else { |
| 645 | name.len = sizeof("combined") - 1; |
Igor Sysoev | da85f7f | 2004-03-16 21:26:01 +0000 | [diff] [blame] | 646 | name.data = (u_char *) "combined"; |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 647 | lmcf->combined_used = 1; |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 648 | } |
| 649 | |
| 650 | fmt = lmcf->formats.elts; |
| 651 | for (i = 0; i < lmcf->formats.nelts; i++) { |
| 652 | if (fmt[i].name.len == name.len |
| 653 | && ngx_strcasecmp(fmt[i].name.data, name.data) == 0) |
| 654 | { |
| 655 | log->ops = fmt[i].ops; |
Igor Sysoev | 697d1ae | 2005-10-27 15:46:13 +0000 | [diff] [blame] | 656 | goto buffer; |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 657 | } |
| 658 | } |
| 659 | |
Igor Sysoev | aa82861 | 2005-02-09 14:31:07 +0000 | [diff] [blame] | 660 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
| 661 | "unknown log format \"%V\"", &name); |
Igor Sysoev | aa82861 | 2005-02-09 14:31:07 +0000 | [diff] [blame] | 662 | return NGX_CONF_ERROR; |
Igor Sysoev | 697d1ae | 2005-10-27 15:46:13 +0000 | [diff] [blame] | 663 | |
| 664 | buffer: |
| 665 | |
| 666 | if (cf->args->nelts == 4) { |
| 667 | if (ngx_strncmp(value[3].data, "buffer=", 7) != 0) { |
| 668 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
| 669 | "invalid parameter \"%V\"", &value[3]); |
| 670 | return NGX_CONF_ERROR; |
| 671 | } |
| 672 | |
| 673 | name.len = value[3].len - 7; |
| 674 | name.data = value[3].data + 7; |
| 675 | |
| 676 | buf = ngx_parse_size(&name); |
| 677 | |
| 678 | if (buf == NGX_ERROR) { |
| 679 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
| 680 | "invalid parameter \"%V\"", &value[3]); |
| 681 | return NGX_CONF_ERROR; |
| 682 | } |
| 683 | |
| 684 | if (log->file->buffer && log->file->last - log->file->pos != buf) { |
| 685 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
| 686 | "access_log \"%V\" already defined " |
| 687 | "with different buffer size", &value[1]); |
| 688 | return NGX_CONF_ERROR; |
| 689 | } |
| 690 | |
| 691 | log->file->buffer = ngx_palloc(cf->pool, buf); |
| 692 | if (log->file->buffer == NULL) { |
| 693 | return NGX_CONF_ERROR; |
| 694 | } |
| 695 | |
| 696 | log->file->pos = log->file->buffer; |
| 697 | log->file->last = log->file->buffer + buf; |
| 698 | } |
| 699 | |
| 700 | return NGX_CONF_OK; |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 701 | } |
| 702 | |
| 703 | |
Igor Sysoev | 11d7532 | 2005-03-01 15:20:36 +0000 | [diff] [blame] | 704 | static char * |
| 705 | ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 706 | { |
| 707 | ngx_http_log_main_conf_t *lmcf = conf; |
| 708 | |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 709 | ngx_str_t *value; |
| 710 | ngx_uint_t i; |
| 711 | ngx_http_log_fmt_t *fmt; |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 712 | |
| 713 | value = cf->args->elts; |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 714 | |
| 715 | fmt = lmcf->formats.elts; |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 716 | for (i = 0; i < lmcf->formats.nelts; i++) { |
| 717 | if (fmt[i].name.len == value[1].len |
| 718 | && ngx_strcmp(fmt[i].name.data, value[1].data) == 0) |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 719 | { |
| 720 | return "duplicate \"log_format\" name"; |
| 721 | } |
| 722 | } |
| 723 | |
Igor Sysoev | c157172 | 2005-03-19 12:38:37 +0000 | [diff] [blame] | 724 | fmt = ngx_array_push(&lmcf->formats); |
| 725 | if (fmt == NULL) { |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 726 | return NGX_CONF_ERROR; |
| 727 | } |
| 728 | |
| 729 | fmt->name = value[1]; |
| 730 | |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 731 | fmt->ops = ngx_array_create(cf->pool, 16, sizeof(ngx_http_log_op_t)); |
Igor Sysoev | c157172 | 2005-03-19 12:38:37 +0000 | [diff] [blame] | 732 | if (fmt->ops == NULL) { |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 733 | return NGX_CONF_ERROR; |
| 734 | } |
| 735 | |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 736 | return ngx_http_log_compile_format(cf, fmt->ops, cf->args, 2); |
| 737 | } |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 738 | |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 739 | |
| 740 | static char * |
| 741 | ngx_http_log_compile_format(ngx_conf_t *cf, ngx_array_t *ops, |
| 742 | ngx_array_t *args, ngx_uint_t s) |
| 743 | { |
Igor Sysoev | a8c54c0 | 2006-11-27 14:46:15 +0000 | [diff] [blame] | 744 | u_char *data, *p, ch; |
| 745 | size_t i, len; |
| 746 | ngx_str_t *value, var; |
| 747 | ngx_uint_t bracket; |
| 748 | ngx_http_log_op_t *op; |
| 749 | ngx_http_log_var_t *v; |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 750 | |
| 751 | value = args->elts; |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 752 | |
| 753 | for ( /* void */ ; s < args->nelts; s++) { |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 754 | |
Igor Sysoev | a8c54c0 | 2006-11-27 14:46:15 +0000 | [diff] [blame] | 755 | for (i = 0; i < value[s].len; i++) { |
| 756 | if (value[s].data[i] != '%') { |
| 757 | continue; |
| 758 | } |
| 759 | |
| 760 | ch = value[s].data[i + 1]; |
| 761 | |
| 762 | if ((ch >= 'A' && ch <= 'Z') |
| 763 | || (ch >= 'a' && ch <= 'z') |
| 764 | || ch == '{') |
| 765 | { |
| 766 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
| 767 | "the parameters in the \"%%name\" form are not supported, " |
| 768 | "use the \"$variable\" instead"); |
| 769 | |
| 770 | return NGX_CONF_ERROR; |
| 771 | } |
| 772 | } |
| 773 | |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 774 | i = 0; |
| 775 | |
| 776 | while (i < value[s].len) { |
| 777 | |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 778 | op = ngx_array_push(ops); |
Igor Sysoev | c157172 | 2005-03-19 12:38:37 +0000 | [diff] [blame] | 779 | if (op == NULL) { |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 780 | return NGX_CONF_ERROR; |
| 781 | } |
| 782 | |
| 783 | data = &value[s].data[i]; |
| 784 | |
Igor Sysoev | a8c54c0 | 2006-11-27 14:46:15 +0000 | [diff] [blame] | 785 | if (value[s].data[i] == '$') { |
Igor Sysoev | 9ac946b | 2005-10-24 15:09:41 +0000 | [diff] [blame] | 786 | |
| 787 | if (++i == value[s].len) { |
| 788 | goto invalid; |
| 789 | } |
| 790 | |
| 791 | if (value[s].data[i] == '{') { |
| 792 | bracket = 1; |
| 793 | |
| 794 | if (++i == value[s].len) { |
| 795 | goto invalid; |
| 796 | } |
| 797 | |
| 798 | var.data = &value[s].data[i]; |
| 799 | |
| 800 | } else { |
| 801 | bracket = 0; |
| 802 | var.data = &value[s].data[i]; |
| 803 | } |
| 804 | |
| 805 | for (var.len = 0; i < value[s].len; i++, var.len++) { |
| 806 | ch = value[s].data[i]; |
| 807 | |
| 808 | if (ch == '}' && bracket) { |
| 809 | i++; |
| 810 | bracket = 0; |
| 811 | break; |
| 812 | } |
| 813 | |
| 814 | if ((ch >= 'A' && ch <= 'Z') |
| 815 | || (ch >= 'a' && ch <= 'z') |
| 816 | || (ch >= '0' && ch <= '9') |
| 817 | || ch == '_') |
| 818 | { |
| 819 | continue; |
| 820 | } |
| 821 | |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 822 | break; |
| 823 | } |
| 824 | |
Igor Sysoev | 9ac946b | 2005-10-24 15:09:41 +0000 | [diff] [blame] | 825 | if (bracket) { |
| 826 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
| 827 | "the closing bracket in \"%V\" " |
| 828 | "variable is missing", &var); |
| 829 | return NGX_CONF_ERROR; |
| 830 | } |
| 831 | |
| 832 | if (var.len == 0) { |
| 833 | goto invalid; |
| 834 | } |
| 835 | |
Igor Sysoev | 0e5dc5c | 2005-11-15 13:30:52 +0000 | [diff] [blame] | 836 | if (ngx_strncmp(var.data, "apache_bytes_sent", 17) == 0) { |
| 837 | ngx_conf_log_error(NGX_LOG_WARN, cf, 0, |
| 838 | "use \"$body_bytes_sent\" instead of " |
| 839 | "\"$apache_bytes_sent\""); |
| 840 | } |
| 841 | |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 842 | for (v = ngx_http_log_vars; v->name.len; v++) { |
| 843 | |
| 844 | if (v->name.len == var.len |
| 845 | && ngx_strncmp(v->name.data, var.data, var.len) == 0) |
| 846 | { |
| 847 | op->len = v->len; |
| 848 | op->getlen = NULL; |
| 849 | op->run = v->run; |
| 850 | op->data = 0; |
| 851 | |
| 852 | goto found; |
| 853 | } |
| 854 | } |
| 855 | |
Igor Sysoev | 9ac946b | 2005-10-24 15:09:41 +0000 | [diff] [blame] | 856 | if (ngx_http_log_variable_compile(cf, op, &var) != NGX_OK) { |
| 857 | return NGX_CONF_ERROR; |
| 858 | } |
| 859 | |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 860 | found: |
| 861 | |
| 862 | continue; |
| 863 | } |
| 864 | |
| 865 | i++; |
| 866 | |
Igor Sysoev | a8c54c0 | 2006-11-27 14:46:15 +0000 | [diff] [blame] | 867 | while (i < value[s].len && value[s].data[i] != '$') { |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 868 | i++; |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 869 | } |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 870 | |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 871 | len = &value[s].data[i] - data; |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 872 | |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 873 | if (len) { |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 874 | |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 875 | op->len = len; |
| 876 | op->getlen = NULL; |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 877 | |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 878 | if (len <= sizeof(uintptr_t)) { |
| 879 | op->run = ngx_http_log_copy_short; |
| 880 | op->data = 0; |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 881 | |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 882 | while (len--) { |
| 883 | op->data <<= 8; |
| 884 | op->data |= data[len]; |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 885 | } |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 886 | |
| 887 | } else { |
| 888 | op->run = ngx_http_log_copy_long; |
| 889 | |
| 890 | p = ngx_palloc(cf->pool, len); |
| 891 | if (p == NULL) { |
| 892 | return NGX_CONF_ERROR; |
| 893 | } |
| 894 | |
| 895 | ngx_memcpy(p, data, len); |
| 896 | op->data = (uintptr_t) p; |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 897 | } |
| 898 | } |
| 899 | } |
| 900 | } |
| 901 | |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 902 | return NGX_CONF_OK; |
Igor Sysoev | 9ac946b | 2005-10-24 15:09:41 +0000 | [diff] [blame] | 903 | |
| 904 | invalid: |
| 905 | |
| 906 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%s\"", data); |
| 907 | |
| 908 | return NGX_CONF_ERROR; |
| 909 | } |
| 910 | |
| 911 | |
| 912 | static ngx_int_t |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 913 | ngx_http_log_init(ngx_conf_t *cf) |
Igor Sysoev | 9ac946b | 2005-10-24 15:09:41 +0000 | [diff] [blame] | 914 | { |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 915 | ngx_str_t *value; |
| 916 | ngx_array_t a; |
Igor Sysoev | c31a9bb | 2005-11-26 10:11:11 +0000 | [diff] [blame] | 917 | ngx_http_handler_pt *h; |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 918 | ngx_http_log_fmt_t *fmt; |
| 919 | ngx_http_log_main_conf_t *lmcf; |
Igor Sysoev | 9ac946b | 2005-10-24 15:09:41 +0000 | [diff] [blame] | 920 | ngx_http_core_main_conf_t *cmcf; |
| 921 | |
Igor Sysoev | 09c684b | 2005-11-09 17:25:55 +0000 | [diff] [blame] | 922 | lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_log_module); |
| 923 | |
| 924 | if (lmcf->combined_used) { |
| 925 | if (ngx_array_init(&a, cf->pool, 1, sizeof(ngx_str_t)) != NGX_OK) { |
| 926 | return NGX_ERROR; |
| 927 | } |
| 928 | |
| 929 | value = ngx_array_push(&a); |
| 930 | if (value == NULL) { |
| 931 | return NGX_ERROR; |
| 932 | } |
| 933 | |
| 934 | *value = ngx_http_combined_fmt; |
| 935 | fmt = lmcf->formats.elts; |
| 936 | |
| 937 | if (ngx_http_log_compile_format(cf, fmt->ops, &a, 0) |
| 938 | != NGX_CONF_OK) |
| 939 | { |
| 940 | return NGX_ERROR; |
| 941 | } |
| 942 | } |
| 943 | |
| 944 | cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); |
Igor Sysoev | 9ac946b | 2005-10-24 15:09:41 +0000 | [diff] [blame] | 945 | |
Igor Sysoev | c31a9bb | 2005-11-26 10:11:11 +0000 | [diff] [blame] | 946 | h = ngx_array_push(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers); |
| 947 | if (h == NULL) { |
| 948 | return NGX_ERROR; |
| 949 | } |
| 950 | |
| 951 | *h = ngx_http_log_handler; |
Igor Sysoev | 9ac946b | 2005-10-24 15:09:41 +0000 | [diff] [blame] | 952 | |
| 953 | return NGX_OK; |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 954 | } |