nginx 可以以 ISO 8601 格式记录时间,但包括毫秒吗?

Sam*_*ham 6 nginx logging timestamp

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

有没有办法让 Nginx 在它的日志中包含毫秒?

spa*_*owt 6

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

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

结果是根据正则表达式匹配组构造的,如下所示:

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

如果单行感觉太不透明,请参阅这篇文章(如另一个答案的评论),它使用多个map语句。


Ole*_*rko 5

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

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

然后,在您的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"';
Run Code Online (Sandbox Code Playgroud)

访问日志示例:

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" "-"
Run Code Online (Sandbox Code Playgroud)

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


小智 4

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

有趣的是,几年前就提出了一个补丁,该补丁可以提供足够的灵活性,使其成为可能,但我认为它没有走到任何地方: http ://nginx.2469901.n2.nabble.com/PATCH-time-custom-supports- a-自定义日志时间戳-td3505292.html#none

  • https://thatsamguy.com/nginx-iso8601-time-format/ (3认同)