]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
core: Add millisecond support to ErrorLogFormat time specifiers
authorJoe Orton <jorton@apache.org>
Wed, 21 Jan 2026 11:05:12 +0000 (11:05 +0000)
committerJoe Orton <jorton@apache.org>
Wed, 21 Jan 2026 11:05:12 +0000 (11:05 +0000)
%{m} prints the timestamp in millisecond-resolution.

* include/util_time.h:
  Define new AP_CTIME_OPTION_MSEC option for printing time in milliseconds
  format.

* server/util_time.c (ap_recent_ctime_ex):
  Handle AP_CTIME_OPTION_MSEC to print time in a millisecond format.

* server/log.c (log_ctime):
  Recognize the m time option in both fast-path and composite %{...}t formats.

Submitted by: Luboš Uhliarik <luhliari redhat.com>
Github: closes #597

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1931452 13f79535-47bb-0310-9956-ffa450edef68

changes-entries/log-msec.txt [new file with mode: 0644]
docs/manual/mod/core.xml
include/util_time.h
server/log.c
server/util_time.c

diff --git a/changes-entries/log-msec.txt b/changes-entries/log-msec.txt
new file mode 100644 (file)
index 0000000..dd4567e
--- /dev/null
@@ -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 <luhliari redhat.com>]
index 7d53270224508426501a414a73f184736af80755..1ff13985a4e4b0d43b626a4fc7dc3a6dd4b9e57d 100644 (file)
@@ -1761,6 +1761,9 @@ ErrorLogFormat "[%t] [%l] [pid %P] %F: %E: [client %a] %M"
     <tr><td><code>%{u}t</code></td>
         <td>The current time including micro-seconds</td></tr>
 
+    <tr><td><code>%{m}t</code></td>
+        <td>The current time including milliseconds</td></tr>
+
     <tr><td><code>%{cu}t</code></td>
         <td>The current time in ISO 8601 extended format (compact), including
             micro-seconds</td></tr>
index 1ba6353c0253d90a86a94466d480343b4e856c49..c149e52166aaf13014133de1c7893b20f5c12827 100644 (file)
@@ -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
 
 
 /**
index 91dcf2c3eb02be93c2116d6ba1e773c5c9105a0f..d5236f45f8674e53a8448bcdf662e7a335f04324 100644 (file)
@@ -585,9 +585,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;
index 8dcf2fb293f2589e4714e15ff7ec6e1e19c227fd..020fced8b104d27840ba5a3e1c0357508041e558 100644 (file)
  *   */
 #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
 
@@ -184,6 +189,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;
@@ -244,11 +252,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;
         }