php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
zlog.c
Go to the documentation of this file.
1 /* (c) 2004-2007 Andrei Nigmatulin */
2
3#include "fpm_config.h"
4
5#include <stdio.h>
6#include <unistd.h>
7#include <time.h>
8#include <string.h>
9#include <stdarg.h>
10#include <sys/time.h>
11#include <errno.h>
12
13#include "php_syslog.h"
14
15#include "zlog.h"
16#include "fpm.h"
17#include "zend_portability.h"
18
19/* buffer is used for fmt result and it should never be over 2048 */
20#define MAX_BUF_LENGTH 2048
21
22/* maximal length for wrapping prefix */
23#define MAX_WRAPPING_PREFIX_LENGTH 512
24
25#define EXTRA_SPACE_FOR_PREFIX 128
26
27static int zlog_fd = -1;
28static bool zlog_fd_is_stderr = false;
29static int zlog_level = ZLOG_NOTICE;
30static int zlog_limit = ZLOG_DEFAULT_LIMIT;
31static zlog_bool zlog_buffering = ZLOG_DEFAULT_BUFFERING;
32static int launched = 0;
33static void (*external_logger)(int, char *, size_t) = NULL;
34
35static const char *level_names[] = {
36 [ZLOG_DEBUG] = "DEBUG",
37 [ZLOG_NOTICE] = "NOTICE",
38 [ZLOG_WARNING] = "WARNING",
39 [ZLOG_ERROR] = "ERROR",
40 [ZLOG_ALERT] = "ALERT",
41};
42
43#ifdef HAVE_SYSLOG_H
44const int syslog_priorities[] = {
50};
51#endif
52
53void zlog_set_external_logger(void (*logger)(int, char *, size_t)) /* {{{ */
54{
55 external_logger = logger;
56}
57/* }}} */
58
59const char *zlog_get_level_name(int log_level) /* {{{ */
60{
61 if (log_level < 0) {
62 log_level = zlog_level;
63 } else if (log_level < ZLOG_DEBUG || log_level > ZLOG_ALERT) {
64 return "unknown value";
65 }
66
67 return level_names[log_level];
68}
69/* }}} */
70
71void zlog_set_launched(void) /* {{{ */
72{
73 launched = 1;
74}
75/* }}} */
76
77size_t zlog_print_time(struct timeval *tv, char *timebuf, size_t timebuf_len) /* {{{ */
78{
79 struct tm t;
80 size_t len;
81
82 len = strftime(timebuf, timebuf_len, "[%d-%b-%Y %H:%M:%S",
83 localtime_r((const time_t *) &tv->tv_sec, &t));
84 if (zlog_level == ZLOG_DEBUG) {
85 len += snprintf(timebuf + len, timebuf_len - len, ".%06d", (int) tv->tv_usec);
86 }
87 len += snprintf(timebuf + len, timebuf_len - len, "] ");
88 return len;
89}
90/* }}} */
91
92int zlog_set_fd(int new_fd, zlog_bool is_stderr) /* {{{ */
93{
94 int old_fd = zlog_fd;
95
96 zlog_fd = new_fd;
97 zlog_fd_is_stderr = is_stderr;
98
99 return old_fd;
100}
101/* }}} */
102
103int zlog_set_level(int new_value) /* {{{ */
104{
105 int old_value = zlog_level;
106
107 if (new_value < ZLOG_DEBUG || new_value > ZLOG_ALERT) return old_value;
108
109 zlog_level = new_value;
110 return old_value;
111}
112/* }}} */
113
114int zlog_set_limit(int new_value) /* {{{ */
115{
116 int old_value = zlog_limit;
117
118 zlog_limit = new_value;
119 return old_value;
120}
121/* }}} */
122
123int zlog_set_buffering(zlog_bool buffering) /* {{{ */
124{
125 int old_value = zlog_buffering;
126
127 zlog_buffering = buffering;
128 return old_value;
129}
130/* }}} */
131
132static inline size_t zlog_truncate_buf(char *buf, size_t buf_size, size_t space_left) /* {{{ */
133{
134 memcpy(buf + buf_size - sizeof("...") + 1 - space_left, "...", sizeof("...") - 1);
135 return buf_size - space_left;
136}
137/* }}} */
138
139static inline void zlog_external(
140 int flags, char *buf, size_t buf_size, const char *fmt, va_list args) /* {{{ */
141{
142 va_list ap;
143 size_t len;
144
145 va_copy(ap, args);
146 len = vsnprintf(buf, buf_size, fmt, ap);
147 va_end(ap);
148
149 if (len >= buf_size) {
150 len = zlog_truncate_buf(buf, buf_size, 0);
151 }
152 external_logger(flags & ZLOG_LEVEL_MASK, buf, len);
153}
154/* }}} */
155
156/* Returns the length if the print were complete, this can be larger than buf_size. */
157static size_t zlog_buf_prefix(
158 const char *function, int line, int flags,
159 char *buf, size_t buf_size, int use_syslog) /* {{{ */
160{
161 struct timeval tv;
162 size_t len = 0;
163
164#ifdef HAVE_SYSLOG_H
165 if (use_syslog /* && !fpm_globals.is_child */) {
166 if (zlog_level == ZLOG_DEBUG) {
167 len += snprintf(buf, buf_size, "[%s] %s(), line %d: ",
168 level_names[flags & ZLOG_LEVEL_MASK], function, line);
169 } else {
170 len += snprintf(buf, buf_size, "[%s] ", level_names[flags & ZLOG_LEVEL_MASK]);
171 }
172 } else
173#endif
174 {
175 if (!fpm_globals.is_child) {
176 gettimeofday(&tv, 0);
177 len = zlog_print_time(&tv, buf, buf_size);
178 }
179 if (zlog_level == ZLOG_DEBUG) {
180 if (!fpm_globals.is_child) {
181 len += snprintf(buf + len, buf_size - len, "%s: pid %d, %s(), line %d: ",
182 level_names[flags & ZLOG_LEVEL_MASK], getpid(), function, line);
183 } else {
184 len += snprintf(buf + len, buf_size - len, "%s: %s(), line %d: ",
185 level_names[flags & ZLOG_LEVEL_MASK], function, line);
186 }
187 } else {
188 len += snprintf(buf + len, buf_size - len, "%s: ",
189 level_names[flags & ZLOG_LEVEL_MASK]);
190 }
191 }
192
193 /* Important: snprintf returns the number of bytes if the print were complete. */
194 return len;
195}
196/* }}} */
197
198void vzlog(const char *function, int line, int flags, const char *fmt, va_list args) /* {{{ */
199{
200 char buf[MAX_BUF_LENGTH];
201 size_t buf_size = MAX_BUF_LENGTH;
202 size_t len = 0;
203 int truncated = 0;
204 int saved_errno;
205
206 if (external_logger) {
207 zlog_external(flags, buf, buf_size, fmt, args);
208 }
209
210 if ((flags & ZLOG_LEVEL_MASK) < zlog_level) {
211 return;
212 }
213
214 saved_errno = errno;
215 len = zlog_buf_prefix(function, line, flags, buf, buf_size, zlog_fd == ZLOG_SYSLOG);
216
217 if (len > buf_size - 1) {
218 truncated = 1;
219 } else {
220 len += vsnprintf(buf + len, buf_size - len, fmt, args);
221 if (len >= buf_size) {
222 truncated = 1;
223 }
224 }
225
226 if (!truncated) {
227 if (flags & ZLOG_HAVE_ERRNO) {
228 len += snprintf(buf + len, buf_size - len,
229 ": %s (%d)", strerror(saved_errno), saved_errno);
230 if (len >= zlog_limit) {
231 truncated = 1;
232 }
233 }
234 }
235
236 if (truncated) {
237 len = zlog_truncate_buf(buf, zlog_limit < buf_size ? zlog_limit : buf_size, 1);
238 }
239
240#ifdef HAVE_SYSLOG_H
241 if (zlog_fd == ZLOG_SYSLOG) {
242 buf[len] = '\0';
243 php_syslog(syslog_priorities[zlog_level], "%s", buf);
244 buf[len++] = '\n';
245 } else
246#endif
247 {
248 buf[len++] = '\n';
249 zend_quiet_write(zlog_fd > -1 ? zlog_fd : STDERR_FILENO, buf, len);
250 }
251
252 if (!zlog_fd_is_stderr && zlog_fd != -1 &&
253 !launched && (flags & ZLOG_LEVEL_MASK) >= ZLOG_NOTICE) {
255 }
256}
257/* }}} */
258
259void zlog_ex(const char *function, int line, int flags, const char *fmt, ...) /* {{{ */
260{
261 va_list args;
262 va_start(args, fmt);
263 vzlog(function, line, flags, fmt, args);
264 va_end(args);
265}
266/* }}} */
267
268/* predefine stream init that is used by zlog_msg_ex */
269static inline void zlog_stream_init_internal(
270 struct zlog_stream *stream, int flags, size_t capacity, int fd);
271
272void zlog_msg_ex(const char *function, int line, int flags,
273 const char *prefix, const char *msg) /* {{{ */
274{
275 struct zlog_stream stream;
276 size_t prefix_len = strlen(prefix);
277 size_t msg_len = strlen(msg);
278
279 zlog_stream_init_internal(&stream, flags, msg_len + prefix_len, 0);
282 zlog_stream_str(&stream, msg, msg_len);
283 zlog_stream_finish(&stream);
284 zlog_stream_destroy(&stream);
285}
286/* }}} */
287
288/* STREAM OPS */
289
290static zlog_bool zlog_stream_buf_alloc_ex(struct zlog_stream *stream, size_t needed) /* {{{ */
291{
292 char *buf;
293 size_t size = stream->buf.size ?: stream->buf_init_size;
294 size = MIN(zlog_limit, MAX((stream->buf.data ? (size << 1) : size), needed));
295 buf = realloc(stream->buf.data, size);
296
297 if (buf == NULL) {
298 return 0;
299 }
300
301 stream->buf.data = buf;
302 stream->buf.size = size;
303
304 return 1;
305}
306/* }}} */
307
308inline static zlog_bool zlog_stream_buf_alloc(struct zlog_stream *stream) /* {{{ */
309{
310 /* if there is enough space in the buffer, we do not need to reallocate */
311 if (stream->buf.data && stream->buf.size >= MIN(zlog_limit, stream->buf_init_size)) {
312 return 1;
313 }
314 return zlog_stream_buf_alloc_ex(stream, 0);
315}
316/* }}} */
317
318static inline ssize_t zlog_stream_direct_write_ex(
319 struct zlog_stream *stream, const char *buf, size_t len,
320 const char *append, size_t append_len) /* {{{ */
321{
322 if (stream->use_fd) {
323 zend_quiet_write(stream->fd, buf, len);
324 if (append_len > 0) {
325 zend_quiet_write(stream->fd, append, append_len);
326 }
327 }
328
329 if (stream->use_stderr) {
331 if (append_len > 0) {
332 zend_quiet_write(STDERR_FILENO, append, append_len);
333 }
334 }
335
336 return len;
337}
338/* }}} */
339
340static ssize_t zlog_stream_direct_write(
341 struct zlog_stream *stream, const char *buf, size_t len) /* {{{ */
342{
343 return zlog_stream_direct_write_ex(stream, buf, len, NULL, 0);
344}
345/* }}} */
346
347static inline ssize_t zlog_stream_unbuffered_write(
348 struct zlog_stream *stream, const char *buf, size_t len) /* {{{ */
349{
350 const char *append = NULL;
351 size_t append_len = 0, required_len, reserved_len;
352 ssize_t written;
353
354 if (stream->len == 0) {
355 stream->len = zlog_stream_prefix_ex(stream, stream->function, stream->line);
356 }
357
358 /* msg_suffix_len and msg_quote are used only for wrapping */
359 reserved_len = stream->len + stream->msg_suffix_len + stream->msg_quote;
360 required_len = reserved_len + len;
361 if (required_len >= zlog_limit) {
362 if (stream->wrap) {
363 size_t available_len;
364 if (required_len == zlog_limit) {
365 append = NULL;
366 append_len = 0;
367 } else {
368 append = "\n";
369 append_len = 1;
370 }
371 available_len = zlog_limit - reserved_len - 1;
372 zlog_stream_direct_write(stream, buf, available_len);
373 if (append != NULL) {
374 if (stream->msg_quote) {
375 zlog_stream_direct_write(stream, "\"", 1);
376 }
377 if (stream->msg_suffix) {
378 zlog_stream_direct_write(stream, stream->msg_suffix, stream->msg_suffix_len);
379 }
380 zlog_stream_direct_write(stream, append, append_len);
381 }
382 stream->len = 0;
383 written = zlog_stream_unbuffered_write(
384 stream, buf + available_len, len - available_len);
385 if (written > 0) {
386 return available_len + written;
387 }
388
389 return written;
390 }
391 /* this would be used in case of an option for disabling wrapping in direct write */
392 stream->full = 1;
393 if (required_len == zlog_limit) {
394 append = NULL;
395 } else {
396 append = "...";
397 append_len = sizeof("...") - 1;
398 len = zlog_limit - stream->len - append_len;
399 }
400 }
401
402 written = zlog_stream_direct_write_ex(stream, buf, len, append, append_len);
403 if (written > 0) {
404 /* currently written will be always len as the write is blocking
405 * - this should be address if we change to non-blocking write */
406 stream->len += written;
407 }
408
409 return written;
410}
411/* }}} */
412
413static inline ssize_t zlog_stream_buf_copy_cstr(
414 struct zlog_stream *stream, const char *str, size_t str_len) /* {{{ */
415{
416 ZEND_ASSERT(stream->len <= stream->buf.size);
417 if (stream->buf.size - stream->len <= str_len &&
418 !zlog_stream_buf_alloc_ex(stream, str_len + stream->len)) {
419 return -1;
420 }
421
422 memcpy(stream->buf.data + stream->len, str, str_len);
423 stream->len += str_len;
424
425 return str_len;
426}
427/* }}} */
428
429static inline ssize_t zlog_stream_buf_copy_char(struct zlog_stream *stream, char c) /* {{{ */
430{
431 ZEND_ASSERT(stream->len <= stream->buf.size);
432 if (stream->buf.size - stream->len < 1 && !zlog_stream_buf_alloc_ex(stream, 1)) {
433 return -1;
434 }
435
436 stream->buf.data[stream->len++] = c;
437
438 return 1;
439}
440/* }}} */
441
442static ssize_t zlog_stream_buf_flush(struct zlog_stream *stream) /* {{{ */
443{
444 ssize_t written;
445
446#ifdef HAVE_SYSLOG_H
447 if (stream->use_syslog) {
448 zlog_stream_buf_copy_char(stream, '\0');
449 php_syslog(syslog_priorities[zlog_level], "%s", stream->buf.data);
450 --stream->len;
451 }
452#endif
453
454 if (external_logger != NULL) {
455 external_logger(stream->flags & ZLOG_LEVEL_MASK,
456 stream->buf.data + stream->prefix_len, stream->len - stream->prefix_len);
457 }
458 zlog_stream_buf_copy_char(stream, '\n');
459 written = zlog_stream_direct_write(stream, stream->buf.data, stream->len);
460 stream->len = 0;
461
462 return written;
463}
464/* }}} */
465
466static ssize_t zlog_stream_buf_append(
467 struct zlog_stream *stream, const char *str, size_t str_len) /* {{{ */
468{
469 int over_limit = 0;
470 size_t available_len, required_len, reserved_len;
471
472 if (stream->len == 0) {
473 stream->len = zlog_stream_prefix_ex(stream, stream->function, stream->line);
474 }
475
476 /* msg_suffix_len and msg_quote are used only for wrapping */
477 reserved_len = stream->len + stream->msg_suffix_len + stream->msg_quote;
478 required_len = reserved_len + str_len;
479 if (required_len >= zlog_limit) {
480 over_limit = 1;
481 available_len = zlog_limit - reserved_len - 1;
482 } else {
483 available_len = str_len;
484 }
485
486 if (zlog_stream_buf_copy_cstr(stream, str, available_len) < 0) {
487 return -1;
488 }
489
490 if (!over_limit) {
491 return available_len;
492 }
493
494 if (stream->wrap) {
495 if (stream->msg_quote) {
496 zlog_stream_buf_copy_char(stream, '"');
497 }
498 if (stream->msg_suffix != NULL) {
499 zlog_stream_buf_copy_cstr(stream, stream->msg_suffix, stream->msg_suffix_len);
500 }
501 zlog_stream_buf_flush(stream);
502 zlog_stream_prefix_ex(stream, stream->function, stream->line);
503 return available_len + zlog_stream_buf_append(
504 stream, str + available_len, str_len - available_len);
505 }
506
507 stream->len = zlog_truncate_buf(stream->buf.data, stream->len, 0);
508 stream->full = 1;
509 return available_len;
510}
511/* }}} */
512
513static inline void zlog_stream_init_internal(
514 struct zlog_stream *stream, int flags, size_t capacity, int fd) /* {{{ */
515{
516 if (fd == 0) {
517 fd = zlog_fd;
518 }
519
520 memset(stream, 0, sizeof(struct zlog_stream));
521 stream->flags = flags;
522 stream->use_syslog = fd == ZLOG_SYSLOG;
523 stream->use_fd = fd > 0;
524 stream->use_buffer = zlog_buffering || external_logger != NULL || stream->use_syslog;
525 stream->buf_init_size = capacity;
526 stream->use_stderr = fd < 0 ||
527 (
528 fd != STDERR_FILENO && fd != STDOUT_FILENO && !launched &&
530 );
531 stream->prefix_buffer = (flags & ZLOG_LEVEL_MASK) >= zlog_level &&
532 (stream->use_fd || stream->use_stderr || stream->use_syslog);
533 stream->fd = fd > -1 ? fd : STDERR_FILENO;
534}
535/* }}} */
536
537void zlog_stream_init(struct zlog_stream *stream, int flags) /* {{{ */
538{
539 zlog_stream_init_internal(stream, flags, 1024, 0);
540}
541/* }}} */
542
543void zlog_stream_init_ex(struct zlog_stream *stream, int flags, int fd) /* {{{ */
544{
545 zlog_stream_init_internal(stream, flags, 1024, fd);
546 stream->wrap = 1;
547}
548/* }}} */
549
551{
552 if (decorate) {
553 stream->decorate = 1;
554 } else {
555 stream->decorate = 0;
556 stream->msg_quote = 0;
557 stream->prefix_buffer = 0;
558 }
559}
560/* }}} */
561
562void zlog_stream_set_wrapping(struct zlog_stream *stream, zlog_bool wrap) /* {{{ */
563{
564 stream->wrap = wrap ? 1 : 0;
565}
566/* }}} */
567
569{
570 stream->is_stdout = is_stdout ? 1 : 0;
571}
572/* }}} */
573
574void zlog_stream_set_child_pid(struct zlog_stream *stream, int child_pid) /* {{{ */
575{
576 stream->child_pid = child_pid;
577}
578/* }}} */
579
580void zlog_stream_set_msg_quoting(struct zlog_stream *stream, zlog_bool quote) /* {{{ */
581{
582 stream->msg_quote = quote && stream->decorate ? 1 : 0;
583}
584/* }}} */
585
586zlog_bool zlog_stream_set_msg_prefix(struct zlog_stream *stream, const char *fmt, ...) /* {{{ */
587{
589 size_t len;
590 va_list args;
591
592 if (!stream->decorate) {
593 return ZLOG_TRUE;
594 }
595
596 va_start(args, fmt);
598 va_end(args);
599
600 if (stream->msg_prefix_len < len) {
601 stream->msg_prefix = stream->msg_prefix_len ? realloc(stream->msg_prefix, len + 1) : malloc(len + 1);
602 if (stream->msg_prefix == NULL) {
603 return ZLOG_FALSE;
604 }
605 }
606 memcpy(stream->msg_prefix, buf, len);
607 stream->msg_prefix[len] = 0;
608 stream->msg_prefix_len = len;
609
610 return len;
611}
612/* }}} */
613
615 struct zlog_stream *stream, const char *suffix, const char *final_suffix) /* {{{ */
616{
617 size_t len;
618 if (!stream->wrap || !stream->decorate) {
619 return ZLOG_TRUE;
620 }
621
622 if (suffix != NULL && final_suffix != NULL) {
623 stream->msg_suffix_len = strlen(suffix);
624 stream->msg_final_suffix_len = strlen(final_suffix);
625 len = stream->msg_suffix_len + stream->msg_final_suffix_len + 2;
626 if (stream->msg_suffix != NULL) {
627 free(stream->msg_suffix);
628 }
629 stream->msg_suffix = malloc(len);
630 if (stream->msg_suffix == NULL) {
631 return ZLOG_FALSE;
632 }
633 stream->msg_final_suffix = stream->msg_suffix + stream->msg_suffix_len + 1;
634 memcpy(stream->msg_suffix, suffix, stream->msg_suffix_len + 1);
635 memcpy(stream->msg_final_suffix, final_suffix, stream->msg_final_suffix_len + 1);
636 return ZLOG_TRUE;
637 }
638 if (suffix != NULL) {
639 stream->msg_suffix_len = strlen(suffix);
640 len = stream->msg_suffix_len + 1;
641 if (stream->msg_suffix != NULL) {
642 free(stream->msg_suffix);
643 }
644 stream->msg_suffix = malloc(len);
645 if (stream->msg_suffix == NULL) {
646 return ZLOG_FALSE;
647 }
648 memcpy(stream->msg_suffix, suffix, len);
649 return ZLOG_TRUE;
650 }
651 if (final_suffix != NULL) {
652 stream->msg_final_suffix_len = strlen(final_suffix);
653 len = stream->msg_final_suffix_len + 1;
654 if (stream->msg_final_suffix != NULL) {
655 free(stream->msg_final_suffix);
656 }
657 stream->msg_final_suffix = malloc(len);
658 if (stream->msg_final_suffix == NULL) {
659 return ZLOG_FALSE;
660 }
661 memcpy(stream->msg_final_suffix, final_suffix, len);
662 return ZLOG_TRUE;
663 }
664
665 return ZLOG_TRUE;
666}
667/* }}} */
668
669ssize_t zlog_stream_prefix_ex(struct zlog_stream *stream, const char *function, int line) /* {{{ */
670{
671 size_t len;
672
673 if (!stream->prefix_buffer) {
674 return 0;
675 }
676 if (stream->wrap && stream->function == NULL) {
677 stream->function = function;
678 stream->line = line;
679 }
680
681 if (stream->use_buffer) {
682 if (!zlog_stream_buf_alloc(stream)) {
683 return -1;
684 }
685 len = zlog_buf_prefix(
686 function, line, stream->flags,
687 stream->buf.data, stream->buf.size, stream->use_syslog);
688 if (!EXPECTED(len + 1 <= stream->buf.size)) {
689 /* If the buffer was not large enough, try with a larger buffer.
690 * Note that this may still truncate if the zlog_limit is reached. */
691 len = MIN(len + 1, zlog_limit);
692 if (!zlog_stream_buf_alloc_ex(stream, len)) {
693 return -1;
694 }
695 zlog_buf_prefix(
696 function, line, stream->flags,
697 stream->buf.data, stream->buf.size, stream->use_syslog);
698 }
699 stream->len = stream->prefix_len = len;
700 if (stream->msg_prefix != NULL) {
701 zlog_stream_buf_copy_cstr(stream, stream->msg_prefix, stream->msg_prefix_len);
702 }
703 if (stream->msg_quote) {
704 zlog_stream_buf_copy_char(stream, '"');
705 }
706 return stream->len;
707 } else {
708 char sbuf[1024];
709 ssize_t written;
710 len = zlog_buf_prefix(function, line, stream->flags, sbuf, sizeof(sbuf), stream->use_syslog);
711 written = zlog_stream_direct_write(stream, sbuf, MIN(len, sizeof(sbuf)));
712 if (stream->msg_prefix != NULL) {
713 written += zlog_stream_direct_write(
714 stream, stream->msg_prefix, stream->msg_prefix_len);
715 }
716 if (stream->msg_quote) {
717 written += zlog_stream_direct_write(stream, "\"", 1);
718 }
719 return written;
720 }
721}
722/* }}} */
723
724ssize_t zlog_stream_vformat(struct zlog_stream *stream, const char *fmt, va_list args) /* {{{ */
725{
726 char sbuf[1024];
727 size_t len;
728
729 len = vsnprintf(sbuf, 1024, fmt, args);
730
731 return zlog_stream_str(stream, sbuf, len);
732}
733/* }}} */
734
735ssize_t zlog_stream_format(struct zlog_stream *stream, const char *fmt, ...) /* {{{ */
736{
737 ssize_t len;
738
739 va_list args;
740 va_start(args, fmt);
741 len = zlog_stream_vformat(stream, fmt, args);
742 va_end(args);
743
744 return len;
745}
746/* }}} */
747
748ssize_t zlog_stream_str(struct zlog_stream *stream, const char *str, size_t str_len) /* {{{ */
749{
750 /* do not write anything if the stream is full or str is empty */
751 if (str_len == 0 || stream->full) {
752 return 0;
753 }
754
755 /* reset stream if it is finished */
756 if (stream->finished) {
757 stream->finished = 0;
758 stream->len = 0;
759 stream->full = 0;
760 }
761
762 if (stream->use_buffer) {
763 return zlog_stream_buf_append(stream, str, str_len);
764 }
765
766 return zlog_stream_unbuffered_write(stream, str, str_len);
767}
768/* }}} */
769
770static inline void zlog_stream_finish_buffer_suffix(struct zlog_stream *stream) /* {{{ */
771{
772 if (stream->msg_quote) {
773 zlog_stream_buf_copy_char(stream, '"');
774 }
775 if (stream->msg_suffix != NULL) {
776 zlog_stream_buf_copy_cstr(stream, stream->msg_suffix, stream->msg_suffix_len);
777 }
778 if (stream->msg_final_suffix != NULL) {
779 if (stream->len + stream->msg_final_suffix_len >= zlog_limit) {
780 zlog_bool quoting = stream->msg_quote;
781 size_t final_suffix_wrap = stream->len + stream->msg_final_suffix_len + 1 - zlog_limit;
782 zlog_stream_buf_copy_cstr(
783 stream, stream->msg_final_suffix,
784 stream->msg_final_suffix_len - final_suffix_wrap);
785 zlog_stream_buf_copy_char(stream, '\n');
786 zlog_stream_buf_flush(stream);
787 stream->msg_quote = 0;
788 zlog_stream_prefix_ex(stream, stream->function, stream->line);
789 stream->msg_quote = quoting;
790 zlog_stream_buf_copy_cstr(
791 stream,
792 stream->msg_final_suffix + (stream->msg_final_suffix_len - final_suffix_wrap),
793 final_suffix_wrap);
794 zlog_stream_buf_copy_char(stream, '\n');
795 } else {
796 zlog_stream_buf_copy_cstr(
797 stream, stream->msg_final_suffix, stream->msg_final_suffix_len);
798 }
799 }
800}
801/* }}} */
802
803static inline void zlog_stream_finish_direct_suffix(struct zlog_stream *stream) /* {{{ */
804{
805 if (stream->msg_quote) {
806 zlog_stream_direct_write(stream, "\"", 1);
807 ++stream->len;
808 }
809 if (stream->msg_suffix != NULL) {
810 /* we should always have space for wrap suffix so we don't have to check it */
811 zlog_stream_direct_write(stream, stream->msg_suffix, stream->msg_suffix_len);
812 stream->len += stream->msg_suffix_len;
813 }
814 if (stream->msg_final_suffix != NULL) {
815 if (stream->len + stream->msg_final_suffix_len >= zlog_limit) {
816 zlog_bool quoting = stream->msg_quote;
817 size_t final_suffix_wrap = stream->len + stream->msg_final_suffix_len + 1 - zlog_limit;
818 zlog_stream_direct_write_ex(
819 stream, stream->msg_final_suffix,
820 stream->msg_final_suffix_len - final_suffix_wrap, "\n", 1);
821 stream->msg_quote = 0;
822 zlog_stream_prefix_ex(stream, stream->function, stream->line);
823 stream->msg_quote = quoting;
824 zlog_stream_direct_write_ex(
825 stream,
826 stream->msg_final_suffix + (stream->msg_final_suffix_len - final_suffix_wrap),
827 final_suffix_wrap, "\n", 1);
828 } else {
829 zlog_stream_direct_write_ex(
830 stream, stream->msg_final_suffix, stream->msg_final_suffix_len, "\n", 1);
831 }
832 } else {
833 zlog_stream_direct_write(stream, "\n", 1);
834 }
835}
836/* }}} */
837
838zlog_bool zlog_stream_finish(struct zlog_stream *stream) /* {{{ */
839{
840 if (stream->finished || stream->len == 0) {
841 return ZLOG_TRUE;
842 }
843
844 if (stream->use_buffer) {
845 if (stream->decorate) {
846 zlog_stream_finish_buffer_suffix(stream);
847 }
848 zlog_stream_buf_flush(stream);
849 } else {
850 if (stream->decorate) {
851 zlog_stream_finish_direct_suffix(stream);
852 } else {
853 zlog_stream_direct_write(stream, "\n", 1);
854 }
855 }
856 stream->finished = 1;
857
858 return ZLOG_TRUE;
859}
860/* }}} */
861
862void zlog_stream_destroy(struct zlog_stream *stream) /* {{{ */
863{
864 if (stream->buf.data != NULL) {
865 free(stream->buf.data);
866 }
867 if (stream->msg_prefix != NULL) {
868 free(stream->msg_prefix);
869 }
870 if (stream->msg_suffix != NULL) {
871 free(stream->msg_suffix);
872 } else if (stream->msg_final_suffix != NULL) {
873 free(stream->msg_final_suffix);
874 }
875}
876/* }}} */
877
878zlog_bool zlog_stream_close(struct zlog_stream *stream) /* {{{ */
879{
881 zlog_stream_destroy(stream);
882
883 return finished;
884}
885/* }}} */
size_t len
Definition apprentice.c:174
gettimeofday(bool $as_float=false)
#define STDOUT_FILENO
Definition cgi_main.c:291
new_type size
Definition ffi.c:4365
memcpy(ptr1, ptr2, size)
memset(ptr, 0, type->size)
zend_ffi_ctype_name_buf buf
Definition ffi.c:4685
struct fpm_globals_s fpm_globals
Definition fpm.c:24
#define NULL
Definition gdcache.h:45
#define prefix
#define STDERR_FILENO
Definition php_cli.c:221
strftime(string $format, ?int $timestamp=null)
int line
Definition php_ffi.h:54
PHPAPI void php_syslog(int priority, const char *format,...)
Definition php_syslog.c:106
char * msg
Definition phpdbg.h:289
int fd
Definition phpdbg.h:282
struct timeval tv
Definition session.c:1280
#define vsnprintf
Definition snprintf.h:104
char * data
Definition zlog.h:60
size_t size
Definition zlog.h:61
size_t msg_suffix_len
Definition zlog.h:88
int fd
Definition zlog.h:77
unsigned int wrap
Definition zlog.h:73
char * msg_prefix
Definition zlog.h:85
unsigned int use_buffer
Definition zlog.h:68
size_t prefix_len
Definition zlog.h:84
unsigned int use_fd
Definition zlog.h:67
unsigned int finished
Definition zlog.h:71
unsigned int use_stderr
Definition zlog.h:69
const char * function
Definition zlog.h:80
char * msg_suffix
Definition zlog.h:87
unsigned int full
Definition zlog.h:72
char * msg_final_suffix
Definition zlog.h:89
unsigned int use_syslog
Definition zlog.h:66
unsigned int prefix_buffer
Definition zlog.h:70
size_t buf_init_size
Definition zlog.h:83
int child_pid
Definition zlog.h:79
struct zlog_stream_buffer buf
Definition zlog.h:81
size_t len
Definition zlog.h:82
int flags
Definition zlog.h:65
size_t msg_final_suffix_len
Definition zlog.h:90
unsigned int msg_quote
Definition zlog.h:74
unsigned int is_stdout
Definition zlog.h:76
int line
Definition zlog.h:78
unsigned int decorate
Definition zlog.h:75
size_t msg_prefix_len
Definition zlog.h:86
#define LOG_ALERT
Definition syslog.h:23
#define LOG_DEBUG
Definition syslog.h:29
#define LOG_ERR
Definition syslog.h:25
#define LOG_NOTICE
Definition syslog.h:27
#define LOG_WARNING
Definition syslog.h:26
#define errno
strlen(string $string)
zval * args
#define snprintf
ZEND_API void(ZEND_FASTCALL *zend_touch_vm_stack_data)(void *vm_stack_data)
#define zend_quiet_write(...)
#define MIN(a, b)
#define EXPECTED(condition)
#define ZEND_ASSERT(c)
#define MAX(a, b)
function(EX_VAR(opline->result.var))
zlog_bool zlog_stream_finish(struct zlog_stream *stream)
Definition zlog.c:838
void zlog_set_launched(void)
Definition zlog.c:71
ssize_t zlog_stream_str(struct zlog_stream *stream, const char *str, size_t str_len)
Definition zlog.c:748
void zlog_stream_init_ex(struct zlog_stream *stream, int flags, int fd)
Definition zlog.c:543
#define MAX_WRAPPING_PREFIX_LENGTH
Definition zlog.c:23
void zlog_msg_ex(const char *function, int line, int flags, const char *prefix, const char *msg)
Definition zlog.c:272
int zlog_set_limit(int new_value)
Definition zlog.c:114
void zlog_stream_init(struct zlog_stream *stream, int flags)
Definition zlog.c:537
zlog_bool zlog_stream_set_msg_prefix(struct zlog_stream *stream, const char *fmt,...)
Definition zlog.c:586
void zlog_stream_set_child_pid(struct zlog_stream *stream, int child_pid)
Definition zlog.c:574
int zlog_set_level(int new_value)
Definition zlog.c:103
zlog_bool zlog_stream_close(struct zlog_stream *stream)
Definition zlog.c:878
void zlog_stream_set_msg_quoting(struct zlog_stream *stream, zlog_bool quote)
Definition zlog.c:580
ssize_t zlog_stream_prefix_ex(struct zlog_stream *stream, const char *function, int line)
Definition zlog.c:669
zlog_bool zlog_stream_set_msg_suffix(struct zlog_stream *stream, const char *suffix, const char *final_suffix)
Definition zlog.c:614
void zlog_stream_set_decorating(struct zlog_stream *stream, zlog_bool decorate)
Definition zlog.c:550
void zlog_stream_set_is_stdout(struct zlog_stream *stream, zlog_bool is_stdout)
Definition zlog.c:568
void zlog_ex(const char *function, int line, int flags, const char *fmt,...)
Definition zlog.c:259
void zlog_stream_destroy(struct zlog_stream *stream)
Definition zlog.c:862
const char * zlog_get_level_name(int log_level)
Definition zlog.c:59
ssize_t zlog_stream_vformat(struct zlog_stream *stream, const char *fmt, va_list args)
Definition zlog.c:724
void zlog_set_external_logger(void(*logger)(int, char *, size_t))
Definition zlog.c:53
#define MAX_BUF_LENGTH
Definition zlog.c:20
void vzlog(const char *function, int line, int flags, const char *fmt, va_list args)
Definition zlog.c:198
ssize_t zlog_stream_format(struct zlog_stream *stream, const char *fmt,...)
Definition zlog.c:735
void zlog_stream_set_wrapping(struct zlog_stream *stream, zlog_bool wrap)
Definition zlog.c:562
size_t zlog_print_time(struct timeval *tv, char *timebuf, size_t timebuf_len)
Definition zlog.c:77
int zlog_set_fd(int new_fd, zlog_bool is_stderr)
Definition zlog.c:92
int zlog_set_buffering(zlog_bool buffering)
Definition zlog.c:123
unsigned char zlog_bool
Definition zlog.h:14
#define ZLOG_SYSLOG
Definition zlog.h:55
#define ZLOG_LEVEL_MASK
Definition zlog.h:49
#define ZLOG_DEFAULT_LIMIT
Definition zlog.h:116
#define ZLOG_DEFAULT_BUFFERING
Definition zlog.h:120
#define ZLOG_TRUE
Definition zlog.h:16
#define ZLOG_FALSE
Definition zlog.h:17
#define ZLOG_HAVE_ERRNO
Definition zlog.h:51
@ ZLOG_DEBUG
Definition zlog.h:42
@ ZLOG_ERROR
Definition zlog.h:45
@ ZLOG_ALERT
Definition zlog.h:46
@ ZLOG_NOTICE
Definition zlog.h:43
@ ZLOG_WARNING
Definition zlog.h:44