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