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