xref: /unit/src/nxt_app_log.c (revision 0:a63ceefd6ab0)
1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) NGINX, Inc.
5  */
6 
7 #include <nxt_main.h>
8 #include <nxt_cycle.h>
9 
10 
11 static nxt_time_string_t  nxt_log_error_time_cache;
12 static u_char *nxt_log_error_time(u_char *buf, nxt_realtime_t *now,
13     struct tm *tm, size_t size, const char *format);
14 static nxt_time_string_t  nxt_log_debug_time_cache;
15 static u_char *nxt_log_debug_time(u_char *buf, nxt_realtime_t *now,
16     struct tm *tm, size_t size, const char *format);
17 
18 
19 void nxt_cdecl
20 nxt_log_time_handler(nxt_uint_t level, nxt_log_t *log, const char *fmt, ...)
21 {
22     u_char             *p, *syslogmsg, *end;
23     va_list            args;
24     nxt_fid_t          fid;
25     const char         *id;
26     nxt_fiber_t        *fib;
27     nxt_thread_t       *thr;
28     nxt_time_string_t  *time_cache;
29     u_char             msg[NXT_MAX_ERROR_STR];
30 
31     thr = nxt_thread();
32 
33     end = msg + NXT_MAX_ERROR_STR;
34 
35     time_cache = (log->level != NXT_LOG_DEBUG) ? &nxt_log_error_time_cache:
36                                                  &nxt_log_debug_time_cache;
37 
38     p = nxt_thread_time_string(thr, time_cache, msg);
39 
40     syslogmsg = p;
41 
42     fib = nxt_fiber_self(thr);
43 
44     if (fib != NULL) {
45         id = "[%V] %PI#%PT#%PF ";
46         fid = nxt_fiber_id(fib);
47 
48     } else {
49         id = "[%V] %PI#%PT ";
50         fid = 0;
51     }
52 
53     p = nxt_sprintf(p, end, id, &nxt_log_levels[level], nxt_pid,
54                     nxt_thread_tid(thr), fid);
55 
56     if (log->ident != 0) {
57         p = nxt_sprintf(p, end, "*%D ", log->ident);
58     }
59 
60     va_start(args, fmt);
61     p = nxt_vsprintf(p, end, fmt, args);
62     va_end(args);
63 
64     if (level != NXT_LOG_DEBUG && log->ctx_handler != NULL) {
65         p = log->ctx_handler(log->ctx, p, end);
66     }
67 
68     if (p > end - NXT_LINEFEED_SIZE) {
69         p = end - NXT_LINEFEED_SIZE;
70     }
71 
72     nxt_linefeed(p);
73 
74     (void) nxt_write_console(nxt_stderr, msg, p - msg);
75 
76     if (level <= NXT_LOG_ALERT) {
77         *(p - NXT_LINEFEED_SIZE) = '\0';
78 
79         /*
80          * The syslog LOG_ALERT level is enough, because
81          * LOG_EMERG level broadcasts a message to all users.
82          */
83         nxt_write_syslog(LOG_ALERT, syslogmsg);
84     }
85 }
86 
87 
88 static nxt_time_string_t  nxt_log_error_time_cache = {
89     (nxt_atomic_uint_t) -1,
90     nxt_log_error_time,
91     "%4d/%02d/%02d %02d:%02d:%02d ",
92     sizeof("1970/09/28 12:00:00 ") - 1,
93     NXT_THREAD_TIME_LOCAL,
94     NXT_THREAD_TIME_MSEC,
95 };
96 
97 
98 static u_char *
99 nxt_log_error_time(u_char *buf, nxt_realtime_t *now, struct tm *tm, size_t size,
100     const char *format)
101 {
102     return nxt_sprintf(buf, buf + size, format,
103                        tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
104                        tm->tm_hour, tm->tm_min, tm->tm_sec);
105 }
106 
107 
108 static nxt_time_string_t  nxt_log_debug_time_cache = {
109     (nxt_atomic_uint_t) -1,
110     nxt_log_debug_time,
111     "%4d/%02d/%02d %02d:%02d:%02d.%03d ",
112     sizeof("1970/09/28 12:00:00.000 ") - 1,
113     NXT_THREAD_TIME_LOCAL,
114     NXT_THREAD_TIME_MSEC,
115 };
116 
117 
118 static u_char *
119 nxt_log_debug_time(u_char *buf, nxt_realtime_t *now, struct tm *tm, size_t size,
120     const char *format)
121 {
122     return nxt_sprintf(buf, buf + size, format,
123                        tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
124                        tm->tm_hour, tm->tm_min, tm->tm_sec,
125                        now->nsec / 1000000);
126 }
127