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