1e18a033bSKonstantin Ananyev
2e18a033bSKonstantin Ananyev/*
3e18a033bSKonstantin Ananyev * Copyright (C) Igor Sysoev
4e18a033bSKonstantin Ananyev * Copyright (C) Nginx, Inc.
5e18a033bSKonstantin Ananyev */
6e18a033bSKonstantin Ananyev
7e18a033bSKonstantin Ananyev
8e18a033bSKonstantin Ananyev#include <ngx_config.h>
9e18a033bSKonstantin Ananyev#include <ngx_core.h>
10e18a033bSKonstantin Ananyev#include <ngx_http.h>
11e18a033bSKonstantin Ananyev
12e18a033bSKonstantin Ananyev#if (NGX_ZLIB)
13e18a033bSKonstantin Ananyev#include <zlib.h>
14e18a033bSKonstantin Ananyev#endif
15e18a033bSKonstantin Ananyev
16e18a033bSKonstantin Ananyev
17e18a033bSKonstantin Ananyevtypedef struct ngx_http_log_op_s  ngx_http_log_op_t;
18e18a033bSKonstantin Ananyev
19e18a033bSKonstantin Ananyevtypedef u_char *(*ngx_http_log_op_run_pt) (ngx_http_request_t *r, u_char *buf,
20e18a033bSKonstantin Ananyev    ngx_http_log_op_t *op);
21e18a033bSKonstantin Ananyev
22e18a033bSKonstantin Ananyevtypedef size_t (*ngx_http_log_op_getlen_pt) (ngx_http_request_t *r,
23e18a033bSKonstantin Ananyev    uintptr_t data);
24e18a033bSKonstantin Ananyev
25e18a033bSKonstantin Ananyev
26e18a033bSKonstantin Ananyevstruct ngx_http_log_op_s {
27e18a033bSKonstantin Ananyev    size_t                      len;
28e18a033bSKonstantin Ananyev    ngx_http_log_op_getlen_pt   getlen;
29e18a033bSKonstantin Ananyev    ngx_http_log_op_run_pt      run;
30e18a033bSKonstantin Ananyev    uintptr_t                   data;
31e18a033bSKonstantin Ananyev};
32e18a033bSKonstantin Ananyev
33e18a033bSKonstantin Ananyev
34e18a033bSKonstantin Ananyevtypedef struct {
35e18a033bSKonstantin Ananyev    ngx_str_t                   name;
36e18a033bSKonstantin Ananyev    ngx_array_t                *flushes;
37e18a033bSKonstantin Ananyev    ngx_array_t                *ops;        /* array of ngx_http_log_op_t */
38e18a033bSKonstantin Ananyev} ngx_http_log_fmt_t;
39e18a033bSKonstantin Ananyev
40e18a033bSKonstantin Ananyev
41e18a033bSKonstantin Ananyevtypedef struct {
42e18a033bSKonstantin Ananyev    ngx_array_t                 formats;    /* array of ngx_http_log_fmt_t */
43e18a033bSKonstantin Ananyev    ngx_uint_t                  combined_used; /* unsigned  combined_used:1 */
44e18a033bSKonstantin Ananyev} ngx_http_log_main_conf_t;
45e18a033bSKonstantin Ananyev
46e18a033bSKonstantin Ananyev
47e18a033bSKonstantin Ananyevtypedef struct {
48e18a033bSKonstantin Ananyev    u_char                     *start;
49e18a033bSKonstantin Ananyev    u_char                     *pos;
50e18a033bSKonstantin Ananyev    u_char                     *last;
51e18a033bSKonstantin Ananyev
52e18a033bSKonstantin Ananyev    ngx_event_t                *event;
53e18a033bSKonstantin Ananyev    ngx_msec_t                  flush;
54e18a033bSKonstantin Ananyev    ngx_int_t                   gzip;
55e18a033bSKonstantin Ananyev} ngx_http_log_buf_t;
56e18a033bSKonstantin Ananyev
57e18a033bSKonstantin Ananyev
58e18a033bSKonstantin Ananyevtypedef struct {
59e18a033bSKonstantin Ananyev    ngx_array_t                *lengths;
60e18a033bSKonstantin Ananyev    ngx_array_t                *values;
61e18a033bSKonstantin Ananyev} ngx_http_log_script_t;
62e18a033bSKonstantin Ananyev
63e18a033bSKonstantin Ananyev
64e18a033bSKonstantin Ananyevtypedef struct {
65e18a033bSKonstantin Ananyev    ngx_open_file_t            *file;
66e18a033bSKonstantin Ananyev    ngx_http_log_script_t      *script;
67e18a033bSKonstantin Ananyev    time_t                      disk_full_time;
68e18a033bSKonstantin Ananyev    time_t                      error_log_time;
69e18a033bSKonstantin Ananyev    ngx_syslog_peer_t          *syslog_peer;
70e18a033bSKonstantin Ananyev    ngx_http_log_fmt_t         *format;
71e18a033bSKonstantin Ananyev    ngx_http_complex_value_t   *filter;
72e18a033bSKonstantin Ananyev} ngx_http_log_t;
73e18a033bSKonstantin Ananyev
74e18a033bSKonstantin Ananyev
75e18a033bSKonstantin Ananyevtypedef struct {
76e18a033bSKonstantin Ananyev    ngx_array_t                *logs;       /* array of ngx_http_log_t */
77e18a033bSKonstantin Ananyev
78e18a033bSKonstantin Ananyev    ngx_open_file_cache_t      *open_file_cache;
79e18a033bSKonstantin Ananyev    time_t                      open_file_cache_valid;
80e18a033bSKonstantin Ananyev    ngx_uint_t                  open_file_cache_min_uses;
81e18a033bSKonstantin Ananyev
82e18a033bSKonstantin Ananyev    ngx_uint_t                  off;        /* unsigned  off:1 */
83e18a033bSKonstantin Ananyev} ngx_http_log_loc_conf_t;
84e18a033bSKonstantin Ananyev
85e18a033bSKonstantin Ananyev
86e18a033bSKonstantin Ananyevtypedef struct {
87e18a033bSKonstantin Ananyev    ngx_str_t                   name;
88e18a033bSKonstantin Ananyev    size_t                      len;
89e18a033bSKonstantin Ananyev    ngx_http_log_op_run_pt      run;
90e18a033bSKonstantin Ananyev} ngx_http_log_var_t;
91e18a033bSKonstantin Ananyev
92e18a033bSKonstantin Ananyev
93e18a033bSKonstantin Ananyevstatic void ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log,
94e18a033bSKonstantin Ananyev    u_char *buf, size_t len);
95e18a033bSKonstantin Ananyevstatic ssize_t ngx_http_log_script_write(ngx_http_request_t *r,
96e18a033bSKonstantin Ananyev    ngx_http_log_script_t *script, u_char **name, u_char *buf, size_t len);
97e18a033bSKonstantin Ananyev
98e18a033bSKonstantin Ananyev#if (NGX_ZLIB)
99e18a033bSKonstantin Ananyevstatic ssize_t ngx_http_log_gzip(ngx_fd_t fd, u_char *buf, size_t len,
100e18a033bSKonstantin Ananyev    ngx_int_t level, ngx_log_t *log);
101e18a033bSKonstantin Ananyev
102e18a033bSKonstantin Ananyevstatic void *ngx_http_log_gzip_alloc(void *opaque, u_int items, u_int size);
103e18a033bSKonstantin Ananyevstatic void ngx_http_log_gzip_free(void *opaque, void *address);
104e18a033bSKonstantin Ananyev#endif
105e18a033bSKonstantin Ananyev
106e18a033bSKonstantin Ananyevstatic void ngx_http_log_flush(ngx_open_file_t *file, ngx_log_t *log);
107e18a033bSKonstantin Ananyevstatic void ngx_http_log_flush_handler(ngx_event_t *ev);
108e18a033bSKonstantin Ananyev
109e18a033bSKonstantin Ananyevstatic u_char *ngx_http_log_pipe(ngx_http_request_t *r, u_char *buf,
110e18a033bSKonstantin Ananyev    ngx_http_log_op_t *op);
111e18a033bSKonstantin Ananyevstatic u_char *ngx_http_log_time(ngx_http_request_t *r, u_char *buf,
112e18a033bSKonstantin Ananyev    ngx_http_log_op_t *op);
113e18a033bSKonstantin Ananyevstatic u_char *ngx_http_log_iso8601(ngx_http_request_t *r, u_char *buf,
114e18a033bSKonstantin Ananyev    ngx_http_log_op_t *op);
115e18a033bSKonstantin Ananyevstatic u_char *ngx_http_log_msec(ngx_http_request_t *r, u_char *buf,
116e18a033bSKonstantin Ananyev    ngx_http_log_op_t *op);
117e18a033bSKonstantin Ananyevstatic u_char *ngx_http_log_request_time(ngx_http_request_t *r, u_char *buf,
118e18a033bSKonstantin Ananyev    ngx_http_log_op_t *op);
119e18a033bSKonstantin Ananyevstatic u_char *ngx_http_log_status(ngx_http_request_t *r, u_char *buf,
120e18a033bSKonstantin Ananyev    ngx_http_log_op_t *op);
121e18a033bSKonstantin Ananyevstatic u_char *ngx_http_log_bytes_sent(ngx_http_request_t *r, u_char *buf,
122e18a033bSKonstantin Ananyev    ngx_http_log_op_t *op);
123e18a033bSKonstantin Ananyevstatic u_char *ngx_http_log_body_bytes_sent(ngx_http_request_t *r,
124e18a033bSKonstantin Ananyev    u_char *buf, ngx_http_log_op_t *op);
125e18a033bSKonstantin Ananyevstatic u_char *ngx_http_log_request_length(ngx_http_request_t *r, u_char *buf,
126e18a033bSKonstantin Ananyev    ngx_http_log_op_t *op);
127e18a033bSKonstantin Ananyev
128e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_log_variable_compile(ngx_conf_t *cf,
129e18a033bSKonstantin Ananyev    ngx_http_log_op_t *op, ngx_str_t *value, ngx_uint_t json);
130e18a033bSKonstantin Ananyevstatic size_t ngx_http_log_variable_getlen(ngx_http_request_t *r,
131e18a033bSKonstantin Ananyev    uintptr_t data);
132e18a033bSKonstantin Ananyevstatic u_char *ngx_http_log_variable(ngx_http_request_t *r, u_char *buf,
133e18a033bSKonstantin Ananyev    ngx_http_log_op_t *op);
134e18a033bSKonstantin Ananyevstatic uintptr_t ngx_http_log_escape(u_char *dst, u_char *src, size_t size);
135e18a033bSKonstantin Ananyevstatic size_t ngx_http_log_json_variable_getlen(ngx_http_request_t *r,
136e18a033bSKonstantin Ananyev    uintptr_t data);
137e18a033bSKonstantin Ananyevstatic u_char *ngx_http_log_json_variable(ngx_http_request_t *r, u_char *buf,
138e18a033bSKonstantin Ananyev    ngx_http_log_op_t *op);
139e18a033bSKonstantin Ananyev
140e18a033bSKonstantin Ananyev
141e18a033bSKonstantin Ananyevstatic void *ngx_http_log_create_main_conf(ngx_conf_t *cf);
142e18a033bSKonstantin Ananyevstatic void *ngx_http_log_create_loc_conf(ngx_conf_t *cf);
143e18a033bSKonstantin Ananyevstatic char *ngx_http_log_merge_loc_conf(ngx_conf_t *cf, void *parent,
144e18a033bSKonstantin Ananyev    void *child);
145e18a033bSKonstantin Ananyevstatic char *ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd,
146e18a033bSKonstantin Ananyev    void *conf);
147e18a033bSKonstantin Ananyevstatic char *ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd,
148e18a033bSKonstantin Ananyev    void *conf);
149e18a033bSKonstantin Ananyevstatic char *ngx_http_log_compile_format(ngx_conf_t *cf,
150e18a033bSKonstantin Ananyev    ngx_array_t *flushes, ngx_array_t *ops, ngx_array_t *args, ngx_uint_t s);
151e18a033bSKonstantin Ananyevstatic char *ngx_http_log_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd,
152e18a033bSKonstantin Ananyev    void *conf);
153e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_log_init(ngx_conf_t *cf);
154e18a033bSKonstantin Ananyev
155e18a033bSKonstantin Ananyev
156e18a033bSKonstantin Ananyevstatic ngx_command_t  ngx_http_log_commands[] = {
157e18a033bSKonstantin Ananyev
158e18a033bSKonstantin Ananyev    { ngx_string("log_format"),
159e18a033bSKonstantin Ananyev      NGX_HTTP_MAIN_CONF|NGX_CONF_2MORE,
160e18a033bSKonstantin Ananyev      ngx_http_log_set_format,
161e18a033bSKonstantin Ananyev      NGX_HTTP_MAIN_CONF_OFFSET,
162e18a033bSKonstantin Ananyev      0,
163e18a033bSKonstantin Ananyev      NULL },
164e18a033bSKonstantin Ananyev
165e18a033bSKonstantin Ananyev    { ngx_string("access_log"),
166e18a033bSKonstantin Ananyev      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
167e18a033bSKonstantin Ananyev                        |NGX_HTTP_LMT_CONF|NGX_CONF_1MORE,
168e18a033bSKonstantin Ananyev      ngx_http_log_set_log,
169e18a033bSKonstantin Ananyev      NGX_HTTP_LOC_CONF_OFFSET,
170e18a033bSKonstantin Ananyev      0,
171e18a033bSKonstantin Ananyev      NULL },
172e18a033bSKonstantin Ananyev
173e18a033bSKonstantin Ananyev    { ngx_string("open_log_file_cache"),
174e18a033bSKonstantin Ananyev      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
175e18a033bSKonstantin Ananyev      ngx_http_log_open_file_cache,
176e18a033bSKonstantin Ananyev      NGX_HTTP_LOC_CONF_OFFSET,
177e18a033bSKonstantin Ananyev      0,
178e18a033bSKonstantin Ananyev      NULL },
179e18a033bSKonstantin Ananyev
180e18a033bSKonstantin Ananyev      ngx_null_command
181e18a033bSKonstantin Ananyev};
182e18a033bSKonstantin Ananyev
183e18a033bSKonstantin Ananyev
184e18a033bSKonstantin Ananyevstatic ngx_http_module_t  ngx_http_log_module_ctx = {
185e18a033bSKonstantin Ananyev    NULL,                                  /* preconfiguration */
186e18a033bSKonstantin Ananyev    ngx_http_log_init,                     /* postconfiguration */
187e18a033bSKonstantin Ananyev
188e18a033bSKonstantin Ananyev    ngx_http_log_create_main_conf,         /* create main configuration */
189e18a033bSKonstantin Ananyev    NULL,                                  /* init main configuration */
190e18a033bSKonstantin Ananyev
191e18a033bSKonstantin Ananyev    NULL,                                  /* create server configuration */
192e18a033bSKonstantin Ananyev    NULL,                                  /* merge server configuration */
193e18a033bSKonstantin Ananyev
194e18a033bSKonstantin Ananyev    ngx_http_log_create_loc_conf,          /* create location configuration */
195e18a033bSKonstantin Ananyev    ngx_http_log_merge_loc_conf            /* merge location configuration */
196e18a033bSKonstantin Ananyev};
197e18a033bSKonstantin Ananyev
198e18a033bSKonstantin Ananyev
199e18a033bSKonstantin Ananyevngx_module_t  ngx_http_log_module = {
200e18a033bSKonstantin Ananyev    NGX_MODULE_V1,
201e18a033bSKonstantin Ananyev    &ngx_http_log_module_ctx,              /* module context */
202e18a033bSKonstantin Ananyev    ngx_http_log_commands,                 /* module directives */
203e18a033bSKonstantin Ananyev    NGX_HTTP_MODULE,                       /* module type */
204e18a033bSKonstantin Ananyev    NULL,                                  /* init master */
205e18a033bSKonstantin Ananyev    NULL,                                  /* init module */
206e18a033bSKonstantin Ananyev    NULL,                                  /* init process */
207e18a033bSKonstantin Ananyev    NULL,                                  /* init thread */
208e18a033bSKonstantin Ananyev    NULL,                                  /* exit thread */
209e18a033bSKonstantin Ananyev    NULL,                                  /* exit process */
210e18a033bSKonstantin Ananyev    NULL,                                  /* exit master */
211e18a033bSKonstantin Ananyev    NGX_MODULE_V1_PADDING
212e18a033bSKonstantin Ananyev};
213e18a033bSKonstantin Ananyev
214e18a033bSKonstantin Ananyev
215e18a033bSKonstantin Ananyevstatic ngx_str_t  ngx_http_access_log = ngx_string(NGX_HTTP_LOG_PATH);
216e18a033bSKonstantin Ananyev
217e18a033bSKonstantin Ananyev
218e18a033bSKonstantin Ananyevstatic ngx_str_t  ngx_http_combined_fmt =
219e18a033bSKonstantin Ananyev    ngx_string("$remote_addr - $remote_user [$time_local] "
220e18a033bSKonstantin Ananyev               "\"$request\" $status $body_bytes_sent "
221e18a033bSKonstantin Ananyev               "\"$http_referer\" \"$http_user_agent\"");
222e18a033bSKonstantin Ananyev
223e18a033bSKonstantin Ananyev
224e18a033bSKonstantin Ananyevstatic ngx_http_log_var_t  ngx_http_log_vars[] = {
225e18a033bSKonstantin Ananyev    { ngx_string("pipe"), 1, ngx_http_log_pipe },
226e18a033bSKonstantin Ananyev    { ngx_string("time_local"), sizeof("28/Sep/1970:12:00:00 +0600") - 1,
227e18a033bSKonstantin Ananyev                          ngx_http_log_time },
228e18a033bSKonstantin Ananyev    { ngx_string("time_iso8601"), sizeof("1970-09-28T12:00:00+06:00") - 1,
229e18a033bSKonstantin Ananyev                          ngx_http_log_iso8601 },
230e18a033bSKonstantin Ananyev    { ngx_string("msec"), NGX_TIME_T_LEN + 4, ngx_http_log_msec },
231e18a033bSKonstantin Ananyev    { ngx_string("request_time"), NGX_TIME_T_LEN + 4,
232e18a033bSKonstantin Ananyev                          ngx_http_log_request_time },
233e18a033bSKonstantin Ananyev    { ngx_string("status"), NGX_INT_T_LEN, ngx_http_log_status },
234e18a033bSKonstantin Ananyev    { ngx_string("bytes_sent"), NGX_OFF_T_LEN, ngx_http_log_bytes_sent },
235e18a033bSKonstantin Ananyev    { ngx_string("body_bytes_sent"), NGX_OFF_T_LEN,
236e18a033bSKonstantin Ananyev                          ngx_http_log_body_bytes_sent },
237e18a033bSKonstantin Ananyev    { ngx_string("request_length"), NGX_SIZE_T_LEN,
238e18a033bSKonstantin Ananyev                          ngx_http_log_request_length },
239e18a033bSKonstantin Ananyev
240e18a033bSKonstantin Ananyev    { ngx_null_string, 0, NULL }
241e18a033bSKonstantin Ananyev};
242e18a033bSKonstantin Ananyev
243e18a033bSKonstantin Ananyev
244e18a033bSKonstantin Ananyevstatic ngx_int_t
245e18a033bSKonstantin Ananyevngx_http_log_handler(ngx_http_request_t *r)
246e18a033bSKonstantin Ananyev{
247e18a033bSKonstantin Ananyev    u_char                   *line, *p;
248e18a033bSKonstantin Ananyev    size_t                    len, size;
249e18a033bSKonstantin Ananyev    ssize_t                   n;
250e18a033bSKonstantin Ananyev    ngx_str_t                 val;
251e18a033bSKonstantin Ananyev    ngx_uint_t                i, l;
252e18a033bSKonstantin Ananyev    ngx_http_log_t           *log;
253e18a033bSKonstantin Ananyev    ngx_http_log_op_t        *op;
254e18a033bSKonstantin Ananyev    ngx_http_log_buf_t       *buffer;
255e18a033bSKonstantin Ananyev    ngx_http_log_loc_conf_t  *lcf;
256e18a033bSKonstantin Ananyev
257e18a033bSKonstantin Ananyev    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
258e18a033bSKonstantin Ananyev                   "http log handler");
259e18a033bSKonstantin Ananyev
260e18a033bSKonstantin Ananyev    lcf = ngx_http_get_module_loc_conf(r, ngx_http_log_module);
261e18a033bSKonstantin Ananyev
262e18a033bSKonstantin Ananyev    if (lcf->off) {
263e18a033bSKonstantin Ananyev        return NGX_OK;
264e18a033bSKonstantin Ananyev    }
265e18a033bSKonstantin Ananyev
266e18a033bSKonstantin Ananyev    log = lcf->logs->elts;
267e18a033bSKonstantin Ananyev    for (l = 0; l < lcf->logs->nelts; l++) {
268e18a033bSKonstantin Ananyev
269e18a033bSKonstantin Ananyev        if (log[l].filter) {
270e18a033bSKonstantin Ananyev            if (ngx_http_complex_value(r, log[l].filter, &val) != NGX_OK) {
271e18a033bSKonstantin Ananyev                return NGX_ERROR;
272e18a033bSKonstantin Ananyev            }
273e18a033bSKonstantin Ananyev
274e18a033bSKonstantin Ananyev            if (val.len == 0 || (val.len == 1 && val.data[0] == '0')) {
275e18a033bSKonstantin Ananyev                continue;
276e18a033bSKonstantin Ananyev            }
277e18a033bSKonstantin Ananyev        }
278e18a033bSKonstantin Ananyev
279e18a033bSKonstantin Ananyev        if (ngx_time() == log[l].disk_full_time) {
280e18a033bSKonstantin Ananyev
281e18a033bSKonstantin Ananyev            /*
282e18a033bSKonstantin Ananyev             * on FreeBSD writing to a full filesystem with enabled softupdates
283e18a033bSKonstantin Ananyev             * may block process for much longer time than writing to non-full
284e18a033bSKonstantin Ananyev             * filesystem, so we skip writing to a log for one second
285e18a033bSKonstantin Ananyev             */
286e18a033bSKonstantin Ananyev
287e18a033bSKonstantin Ananyev            continue;
288e18a033bSKonstantin Ananyev        }
289e18a033bSKonstantin Ananyev
290e18a033bSKonstantin Ananyev        ngx_http_script_flush_no_cacheable_variables(r, log[l].format->flushes);
291e18a033bSKonstantin Ananyev
292e18a033bSKonstantin Ananyev        len = 0;
293e18a033bSKonstantin Ananyev        op = log[l].format->ops->elts;
294e18a033bSKonstantin Ananyev        for (i = 0; i < log[l].format->ops->nelts; i++) {
295e18a033bSKonstantin Ananyev            if (op[i].len == 0) {
296e18a033bSKonstantin Ananyev                len += op[i].getlen(r, op[i].data);
297e18a033bSKonstantin Ananyev
298e18a033bSKonstantin Ananyev            } else {
299e18a033bSKonstantin Ananyev                len += op[i].len;
300e18a033bSKonstantin Ananyev            }
301e18a033bSKonstantin Ananyev        }
302e18a033bSKonstantin Ananyev
303e18a033bSKonstantin Ananyev        if (log[l].syslog_peer) {
304e18a033bSKonstantin Ananyev
305e18a033bSKonstantin Ananyev            /* length of syslog's PRI and HEADER message parts */
306e18a033bSKonstantin Ananyev            len += sizeof("<255>Jan 01 00:00:00 ") - 1
307e18a033bSKonstantin Ananyev                   + ngx_cycle->hostname.len + 1
308e18a033bSKonstantin Ananyev                   + log[l].syslog_peer->tag.len + 2;
309e18a033bSKonstantin Ananyev
310e18a033bSKonstantin Ananyev            goto alloc_line;
311e18a033bSKonstantin Ananyev        }
312e18a033bSKonstantin Ananyev
313e18a033bSKonstantin Ananyev        len += NGX_LINEFEED_SIZE;
314e18a033bSKonstantin Ananyev
315e18a033bSKonstantin Ananyev        buffer = log[l].file ? log[l].file->data : NULL;
316e18a033bSKonstantin Ananyev
317e18a033bSKonstantin Ananyev        if (buffer) {
318e18a033bSKonstantin Ananyev
319e18a033bSKonstantin Ananyev            if (len > (size_t) (buffer->last - buffer->pos)) {
320e18a033bSKonstantin Ananyev
321e18a033bSKonstantin Ananyev                ngx_http_log_write(r, &log[l], buffer->start,
322e18a033bSKonstantin Ananyev                                   buffer->pos - buffer->start);
323e18a033bSKonstantin Ananyev
324e18a033bSKonstantin Ananyev                buffer->pos = buffer->start;
325e18a033bSKonstantin Ananyev            }
326e18a033bSKonstantin Ananyev
327e18a033bSKonstantin Ananyev            if (len <= (size_t) (buffer->last - buffer->pos)) {
328e18a033bSKonstantin Ananyev
329e18a033bSKonstantin Ananyev                p = buffer->pos;
330e18a033bSKonstantin Ananyev
331e18a033bSKonstantin Ananyev                if (buffer->event && p == buffer->start) {
332e18a033bSKonstantin Ananyev                    ngx_add_timer(buffer->event, buffer->flush);
333e18a033bSKonstantin Ananyev                }
334e18a033bSKonstantin Ananyev
335e18a033bSKonstantin Ananyev                for (i = 0; i < log[l].format->ops->nelts; i++) {
336e18a033bSKonstantin Ananyev                    p = op[i].run(r, p, &op[i]);
337e18a033bSKonstantin Ananyev                }
338e18a033bSKonstantin Ananyev
339e18a033bSKonstantin Ananyev                ngx_linefeed(p);
340e18a033bSKonstantin Ananyev
341e18a033bSKonstantin Ananyev                buffer->pos = p;
342e18a033bSKonstantin Ananyev
343e18a033bSKonstantin Ananyev                continue;
344e18a033bSKonstantin Ananyev            }
345e18a033bSKonstantin Ananyev
346e18a033bSKonstantin Ananyev            if (buffer->event && buffer->event->timer_set) {
347e18a033bSKonstantin Ananyev                ngx_del_timer(buffer->event);
348e18a033bSKonstantin Ananyev            }
349e18a033bSKonstantin Ananyev        }
350e18a033bSKonstantin Ananyev
351e18a033bSKonstantin Ananyev    alloc_line:
352e18a033bSKonstantin Ananyev
353e18a033bSKonstantin Ananyev        line = ngx_pnalloc(r->pool, len);
354e18a033bSKonstantin Ananyev        if (line == NULL) {
355e18a033bSKonstantin Ananyev            return NGX_ERROR;
356e18a033bSKonstantin Ananyev        }
357e18a033bSKonstantin Ananyev
358e18a033bSKonstantin Ananyev        p = line;
359e18a033bSKonstantin Ananyev
360e18a033bSKonstantin Ananyev        if (log[l].syslog_peer) {
361e18a033bSKonstantin Ananyev            p = ngx_syslog_add_header(log[l].syslog_peer, line);
362e18a033bSKonstantin Ananyev        }
363e18a033bSKonstantin Ananyev
364e18a033bSKonstantin Ananyev        for (i = 0; i < log[l].format->ops->nelts; i++) {
365e18a033bSKonstantin Ananyev            p = op[i].run(r, p, &op[i]);
366e18a033bSKonstantin Ananyev        }
367e18a033bSKonstantin Ananyev
368e18a033bSKonstantin Ananyev        if (log[l].syslog_peer) {
369e18a033bSKonstantin Ananyev
370e18a033bSKonstantin Ananyev            size = p - line;
371e18a033bSKonstantin Ananyev
372e18a033bSKonstantin Ananyev            n = ngx_syslog_send(log[l].syslog_peer, line, size);
373e18a033bSKonstantin Ananyev
374e18a033bSKonstantin Ananyev            if (n < 0) {
375e18a033bSKonstantin Ananyev                ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
376e18a033bSKonstantin Ananyev                              "send() to syslog failed");
377e18a033bSKonstantin Ananyev
378e18a033bSKonstantin Ananyev            } else if ((size_t) n != size) {
379e18a033bSKonstantin Ananyev                ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
380e18a033bSKonstantin Ananyev                              "send() to syslog has written only %z of %uz",
381e18a033bSKonstantin Ananyev                              n, size);
382e18a033bSKonstantin Ananyev            }
383e18a033bSKonstantin Ananyev
384e18a033bSKonstantin Ananyev            continue;
385e18a033bSKonstantin Ananyev        }
386e18a033bSKonstantin Ananyev
387e18a033bSKonstantin Ananyev        ngx_linefeed(p);
388e18a033bSKonstantin Ananyev
389e18a033bSKonstantin Ananyev        ngx_http_log_write(r, &log[l], line, p - line);
390e18a033bSKonstantin Ananyev    }
391e18a033bSKonstantin Ananyev
392e18a033bSKonstantin Ananyev    return NGX_OK;
393e18a033bSKonstantin Ananyev}
394e18a033bSKonstantin Ananyev
395e18a033bSKonstantin Ananyev
396e18a033bSKonstantin Ananyevstatic void
397e18a033bSKonstantin Ananyevngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log, u_char *buf,
398e18a033bSKonstantin Ananyev    size_t len)
399e18a033bSKonstantin Ananyev{
400e18a033bSKonstantin Ananyev    u_char              *name;
401e18a033bSKonstantin Ananyev    time_t               now;
402e18a033bSKonstantin Ananyev    ssize_t              n;
403e18a033bSKonstantin Ananyev    ngx_err_t            err;
404e18a033bSKonstantin Ananyev#if (NGX_ZLIB)
405e18a033bSKonstantin Ananyev    ngx_http_log_buf_t  *buffer;
406e18a033bSKonstantin Ananyev#endif
407e18a033bSKonstantin Ananyev
408e18a033bSKonstantin Ananyev    if (log->script == NULL) {
409e18a033bSKonstantin Ananyev        name = log->file->name.data;
410e18a033bSKonstantin Ananyev
411e18a033bSKonstantin Ananyev#if (NGX_ZLIB)
412e18a033bSKonstantin Ananyev        buffer = log->file->data;
413e18a033bSKonstantin Ananyev
414e18a033bSKonstantin Ananyev        if (buffer && buffer->gzip) {
415