Nginx 输出 JSON 格式日志

发布于 2024-02-06 19:26:41 字数 3813 浏览 61 评论 0

为了配合 nginx 日志分析,需要将 Nginx 的日志转为 json 格式,这个本身并不是很难,配置一个 log_format 即可,但在具体操作中却遇到了很多意想不到的问题。

根据实际需求,将记录的字段以 json 格式创建一个命名的日志,下面是我创建的一个示例:

log_format json '{"@timestamp":"$time_iso8601",'
            '"@version":"1",'
            '"server_addr":"$server_addr",'
            '"remote_addr":"$remote_addr",'
            '"host":"$host",'
            '"uri":"$uri",'
            '"body_bytes_sent":$body_bytes_sent,'
            '"bytes_sent":$body_bytes_sent,'
            '"upstream_response_time":$upstream_response_time,'
            '"request":"$request",'
            '"request_length":$request_length,'
            '"request_time":$request_time,'
            '"status":"$status",'
            '"http_referer":"$http_referer",'
            '"http_x_forwarded_for":"$http_x_forwarded_for",'
            '"http_user_agent":"$http_user_agent"'
            '}';

发布到线上之后发现部分 json 字符串不能正常解析,主要体现在非法 json 值未转义字符串的问题。

0x01 非法 json 值处理

非法 json 值

非法 json 值

json 中 key 为 upstream_response_time 的 value 为 - ,这很明显不是一个 json 字符串,而且这种情况大多出现在301的响应中。通过排查发现是在 Nginx 中配置了 301 跳转,也就是说 Nginx 自己处理了这个请求,不再将请求向后端转发,这直接导致 upstream_response_time 的值为空,写入日志后,Nginx 将空值替换为了 - ,从而导致了惨案的发生。

那如何处理呢?Google 之后发现 Nginx 有个 [map](http://nginx.org/en/docs/http/ngx_http_map_module.html#map) 的指令,该指令的作用是创建一个变量,而这个变量由其它变量通过一个映射表置换得来,跟 Python 中的 map 很像,但是 Nginx 的 map 值支持正则等。

根据描述,我们在配置文件中添加一个入下的 map ,在 $upstream_response_time 为空的时候返回为 0,将该值赋值给新变量 $upstream_response_timer ,添加之后该问题得到了处理,但是接着出现了另外一个问题。

map $upstream_response_time $upstream_response_timer {
    default $upstream_response_time;
    ""        0;
}

0x02 未转义字符串问题

运行一段时间后,发现依然后很多请求未解析,查找发现日志中充斥了大量如下图的字符:

特殊字符

特殊字符

很显然这是“恶意”扫描的请求,这类请求的特点是可能会包含如双引号(“)、反斜杠等在 json 字符串中被认为非法的字符,处理这类问题的最直接手段就是转义,那 Nginx 下如何处理呢?

通过查询 nginx 日志,发现 [log\_format](http://nginx.org/ru/docs/http/ngx_http_log_module.html#log_format) 本身就可以对字符串进行转义,这个参数的名称是 escape ,这个参数本身也需要指定一个值,可以是 defaultjsonnone ,很明显,我们需要指定为 json

log_format json escape=json '{"@timestamp":"$time_iso8601",'
...

配置之后,所有 json 字符串格式的非法字符都会被转义处理。

0x03 结论

总结起来,对于 Nginx 输出 json 格式日志需要添加如下配置来保证 json 格式的正确性:

map $upstream_response_time $upstream_response_timer {
    default $upstream_response_time;
    ""        0;
}
log_format json escape=json '{"@timestamp":"$time_iso8601",'
            '"@version":"1",'
            '"server_addr":"$server_addr",'
            '"remote_addr":"$remote_addr",'
            '"host":"$host",'
            '"uri":"$uri",'
            '"body_bytes_sent":$body_bytes_sent,'
            '"bytes_sent":$body_bytes_sent,'
            '"upstream_response_time":$upstream_response_timer,'
            '"request":"$request",'
            '"request_length":$request_length,'
            '"request_time":$request_time,'
            '"status":"$status",'
            '"http_referer":"$http_referer",'
            '"http_x_forwarded_for":"$http_x_forwarded_for",'
            '"http_user_agent":"$http_user_agent"'
            '}';

server {
    ...
    access_log /path/to/access.log json;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

雾里花

暂无简介

文章
评论
27 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文