int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...) { va_list ap; switch(srv->errorlog_mode) { case ERRORLOG_PIPE: case ERRORLOG_FILE: case ERRORLOG_FD: if (-1 == srv->errorlog_fd) return 0; /* cache the generated timestamp */ if (srv->cur_ts != srv->last_generated_debug_ts) { buffer_prepare_copy(srv->ts_debug_str, 255); strftime(srv->ts_debug_str->ptr, srv->ts_debug_str->size - 1, "%Y-%m-%d %H:%M:%S", localtime(&(srv->cur_ts))); srv->ts_debug_str->used = strlen(srv->ts_debug_str->ptr) + 1; srv->last_generated_debug_ts = srv->cur_ts; } buffer_copy_string_buffer(srv->errorlog_buf, srv->ts_debug_str); buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(": (")); break; case ERRORLOG_SYSLOG: /* syslog is generating its own timestamps */ buffer_copy_string_len(srv->errorlog_buf, CONST_STR_LEN("(")); break; } buffer_append_string(srv->errorlog_buf, filename); buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(".")); buffer_append_long(srv->errorlog_buf, line); buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(") ")); for(va_start(ap, fmt); *fmt; fmt++) { int d; char *s; buffer *b; off_t o; switch(*fmt) { case 's': /* string */ s = va_arg(ap, char *); buffer_append_string(srv->errorlog_buf, s); buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(" ")); break; case 'b': /* buffer */ b = va_arg(ap, buffer *); buffer_append_string_buffer(srv->errorlog_buf, b); buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(" ")); break; case 'd': /* int */ d = va_arg(ap, int); buffer_append_long(srv->errorlog_buf, d); buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(" ")); break; case 'o': /* off_t */ o = va_arg(ap, off_t); buffer_append_off_t(srv->errorlog_buf, o); buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(" ")); break; case 'x': /* int (hex) */ d = va_arg(ap, int); buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN("0x")); buffer_append_long_hex(srv->errorlog_buf, d); buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(" ")); break; case 'S': /* string */ s = va_arg(ap, char *); buffer_append_string(srv->errorlog_buf, s); break; case 'B': /* buffer */ b = va_arg(ap, buffer *); buffer_append_string_buffer(srv->errorlog_buf, b); break; case 'D': /* int */ d = va_arg(ap, int); buffer_append_long(srv->errorlog_buf, d); break; case 'O': /* off_t */ o = va_arg(ap, off_t); buffer_append_off_t(srv->errorlog_buf, o); break; case 'X': /* int (hex) */ d = va_arg(ap, int); buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN("0x")); buffer_append_long_hex(srv->errorlog_buf, d); break; case '(': case ')': case '<': case '>': case ',': case ' ': buffer_append_string_len(srv->errorlog_buf, fmt, 1); break; } } va_end(ap); switch(srv->errorlog_mode) { case ERRORLOG_PIPE: case ERRORLOG_FILE: case ERRORLOG_FD: buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN("\n")); write(srv->errorlog_fd, srv->errorlog_buf->ptr, srv->errorlog_buf->used - 1); break; case ERRORLOG_SYSLOG: syslog(LOG_ERR, "%s", srv->errorlog_buf->ptr); break; } return 0; }
/** * 输出日志. * 日志的格式: * 2009-11-25 22:31:25: (filename.line) information * * 参数fmt的说明如下: * 's':字符串 'b':buffer 'd':int 'o':off_t 'x':int的十六进制 * 上面的几个参数,在输出相应的值后都追加一个空格' '。 * 如果参数为大写,则不追加空格。 * */ int log_error_write(server * srv, const char *filename, unsigned int line, const char *fmt, ...) { pthread_mutex_lock(&srv -> log_lock); va_list ap; switch (srv->errorlog_mode) { case ERRORLOG_FILE: case ERRORLOG_STDERR: /* * 日志文件和标准错误输出要设定日志的时间。 */ if (srv->cur_ts != srv->last_generated_debug_ts) { buffer_prepare_copy(srv->ts_debug_str, 1024); strftime(srv->ts_debug_str->ptr, srv->ts_debug_str->size - 1, "%Y-%m-%d %H:%M:%S", localtime(&(srv->cur_ts))); srv->ts_debug_str->used = strlen(srv->ts_debug_str->ptr) + 1; srv->last_generated_debug_ts = srv->cur_ts; } buffer_copy_string_buffer(srv->errorlog_buf, srv->ts_debug_str); buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(": (")); break; case ERRORLOG_SYSLOG: /* * syslog自己产生时间 */ buffer_copy_string_len(srv->errorlog_buf, CONST_STR_LEN("(")); break; } buffer_append_string(srv->errorlog_buf, filename); buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(".")); buffer_append_long(srv->errorlog_buf, line); buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(") ")); //根据字符串fmt来遍历可变参数。 for (va_start(ap, fmt); *fmt; fmt++) { int d; char *s; buffer *b; off_t o; switch (*fmt) { case 's': /* string */ s = va_arg(ap, char *); buffer_append_string(srv->errorlog_buf, s); buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(" ")); break; case 'b': /* buffer */ b = va_arg(ap, buffer *); buffer_append_string_buffer(srv->errorlog_buf, b); buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(" ")); break; case 'd': /* int */ d = va_arg(ap, int); buffer_append_long(srv->errorlog_buf, d); buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(" ")); break; case 'o': /* off_t */ o = va_arg(ap, off_t); buffer_append_off_t(srv->errorlog_buf, o); buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(" ")); break; case 'x': /* int (hex) */ d = va_arg(ap, int); buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN("0x")); buffer_append_long_hex(srv->errorlog_buf, d); buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(" ")); break; case 'S': /* string */ s = va_arg(ap, char *); buffer_append_string(srv->errorlog_buf, s); break; case 'B': /* buffer */ b = va_arg(ap, buffer *); buffer_append_string_buffer(srv->errorlog_buf, b); break; case 'D': /* int */ d = va_arg(ap, int); buffer_append_long(srv->errorlog_buf, d); break; case 'O': /* off_t */ o = va_arg(ap, off_t); buffer_append_off_t(srv->errorlog_buf, o); break; case 'X': /* int (hex) */ d = va_arg(ap, int); buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN("0x")); buffer_append_long_hex(srv->errorlog_buf, d); break; case '(': case ')': case '<': case '>': case ',': case ' ': buffer_append_string_len(srv->errorlog_buf, fmt, 1); break; } } va_end(ap); switch (srv->errorlog_mode) { case ERRORLOG_FILE: buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN("\n")); write(srv->errorlog_fd, srv->errorlog_buf->ptr, srv->errorlog_buf->used - 1); break; case ERRORLOG_STDERR: buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN("\n")); write(STDERR_FILENO, srv->errorlog_buf->ptr, srv->errorlog_buf->used - 1); break; case ERRORLOG_SYSLOG: syslog(LOG_ERR, "%s", srv->errorlog_buf->ptr); break; } pthread_mutex_unlock(&srv -> log_lock); return 0; }
/* lowercase: append space, uppercase: don't */ static void log_buffer_append_printf(buffer *out, const char *fmt, va_list ap) { for(; *fmt; fmt++) { int d; char *s; buffer *b; off_t o; switch(*fmt) { case 's': /* string */ s = va_arg(ap, char *); buffer_append_string(out, s); buffer_append_string_len(out, CONST_STR_LEN(" ")); break; case 'b': /* buffer */ b = va_arg(ap, buffer *); buffer_append_string_buffer(out, b); buffer_append_string_len(out, CONST_STR_LEN(" ")); break; case 'd': /* int */ d = va_arg(ap, int); buffer_append_long(out, d); buffer_append_string_len(out, CONST_STR_LEN(" ")); break; case 'o': /* off_t */ o = va_arg(ap, off_t); buffer_append_off_t(out, o); buffer_append_string_len(out, CONST_STR_LEN(" ")); break; case 'x': /* int (hex) */ d = va_arg(ap, int); buffer_append_string_len(out, CONST_STR_LEN("0x")); buffer_append_long_hex(out, d); buffer_append_string_len(out, CONST_STR_LEN(" ")); break; case 'S': /* string */ s = va_arg(ap, char *); buffer_append_string(out, s); break; case 'B': /* buffer */ b = va_arg(ap, buffer *); buffer_append_string_buffer(out, b); break; case 'D': /* int */ d = va_arg(ap, int); buffer_append_long(out, d); break; case 'O': /* off_t */ o = va_arg(ap, off_t); buffer_append_off_t(out, o); break; case 'X': /* int (hex) */ d = va_arg(ap, int); buffer_append_string_len(out, CONST_STR_LEN("0x")); buffer_append_long_hex(out, d); break; case '(': case ')': case '<': case '>': case ',': case ' ': buffer_append_string_len(out, fmt, 1); break; } } }