Nginx快速入门:访问日志access.log参数详解 |访问日志记录自定义请求头(三)

发布时间:2023年12月20日

0. 引言

在企业的生产环境中,我们时常需要通过nginx的访问日志来统计流量、排查调用问题等,而nginx默认的日志格式所包含的信息远无法满足我们使用,因此常常需要对日志进行自定义,所以今天我们就来看如何自定义nginx的访问日志格式,并了解nginx的访问日志支持多少参数。

1. 自定义日志格式

首先我们在默认的nginx.conf文件中可以看到,对访问日志是有默认定义的,其中包含了定义日志格式,定义日志文件位置。如下所示,其中main为定义的日志格式别名,你可以定义成其他的名称。

log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
access_log  /var/log/nginx/access.log  main;

默认日志输出示例
在这里插入图片描述
nginx的访问日志定义的语法是:

log_format name [escape=default | json] string ...;
  • name: 定义的格式名称,自定义,后续在access_log参数中引用
  • escape: 设置日志格式,默认为default,即默认输出,或者支持json, 按照json格式输出
  • string: 要定义的日志格式的内容,可以在里面设置要记录的日志参数

在默认日志格式中,定义的参数含义如下:

参数说明
$remote_addr客户端IP地址
$remote_user客户端用户名
$time_local请求时间
$request请求的URI和HTTP协议版本
$status请求返回的状态码
$body_bytes_sent发送给客户端的字节数
$http_referer引用的页面地址
$http_user_agent客户端代理信息, 比如浏览器信息等

nginx还支持的常用参数有:

参数说明
$http_host请求头中的 “Host” 字段的值,如果请求中没有 “Host” 字段,则会使用服务器监听的 server_name 中定义的第一个名称
$uri请求的 URI,即 URL 的后半部分,不包括查询字符串
$ssl_protocol使用的 SSL 协议版本,如 “SSLv3”、“TLSv1” 等
$ssl_cipher用于加密连接的加密算法,例如 “AES128-SHA”
$http_x_forwarded_for当前端有代理服务器时,设置web节点记录客户端地址的配置,此参数生效的前提是代理服务器也要进行相关的x_forwarded_for设置
$upstream_addr后端服务器的地址和端口,用于识别请求被转发到的服务器
$request_body客户端发送的请求体,即请求消息的主体部分,通常用于 POST 请求
$upstream_status后端服务器的响应状态码,如 “200”、“404” 等
$upstream_header_time后端服务器处理请求并返回响应头的时间
$upstream_response_time后端服务器从开始处理请求到返回响应的整个时间
$bytes_sent发送给客户端的字节数
$connection连接序列号
$connection_requests当前通过连接发出的请求数量
$msec日志写入时间,单位为秒,精度是毫秒
$pipe如果请求是通过http流水线发送,则其值为"p",否则为“."
$request_length请求长度(包括请求行,请求头和请求体)
$request_time请求处理时长,单位为秒,精度为毫秒,从读入客户端的第一个字节开始,直到把最后一个字符发送给客户端进行日志写入为止
$time_iso8601标准格式的本地时间,形如“2017-05-24T18:31:27+08:00”
$remote_addr客户端IP
$request完整的原始请求行,如 “GET / HTTP/1.1”
$request_uri完整的请求地址,如 “https://baidu.com”

2. 日志配置案例

下面我们按照生产环境的日志标准配置一个样例,包括请求时间、地址、加密算法、响应时长、请求体大小等信息

log_format main escape=json '{"@timestamp":"$time_iso8601",'
                '"remote_addr":"$remote_addr",'
                '"remote_user":"$remote_user",'
                '"http_host":"$http_host",'
                '"uri":"$uri",'
                '"http_referer":"$http_referer",'
                '"ssl_protocol":"$ssl_protocol",'
                '"ssl_cipher":"$ssl_cipher",'
                '"http_x_forwarded_for":"$http_x_forwarded_for",'
                '"upstream_addr":"$upstream_addr",'
                '"bytes":$body_bytes_sent,'
                '"request":"$request",'
                '"request_length":$request_length,'
                '"request_time":$request_time,'
                '"upstream_status":$upstream_status,'
                '"upstream_header_time":$upstream_header_time,'
                '"upstream_response_time":$upstream_response_time,'
                '"status":"$status",'
                '"http_referer":"$http_referer",'
                '"http_user_agent":"$http_user_agent"'
                '}';
 access_log  /var/log/nginx/access.log  main;

配置好记得重启,让配置生效

# 检查语法
nginx -t
# 重启
nginx -s reload

输出样式:
可以看到日志就以json格式的形式输出了
在这里插入图片描述

3. 日志记录自定义请求头

某些场景下,我们需要打印自定义的请求头,比如设置请求头参数为这次请求的流水号,这样将其打印后,我们就能快速定位到这笔请求的nginx日志了

1、而打印也很简单,就直接在日志格式里添加上这个header即可,如下添加一个自定义header:http_x_seqno,需要注意的是这里日志中引用的header变量,需要是原来的请求头名称小写,并且前面加上"http_“,比如请求头是"x_seqno”, 那么这里配置的就是"$http_x_seqno"

log_format main escape=json '{"@timestamp":"$time_iso8601",'
                '"http_user_agent":"$http_user_agent",'
                  '""http_x_seqno":"$http_x_seqno"'
                '}';
 access_log  /var/log/nginx/access.log  main;

2、如果这里直接重启访问,会发现日志并不会打印该header值,这是因为我们还需要在http或server模块中开启underscores_in_headers,以此支持读取下划线header

underscores_in_headers on; # 下划线支持,开启自定义header

在这里插入图片描述
然后重启nginx,测试访问
在这里插入图片描述
日志中会发现该header已经打印
在这里插入图片描述

4. 总结

如上,我们就掌握了关于nginx的访问日志的自定义,但还有一个问题,就是nginx的日志文件是一个,没有按天分割,时间一长,那么这个文件就会很大,影响我们维护阅读。于是如何实现nginx日志文件的按天分割呢?

以下提供几种思路,大家可以自己拓展:

  • 1、借助脚本实现,通过编写脚本,通过mv指令将日志文件迁移到有带日期名的日志文件,该脚本添加到linux每日定时任务中
  • 2、使用cronlog工具实现
  • 3、使用Logrotate工具实现

尽量避免使用通过在nginx http模块用map定义变量,然后声明日志文件名,或者其他类似的通过nginx本身变量声明而修改日志文件名的形式,因为这样每次请求进来都要进行判断,影响性能。

文章来源:https://blog.csdn.net/qq_24950043/article/details/135087483
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。