diff --git a/changes-entries/errorlogformat.txt b/changes-entries/errorlogformat.txt new file mode 100644 index 00000000000..1c2a308cced --- /dev/null +++ b/changes-entries/errorlogformat.txt @@ -0,0 +1,4 @@ + *) core: Add formats %{z} and %{strftime-format} to ErrorLogFormat, and make + sure that if the format is configured early enough it applies to every log + line. PR 62161. [Yann Ylavic] + diff --git a/include/ap_mmn.h b/include/ap_mmn.h index ace7c43ed90..59463532c8c 100644 --- a/include/ap_mmn.h +++ b/include/ap_mmn.h @@ -595,6 +595,7 @@ * 20120211.125 (2.4.55-dev) Export mod_http2.h as public header * 20120211.126 (2.4.55-dev) Add additional hcmethod_t enums and PROXY_WORKER_IS_ERROR * 20120211.127 (2.4.56-dev) Add ap_proxy_canonenc_ex + * 20120211.128 (2.4.55-dev) Add AP_CTIME_OPTION_GMTOFF to util_time.h */ #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */ @@ -602,7 +603,7 @@ #ifndef MODULE_MAGIC_NUMBER_MAJOR #define MODULE_MAGIC_NUMBER_MAJOR 20120211 #endif -#define MODULE_MAGIC_NUMBER_MINOR 127 /* 0...n */ +#define MODULE_MAGIC_NUMBER_MINOR 128 /* 0...n */ /** * Determine if the server's current MODULE_MAGIC_NUMBER is at least a diff --git a/include/util_time.h b/include/util_time.h index 2cd283306eb..92082182e3c 100644 --- a/include/util_time.h +++ b/include/util_time.h @@ -47,6 +47,8 @@ extern "C" { #define AP_CTIME_OPTION_USEC 0x1 /* Use more compact ISO 8601 format */ #define AP_CTIME_OPTION_COMPACT 0x2 +/* Add timezone offset from GMT ([+-]hhmm) */ +#define AP_CTIME_OPTION_GMTOFF 0x4 /** @@ -95,7 +97,7 @@ AP_DECLARE(apr_status_t) ap_recent_ctime(char *date_str, apr_time_t t); * @param option Additional formatting options (AP_CTIME_OPTION_*). * @param len Pointer to an int containing the length of the provided buffer. * On successful return it contains the number of bytes written to the - * buffer. + * buffer (including trailing NUL byte). * @return APR_SUCCESS iff successful, APR_ENOMEM if buffer was to short. */ AP_DECLARE(apr_status_t) ap_recent_ctime_ex(char *date_str, apr_time_t t, diff --git a/server/config.c b/server/config.c index be889dbf2f0..3d11ff58a44 100644 --- a/server/config.c +++ b/server/config.c @@ -2301,6 +2301,9 @@ AP_DECLARE(server_rec*) ap_read_config(process_rec *process, apr_pool_t *ptemp, if (s == NULL) { return s; } + if (ap_server_conf == NULL) { + ap_server_conf = s; + } init_config_globals(p); diff --git a/server/core.c b/server/core.c index e1493fd4091..d06864abc8d 100644 --- a/server/core.c +++ b/server/core.c @@ -489,6 +489,11 @@ static void *create_core_server_config(apr_pool_t *a, server_rec *s) conf->flush_max_pipelined = AP_FLUSH_MAX_PIPELINED; } else { + /* Use main ErrorLogFormat while the vhost is loading */ + core_server_config *main_conf = + ap_get_core_module_config(ap_server_conf->module_config); + conf->error_log_format = main_conf->error_log_format; + conf->flush_max_pipelined = -1; } diff --git a/server/log.c b/server/log.c index cc04c38059b..dae94e63bfa 100644 --- a/server/log.c +++ b/server/log.c @@ -652,14 +652,32 @@ static int log_ctime(const ap_errorlog_info *info, const char *arg, int time_len = buflen; int option = AP_CTIME_OPTION_NONE; - while (arg && *arg) { - switch (*arg) { - case 'u': option |= AP_CTIME_OPTION_USEC; - break; - case 'c': option |= AP_CTIME_OPTION_COMPACT; - break; + if (arg) { + if (arg[0] == 'u' && !arg[1]) { /* no ErrorLogFormat (fast path) */ + option |= AP_CTIME_OPTION_USEC; + } + else if (!ap_strchr_c(arg, '%')) { /* special "%{cuz}t" formats */ + while (*arg) { + switch (*arg++) { + case 'u': + option |= AP_CTIME_OPTION_USEC; + break; + case 'c': + option |= AP_CTIME_OPTION_COMPACT; + break; + case 'z': + option |= AP_CTIME_OPTION_GMTOFF; + break; + } + } + } + else { /* "%{strftime %-format}t" */ + apr_size_t len = 0; + apr_time_exp_t expt; + ap_explode_recent_localtime(&expt, apr_time_now()); + apr_strftime(buf, &len, buflen, arg, &expt); + return (int)len; } - arg++; } ap_recent_ctime_ex(buf, apr_time_now(), option, &time_len); @@ -1166,6 +1184,11 @@ static void log_error_core(const char *file, int line, int module_index, #endif logf = stderr_log; + + /* Use the main ErrorLogFormat if any */ + if (ap_server_conf) { + sconf = ap_get_core_module_config(ap_server_conf->module_config); + } } else { int configured_level = r ? ap_get_request_module_loglevel(r, module_index) : @@ -1219,6 +1242,10 @@ static void log_error_core(const char *file, int line, int module_index, } } } + else if (ap_server_conf) { + /* Use the main ErrorLogFormat if any */ + sconf = ap_get_core_module_config(ap_server_conf->module_config); + } } info.s = s; diff --git a/server/main.c b/server/main.c index 7da7aa2ca20..fb23f01d1d4 100644 --- a/server/main.c +++ b/server/main.c @@ -678,8 +678,8 @@ int main(int argc, const char * const argv[]) if (temp_error_log) { ap_replace_stderr_log(process->pool, temp_error_log); } - ap_server_conf = ap_read_config(process, ptemp, confname, &ap_conftree); - if (!ap_server_conf) { + ap_server_conf = NULL; /* set early by ap_read_config() for logging */ + if (!ap_read_config(process, ptemp, confname, &ap_conftree)) { if (showcompile) { /* Well, we tried. Show as much as we can, but exit nonzero to * indicate that something's not right. The cause should have @@ -688,6 +688,7 @@ int main(int argc, const char * const argv[]) } destroy_and_exit_process(process, 1); } + ap_assert(ap_server_conf != NULL); apr_pool_cleanup_register(pconf, &ap_server_conf, ap_pool_cleanup_set_null, apr_pool_cleanup_null); @@ -785,10 +786,11 @@ int main(int argc, const char * const argv[]) apr_pool_create(&ptemp, pconf); apr_pool_tag(ptemp, "ptemp"); ap_server_root = def_server_root; - ap_server_conf = ap_read_config(process, ptemp, confname, &ap_conftree); - if (!ap_server_conf) { + ap_server_conf = NULL; /* set early by ap_read_config() for logging */ + if (!ap_read_config(process, ptemp, confname, &ap_conftree)) { destroy_and_exit_process(process, 1); } + ap_assert(ap_server_conf != NULL); apr_pool_cleanup_register(pconf, &ap_server_conf, ap_pool_cleanup_set_null, apr_pool_cleanup_null); /* sort hooks here to make sure pre_config hooks are sorted properly */ diff --git a/server/util_time.c b/server/util_time.c index 3632d0d5831..299b53c2535 100644 --- a/server/util_time.c +++ b/server/util_time.c @@ -22,9 +22,11 @@ * */ #define AP_CTIME_USEC_LENGTH 7 -/* Length of ISO 8601 date/time */ +/* Length of ISO 8601 date/time (including trailing '\0') */ #define AP_CTIME_COMPACT_LEN 20 +/* Length of timezone offset from GMT ([+-]hhmm) plus leading space */ +#define AP_CTIME_GMTOFF_LEN 6 /* Cache for exploded values of recent timestamps */ @@ -181,7 +183,13 @@ AP_DECLARE(apr_status_t) ap_recent_ctime_ex(char *date_str, apr_time_t t, needed += AP_CTIME_USEC_LENGTH; } - /* Check the provided buffer length */ + if (option & AP_CTIME_OPTION_GMTOFF) { + needed += AP_CTIME_GMTOFF_LEN; + } + + /* Check the provided buffer length (note: above AP_CTIME_COMPACT_LEN + * and APR_CTIME_LEN include the trailing '\0'; so does 'needed' then). + */ if (len && *len >= needed) { *len = needed; } @@ -193,9 +201,10 @@ AP_DECLARE(apr_status_t) ap_recent_ctime_ex(char *date_str, apr_time_t t, } /* example without options: "Wed Jun 30 21:49:08 1993" */ - /* 123456789012345678901234 */ /* example for compact format: "1993-06-30 21:49:08" */ - /* 1234567890123456789 */ + /* example for compact+usec+gmtoff format: + * "1993-06-30 22:49:08.123456 +0100" + */ ap_explode_recent_localtime(&xt, t); real_year = 1900 + xt.tm_year; @@ -249,7 +258,23 @@ AP_DECLARE(apr_status_t) ap_recent_ctime_ex(char *date_str, apr_time_t t, *date_str++ = real_year % 100 / 10 + '0'; *date_str++ = real_year % 10 + '0'; } - *date_str++ = 0; + if (option & AP_CTIME_OPTION_GMTOFF) { + int off = xt.tm_gmtoff, off_hh, off_mm; + char sign = '+'; + if (off < 0) { + off = -off; + sign = '-'; + } + off_hh = off / 3600; + off_mm = off % 3600 / 60; + *date_str++ = ' '; + *date_str++ = sign; + *date_str++ = off_hh / 10 + '0'; + *date_str++ = off_hh % 10 + '0'; + *date_str++ = off_mm / 10 + '0'; + *date_str++ = off_mm % 10 + '0'; + } + *date_str = 0; return APR_SUCCESS; }