调整格式化nginx日志时间方式
1 需求
前端在项目的一些页面做了js脚本埋点,以获取用户访问站点的相关信息,比如,用户页面停留时长,用户id,访问的产品id等。然后会从nginx日志里面提取这些信息为json格式,但是nginx 日志时间变量可配置的就两种
第一个时间变量:$time_local 输出格式为:127.0.0.1 - - [03/Nov/2020:14:38:06 +0800] "GET / HTTP/1.1" 200 23 "-" "curl/7.29.0"
第二个时间变量:$time_iso8601 输出格式为: 127.0.0.1 - - [2020-11-03T14:42:53+08:00] "GET / HTTP/1.1" 200 23 "-" "curl/7.29.0" "-"
然而希望的时间格式是: 2020-11-03 14:46:44
大概查了下可以实现的方案:
1、修改nginx 日志模块的源码 参考:https://www.cnblogs.com/t-road/p/6868683.html
2、启用lua模块 参考:https://developer.aliyun.com/article/69512
3、python datetime模块转换
4、第一种时间变量格式的值可以用数据库的函数str_to_date转换 str_to_date('%s','%s') str_to_date('02/Nov/2020:07:07:05','%d/%b/%Y:%H:%i:%s')
由于生产是yum方式安装的,前两种方案比较麻烦,且有点小风险,因为需要重新编译。反正都需要对日志做处理的,就用date命令来转换上面的两种格式
2 测试date命令转换
2.1 $time_local格式测试
[root@msht-sh-g-test-01 ~]# date -d '03/Nov/2020:14:38:06' "+%Y-%m-%d %H:%M:%S" date: invalid date ‘03/Nov/2020:14:38:06’ [root@msht-sh-g-test-01 ~]#
这种格式date命令无法识别
2.2 $time_iso8601格式测试
[root@msht-sh-g-test-01 ~]# date -d '2020-11-03T14:45:06+08:00' "+%Y-%m-%d %H:%M:%S" 2020-11-03 14:45:06 [root@msht-sh-g-test-01 ~]#
这种能达到预期
因此,在nginx的日志时间变量定义为$time_iso8601,再用date转换一次就可以,不需要重新编译nginx带来的风险;如果不希望额外用date命令或python来转的话,修改nginx源码更合适。
3 模拟脚本里面的操作
[root@msht-sh-g-test-01 ~]# line='127.0.0.1 - - 2020-11-03T14:46:44+08:00 "GET / HTTP/1.1" 200 23 "-" "curl/7.29.0" "-"' [root@msht-sh-g-test-01 ~]# str_date=$(echo $line|awk '{print $4}') [root@msht-sh-g-test-01 ~]# format_date=$(date -d $str_date "+%Y-%m-%d %H:%M:%S") [root@msht-sh-g-test-01 ~]# echo $format_date 2020-11-03 14:46:44 [root@msht-sh-g-test-01 ~]# printf '{"request_time":"%s %s"}\n' $format_date {"request_time":"2020-11-03 14:46:44"} [root@msht-sh-g-test-01 ~]#
小提示:由于printf会接收格式参数是以空格分割的,上面格式化后的变量中的值有空格,printf会把2020-11-03当成一个格式化值,另外一部分14:45:06 会重新当成一个值,类似下面这种
[root@msht-sh-g-test-01 ~]# line='127.0.0.1 - - 2020-11-03T14:46:44+08:00 "GET / HTTP/1.1" 200 23 "-" "curl/7.29.0" "-"' [root@msht-sh-g-test-01 ~]# str_date=$(echo $line|awk '{print $4}') [root@msht-sh-g-test-01 ~]# format_date=$(date -d $str_date "+%Y-%m-%d %H:%M:%S") [root@msht-sh-g-test-01 ~]# echo $format_date 2020-11-03 14:46:44 [root@msht-sh-g-test-01 ~]# printf '{"request_time":"%s"}\n' $format_date {"request_time":"2020-11-03"} {"request_time":"14:46:44"} [root@msht-sh-g-test-01 ~]# [root@msht-sh-g-test-01 ~]# printf '{"request_time":"%s %s"}\n' $format_date {"request_time":"2020-11-03 14:46:44"} [root@msht-sh-g-test-01 ~]#
因此需要写两个 %s 来接收后面那一个变量里面的值。