1 #ifndef __DragonFly__
2 #include "uwsgi.h"
3 #endif
4 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
5 #include <sys/user.h>
6 #include <sys/sysctl.h>
7 #include <kvm.h>
8 #elif defined(__sun__)
9 /* Terrible Hack !!! */
10 #ifndef _LP64
11 #undef _FILE_OFFSET_BITS
12 #endif
13 #include <procfs.h>
14 #define _FILE_OFFSET_BITS 64
15 #endif
16 
17 #ifdef __DragonFly__
18 #include "uwsgi.h"
19 #endif
20 
21 extern struct uwsgi_server uwsgi;
22 
23 //use this instead of fprintf to avoid buffering mess with udp logging
uwsgi_log(const char * fmt,...)24 void uwsgi_log(const char *fmt, ...) {
25 	va_list ap;
26 	char logpkt[4096];
27 	int rlen = 0;
28 	int ret;
29 
30 	struct timeval tv;
31 	char sftime[64];
32 	char ctime_storage[26];
33 	time_t now;
34 
35 	if (uwsgi.logdate) {
36 		if (uwsgi.log_strftime) {
37 			now = uwsgi_now();
38 			rlen = strftime(sftime, 64, uwsgi.log_strftime, localtime(&now));
39 			memcpy(logpkt, sftime, rlen);
40 			memcpy(logpkt + rlen, " - ", 3);
41 			rlen += 3;
42 		}
43 		else {
44 			gettimeofday(&tv, NULL);
45 #if defined(__sun__) && !defined(__clang__)
46 			ctime_r((const time_t *) &tv.tv_sec, ctime_storage, 26);
47 #else
48 			ctime_r((const time_t *) &tv.tv_sec, ctime_storage);
49 #endif
50 			memcpy(logpkt, ctime_storage, 24);
51 			memcpy(logpkt + 24, " - ", 3);
52 
53 			rlen = 24 + 3;
54 		}
55 	}
56 
57 	va_start(ap, fmt);
58 	ret = vsnprintf(logpkt + rlen, 4096 - rlen, fmt, ap);
59 	va_end(ap);
60 
61 	if (ret >= 4096) {
62 		char *tmp_buf = uwsgi_malloc(rlen + ret + 1);
63 		memcpy(tmp_buf, logpkt, rlen);
64 		va_start(ap, fmt);
65 		ret = vsnprintf(tmp_buf + rlen, ret + 1, fmt, ap);
66 		va_end(ap);
67 		rlen = write(2, tmp_buf, rlen + ret);
68 		free(tmp_buf);
69 		return;
70 	}
71 
72 	rlen += ret;
73 	// do not check for errors
74 	rlen = write(2, logpkt, rlen);
75 }
76 
uwsgi_log_verbose(const char * fmt,...)77 void uwsgi_log_verbose(const char *fmt, ...) {
78 
79 	va_list ap;
80 	char logpkt[4096];
81 	int rlen = 0;
82 
83 	struct timeval tv;
84 	char sftime[64];
85 	time_t now;
86 	char ctime_storage[26];
87 
88 	if (uwsgi.log_strftime) {
89 		now = uwsgi_now();
90 		rlen = strftime(sftime, 64, uwsgi.log_strftime, localtime(&now));
91 		memcpy(logpkt, sftime, rlen);
92 		memcpy(logpkt + rlen, " - ", 3);
93 		rlen += 3;
94 	}
95 	else {
96 		gettimeofday(&tv, NULL);
97 #if defined(__sun__) && !defined(__clang__)
98 		ctime_r((const time_t *) &tv.tv_sec, ctime_storage, 26);
99 #else
100 		ctime_r((const time_t *) &tv.tv_sec, ctime_storage);
101 #endif
102 		memcpy(logpkt, ctime_storage, 24);
103 		memcpy(logpkt + 24, " - ", 3);
104 
105 		rlen = 24 + 3;
106 	}
107 
108 
109 
110 	va_start(ap, fmt);
111 	rlen += vsnprintf(logpkt + rlen, 4096 - rlen, fmt, ap);
112 	va_end(ap);
113 
114 	// do not check for errors
115 	rlen = write(2, logpkt, rlen);
116 }
117 
118 
119 /*
120 	commodity function mainly useful in log rotation
121 */
uwsgi_logfile_write(const char * fmt,...)122 void uwsgi_logfile_write(const char *fmt, ...) {
123 	va_list ap;
124         char logpkt[4096];
125 
126         struct timeval tv;
127         char ctime_storage[26];
128 
129 	gettimeofday(&tv, NULL);
130 #if defined(__sun__) && !defined(__clang__)
131         ctime_r((const time_t *) &tv.tv_sec, ctime_storage, 26);
132 #else
133         ctime_r((const time_t *) &tv.tv_sec, ctime_storage);
134 #endif
135         memcpy(logpkt, ctime_storage, 24);
136         memcpy(logpkt + 24, " - ", 3);
137 
138         int rlen = 24 + 3;
139 
140         va_start(ap, fmt);
141         rlen += vsnprintf(logpkt + rlen, 4096 - rlen, fmt, ap);
142         va_end(ap);
143 
144         // do not check for errors
145         rlen = write(uwsgi.original_log_fd, logpkt, rlen);
146 }
147 
148 
149 
fix_logpipe_buf(int * fd)150 static void fix_logpipe_buf(int *fd) {
151 	int so_bufsize;
152         socklen_t so_bufsize_len = sizeof(int);
153 
154         if (getsockopt(fd[0], SOL_SOCKET, SO_RCVBUF, &so_bufsize, &so_bufsize_len)) {
155                 uwsgi_error("fix_logpipe_buf()/getsockopt()");
156 		return;
157         }
158 
159 	if ((size_t)so_bufsize < uwsgi.log_master_bufsize) {
160 		so_bufsize = uwsgi.log_master_bufsize;
161 		if (setsockopt(fd[0], SOL_SOCKET, SO_RCVBUF, &so_bufsize, so_bufsize_len)) {
162                         uwsgi_error("fix_logpipe_buf()/setsockopt()");
163         	}
164 	}
165 
166 	if (getsockopt(fd[1], SOL_SOCKET, SO_SNDBUF, &so_bufsize, &so_bufsize_len)) {
167                 uwsgi_error("fix_logpipe_buf()/getsockopt()");
168                 return;
169         }
170 
171         if ((size_t)so_bufsize < uwsgi.log_master_bufsize) {
172                 so_bufsize = uwsgi.log_master_bufsize;
173                 if (setsockopt(fd[1], SOL_SOCKET, SO_SNDBUF, &so_bufsize, so_bufsize_len)) {
174                         uwsgi_error("fix_logpipe_buf()/setsockopt()");
175                 }
176         }
177 }
178 
179 // create the logpipe
create_logpipe(void)180 void create_logpipe(void) {
181 
182 	if (uwsgi.log_master_stream) {
183 		if (socketpair(AF_UNIX, SOCK_STREAM, 0, uwsgi.shared->worker_log_pipe)) {
184 			uwsgi_error("create_logpipe()/socketpair()\n");
185 			exit(1);
186 		}
187 	}
188 	else {
189 #if defined(SOCK_SEQPACKET) && defined(__linux__)
190 		if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, uwsgi.shared->worker_log_pipe)) {
191 #else
192 		if (socketpair(AF_UNIX, SOCK_DGRAM, 0, uwsgi.shared->worker_log_pipe)) {
193 #endif
194 			uwsgi_error("create_logpipe()/socketpair()\n");
195 			exit(1);
196 		}
197 		fix_logpipe_buf(uwsgi.shared->worker_log_pipe);
198 	}
199 
200 	uwsgi_socket_nb(uwsgi.shared->worker_log_pipe[0]);
201 	uwsgi_socket_nb(uwsgi.shared->worker_log_pipe[1]);
202 
203 	if (uwsgi.shared->worker_log_pipe[1] != 1) {
204 		if (dup2(uwsgi.shared->worker_log_pipe[1], 1) < 0) {
205 			uwsgi_error("dup2()");
206 			exit(1);
207 		}
208 	}
209 
210 	if (dup2(1, 2) < 0) {
211 		uwsgi_error("dup2()");
212 		exit(1);
213 	}
214 
215 	if (uwsgi.req_log_master) {
216 		if (uwsgi.log_master_req_stream) {
217 			if (socketpair(AF_UNIX, SOCK_STREAM, 0, uwsgi.shared->worker_req_log_pipe)) {
218 				uwsgi_error("create_logpipe()/socketpair()\n");
219 				exit(1);
220 			}
221 		}
222 		else {
223 #if defined(SOCK_SEQPACKET) && defined(__linux__)
224 			if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, uwsgi.shared->worker_req_log_pipe)) {
225 #else
226 			if (socketpair(AF_UNIX, SOCK_DGRAM, 0, uwsgi.shared->worker_req_log_pipe)) {
227 #endif
228 				uwsgi_error("create_logpipe()/socketpair()\n");
229 				exit(1);
230 			}
231 			fix_logpipe_buf(uwsgi.shared->worker_req_log_pipe);
232 		}
233 
234 		uwsgi_socket_nb(uwsgi.shared->worker_req_log_pipe[0]);
235 		uwsgi_socket_nb(uwsgi.shared->worker_req_log_pipe[1]);
236 		uwsgi.req_log_fd = uwsgi.shared->worker_req_log_pipe[1];
237 	}
238 
239 }
240 
241 // log to the specified file or udp address
242 void logto(char *logfile) {
243 
244 	int fd;
245 
246 	char *udp_port;
247 	struct sockaddr_in udp_addr;
248 
249 	udp_port = strchr(logfile, ':');
250 	if (udp_port) {
251 		udp_port[0] = 0;
252 		if (!udp_port[1] || !logfile[0]) {
253 			uwsgi_log("invalid udp address\n");
254 			exit(1);
255 		}
256 
257 		fd = socket(AF_INET, SOCK_DGRAM, 0);
258 		if (fd < 0) {
259 			uwsgi_error("socket()");
260 			exit(1);
261 		}
262 
263 		memset(&udp_addr, 0, sizeof(struct sockaddr_in));
264 
265 		udp_addr.sin_family = AF_INET;
266 		udp_addr.sin_port = htons(atoi(udp_port + 1));
267 		char *resolved = uwsgi_resolve_ip(logfile);
268 		if (resolved) {
269 			udp_addr.sin_addr.s_addr = inet_addr(resolved);
270 		}
271 		else {
272 			udp_addr.sin_addr.s_addr = inet_addr(logfile);
273 		}
274 
275 		if (connect(fd, (const struct sockaddr *) &udp_addr, sizeof(struct sockaddr_in)) < 0) {
276 			uwsgi_error("connect()");
277 			exit(1);
278 		}
279 	}
280 	else {
281 		if (uwsgi.log_truncate) {
282 			fd = open(logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
283 		}
284 		else {
285 			fd = open(logfile, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
286 		}
287 		if (fd < 0) {
288 			uwsgi_error_open(logfile);
289 			exit(1);
290 		}
291 		uwsgi.logfile = logfile;
292 
293 		if (uwsgi.chmod_logfile_value) {
294 			if (chmod(uwsgi.logfile, uwsgi.chmod_logfile_value)) {
295 				uwsgi_error("chmod()");
296 			}
297 		}
298 	}
299 
300 
301 	// if the log-master is already active, just re-set the original_log_fd
302 	if (uwsgi.shared->worker_log_pipe[0] == -1) {
303 		/* stdout */
304 		if (fd != 1) {
305 			if (dup2(fd, 1) < 0) {
306 				uwsgi_error("dup2()");
307 				exit(1);
308 			}
309 			close(fd);
310 		}
311 
312 		/* stderr */
313 		if (dup2(1, 2) < 0) {
314 			uwsgi_error("dup2()");
315 			exit(1);
316 		}
317 
318 		 uwsgi.original_log_fd = 2;
319 	}
320 	else {
321 		uwsgi.original_log_fd = fd;
322 	}
323 }
324 
325 
326 
327 void uwsgi_setup_log() {
328 
329 	uwsgi_setup_log_encoders();
330 
331 	if (uwsgi.daemonize) {
332 		if (uwsgi.has_emperor) {
333 			logto(uwsgi.daemonize);
334 		}
335 		else {
336 			if (!uwsgi.is_a_reload) {
337 				daemonize(uwsgi.daemonize);
338 			}
339 			else if (uwsgi.log_reopen) {
340 				logto(uwsgi.daemonize);
341 			}
342 		}
343 	}
344 	else if (uwsgi.logfile) {
345 		if (!uwsgi.is_a_reload || uwsgi.log_reopen) {
346 			logto(uwsgi.logfile);
347 		}
348 	}
349 
350 }
351 
352 static struct uwsgi_logger *setup_choosen_logger(struct uwsgi_string_list *usl) {
353 	char *id = NULL;
354 	char *name = usl->value;
355 
356 	char *space = strchr(name, ' ');
357 	if (space) {
358 		int is_id = 1;
359 		int i;
360 		for (i = 0; i < (space - name); i++) {
361 			if (!isalnum((int)name[i])) {
362 				is_id = 0;
363 				break;
364 			}
365 		}
366 		if (is_id) {
367 			id = uwsgi_concat2n(name, space - name, "", 0);
368 			name = space + 1;
369 		}
370 	}
371 
372 	char *colon = strchr(name, ':');
373 	if (colon) {
374 		*colon = 0;
375 	}
376 
377 	struct uwsgi_logger *choosen_logger = uwsgi_get_logger(name);
378 	if (!choosen_logger) {
379 		uwsgi_log("unable to find logger %s\n", name);
380 		exit(1);
381 	}
382 
383 	// make a copy of the logger
384 	struct uwsgi_logger *copy_of_choosen_logger = uwsgi_malloc(sizeof(struct uwsgi_logger));
385 	memcpy(copy_of_choosen_logger, choosen_logger, sizeof(struct uwsgi_logger));
386 	choosen_logger = copy_of_choosen_logger;
387 	choosen_logger->id = id;
388 	choosen_logger->next = NULL;
389 
390 	if (colon) {
391 		choosen_logger->arg = colon + 1;
392 		// check for empty string
393 		if (*choosen_logger->arg == 0) {
394 			choosen_logger->arg = NULL;
395 		}
396 		*colon = ':';
397 	}
398 	return choosen_logger;
399 }
400 
401 void uwsgi_setup_log_master(void) {
402 
403 	struct uwsgi_string_list *usl = uwsgi.requested_logger;
404 	while (usl) {
405 		struct uwsgi_logger *choosen_logger = setup_choosen_logger(usl);
406 		uwsgi_append_logger(choosen_logger);
407 		usl = usl->next;
408 	}
409 
410 	usl = uwsgi.requested_req_logger;
411 	while (usl) {
412                 struct uwsgi_logger *choosen_logger = setup_choosen_logger(usl);
413                 uwsgi_append_req_logger(choosen_logger);
414                 usl = usl->next;
415         }
416 
417 #ifdef UWSGI_PCRE
418 	// set logger by its id
419 	struct uwsgi_regexp_list *url = uwsgi.log_route;
420 	while (url) {
421 		url->custom_ptr = uwsgi_get_logger_from_id(url->custom_str);
422 		url = url->next;
423 	}
424 	url = uwsgi.log_req_route;
425 	while (url) {
426 		url->custom_ptr = uwsgi_get_logger_from_id(url->custom_str);
427 		url = url->next;
428 	}
429 #endif
430 
431 	uwsgi.original_log_fd = dup(1);
432 	create_logpipe();
433 }
434 
435 struct uwsgi_logvar *uwsgi_logvar_get(struct wsgi_request *wsgi_req, char *key, uint8_t keylen) {
436 	struct uwsgi_logvar *lv = wsgi_req->logvars;
437 	while (lv) {
438 		if (!uwsgi_strncmp(key, keylen, lv->key, lv->keylen)) {
439 			return lv;
440 		}
441 		lv = lv->next;
442 	}
443 	return NULL;
444 }
445 
446 void uwsgi_logvar_add(struct wsgi_request *wsgi_req, char *key, uint8_t keylen, char *val, uint8_t vallen) {
447 
448 	struct uwsgi_logvar *lv = uwsgi_logvar_get(wsgi_req, key, keylen);
449 	if (lv) {
450 		memcpy(lv->val, val, vallen);
451 		lv->vallen = vallen;
452 		return;
453 	}
454 
455 	// add a new log object
456 
457 	lv = wsgi_req->logvars;
458 	if (lv) {
459 		while (lv) {
460 			if (!lv->next) {
461 				lv->next = uwsgi_malloc(sizeof(struct uwsgi_logvar));
462 				lv = lv->next;
463 				break;
464 			}
465 			lv = lv->next;
466 		}
467 	}
468 	else {
469 		lv = uwsgi_malloc(sizeof(struct uwsgi_logvar));
470 		wsgi_req->logvars = lv;
471 	}
472 
473 	memcpy(lv->key, key, keylen);
474 	lv->keylen = keylen;
475 	memcpy(lv->val, val, vallen);
476 	lv->vallen = vallen;
477 	lv->next = NULL;
478 
479 }
480 
481 void uwsgi_check_logrotate(void) {
482 
483 	int need_rotation = 0;
484 	int need_reopen = 0;
485 	off_t logsize;
486 
487 	if (uwsgi.log_master) {
488 		logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR);
489 	}
490 	else {
491 		logsize = lseek(2, 0, SEEK_CUR);
492 	}
493 	if (logsize < 0) {
494 		uwsgi_error("uwsgi_check_logrotate()/lseek()");
495 		return;
496 	}
497 	uwsgi.shared->logsize = logsize;
498 
499 	if (uwsgi.log_maxsize > 0 && (uint64_t) uwsgi.shared->logsize > uwsgi.log_maxsize) {
500 		need_rotation = 1;
501 	}
502 
503 	if (uwsgi_check_touches(uwsgi.touch_logrotate)) {
504 		need_rotation = 1;
505 	}
506 
507 	if (uwsgi_check_touches(uwsgi.touch_logreopen)) {
508 		need_reopen = 1;
509 	}
510 
511 	if (need_rotation) {
512 		uwsgi_log_rotate();
513 	}
514 	else if (need_reopen) {
515 		uwsgi_log_reopen();
516 	}
517 }
518 
519 void uwsgi_log_do_rotate(char *logfile, char *rotatedfile, off_t logsize, int log_fd) {
520 	int need_free = 0;
521 	char *rot_name = rotatedfile;
522 
523 	if (rot_name == NULL) {
524 		char *ts_str = uwsgi_num2str((int) uwsgi_now());
525 		rot_name = uwsgi_concat3(logfile, ".", ts_str);
526 		free(ts_str);
527 		need_free = 1;
528 	}
529 	// this will be rawly written to the logfile
530 	uwsgi_logfile_write("logsize: %llu, triggering rotation to %s...\n", (unsigned long long) logsize, rot_name);
531 	if (rename(logfile, rot_name) == 0) {
532 		// reopen logfile and dup'it, on dup2 error, exit(1)
533 		int fd = open(logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
534 		if (fd < 0) {
535 			// this will be written to the original file
536 			uwsgi_error_open(logfile);
537 			exit(1);
538 		}
539 		if (dup2(fd, log_fd) < 0) {
540 			// this could be lost :(
541 			uwsgi_error("uwsgi_log_do_rotate()/dup2()");
542 			close(fd);
543 			exit(1);
544 		}
545 		close(fd);
546 
547 		if (uwsgi.chmod_logfile_value) {
548 			if (fchmod(log_fd, uwsgi.chmod_logfile_value)) {
549 				uwsgi_error("fchmod()");
550 			}
551 		}
552 		if (uwsgi.logfile_chown) {
553 			if (fchown(log_fd, uwsgi.uid, uwsgi.gid)) {
554 				uwsgi_error("fchown()");
555 			}
556 		}
557 	}
558 	else {
559 		uwsgi_error("unable to rotate log: rename()");
560 	}
561 	if (need_free)
562 		free(rot_name);
563 }
564 
565 void uwsgi_log_rotate() {
566 	if (!uwsgi.logfile)
567 		return;
568 	uwsgi_log_do_rotate(uwsgi.logfile, uwsgi.log_backupname, uwsgi.shared->logsize, uwsgi.original_log_fd);
569 }
570 
571 void uwsgi_log_reopen() {
572 	char message[1024];
573 	if (!uwsgi.logfile) return;
574 	int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering log-reopen...\n", (int) uwsgi_now(), (unsigned long long) uwsgi.shared->logsize);
575         if (ret > 0 && ret < 1024) {
576                         if (write(uwsgi.original_log_fd, message, ret) != ret) {
577                                 // very probably this will never be printed
578                                 uwsgi_error("write()");
579                         }
580                 }
581 
582                 // reopen logfile;
583                 close(uwsgi.original_log_fd);
584                 uwsgi.original_log_fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
585                 if (uwsgi.original_log_fd < 0) {
586                         uwsgi_error_open(uwsgi.logfile);
587                         grace_them_all(0);
588 			return;
589                 }
590                 ret = snprintf(message, 1024, "[%d] %s reopened.\n", (int) uwsgi_now(), uwsgi.logfile);
591                 if (ret > 0 && ret < 1024) {
592                         if (write(uwsgi.original_log_fd, message, ret) != ret) {
593                                 // very probably this will never be printed
594                                 uwsgi_error("write()");
595                         }
596                 }
597                 uwsgi.shared->logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR);
598 }
599 
600 
601 void log_request(struct wsgi_request *wsgi_req) {
602 
603 	int log_it = uwsgi.logging_options.enabled;
604 
605 	if (wsgi_req->do_not_log)
606 		return;
607 
608 	if (wsgi_req->log_this) {
609 		goto logit;
610 	}
611 
612 /* conditional logging */
613 	if (uwsgi.logging_options.zero && wsgi_req->response_size == 0) {
614 		goto logit;
615 	}
616 	if (uwsgi.logging_options.slow && (uint32_t) wsgi_req_time >= uwsgi.logging_options.slow) {
617 		goto logit;
618 	}
619 	if (uwsgi.logging_options._4xx && (wsgi_req->status >= 400 && wsgi_req->status <= 499)) {
620 		goto logit;
621 	}
622 	if (uwsgi.logging_options._5xx && (wsgi_req->status >= 500 && wsgi_req->status <= 599)) {
623 		goto logit;
624 	}
625 	if (uwsgi.logging_options.big && (wsgi_req->response_size >= uwsgi.logging_options.big)) {
626 		goto logit;
627 	}
628 	if (uwsgi.logging_options.sendfile && wsgi_req->via == UWSGI_VIA_SENDFILE) {
629 		goto logit;
630 	}
631 	if (uwsgi.logging_options.ioerror && wsgi_req->read_errors > 0 && wsgi_req->write_errors > 0) {
632 		goto logit;
633 	}
634 
635 	if (!log_it)
636 		return;
637 
638 logit:
639 
640 	uwsgi.logit(wsgi_req);
641 }
642 
643 void uwsgi_logit_simple(struct wsgi_request *wsgi_req) {
644 
645 	// optimize this (please)
646 	char time_request[26];
647 	int rlen;
648 	int app_req = -1;
649 	char *msg2 = " ";
650 	char *via = msg2;
651 
652 	char mempkt[4096];
653 	char logpkt[4096];
654 
655 	struct iovec logvec[4];
656 	int logvecpos = 0;
657 
658 	const char *msecs = "msecs";
659 	const char *micros = "micros";
660 
661 	char *tsize = (char *) msecs;
662 
663 	char *msg1 = " via sendfile() ";
664 	char *msg3 = " via route() ";
665 	char *msg4 = " via offload() ";
666 
667 	struct uwsgi_app *wi;
668 
669 	if (wsgi_req->app_id >= 0) {
670 		wi = &uwsgi_apps[wsgi_req->app_id];
671 		if (wi->requests > 0) {
672 			app_req = wi->requests;
673 		}
674 	}
675 
676 	// mark requests via (sendfile, route, offload...)
677 	switch(wsgi_req->via) {
678 		case UWSGI_VIA_SENDFILE:
679 			via = msg1;
680 			break;
681 		case UWSGI_VIA_ROUTE:
682 			via = msg3;
683 			break;
684 		case UWSGI_VIA_OFFLOAD:
685 			via = msg4;
686 			break;
687 		default:
688 			break;
689 	}
690 
691 #if defined(__sun__) && !defined(__clang__)
692 	ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, time_request, 26);
693 #else
694 	ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, time_request);
695 #endif
696 
697 	uint64_t rt = 0;
698 	// avoid overflow on clock instability (#1489)
699 	if (wsgi_req->end_of_request > wsgi_req->start_of_request)
700 		rt = wsgi_req->end_of_request - wsgi_req->start_of_request;
701 
702 	if (uwsgi.log_micros) {
703 		tsize = (char *) micros;
704 	}
705 	else {
706 		rt /= 1000;
707 	}
708 
709 	if (uwsgi.vhost) {
710 		logvec[logvecpos].iov_base = wsgi_req->host;
711 		logvec[logvecpos].iov_len = wsgi_req->host_len;
712 		logvecpos++;
713 
714 		logvec[logvecpos].iov_base = " ";
715 		logvec[logvecpos].iov_len = 1;
716 		logvecpos++;
717 	}
718 
719 	if (uwsgi.logging_options.memory_report == 1) {
720 		rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} {rss usage: %llu bytes/%lluMB} ", (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024,
721 			(unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024);
722 		logvec[logvecpos].iov_base = mempkt;
723 		logvec[logvecpos].iov_len = rlen;
724 		logvecpos++;
725 
726 	}
727 
728 	char *remote_user = wsgi_req->remote_user == NULL ? "" : wsgi_req->remote_user;
729 	rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] %.*s (%.*s) {%d vars in %d bytes} [%.*s] %.*s %.*s => generated %llu bytes in %llu %s%s(%.*s %d) %d headers in %llu bytes (%d switches on core %d)\n", (int) uwsgi.mypid, wsgi_req->app_id, app_req, (unsigned long long) uwsgi.workers[0].requests, wsgi_req->remote_addr_len, wsgi_req->remote_addr, wsgi_req->remote_user_len, remote_user, wsgi_req->var_cnt, wsgi_req->uh->pktsize,
730 			24, time_request, wsgi_req->method_len, wsgi_req->method, wsgi_req->uri_len, wsgi_req->uri, (unsigned long long) wsgi_req->response_size, (unsigned long long) rt, tsize, via, wsgi_req->protocol_len, wsgi_req->protocol, wsgi_req->status, wsgi_req->header_cnt, (unsigned long long) wsgi_req->headers_size, wsgi_req->switches, wsgi_req->async_id);
731 
732 	// not enough space for logging the request, just log a (safe) minimal message
733 	if (rlen > 4096) {
734 		rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] 0.0.0.0 () {%d vars in %d bytes} [%.*s] - - => generated %llu bytes in %llu %s%s(- %d) %d headers in %llu bytes (%d switches on core %d)\n", (int) uwsgi.mypid, wsgi_req->app_id, app_req, (unsigned long long) uwsgi.workers[0].requests, wsgi_req->var_cnt, wsgi_req->uh->pktsize,
735 		24, time_request, (unsigned long long) wsgi_req->response_size, (unsigned long long) rt, tsize, via, wsgi_req->status, wsgi_req->header_cnt, (unsigned long long) wsgi_req->headers_size, wsgi_req->switches, wsgi_req->async_id);
736 		// argh, last resort, truncate it
737 		if (rlen > 4096) {
738 			rlen = 4096;
739 		}
740 	}
741 
742 	logvec[logvecpos].iov_base = logpkt;
743 	logvec[logvecpos].iov_len = rlen;
744 
745 	// do not check for errors
746 	rlen = writev(uwsgi.req_log_fd, logvec, logvecpos + 1);
747 }
748 
749 void get_memusage(uint64_t * rss, uint64_t * vsz) {
750 
751 #ifdef UNBIT
752 	uint64_t ret[2];
753 	ret[0] = 0; ret[1] = 0;
754 	syscall(358, ret);
755 	*vsz = ret[0];
756 	*rss = ret[1] * uwsgi.page_size;
757 #elif defined(__linux__)
758 	FILE *procfile;
759 	int i;
760 	procfile = fopen("/proc/self/stat", "r");
761 	if (procfile) {
762 		i = fscanf(procfile, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %llu %lld", (unsigned long long *) vsz, (unsigned long long *) rss);
763 		if (i != 2) {
764 			uwsgi_log("warning: invalid record in /proc/self/stat\n");
765 		} else {
766 			*rss = *rss * uwsgi.page_size;
767 		}
768 		fclose(procfile);
769 	}
770 #elif defined(__CYGWIN__)
771 	// same as Linux but rss is not in pages...
772 	FILE *procfile;
773         int i;
774         procfile = fopen("/proc/self/stat", "r");
775         if (procfile) {
776                 i = fscanf(procfile, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %llu %lld", (unsigned long long *) vsz, (unsigned long long *) rss);
777                 if (i != 2) {
778                         uwsgi_log("warning: invalid record in /proc/self/stat\n");
779                 }
780                 fclose(procfile);
781         }
782 #elif defined (__sun__)
783 	psinfo_t info;
784 	int procfd;
785 
786 	procfd = open("/proc/self/psinfo", O_RDONLY);
787 	if (procfd >= 0) {
788 		if (read(procfd, (char *) &info, sizeof(info)) > 0) {
789 			*rss = (uint64_t) info.pr_rssize * 1024;
790 			*vsz = (uint64_t) info.pr_size * 1024;
791 		}
792 		close(procfd);
793 	}
794 
795 #elif defined(__APPLE__)
796 	/* darwin documentation says that the value are in pages, but they are bytes !!! */
797 	struct task_basic_info t_info;
798 	mach_msg_type_number_t t_size = sizeof(struct task_basic_info);
799 
800 	if (task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t) & t_info, &t_size) == KERN_SUCCESS) {
801 		*rss = t_info.resident_size;
802 		*vsz = t_info.virtual_size;
803 	}
804 #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
805 	kvm_t *kv;
806 	int cnt;
807 
808 #if defined(__FreeBSD__)
809 	kv = kvm_open(NULL, "/dev/null", NULL, O_RDONLY, NULL);
810 #elif defined(__NetBSD__) || defined(__OpenBSD__)
811 	kv = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, NULL);
812 #else
813 	kv = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);
814 #endif
815 	if (kv) {
816 #if defined(__FreeBSD__) || defined(__DragonFly__)
817 
818 		struct kinfo_proc *kproc;
819 		kproc = kvm_getprocs(kv, KERN_PROC_PID, uwsgi.mypid, &cnt);
820 		if (kproc && cnt > 0) {
821 #if defined(__FreeBSD__)
822 			*vsz = kproc->ki_size;
823 			*rss = kproc->ki_rssize * uwsgi.page_size;
824 #elif defined(__DragonFly__)
825 			*vsz = kproc->kp_vm_map_size;
826 			*rss = kproc->kp_vm_rssize * uwsgi.page_size;
827 #endif
828 		}
829 #elif defined(UWSGI_NEW_OPENBSD)
830 		struct kinfo_proc *kproc;
831 		kproc = kvm_getprocs(kv, KERN_PROC_PID, uwsgi.mypid, sizeof(struct kinfo_proc), &cnt);
832 		if (kproc && cnt > 0) {
833 			*vsz = (kproc->p_vm_dsize + kproc->p_vm_ssize + kproc->p_vm_tsize) * uwsgi.page_size;
834 			*rss = kproc->p_vm_rssize * uwsgi.page_size;
835 		}
836 #elif defined(__NetBSD__) || defined(__OpenBSD__)
837 		struct kinfo_proc2 *kproc2;
838 
839 		kproc2 = kvm_getproc2(kv, KERN_PROC_PID, uwsgi.mypid, sizeof(struct kinfo_proc2), &cnt);
840 		if (kproc2 && cnt > 0) {
841 #ifdef __OpenBSD__
842 			*vsz = (kproc2->p_vm_dsize + kproc2->p_vm_ssize + kproc2->p_vm_tsize) * uwsgi.page_size;
843 #else
844 			*vsz = kproc2->p_vm_msize * uwsgi.page_size;
845 #endif
846 			*rss = kproc2->p_vm_rssize * uwsgi.page_size;
847 		}
848 #endif
849 
850 		kvm_close(kv);
851 	}
852 #elif defined(__HAIKU__)
853 	area_info ai;
854 	int32 cookie;
855 
856 	*vsz = 0;
857 	*rss = 0;
858 	while (get_next_area_info(0, &cookie, &ai) == B_OK) {
859 		*vsz += ai.ram_size;
860 		if ((ai.protection & B_WRITE_AREA) != 0) {
861 			*rss += ai.ram_size;
862 		}
863 	}
864 #endif
865 
866 }
867 
868 void uwsgi_register_logger(char *name, ssize_t(*func) (struct uwsgi_logger *, char *, size_t)) {
869 
870 	struct uwsgi_logger *ul = uwsgi.loggers, *old_ul;
871 
872 	if (!ul) {
873 		uwsgi.loggers = uwsgi_malloc(sizeof(struct uwsgi_logger));
874 		ul = uwsgi.loggers;
875 	}
876 	else {
877 		while (ul) {
878 			old_ul = ul;
879 			ul = ul->next;
880 		}
881 
882 		ul = uwsgi_malloc(sizeof(struct uwsgi_logger));
883 		old_ul->next = ul;
884 	}
885 
886 	ul->name = name;
887 	ul->func = func;
888 	ul->next = NULL;
889 	ul->configured = 0;
890 	ul->fd = -1;
891 	ul->data = NULL;
892 	ul->buf = NULL;
893 
894 
895 #ifdef UWSGI_DEBUG
896 	uwsgi_log("[uwsgi-logger] registered \"%s\"\n", ul->name);
897 #endif
898 }
899 
900 void uwsgi_append_logger(struct uwsgi_logger *ul) {
901 
902 	if (!uwsgi.choosen_logger) {
903 		uwsgi.choosen_logger = ul;
904 		return;
905 	}
906 
907 	struct uwsgi_logger *ucl = uwsgi.choosen_logger;
908 	while (ucl) {
909 		if (!ucl->next) {
910 			ucl->next = ul;
911 			return;
912 		}
913 		ucl = ucl->next;
914 	}
915 }
916 
917 void uwsgi_append_req_logger(struct uwsgi_logger *ul) {
918 
919         if (!uwsgi.choosen_req_logger) {
920                 uwsgi.choosen_req_logger = ul;
921                 return;
922         }
923 
924         struct uwsgi_logger *ucl = uwsgi.choosen_req_logger;
925         while (ucl) {
926                 if (!ucl->next) {
927                         ucl->next = ul;
928                         return;
929                 }
930                 ucl = ucl->next;
931         }
932 }
933 
934 
935 struct uwsgi_logger *uwsgi_get_logger(char *name) {
936 	struct uwsgi_logger *ul = uwsgi.loggers;
937 
938 	while (ul) {
939 		if (!strcmp(ul->name, name)) {
940 			return ul;
941 		}
942 		ul = ul->next;
943 	}
944 
945 	return NULL;
946 }
947 
948 struct uwsgi_logger *uwsgi_get_logger_from_id(char *id) {
949 	struct uwsgi_logger *ul = uwsgi.choosen_logger;
950 
951 	while (ul) {
952 		if (ul->id && !strcmp(ul->id, id)) {
953 			return ul;
954 		}
955 		ul = ul->next;
956 	}
957 
958 	return NULL;
959 }
960 
961 
962 void uwsgi_logit_lf(struct wsgi_request *wsgi_req) {
963 	struct uwsgi_logchunk *logchunk = uwsgi.logchunks;
964 	ssize_t rlen = 0;
965 	const char *empty_var = "-";
966 	while (logchunk) {
967 		int pos = logchunk->vec;
968 		// raw string
969 		if (logchunk->type == 0) {
970 			uwsgi.logvectors[wsgi_req->async_id][pos].iov_base = logchunk->ptr;
971 			uwsgi.logvectors[wsgi_req->async_id][pos].iov_len = logchunk->len;
972 		}
973 		// offsetof
974 		else if (logchunk->type == 1) {
975 			char **var = (char **) (((char *) wsgi_req) + logchunk->pos);
976 			uint16_t *varlen = (uint16_t *) (((char *) wsgi_req) + logchunk->pos_len);
977 			uwsgi.logvectors[wsgi_req->async_id][pos].iov_base = *var;
978 			uwsgi.logvectors[wsgi_req->async_id][pos].iov_len = *varlen;
979 		}
980 		// logvar
981 		else if (logchunk->type == 2) {
982 			struct uwsgi_logvar *lv = uwsgi_logvar_get(wsgi_req, logchunk->ptr, logchunk->len);
983 			if (lv) {
984 				uwsgi.logvectors[wsgi_req->async_id][pos].iov_base = lv->val;
985 				uwsgi.logvectors[wsgi_req->async_id][pos].iov_len = lv->vallen;
986 			}
987 			else {
988 				uwsgi.logvectors[wsgi_req->async_id][pos].iov_base = NULL;
989 				uwsgi.logvectors[wsgi_req->async_id][pos].iov_len = 0;
990 			}
991 		}
992 		// func
993 		else if (logchunk->type == 3) {
994 			rlen = logchunk->func(wsgi_req, (char **) &uwsgi.logvectors[wsgi_req->async_id][pos].iov_base);
995 			if (rlen > 0) {
996 				uwsgi.logvectors[wsgi_req->async_id][pos].iov_len = rlen;
997 			}
998 			else {
999 				uwsgi.logvectors[wsgi_req->async_id][pos].iov_len = 0;
1000 			}
1001 		}
1002 		// var
1003 		else if (logchunk->type == 5) {
1004 			uint16_t value_len = 0;
1005 			char *value = uwsgi_get_var(wsgi_req, logchunk->ptr, logchunk->len, &value_len);
1006 			// could be NULL
1007                         uwsgi.logvectors[wsgi_req->async_id][pos].iov_base = value;
1008                         uwsgi.logvectors[wsgi_req->async_id][pos].iov_len = (size_t) value_len;
1009                 }
1010 		// metric
1011 		else if (logchunk->type == 4) {
1012 			int64_t metric = uwsgi_metric_get(logchunk->ptr, NULL);
1013 			uwsgi.logvectors[wsgi_req->async_id][pos].iov_base = uwsgi_64bit2str(metric);
1014 			uwsgi.logvectors[wsgi_req->async_id][pos].iov_len = strlen(uwsgi.logvectors[wsgi_req->async_id][pos].iov_base);
1015 		}
1016 
1017 		if (uwsgi.logvectors[wsgi_req->async_id][pos].iov_len == 0 && logchunk->type != 0) {
1018 			uwsgi.logvectors[wsgi_req->async_id][pos].iov_base = (char *) empty_var;
1019 			uwsgi.logvectors[wsgi_req->async_id][pos].iov_len = 1;
1020 		}
1021 		logchunk = logchunk->next;
1022 	}
1023 
1024 	// do not check for errors
1025 	rlen = writev(uwsgi.req_log_fd, uwsgi.logvectors[wsgi_req->async_id], uwsgi.logformat_vectors);
1026 
1027 	// free allocated memory
1028 	logchunk = uwsgi.logchunks;
1029 	while (logchunk) {
1030 		if (logchunk->free) {
1031 			if (uwsgi.logvectors[wsgi_req->async_id][logchunk->vec].iov_len > 0) {
1032 				if (uwsgi.logvectors[wsgi_req->async_id][logchunk->vec].iov_base != empty_var) {
1033 					free(uwsgi.logvectors[wsgi_req->async_id][logchunk->vec].iov_base);
1034 				}
1035 			}
1036 		}
1037 		logchunk = logchunk->next;
1038 	}
1039 }
1040 
1041 void uwsgi_build_log_format(char *format) {
1042 	int state = 0;
1043 	char *ptr = format;
1044 	char *current = ptr;
1045 	char *logvar = NULL;
1046 	// get the number of required iovec
1047 	while (*ptr) {
1048 		if (*ptr == '%') {
1049 			if (state == 0) {
1050 				state = 1;
1051 			}
1052 		}
1053 		// start of the variable
1054 		else if (*ptr == '(') {
1055 			if (state == 1) {
1056 				state = 2;
1057 			}
1058 		}
1059 		// end of the variable
1060 		else if (*ptr == ')') {
1061 			if (logvar) {
1062 				uwsgi_add_logchunk(1, uwsgi.logformat_vectors, logvar, ptr - logvar);
1063 				uwsgi.logformat_vectors++;
1064 				state = 0;
1065 				logvar = NULL;
1066 				current = ptr + 1;
1067 			}
1068 		}
1069 		else {
1070 			if (state == 2) {
1071 				uwsgi_add_logchunk(0, uwsgi.logformat_vectors, current, (ptr - current) - 2);
1072 				uwsgi.logformat_vectors++;
1073 				logvar = ptr;
1074 			}
1075 			state = 0;
1076 		}
1077 		ptr++;
1078 	}
1079 
1080 	if (ptr - current > 0) {
1081 		uwsgi_add_logchunk(0, uwsgi.logformat_vectors, current, ptr - current);
1082 		uwsgi.logformat_vectors++;
1083 	}
1084 
1085 	// +1 for "\n"
1086 
1087 	uwsgi.logformat_vectors++;
1088 
1089 }
1090 
1091 static ssize_t uwsgi_lf_status(struct wsgi_request *wsgi_req, char **buf) {
1092 	*buf = uwsgi_num2str(wsgi_req->status);
1093 	return strlen(*buf);
1094 }
1095 
1096 static ssize_t uwsgi_lf_rsize(struct wsgi_request *wsgi_req, char **buf) {
1097 	*buf = uwsgi_size2str(wsgi_req->response_size);
1098 	return strlen(*buf);
1099 }
1100 
1101 static ssize_t uwsgi_lf_hsize(struct wsgi_request *wsgi_req, char **buf) {
1102 	*buf = uwsgi_size2str(wsgi_req->headers_size);
1103 	return strlen(*buf);
1104 }
1105 
1106 static ssize_t uwsgi_lf_size(struct wsgi_request *wsgi_req, char **buf) {
1107 	*buf = uwsgi_size2str(wsgi_req->headers_size+wsgi_req->response_size);
1108 	return strlen(*buf);
1109 }
1110 
1111 static ssize_t uwsgi_lf_cl(struct wsgi_request *wsgi_req, char **buf) {
1112 	*buf = uwsgi_num2str(wsgi_req->post_cl);
1113 	return strlen(*buf);
1114 }
1115 
1116 
1117 static ssize_t uwsgi_lf_epoch(struct wsgi_request * wsgi_req, char **buf) {
1118 	*buf = uwsgi_num2str(uwsgi_now());
1119 	return strlen(*buf);
1120 }
1121 
1122 static ssize_t uwsgi_lf_ctime(struct wsgi_request * wsgi_req, char **buf) {
1123 	*buf = uwsgi_malloc(26);
1124 #if defined(__sun__) && !defined(__clang__)
1125 	ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, *buf, 26);
1126 #else
1127 	ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, *buf);
1128 #endif
1129 	return 24;
1130 }
1131 
1132 static ssize_t uwsgi_lf_time(struct wsgi_request * wsgi_req, char **buf) {
1133 	*buf = uwsgi_num2str(wsgi_req->start_of_request / 1000000);
1134 	return strlen(*buf);
1135 }
1136 
1137 
1138 static ssize_t uwsgi_lf_ltime(struct wsgi_request * wsgi_req, char **buf) {
1139 	*buf = uwsgi_malloc(64);
1140 	time_t now = wsgi_req->start_of_request / 1000000;
1141 	size_t ret = strftime(*buf, 64, "%d/%b/%Y:%H:%M:%S %z", localtime(&now));
1142 	if (ret == 0) {
1143 		*buf[0] = 0;
1144 		return 0;
1145 	}
1146 	return ret;
1147 }
1148 
1149 static ssize_t uwsgi_lf_ftime(struct wsgi_request * wsgi_req, char **buf) {
1150 	if (!uwsgi.logformat_strftime || !uwsgi.log_strftime) {
1151 		return uwsgi_lf_ltime(wsgi_req, buf);
1152 	}
1153 	*buf = uwsgi_malloc(64);
1154 	time_t now = wsgi_req->start_of_request / 1000000;
1155 	size_t ret = strftime(*buf, 64, uwsgi.log_strftime, localtime(&now));
1156 	if (ret == 0) {
1157 		*buf[0] = 0;
1158 		return 0;
1159 	}
1160 	return ret;
1161 }
1162 
1163 static ssize_t uwsgi_lf_tmsecs(struct wsgi_request * wsgi_req, char **buf) {
1164 	*buf = uwsgi_64bit2str(wsgi_req->start_of_request / (int64_t) 1000);
1165 	return strlen(*buf);
1166 }
1167 
1168 static ssize_t uwsgi_lf_tmicros(struct wsgi_request * wsgi_req, char **buf) {
1169 	*buf = uwsgi_64bit2str(wsgi_req->start_of_request);
1170 	return strlen(*buf);
1171 }
1172 
1173 static ssize_t uwsgi_lf_micros(struct wsgi_request * wsgi_req, char **buf) {
1174 	*buf = uwsgi_num2str(wsgi_req->end_of_request - wsgi_req->start_of_request);
1175 	return strlen(*buf);
1176 }
1177 
1178 static ssize_t uwsgi_lf_msecs(struct wsgi_request * wsgi_req, char **buf) {
1179 	*buf = uwsgi_num2str((wsgi_req->end_of_request - wsgi_req->start_of_request) / 1000);
1180 	return strlen(*buf);
1181 }
1182 
1183 static ssize_t uwsgi_lf_secs(struct wsgi_request * wsgi_req, char **buf) {
1184 	*buf = uwsgi_float2str((wsgi_req->end_of_request - wsgi_req->start_of_request) / 1000000.0);
1185 	return strlen(*buf);
1186 }
1187 
1188 static ssize_t uwsgi_lf_pid(struct wsgi_request * wsgi_req, char **buf) {
1189 	*buf = uwsgi_num2str(uwsgi.mypid);
1190 	return strlen(*buf);
1191 }
1192 
1193 static ssize_t uwsgi_lf_wid(struct wsgi_request * wsgi_req, char **buf) {
1194 	*buf = uwsgi_num2str(uwsgi.mywid);
1195 	return strlen(*buf);
1196 }
1197 
1198 static ssize_t uwsgi_lf_switches(struct wsgi_request * wsgi_req, char **buf) {
1199 	*buf = uwsgi_num2str(wsgi_req->switches);
1200 	return strlen(*buf);
1201 }
1202 
1203 static ssize_t uwsgi_lf_vars(struct wsgi_request * wsgi_req, char **buf) {
1204 	*buf = uwsgi_num2str(wsgi_req->var_cnt);
1205 	return strlen(*buf);
1206 }
1207 
1208 static ssize_t uwsgi_lf_core(struct wsgi_request * wsgi_req, char **buf) {
1209 	*buf = uwsgi_num2str(wsgi_req->async_id);
1210 	return strlen(*buf);
1211 }
1212 
1213 static ssize_t uwsgi_lf_vsz(struct wsgi_request * wsgi_req, char **buf) {
1214 	*buf = uwsgi_num2str(uwsgi.workers[uwsgi.mywid].vsz_size);
1215 	return strlen(*buf);
1216 }
1217 
1218 static ssize_t uwsgi_lf_rss(struct wsgi_request * wsgi_req, char **buf) {
1219 	*buf = uwsgi_num2str(uwsgi.workers[uwsgi.mywid].rss_size);
1220 	return strlen(*buf);
1221 }
1222 
1223 static ssize_t uwsgi_lf_vszM(struct wsgi_request * wsgi_req, char **buf) {
1224 	*buf = uwsgi_num2str(uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024);
1225 	return strlen(*buf);
1226 }
1227 
1228 static ssize_t uwsgi_lf_rssM(struct wsgi_request * wsgi_req, char **buf) {
1229 	*buf = uwsgi_num2str(uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024);
1230 	return strlen(*buf);
1231 }
1232 
1233 static ssize_t uwsgi_lf_pktsize(struct wsgi_request * wsgi_req, char **buf) {
1234 	*buf = uwsgi_num2str(wsgi_req->uh->pktsize);
1235 	return strlen(*buf);
1236 }
1237 
1238 static ssize_t uwsgi_lf_modifier1(struct wsgi_request * wsgi_req, char **buf) {
1239 	*buf = uwsgi_num2str(wsgi_req->uh->modifier1);
1240 	return strlen(*buf);
1241 }
1242 
1243 static ssize_t uwsgi_lf_modifier2(struct wsgi_request * wsgi_req, char **buf) {
1244 	*buf = uwsgi_num2str(wsgi_req->uh->modifier2);
1245 	return strlen(*buf);
1246 }
1247 
1248 static ssize_t uwsgi_lf_headers(struct wsgi_request * wsgi_req, char **buf) {
1249 	*buf = uwsgi_num2str(wsgi_req->header_cnt);
1250 	return strlen(*buf);
1251 }
1252 
1253 static ssize_t uwsgi_lf_werr(struct wsgi_request * wsgi_req, char **buf) {
1254 	*buf = uwsgi_num2str((int) wsgi_req->write_errors);
1255 	return strlen(*buf);
1256 }
1257 
1258 static ssize_t uwsgi_lf_rerr(struct wsgi_request * wsgi_req, char **buf) {
1259 	*buf = uwsgi_num2str((int) wsgi_req->read_errors);
1260 	return strlen(*buf);
1261 }
1262 
1263 static ssize_t uwsgi_lf_ioerr(struct wsgi_request * wsgi_req, char **buf) {
1264 	*buf = uwsgi_num2str((int) (wsgi_req->write_errors + wsgi_req->read_errors));
1265 	return strlen(*buf);
1266 }
1267 
1268 struct uwsgi_logchunk *uwsgi_register_logchunk(char *name, ssize_t (*func)(struct wsgi_request *, char **), int need_free) {
1269 	struct uwsgi_logchunk *old_logchunk = NULL, *logchunk = uwsgi.registered_logchunks;
1270 	while(logchunk) {
1271 		if (!strcmp(logchunk->name, name)) goto found;
1272 		old_logchunk = logchunk;
1273 		logchunk = logchunk->next;
1274 	}
1275 	logchunk = uwsgi_calloc(sizeof(struct uwsgi_logchunk));
1276 	logchunk->name = name;
1277 	if (old_logchunk) {
1278 		old_logchunk->next = logchunk;
1279 	}
1280 	else {
1281 		uwsgi.registered_logchunks = logchunk;
1282 	}
1283 found:
1284 	logchunk->func = func;
1285 	logchunk->free = need_free;
1286 	logchunk->type = 3;
1287 	return logchunk;
1288 }
1289 
1290 struct uwsgi_logchunk *uwsgi_get_logchunk_by_name(char *name, size_t name_len) {
1291 	struct uwsgi_logchunk *logchunk = uwsgi.registered_logchunks;
1292 	while(logchunk) {
1293 		if (!uwsgi_strncmp(name, name_len, logchunk->name, strlen(logchunk->name))) {
1294 			return logchunk;
1295 		}
1296 		logchunk = logchunk->next;
1297 	}
1298 	return NULL;
1299 }
1300 
1301 void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
1302 
1303 	struct uwsgi_logchunk *logchunk = uwsgi.logchunks;
1304 
1305 	if (logchunk) {
1306 		while (logchunk) {
1307 			if (!logchunk->next) {
1308 				logchunk->next = uwsgi_calloc(sizeof(struct uwsgi_logchunk));
1309 				logchunk = logchunk->next;
1310 				break;
1311 			}
1312 			logchunk = logchunk->next;
1313 		}
1314 	}
1315 	else {
1316 		uwsgi.logchunks = uwsgi_calloc(sizeof(struct uwsgi_logchunk));
1317 		logchunk = uwsgi.logchunks;
1318 	}
1319 
1320 	/*
1321 	   0 -> raw text
1322 	   1 -> offsetof variable
1323 	   2 -> logvar
1324 	   3 -> func
1325 	   4 -> metric
1326 	   5 -> request variable
1327 	 */
1328 
1329 	logchunk->type = variable;
1330 	logchunk->vec = pos;
1331 	// normal text
1332 	logchunk->ptr = ptr;
1333 	logchunk->len = len;
1334 	// variable
1335 	if (variable) {
1336 		struct uwsgi_logchunk *rlc = uwsgi_get_logchunk_by_name(ptr, len);
1337 		if (rlc) {
1338 			if (rlc->type == 1) {
1339 				logchunk->pos = rlc->pos;
1340 				logchunk->pos_len = rlc->pos_len;
1341 			}
1342 			else if (rlc->type == 3) {
1343 				logchunk->type = 3;
1344 				logchunk->func = rlc->func;
1345 				logchunk->free = rlc->free;
1346 			}
1347 		}
1348 		// var
1349 		else if (!uwsgi_starts_with(ptr, len, "var.", 4)) {
1350 			logchunk->type = 5;
1351 			logchunk->ptr = ptr+4;
1352 			logchunk->len = len-4;
1353 			logchunk->free = 0;
1354 		}
1355 		// metric
1356 		else if (!uwsgi_starts_with(ptr, len, "metric.", 7)) {
1357 			logchunk->type = 4;
1358 			logchunk->ptr = uwsgi_concat2n(ptr+7, len - 7, "", 0);
1359 			logchunk->free = 1;
1360 		}
1361 		// logvar
1362 		else {
1363 			logchunk->type = 2;
1364 		}
1365 	}
1366 }
1367 
1368 static void uwsgi_log_func_do(struct uwsgi_string_list *encoders, struct uwsgi_logger *ul, char *msg, size_t len) {
1369 	struct uwsgi_string_list *usl = encoders;
1370 	// note: msg must not be freed !!!
1371 	char *new_msg = msg;
1372 	size_t new_msg_len = len;
1373 	while(usl) {
1374 		struct uwsgi_log_encoder *ule = (struct uwsgi_log_encoder *) usl->custom_ptr;
1375 		if (ule->use_for) {
1376 			if (ul && ul->id) {
1377 				if (strcmp(ule->use_for, ul->id)) {
1378 					goto next;
1379 				}
1380 			}
1381 			else {
1382 				goto next;
1383 			}
1384 		}
1385 		size_t rlen = 0;
1386 		char *buf = ule->func(ule, new_msg, new_msg_len, &rlen);
1387 		if (new_msg != msg) {
1388                 	free(new_msg);
1389         	}
1390 		new_msg = buf;
1391 		new_msg_len = rlen;
1392 next:
1393 		usl = usl->next;
1394 	}
1395 	if (ul) {
1396 		ul->func(ul, new_msg, new_msg_len);
1397 	}
1398 	else {
1399 		new_msg_len = (size_t) write(uwsgi.original_log_fd, new_msg, new_msg_len);
1400 	}
1401 	if (new_msg != msg) {
1402 		free(new_msg);
1403 	}
1404 
1405 }
1406 
1407 int uwsgi_master_log(void) {
1408 
1409         ssize_t rlen = read(uwsgi.shared->worker_log_pipe[0], uwsgi.log_master_buf, uwsgi.log_master_bufsize);
1410         if (rlen > 0) {
1411 #ifdef UWSGI_PCRE
1412                 uwsgi_alarm_log_check(uwsgi.log_master_buf, rlen);
1413                 struct uwsgi_regexp_list *url = uwsgi.log_drain_rules;
1414                 while (url) {
1415                         if (uwsgi_regexp_match(url->pattern, url->pattern_extra, uwsgi.log_master_buf, rlen) >= 0) {
1416                                 return 0;
1417                         }
1418                         url = url->next;
1419                 }
1420                 if (uwsgi.log_filter_rules) {
1421                         int show = 0;
1422                         url = uwsgi.log_filter_rules;
1423                         while (url) {
1424                                 if (uwsgi_regexp_match(url->pattern, url->pattern_extra, uwsgi.log_master_buf, rlen) >= 0) {
1425                                         show = 1;
1426                                         break;
1427                                 }
1428                                 url = url->next;
1429                         }
1430                         if (!show)
1431                                 return 0;
1432                 }
1433 
1434                 url = uwsgi.log_route;
1435                 int finish = 0;
1436                 while (url) {
1437                         if (uwsgi_regexp_match(url->pattern, url->pattern_extra, uwsgi.log_master_buf, rlen) >= 0) {
1438                                 struct uwsgi_logger *ul_route = (struct uwsgi_logger *) url->custom_ptr;
1439                                 if (ul_route) {
1440 					uwsgi_log_func_do(uwsgi.requested_log_encoders, ul_route, uwsgi.log_master_buf, rlen);
1441                                         finish = 1;
1442                                 }
1443                         }
1444                         url = url->next;
1445                 }
1446                 if (finish)
1447                         return 0;
1448 #endif
1449 
1450                 int raw_log = 1;
1451 
1452                 struct uwsgi_logger *ul = uwsgi.choosen_logger;
1453                 while (ul) {
1454                         // check for named logger
1455                         if (ul->id) {
1456                                 goto next;
1457                         }
1458                         uwsgi_log_func_do(uwsgi.requested_log_encoders, ul, uwsgi.log_master_buf, rlen);
1459                         raw_log = 0;
1460 next:
1461                         ul = ul->next;
1462                 }
1463 
1464                 if (raw_log) {
1465 			uwsgi_log_func_do(uwsgi.requested_log_encoders, NULL, uwsgi.log_master_buf, rlen);
1466                 }
1467                 return 0;
1468         }
1469 
1470         return -1;
1471 }
1472 
1473 int uwsgi_master_req_log(void) {
1474 
1475         ssize_t rlen = read(uwsgi.shared->worker_req_log_pipe[0], uwsgi.log_master_buf, uwsgi.log_master_bufsize);
1476         if (rlen > 0) {
1477 #ifdef UWSGI_PCRE
1478                 struct uwsgi_regexp_list *url = uwsgi.log_req_route;
1479                 int finish = 0;
1480                 while (url) {
1481                         if (uwsgi_regexp_match(url->pattern, url->pattern_extra, uwsgi.log_master_buf, rlen) >= 0) {
1482                                 struct uwsgi_logger *ul_route = (struct uwsgi_logger *) url->custom_ptr;
1483                                 if (ul_route) {
1484                                         uwsgi_log_func_do(uwsgi.requested_log_req_encoders, ul_route, uwsgi.log_master_buf, rlen);
1485                                         finish = 1;
1486                                 }
1487                         }
1488                         url = url->next;
1489                 }
1490                 if (finish)
1491                         return 0;
1492 #endif
1493 
1494                 int raw_log = 1;
1495 
1496                 struct uwsgi_logger *ul = uwsgi.choosen_req_logger;
1497                 while (ul) {
1498                         // check for named logger
1499                         if (ul->id) {
1500                                 goto next;
1501                         }
1502                         uwsgi_log_func_do(uwsgi.requested_log_req_encoders, ul, uwsgi.log_master_buf, rlen);
1503                         raw_log = 0;
1504 next:
1505                         ul = ul->next;
1506                 }
1507 
1508                 if (raw_log) {
1509 			uwsgi_log_func_do(uwsgi.requested_log_req_encoders, NULL, uwsgi.log_master_buf, rlen);
1510                 }
1511                 return 0;
1512         }
1513 
1514         return -1;
1515 }
1516 
1517 static void *logger_thread_loop(void *noarg) {
1518         struct pollfd logpoll[2];
1519 
1520         // block all signals
1521         sigset_t smask;
1522         sigfillset(&smask);
1523         pthread_sigmask(SIG_BLOCK, &smask, NULL);
1524 
1525         logpoll[0].events = POLLIN;
1526         logpoll[0].fd = uwsgi.shared->worker_log_pipe[0];
1527 
1528         int logpolls = 1;
1529 
1530         if (uwsgi.req_log_master) {
1531                 logpoll[1].events = POLLIN;
1532                 logpoll[1].fd = uwsgi.shared->worker_req_log_pipe[0];
1533 		logpolls++;
1534         }
1535 
1536 
1537         for (;;) {
1538                 int ret = poll(logpoll, logpolls, -1);
1539                 if (ret > 0) {
1540                         if (logpoll[0].revents & POLLIN) {
1541                                 pthread_mutex_lock(&uwsgi.threaded_logger_lock);
1542                                 uwsgi_master_log();
1543                                 pthread_mutex_unlock(&uwsgi.threaded_logger_lock);
1544                         }
1545                         else if (logpolls > 1 && logpoll[1].revents & POLLIN) {
1546                                 pthread_mutex_lock(&uwsgi.threaded_logger_lock);
1547                                 uwsgi_master_req_log();
1548                                 pthread_mutex_unlock(&uwsgi.threaded_logger_lock);
1549                         }
1550 
1551                 }
1552         }
1553 
1554         return NULL;
1555 }
1556 
1557 
1558 
1559 void uwsgi_threaded_logger_spawn() {
1560 	pthread_t logger_thread;
1561 
1562 	if (pthread_create(&logger_thread, NULL, logger_thread_loop, NULL)) {
1563         	uwsgi_error("pthread_create()");
1564                 uwsgi_log("falling back to non-threaded logger...\n");
1565                 event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->worker_log_pipe[0]);
1566                 if (uwsgi.req_log_master) {
1567                 	event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->worker_req_log_pipe[0]);
1568                 }
1569                 uwsgi.threaded_logger = 0;
1570 	}
1571 }
1572 
1573 void uwsgi_register_log_encoder(char *name, char *(*func)(struct uwsgi_log_encoder *, char *, size_t, size_t *)) {
1574 	struct uwsgi_log_encoder *old_ule = NULL, *ule = uwsgi.log_encoders;
1575 
1576 	while(ule) {
1577 		if (!strcmp(ule->name, name)) {
1578 			ule->func = func;
1579 			return;
1580 		}
1581 		old_ule = ule;
1582 		ule = ule->next;
1583 	}
1584 
1585 	ule = uwsgi_calloc(sizeof(struct uwsgi_log_encoder));
1586 	ule->name = name;
1587 	ule->func = func;
1588 
1589 	if (old_ule) {
1590 		old_ule->next = ule;
1591 	}
1592 	else {
1593 		uwsgi.log_encoders = ule;
1594 	}
1595 }
1596 
1597 struct uwsgi_log_encoder *uwsgi_log_encoder_by_name(char *name) {
1598 	struct uwsgi_log_encoder *ule = uwsgi.log_encoders;
1599 	while(ule) {
1600 		if (!strcmp(name, ule->name)) return ule;
1601 		ule = ule->next;
1602 	}
1603 	return NULL;
1604 }
1605 
1606 void uwsgi_setup_log_encoders() {
1607 	struct uwsgi_string_list *usl = NULL;
1608 	uwsgi_foreach(usl, uwsgi.requested_log_encoders) {
1609 		char *space = strchr(usl->value, ' ');
1610 		if (space) *space = 0;
1611 		char *use_for = strchr(usl->value, ':');
1612 		if (use_for) *use_for = 0;
1613 		struct uwsgi_log_encoder *ule = uwsgi_log_encoder_by_name(usl->value);
1614 		if (!ule) {
1615 			uwsgi_log("log encoder \"%s\" not found\n", usl->value);
1616 			exit(1);
1617 		}
1618 		struct uwsgi_log_encoder *ule2 = uwsgi_malloc(sizeof(struct uwsgi_log_encoder));
1619 		memcpy(ule2, ule, sizeof(struct uwsgi_log_encoder));
1620 		if (use_for) {
1621 			ule2->use_for = uwsgi_str(use_for+1);
1622 			*use_for = ':';
1623 		}
1624 		// we use a copy
1625 		if (space) {
1626 			*space = ' ';
1627 			ule2->args = uwsgi_str(space+1);
1628 		}
1629 		else {
1630 			ule2->args = uwsgi_str("");
1631 		}
1632 
1633 		usl->custom_ptr = ule2;
1634 		uwsgi_log("[log-encoder] registered %s\n", usl->value);
1635 	}
1636 
1637 	uwsgi_foreach(usl, uwsgi.requested_log_req_encoders) {
1638                 char *space = strchr(usl->value, ' ');
1639                 if (space) *space = 0;
1640 		char *use_for = strchr(usl->value, ':');
1641 		if (use_for) *use_for = 0;
1642                 struct uwsgi_log_encoder *ule = uwsgi_log_encoder_by_name(usl->value);
1643                 if (!ule) {
1644                         uwsgi_log("log encoder \"%s\" not found\n", usl->value);
1645                         exit(1);
1646                 }
1647 		struct uwsgi_log_encoder *ule2 = uwsgi_malloc(sizeof(struct uwsgi_log_encoder));
1648                 memcpy(ule2, ule, sizeof(struct uwsgi_log_encoder));
1649                 if (use_for) {
1650 			ule2->use_for = uwsgi_str(use_for+1);
1651                         *use_for = ':';
1652                 }
1653                 // we use a copy
1654                 if (space) {
1655                         *space = ' ';
1656                         ule2->args = uwsgi_str(space+1);
1657                 }
1658                 else {
1659                         ule2->args = uwsgi_str("");
1660                 }
1661                 usl->custom_ptr = ule2;
1662 		uwsgi_log("[log-req-encoder] registered %s\n", usl->value);
1663         }
1664 }
1665 
1666 #ifdef UWSGI_ZLIB
1667 static char *uwsgi_log_encoder_gzip(struct uwsgi_log_encoder *ule, char *msg, size_t len, size_t *rlen) {
1668 	struct uwsgi_buffer *ub = uwsgi_gzip(msg, len);
1669 	if (!ub) return NULL;
1670 	*rlen = ub->pos;
1671 	// avoid destruction
1672 	char *buf = ub->buf;
1673 	ub->buf = NULL;
1674 	uwsgi_buffer_destroy(ub);
1675 	return buf;
1676 }
1677 
1678 static char *uwsgi_log_encoder_compress(struct uwsgi_log_encoder *ule, char *msg, size_t len, size_t *rlen) {
1679 	size_t c_len = (size_t) compressBound(len);
1680 	uLongf destLen = c_len;
1681 	char *buf = uwsgi_malloc(c_len);
1682 	if (compress((Bytef *) buf, &destLen, (Bytef *)msg, (uLong) len) == Z_OK) {
1683 		*rlen = destLen;
1684 		return buf;
1685 	}
1686 	free(buf);
1687 	return NULL;
1688 }
1689 #endif
1690 
1691 /*
1692 
1693 really fast encoder adding only a prefix
1694 
1695 */
1696 static char *uwsgi_log_encoder_prefix(struct uwsgi_log_encoder *ule, char *msg, size_t len, size_t *rlen) {
1697 	char *buf = NULL;
1698 	struct uwsgi_buffer *ub = uwsgi_buffer_new(len + strlen(ule->args));
1699 	if (uwsgi_buffer_append(ub, ule->args, strlen(ule->args))) goto end;
1700 	if (uwsgi_buffer_append(ub, msg, len)) goto end;
1701 	*rlen = ub->pos;
1702 	buf = ub->buf;
1703 	ub->buf = NULL;
1704 end:
1705 	uwsgi_buffer_destroy(ub);
1706 	return buf;
1707 }
1708 
1709 /*
1710 
1711 really fast encoder adding only a newline
1712 
1713 */
1714 static char *uwsgi_log_encoder_nl(struct uwsgi_log_encoder *ule, char *msg, size_t len, size_t *rlen) {
1715         char *buf = NULL;
1716         struct uwsgi_buffer *ub = uwsgi_buffer_new(len + 1);
1717         if (uwsgi_buffer_append(ub, msg, len)) goto end;
1718         if (uwsgi_buffer_byte(ub, '\n')) goto end;
1719         *rlen = ub->pos;
1720         buf = ub->buf;
1721         ub->buf = NULL;
1722 end:
1723         uwsgi_buffer_destroy(ub);
1724         return buf;
1725 }
1726 
1727 /*
1728 
1729 really fast encoder adding only a suffix
1730 
1731 */
1732 static char *uwsgi_log_encoder_suffix(struct uwsgi_log_encoder *ule, char *msg, size_t len, size_t *rlen) {
1733         char *buf = NULL;
1734         struct uwsgi_buffer *ub = uwsgi_buffer_new(len + strlen(ule->args));
1735         if (uwsgi_buffer_append(ub, msg, len)) goto end;
1736         if (uwsgi_buffer_append(ub, ule->args, strlen(ule->args))) goto end;
1737         *rlen = ub->pos;
1738         buf = ub->buf;
1739         ub->buf = NULL;
1740 end:
1741         uwsgi_buffer_destroy(ub);
1742         return buf;
1743 }
1744 
1745 
1746 
1747 void uwsgi_log_encoder_parse_vars(struct uwsgi_log_encoder *ule) {
1748 		char *ptr = ule->args;
1749 		size_t remains = strlen(ptr);
1750 		char *base = ptr;
1751 		size_t base_len = 0;
1752 		char *var = NULL;
1753 		size_t var_len = 0;
1754 		int status = 0; // 1 -> $ 2-> { end -> }
1755 		while(remains--) {
1756 			char b = *ptr++;
1757 			if (status == 1) {
1758 				if (b == '{') {
1759 					status = 2;
1760 					continue;
1761 				}
1762 				base_len+=2;
1763 				status = 0;
1764 				continue;
1765 			}
1766 			else if (status == 2) {
1767 				if (b == '}') {
1768 					status = 0;
1769 					uwsgi_string_new_list((struct uwsgi_string_list **) &ule->data, uwsgi_concat2n(base, base_len, "", 0));
1770 					struct uwsgi_string_list *usl = uwsgi_string_new_list((struct uwsgi_string_list **) &ule->data, uwsgi_concat2n(var, var_len, "", 0));
1771 					usl->custom = 1;
1772 					var = NULL;
1773 					var_len = 0;
1774 					base = NULL;
1775 					base_len = 0;
1776 					continue;
1777 				}
1778 				if (!var) var = (ptr-1);
1779 				var_len++;
1780 				continue;
1781 			}
1782 			// status == 0
1783 			if (b == '$') {
1784 				status = 1;
1785 			}
1786 			else {
1787 				if (!base) base = (ptr-1);
1788 				base_len++;
1789 			}
1790 		}
1791 
1792 		if (base) {
1793 			if (status == 1) {
1794 				base_len+=2;
1795 			}
1796 			else if (status == 2) {
1797 				base_len+=3;
1798 			}
1799 			uwsgi_string_new_list((struct uwsgi_string_list **) &ule->data, uwsgi_concat2n(base, base_len, "", 0));
1800 		}
1801 }
1802 
1803 /*
1804         // format: foo ${var} bar
1805         msg (the logline)
1806         msgnl (the logline with newline)
1807         unix (the time_t value)
1808         micros (current microseconds)
1809         strftime (strftime)
1810 */
1811 static char *uwsgi_log_encoder_format(struct uwsgi_log_encoder *ule, char *msg, size_t len, size_t *rlen) {
1812 
1813 	if (!ule->configured) {
1814 		uwsgi_log_encoder_parse_vars(ule);
1815 		ule->configured = 1;
1816 	}
1817 
1818 	struct uwsgi_buffer *ub = uwsgi_buffer_new(strlen(ule->args) + len);
1819 	struct uwsgi_string_list *usl = (struct uwsgi_string_list *) ule->data;
1820 	char *buf = NULL;
1821 	while(usl) {
1822 		if (usl->custom) {
1823 			if (!uwsgi_strncmp(usl->value, usl->len, "msg", 3)) {
1824 				if (msg[len-1] == '\n') {
1825 					if (uwsgi_buffer_append(ub, msg, len-1)) goto end;
1826 				}
1827 				else {
1828 					if (uwsgi_buffer_append(ub, msg, len)) goto end;
1829 				}
1830 			}
1831 			else if (!uwsgi_strncmp(usl->value, usl->len, "msgnl", 5)) {
1832 				if (uwsgi_buffer_append(ub, msg, len)) goto end;
1833 			}
1834 			else if (!uwsgi_strncmp(usl->value, usl->len, "unix", 4)) {
1835 				if (uwsgi_buffer_num64(ub, uwsgi_now())) goto end;
1836 			}
1837 			else if (!uwsgi_strncmp(usl->value, usl->len, "micros", 6)) {
1838 				if (uwsgi_buffer_num64(ub, uwsgi_micros())) goto end;
1839 			}
1840 			else if (!uwsgi_strncmp(usl->value, usl->len, "millis", 6)) {
1841 				if (uwsgi_buffer_num64(ub, uwsgi_millis())) goto end;
1842 			}
1843 			else if (!uwsgi_starts_with(usl->value, usl->len, "strftime:", 9)) {
1844 				char sftime[64];
1845                                 time_t now = uwsgi_now();
1846 				char *buf = uwsgi_concat2n(usl->value+9, usl->len-9,"", 0);
1847                                 int strftime_len = strftime(sftime, 64, buf, localtime(&now));
1848 				free(buf);
1849 				if (strftime_len > 0) {
1850 					if (uwsgi_buffer_append(ub, sftime, strftime_len)) goto end;
1851 				}
1852 			}
1853 		}
1854 		else {
1855 			if (uwsgi_buffer_append(ub, usl->value, usl->len)) goto end;
1856 		}
1857 		usl = usl->next;
1858 	}
1859 	buf = ub->buf;
1860 	*rlen = ub->pos;
1861 	ub->buf = NULL;
1862 end:
1863 	uwsgi_buffer_destroy(ub);
1864 	return buf;
1865 }
1866 
1867 static char *uwsgi_log_encoder_json(struct uwsgi_log_encoder *ule, char *msg, size_t len, size_t *rlen) {
1868 
1869         if (!ule->configured) {
1870                 uwsgi_log_encoder_parse_vars(ule);
1871                 ule->configured = 1;
1872         }
1873 
1874         struct uwsgi_buffer *ub = uwsgi_buffer_new(strlen(ule->args) + len);
1875         struct uwsgi_string_list *usl = (struct uwsgi_string_list *) ule->data;
1876         char *buf = NULL;
1877         while(usl) {
1878                 if (usl->custom) {
1879                         if (!uwsgi_strncmp(usl->value, usl->len, "msg", 3)) {
1880 				size_t msg_len = len;
1881                                 if (msg[len-1] == '\n') msg_len--;
1882 				char *e_json = uwsgi_malloc((msg_len * 2)+1);
1883 				escape_json(msg, msg_len, e_json);
1884 				if (uwsgi_buffer_append(ub, e_json, strlen(e_json))){
1885                                 	free(e_json);
1886                                         goto end;
1887                                 }
1888                                 free(e_json);
1889                         }
1890                         else if (!uwsgi_strncmp(usl->value, usl->len, "msgnl", 5)) {
1891 				char *e_json = uwsgi_malloc((len * 2)+1);
1892                                 escape_json(msg, len, e_json);
1893                                 if (uwsgi_buffer_append(ub, e_json, strlen(e_json))){
1894                                         free(e_json);
1895                                         goto end;
1896                                 }
1897                                 free(e_json);
1898                         }
1899                         else if (!uwsgi_strncmp(usl->value, usl->len, "unix", 4)) {
1900                                 if (uwsgi_buffer_num64(ub, uwsgi_now())) goto end;
1901                         }
1902                         else if (!uwsgi_strncmp(usl->value, usl->len, "micros", 6)) {
1903                                 if (uwsgi_buffer_num64(ub, uwsgi_micros())) goto end;
1904                         }
1905                         else if (!uwsgi_strncmp(usl->value, usl->len, "millis", 6)) {
1906                                 if (uwsgi_buffer_num64(ub, uwsgi_millis())) goto end;
1907                         }
1908                         else if (!uwsgi_starts_with(usl->value, usl->len, "strftime:", 9)) {
1909                                 char sftime[64];
1910                                 time_t now = uwsgi_now();
1911                                 char *buf = uwsgi_concat2n(usl->value+9, usl->len-9, "", 0);
1912                                 int strftime_len = strftime(sftime, 64, buf, localtime(&now));
1913                                 free(buf);
1914                                 if (strftime_len > 0) {
1915 					char *e_json = uwsgi_malloc((strftime_len * 2)+1);
1916 					escape_json(sftime, strftime_len, e_json);
1917                                         if (uwsgi_buffer_append(ub, e_json, strlen(e_json))){
1918 						free(e_json);
1919 						goto end;
1920 					}
1921 					free(e_json);
1922                                 }
1923                         }
1924                 }
1925                 else {
1926                         if (uwsgi_buffer_append(ub, usl->value, usl->len)) goto end;
1927                 }
1928                 usl = usl->next;
1929         }
1930         buf = ub->buf;
1931         *rlen = ub->pos;
1932         ub->buf = NULL;
1933 end:
1934         uwsgi_buffer_destroy(ub);
1935         return buf;
1936 }
1937 
1938 #define r_logchunk(x) uwsgi_register_logchunk(#x, uwsgi_lf_ ## x, 1)
1939 #define r_logchunk_offset(x, y) { struct uwsgi_logchunk *lc = uwsgi_register_logchunk(#x, NULL, 0); lc->pos = offsetof(struct wsgi_request, y); lc->pos_len = offsetof(struct wsgi_request, y ## _len); lc->type = 1; lc->free=0;}
1940 void uwsgi_register_logchunks() {
1941 	// offsets
1942 	r_logchunk_offset(uri, uri);
1943 	r_logchunk_offset(method, method);
1944 	r_logchunk_offset(user, remote_user);
1945 	r_logchunk_offset(addr, remote_addr);
1946 	r_logchunk_offset(host, host);
1947 	r_logchunk_offset(proto, protocol);
1948 	r_logchunk_offset(uagent, user_agent);
1949 	r_logchunk_offset(referer, referer);
1950 
1951 	// funcs
1952 	r_logchunk(status);
1953 	r_logchunk(rsize);
1954 	r_logchunk(hsize);
1955 	r_logchunk(size);
1956 	r_logchunk(cl);
1957 	r_logchunk(micros);
1958 	r_logchunk(msecs);
1959 	r_logchunk(secs);
1960 	r_logchunk(tmsecs);
1961 	r_logchunk(tmicros);
1962 	r_logchunk(time);
1963 	r_logchunk(ltime);
1964 	r_logchunk(ftime);
1965 	r_logchunk(ctime);
1966 	r_logchunk(epoch);
1967 	r_logchunk(pid);
1968 	r_logchunk(wid);
1969 	r_logchunk(switches);
1970 	r_logchunk(vars);
1971 	r_logchunk(core);
1972 	r_logchunk(vsz);
1973 	r_logchunk(rss);
1974 	r_logchunk(vszM);
1975 	r_logchunk(rssM);
1976 	r_logchunk(pktsize);
1977 	r_logchunk(modifier1);
1978 	r_logchunk(modifier2);
1979 	r_logchunk(headers);
1980 	r_logchunk(werr);
1981 	r_logchunk(rerr);
1982 	r_logchunk(ioerr);
1983 }
1984 
1985 void uwsgi_log_encoders_register_embedded() {
1986 	uwsgi_register_log_encoder("prefix", uwsgi_log_encoder_prefix);
1987 	uwsgi_register_log_encoder("suffix", uwsgi_log_encoder_suffix);
1988 	uwsgi_register_log_encoder("nl", uwsgi_log_encoder_nl);
1989 	uwsgi_register_log_encoder("format", uwsgi_log_encoder_format);
1990 	uwsgi_register_log_encoder("json", uwsgi_log_encoder_json);
1991 #ifdef UWSGI_ZLIB
1992 	uwsgi_register_log_encoder("gzip", uwsgi_log_encoder_gzip);
1993 	uwsgi_register_log_encoder("compress", uwsgi_log_encoder_compress);
1994 #endif
1995 }
1996