nginx 是否可以以 ISO 8601 格式记录时间,但包含毫秒?

nginx 是否可以以 ISO 8601 格式记录时间,但包含毫秒?

在 Tomcat 前面,我们有一个 Nginx 作为反向代理。它们都使用 ISO 8601 时间戳来记录访问,但 tomcat 添加了毫秒(这是标准的一部分)。因此,如果 Nginx 收到请求并将其传递给 Tomcat,则 Nginx 日志的时间戳可能是“2015-10-29T00:37:02+00:00”,而 Tomcat 针对同一访问的时间戳将是“2015-10-29T00:37:02,106+0000”。我并不关心格式上的细微差别,但没有毫秒(Tomcat 日志中的“,106”部分)是一个问题,因为它会阻止我们正确关联日志。

有什么方法可以让 Nginx 在其日志中包含毫秒数?

答案1

不幸的是,根据对 nginx 源代码的阅读,似乎没有简单的方法可以做到这一点。您需要对日志进行后处理(您可以获取 $msec 的输出并使用 ms 自己将其转换为 ISO8601)或修补 nginx 以添加此功能。

有趣的是,几年前就提出了一个补丁,它提供了足够的灵活性来实现这一点,但我认为它没有任何进展: http://nginx.2469901.n2.nabble.com/PATCH-time-custom-supports-a-custom-log-timestamp-td3505292.html#none

答案2

问题要求 ISO 8601 加毫秒 - 这里是针对该特定用例的一行代码,基于 Oleksandr 的答案,但使用 ISO 而不是本地格式:

map "$time_iso8601 # $msec" $time_iso8601_ms { "~(^[^+]+)(\+[0-9:]+) # \d+\.(\d+)$" $1.$3$2; }

结果由正则表达式匹配组构成,如下所示:

  • $1= 仅日期和时间部分,$time_iso8601例如2021-05-21T10:26:19
  • $2= 仅时区部分,$time_iso8601例如+00:00
  • $3= 仅毫秒部分$msec例如123从中提取1621594635.123

如果觉得上面的代码太晦涩,可以参阅这个帖子(如另一个答案所评论的)它使用了多个map语句。

答案3

这是我找到的一个解决方法。将以下行添加到http {}块中:

map "$time_local:$msec" $time_local_ms { ~(^\S+)(\s+\S+):\d+\.(\d+)$ $1.$3$2; }

然后,在您的log_format行中更改[$time_local][$time_local_ms],或创建您自己的日志格式,例如我用于 Datadog 的格式:

log_format  common  '$remote_addr - $remote_user [$time_local_ms] "$request" '
                    '$status $body_bytes_sent $request_time "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';

访问日志示例:

172.17.0.1 - - [23/Apr/2021:13:06:02.802 +0000] "GET /static/image.jpg HTTP/1.1" 304 0 0.000 "http://localhost/" "Mozilla" "-"

来源https://grangerx.wordpress.com/2019/08/28/nginx-improve-logs-by-adding-millisecond-msec-resolution-to-time_local/

相关内容