Nginx/Openresty日志时间显示到毫秒级的三种方法(不改源码)
在这里,我们生成三个自定义变量
#以下为内置变量
$time_iso8601 日期格式示例: 2022-09-08T18:16:01+08:00
$time_local 日期格式示例: 02/Aug/2022:11:11:32 +0800
$msec 日期格式示例: 1663839717.105 当前的Unix时间戳,单位为秒,小数为毫秒
#生成自定义变量
$time_zh 示例值: 2022-10-08 22:00:18
$timestamp 示例值: 1663839717105
$time_zh_ms 示例值: 2022-10-08 22:00:18,888
方法一 :set (只能在server节点内)
建议创建独立 conf 文件,使用include方式,如:time-zh.conf
内容如下:
# 该 文件使用方法 在 nginx 配置 server 节点内: include time-zh.conf;
#
# nginx 内置变量,解析为定义格式,仅支持到秒 (实现支持到毫秒)
#
# $time_iso8601 日期格式示例: 2022-09-08T18:16:01+08:00
# $time_local 日期格式示例: 02/Aug/2022:11:11:32 +0800
# $msec 日期格式示例: 1663839717.105 当前的Unix时间戳,单位为秒,小数为毫秒
# 自定义变量 - 默认值
#set $time_zh $time_iso8601;
#set $timestamp $msec;
#set $time_zh_ms $time_zh,000;
# 格式化日期
if ($time_iso8601 ~ "^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(\+\d{2})") {
set $year $1;
set $month $2;
set $day $3;
set $hour $4;
set $minute $5;
set $second $6;
# 时区,只到小时
set $time_zone $7;
# 自定义 yyyy-MM-dd hh:mi:ss 格式
set $time_zh "$1-$2-$3 $4:$5:$6";
}
# 时间戳,单位毫秒 使用 $msec 去除中间的小数点实现
if ($msec ~ "^(\d+)\.(\d+)") {
set $timestamp $1$2;
# 自定义 yyyy-MM-dd hh:mi:ss,SSS 带毫秒格式
set $time_zh_ms $time_zh,$2;
}
方法二: set_by_lua (只能在server节点内)
建议创建独立 conf 文件,使用include方式,如:time-zh-lua.conf
内容如下:
# 该 文件使用方法 在 nginx 配置 server 节点内: include time-zh-lua.conf;
#
# nginx 内置变量,解析为定义格式,仅支持到秒 (实现支持到毫秒)
#
# 取 ngx_lua 模块提供的带缓存的时间接口
# ngx.now() 日期格式示例: 1663839717.105 当前的Unix时间戳,单位为秒,小数为毫秒; 与 nginx 内置变量 $msec 相同
# -- 因 nginx 有缓存时间,所以与实际服务器时间会有些许偏差,可能偏差几毫秒 - 正常业务可忽略不计
# -- 若 一定要强一致,可先调用 ngx.update_time() 强制更新,但成本较高,不推荐使用
# ngx.time() 日期格式示例: 1663839717 当前的Unix时间戳,单位为秒(1970年至今)
# ngx.var.time_local 日期格式示例: 02/Aug/2022:11:11:32 +0800
# ngx.utctime() 日期格式示例: 2022-09-08 10:16:01
# ngx.localtime() 日期格式示例: 2022-09-08 18:16:01
# ngx.today() 日期格式示例: 2022-09-08
#
# 本地时间(yyyy-MM-dd hh:mi:ss)
set_by_lua $time_zh 'return ngx.localtime()';
# Unix时间戳,单位为毫秒
set_by_lua $timestamp 'return ngx.now() * 1000';
# 本地时间(yyyy-MM-dd hh:mi:ss,SSS)
# 毫秒数: 先用 ngx.now()%1, 取余数去除秒的部分,再*1000获取毫秒部分,再用 math.floor + 0.5 四舍五入,再用 string.format 固定3位长度
set_by_lua $time_zh_ms 'return ngx.localtime()..","..string.format("%03d", math.floor(ngx.now()%1*1000+0.5))';
方法三: map (在http节点内)
建议创建独立 conf 文件,使用include方式,如:time-zh-map.conf
内容如下:
# 该 文件使用方法 在 nginx 配置 http 节点内: include time-zh-map.conf;
#
# nginx 内置变量,解析为定义格式,仅支持到秒
#
# $time_iso8601 日期格式示例: 2022-09-08T18:16:01+08:00
# $time_local 日期格式示例: 02/Aug/2022:11:11:32 +0800
# $msec 日期格式示例: 1663839717.105 当前的Unix时间戳,单位为秒,小数为毫秒
# 使用以下 map 必须增加 map_hash_bucket_size 大小,否则会报异常
# 默认值为 cpu 的缓存行大小,一般为64
map_hash_bucket_size 128;
# 自定义 yyyy-MM-dd hh:mi:ss 格式
map $time_iso8601 $time_zh {
default $time_iso8601;
"~(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2}:\d{2})(\+\d{2})" "$1 $2";
}
# 时间戳,单位毫秒 使用 $msec 去除中间的小数点实现
map $msec $timestamp {
default $msec;
~(\d+)\.(\d+) $1$2;
}
# 自定义 yyyy-MM-dd hh:mi:ss,SSS 带毫秒格式
map "$time_iso8601 # $msec" $time_zh_ms {
default $time_zh,000;
"~(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2}:\d{2})(\+\d{2}:\d{2}) # (\d+)\.(\d+)$" "$1 $2,$5";
}
PS: 若存在多个Server, 推荐使用方法三, 则不需要每个 server 配置一次