GCP容器OS上Nginx日志无法转为JSON格式至Cloud Logging求助
我在运行cos-stable-89-16108-470-1容器OS的GCP虚拟机上部署了Nginx 1.14.0,目标是将Nginx访问日志以JSON格式输出到GCP Cloud Logging。
之前通过添加符号链接让日志能显示在Cloud Logging中:
RUN ln -sf /dev/stdout /var/log/nginx/access.log && ln -sf /dev/stderr /var/log/nginx/error.log
但当前日志还是默认的combined格式:
ip1.ip2.ip3.ip4 - - [24/Feb/2025:11:56:09 +0000] "GET /api/health HTTP/2.0" 200 40 "-" "curl/8.7.1"
我修改了nginx.conf配置来设置JSON日志格式,但未生效,配置如下:
http { log_format json_format escape=json '{' '"msec": "$msec", ' '"connection": "$connection", ' '"connection_requests": "$connection_requests", ' '"pid": "$pid", ' '"request_id": "$request_id", ' '"request_length": "$request_length", ' '"remote_addr": "$remote_addr", ' '"remote_user": "$remote_user", ' '"remote_port": "$remote_port", ' '"time_local": "$time_local", ' '"time_iso8601": "$time_iso8601", ' '"request": "$request", ' '"request_uri": "$request_uri", ' '}'; include /etc/nginx/mime.types; default_type application/octet-stream; access_log /var/log/nginx/access.log json_format; }
相同的JSON格式配置在本地无符号链接的Docker容器中可以正常工作,本地日志示例:
{"msec": "1740393829.310", "connection": "82", "connection_requests": "1", "pid": "11", "request_id": "cdbfe5d1304e04ac78e762560863701d", "request_length": "89", "remote_addr": "ip1.ip2.ip3.ip4", "remote_user": "", "remote_port": "57708", "time_local": "24/Feb/2025:10:43:49 +0000", "time_iso8601": "2025-02-24T10:43:49+00:00", "request": "GET / HTTP/1.1", "request_uri": "/", } {"msec": "1740393831.360", "connection": "83", "connection_requests": "1", "pid": "11", "request_id": "0024b54995759551faa356855cc350e5", "request_length": "89", "remote_addr": "ip1.ip2.ip3.ip4", "remote_user": "", "remote_port": "57712", "time_local": "24/Feb/2025:10:43:51 +0000", "time_iso8601": "2025-02-24T10:43:51+00:00", "request": "GET / HTTP/1.1", "request_uri": "/", }
排查方向与解决建议
验证Nginx配置加载状态
执行nginx -t检查配置语法是否合法,再执行nginx -s reload强制重载配置。如果重载失败,查看Cloud Logging中的Nginx错误日志(已指向/dev/stderr)。同时确认虚拟机上的Nginx是否加载了你修改的nginx.conf,部分部署场景会优先加载/etc/nginx/conf.d/下的子配置文件。检查子配置是否覆盖全局日志设置
查看/etc/nginx/conf.d/或其他被包含的配置文件,确认是否有server块单独设置了access_log并使用combined格式。如果存在,需在对应server块中指定json_format,或者删除子配置中的access_log指令,让全局配置生效。验证符号链接对日志格式的影响
临时取消符号链接,将日志写入实际文件/var/log/nginx/access.log,查看文件内容是否为JSON格式。如果实际文件是JSON,说明问题出在GCP Cloud Logging的采集环节;如果还是默认格式,说明Nginx配置未生效。测试Nginx版本对配置的兼容性
虽然escape=json在Nginx 1.11.8及以上版本支持,但可以简化配置测试:log_format json_format '{"remote_addr": "$remote_addr", "request": "$request"}';重载配置后观察日志格式是否变化,排除参数兼容性问题。
排查Cloud Logging的日志解析规则
如果Nginx确实输出了JSON日志,但Cloud Logging显示为默认格式,可能是日志接收器或解析规则将JSON内容识别为文本。直接查看虚拟机的stdout输出(如docker logs <容器ID>或系统日志),确认输出内容是否为JSON,再检查Cloud Logging的相关配置。
内容的提问来源于stack exchange,提问作者ssk_seek

