diff --git a/changes-entries/log-msec.txt b/changes-entries/log-msec.txt new file mode 100644 index 00000000000..dd4567e2c4b --- /dev/null +++ b/changes-entries/log-msec.txt @@ -0,0 +1,3 @@ + *) core: Add support for %{m}t in ErrorLogFormat to log milli-second + time resolution (in addition to existing %{u}t for micro-seconds). + [Luboš Uhliarik ] diff --git a/docs/manual/mod/core.xml b/docs/manual/mod/core.xml index 7c6bd23857d..f07eab9d8a2 100644 --- a/docs/manual/mod/core.xml +++ b/docs/manual/mod/core.xml @@ -1736,6 +1736,9 @@ ErrorLogFormat "[%t] [%l] [pid %P] %F: %E: [client %a] %M" %{u}t The current time including micro-seconds + %{m}t + The current time including milliseconds + %{cu}t The current time in ISO 8601 extended format (compact), including micro-seconds diff --git a/include/util_time.h b/include/util_time.h index 92082182e3c..7305a3e0a00 100644 --- a/include/util_time.h +++ b/include/util_time.h @@ -49,6 +49,8 @@ extern "C" { #define AP_CTIME_OPTION_COMPACT 0x2 /* Add timezone offset from GMT ([+-]hhmm) */ #define AP_CTIME_OPTION_GMTOFF 0x4 +/* Add sub second timestamps with millisecond resolution */ +#define AP_CTIME_OPTION_MSEC 0x8 /** diff --git a/server/log.c b/server/log.c index 9576d071c27..438171d113d 100644 --- a/server/log.c +++ b/server/log.c @@ -664,9 +664,15 @@ static int log_ctime(const ap_errorlog_info *info, const char *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 */ + else if (arg[0] == 'm' && !arg[1]) { /* no ErrorLogFormat (fast path) - msec */ + option |= AP_CTIME_OPTION_MSEC; + } + else if (!ap_strchr_c(arg, '%')) { /* special "%{mcuz}t" formats */ while (*arg) { switch (*arg++) { + case 'm': + option |= AP_CTIME_OPTION_MSEC; + break; case 'u': option |= AP_CTIME_OPTION_USEC; break; diff --git a/server/util_time.c b/server/util_time.c index 299b53c2535..51f1e32d0f6 100644 --- a/server/util_time.c +++ b/server/util_time.c @@ -22,6 +22,11 @@ * */ #define AP_CTIME_USEC_LENGTH 7 +/* Number of characters needed to format the millisecond part of a timestamp. + * Milliseconds have 3 digits plus one separator character makes 4. + * */ +#define AP_CTIME_MSEC_LENGTH 4 + /* Length of ISO 8601 date/time (including trailing '\0') */ #define AP_CTIME_COMPACT_LEN 20 @@ -182,6 +187,9 @@ AP_DECLARE(apr_status_t) ap_recent_ctime_ex(char *date_str, apr_time_t t, if (option & AP_CTIME_OPTION_USEC) { needed += AP_CTIME_USEC_LENGTH; } + else if (option & AP_CTIME_OPTION_MSEC) { + needed += AP_CTIME_MSEC_LENGTH; + } if (option & AP_CTIME_OPTION_GMTOFF) { needed += AP_CTIME_GMTOFF_LEN; @@ -242,11 +250,16 @@ AP_DECLARE(apr_status_t) ap_recent_ctime_ex(char *date_str, apr_time_t t, *date_str++ = ':'; *date_str++ = xt.tm_sec / 10 + '0'; *date_str++ = xt.tm_sec % 10 + '0'; - if (option & AP_CTIME_OPTION_USEC) { + if (option & (AP_CTIME_OPTION_USEC|AP_CTIME_OPTION_MSEC)) { int div; int usec = (int)xt.tm_usec; *date_str++ = '.'; - for (div=100000; div>0; div=div/10) { + div = 100000; + if (!(option & AP_CTIME_OPTION_USEC)) { + usec = usec / 1000; + div = 100; + } + for (; div>0; div=div/10) { *date_str++ = usec / div + '0'; usec = usec % div; }