nginx/tomcat日志格式规范

栏目: 服务器 · Nginx · 发布时间: 7年前

最近准备设计和开发一套日志收集平台,进而后续进行实时的日志分析、业务监控和预警等。在此之前,需要制定日志的格式规范,当然还有其他的约束性规范,才能良好的实现日志搜集、数据分拣、数据分析等特性。

制定日志格式规范的方式与目的:

1)所有项目,日志格式统一,可以极大的简化日志收集和分析的复杂度。

2)nginx、tomcat等日志格式,需要合理,让日志查看和问题排查更加便捷,排除不用的字段信息,增加更多的有效字段。

3)考虑到日志格式将来总会要变化,但是日志数据会被运维、开发、大数据平台、BI、安全等团队共同使用,为了避免日志格式的变化给所有相关团队带来干扰,降低改动的影响面,我们将日志中的字段进行分“域”;每个域包括多个字段,不同的团队关注不同的域,某个域中的字段列表改动时,不影响其他团队对数据的使用。我们解析日志数据时,首先将日志按照域分隔符分成多个"域",然后根据字段在域中的相对位置来获取字段值,而不是使用字段在整条日志的位置。我们使用“^_^”符号作为域分隔符。

4)为了便于数据分拣、日志收集,我们约定所有的日志文件名必须遵循统一规则,这对Flume进行数据搜集非常有利。比如nginx日志、tomcat access log、业务日志等,日志的文件名遵循: . .log. . ;例如:order-center.error.log.2017-10-11.0,其中

为rolling时生成的索引号。统一日志名称的原因是:易于通过文件名了解日志的来源和核心特性,此外对于Flume而言可以从文件名中得知项目的名称、日志等重要信息,既可以在收集时对日志进行按项目、日志进行分类存储。

5)严格控制日志文件的大小,适时对日志文件进行rolling,我们约定任何日志文件的大小不得超过256M,超过此值时应该对日志进行rolling。原因非常简单,较大的日志文件既不便于收集、传输,也不便于进行查看,此外较大的日志还会降低文件IO的效率。在此基础上,我们要求在打印日志时需要对日志信息进行合理规划,尽可能精简日志信息,冗杂而庞大的日志信息不仅价值较低,而且消耗存储,此外较大的日志内容输出还会增加宿主机器的IO负载,毕竟我们的普通的application机器的IOPS通常不高。

6)为了便于日志分拣、日志内容的可读性、本地性,我们在nginx、tomcat等所有日志内容中,都打印“当前机器的IP”、“日志产生的时间戳”等标记信息。

1、nginx日志格式:

log_format  main  '$time_local|$hostname|$remote_addr|$upstream_addr|$request_time|$upstream_response_time|$upstream_connect_time|'

'$status|$upstream_status|-|$bytes_sent|-|-|$remote_user|$request|$http_user_agent|$http_referer|^_^|'

'$scheme|$request_method|$request_trace_id|$request_trace_seq|^_^|'

'$http_x_forwarded_for|$http_Authorization|$cookie_uid';

其中有几个“-”占位符,本人使用nginx 1.10版本,但是有几个非常重要的字段需要等到1.11版本发布后才能使用,所以此处先用“-”占位。

nginx日志格式,本人参考了AWS ELB,我觉得ELB的日志格式还是比较规范,具有较高的参考价值。此处的nginx格式,与ELB日志格式在字段含以上一一对应,对于nginx缺失的字段,先用“-”占位。

我们将nginx日志分为四个域,第一个域包含一些最常用、最重要的字段,通常与性能评估、数据分拣有关系;第二个域表示此次请求的一些状态信息,排查问题时可以关注此域;第三个域,是关于请求追踪的,我们为每个请求设定request_id等(其中$request_trace_id,$request_trace_seq是自定义的变量),此后在业务监控时可以将异常请求的全追踪链整理出来;第四个域,面向开发,通常用于打印一些HTTP参数等。

$request_trace_id和$request_trace_seq是自定义的变量,分别表示“请求的追踪ID”和“请求追踪的序列数字”:

一个新的请求都会有一个唯一的trace_id,此trace_id通常有最顶层proxy负责生成,生成后将会把trace_id添加到header中并传递给upstream层(tomcat等),upstream应用中如果有请求扇出,则继续将此trace_id下发,最终实现请求的链路追踪,我们将链路的追踪信息收集并整理,后期用于评估接口性能、业务监控、流量异常发现、容量规划等。

如果proxy层发现请求的header中已经包含trace_id,那么我们认为此请求是“链路的一个环节”而不是一个新的请求,此时保留trace_id,并添加到header中继续转发。request_trace_seq默认为0,有upstream负责进行维护seq的值,比如每次下发对其值进行自增,nginx不负责此值的自增的原因是希望有应用程序自己决定seq的顺序。

##trace.setting

set$request_trace_id $http_x_request_id;

set $request_trace_seq $http_x_request_req;

if ( $request_trace_id = '' ) {

set$request_trace_id $pid-$connection-$bytes_sent-$msec;

}

if ( $request_trace_seq = '' ) {

set$request_trace_seq 0;

}

....

server {

listen       80;

server_name  demo.com;

include trace.setting;

access_log  /var/log/nginx/demo.log  main;

proxy_send_timeout      1800s;

proxy_read_timeout      1800s;    

location / {

proxy_pass         http://10.0.0.1:8080;

proxy_set_header   Host             $host;

proxy_set_header   X-Request-ID $request_trace_id;

proxy_set_header   X-Request-Seq $request_trace_seq;

}

}

....

字段含义(逐一对应):

字段名                          解释

time_local                   日志时间

hostname                 当前机器的hostname(非IP)

remote_addr                  客户端地址

upstream_addr               后端Server的地址

request_time            nginx处理请求的时长,从获取Client请求的首个字节开始到响应数据发送完毕,单位为“秒 + 毫秒”

upstream_response_time      从nginx与upstream建立连接开始到response数据接收完毕。

upstream_connect_time     与upstream建立连接的时间。

status                  nginx响应状态码

upstream_status        upstream返回给nginx的状态码(tomcat或者后继nginx)

bytes_received         nginx接收到Client的请求数据大小,1.11版本才能支持,此处用“-”占位符替代

bytes_sent               nginx返回给Client的数据大小

upstream_bytes_sent      nginx发送给upstream的字节数,1.11版本才支持,此处使用“-”占位符替代

upstream_bytes_received   nginx接收到upstream响应的字节数,1.11版本才支持,此处使用“-”占位符替代

remote_user            基本认证中的user信息

request                   HTTP请求行—首行

http_user_agent         标头中“User-Agent”值

http_referer              标头中“Referer”值

scheme                  请求的Scheme,HTTP或者HTTPS

request_method            HTTP(S)请求的方法名:GET,POST等

request_trace_id        获取标头中“X-Request-ID”值,如果不包含此header,则创建新的Trace_id。

request_trace_seq       获取标头中“X-Request-Seq”值,如果存在,表明此请求是trace link下发的请求。此值用于追踪请求链的层级或者顺序

http_{key}           获取HEADER中指定key的值。

cookie_{key}          获取COOKIE中指定key的值。

2、Tomcat Access log格式规范

对于JAVA WEB项目,tomcat提供了内置的access日志机制,有点类似于nginx的access日志;在开启时,tomcat会把接收到的请求信息打印在日志中,这对我们分析数据、排查问题、性能检测等有很大帮助。只需要修改server.xml文件即可:

prefix="access.log" suffix="" renameOnRotate="true"

pattern="%{yyyy-MM-dd HH:mm:ss}t|%A|%a|%p|%m|%s|%D|

%b|%{begin:msec}t|%{end:msec}t|^_^|

%{X-Request-ID}i|%{X-Request-Seq}i|^_^|

%S|%r|%{Referer}i|%{User-Agent}i" />

基本原则跟nginx一样,分域,第一个域仍然是关于数据分拣、性能检测相关;第二个域是关于请求追踪的,将来对接追踪链系统;第三个域,是开发关注的,通常是打印一些HTTP 参数等。不过比较遗憾的是,tomcat access日志所能提供的字段信息比较少,没有nginx那么丰富。

此外,为了让access log的文件名称遵循规范要求,我们在prefix和suffix的配置上做了调整。

为了达成请求追踪的目的,我们在tomcat access log中也打印了request_trace_id和seq的相关信息。

3、业务日志格式

我们的 java 程序内部也会打印一些日志,这些日志对问题排查、业务监控、数据统计非常重要,但是这些数据的使用者通常是大数据团队、BI部分、架构团队等,因此规范这些日志的格式至关重要;此外格式统一,对于开发工程师跨团队协作也非常有益。

原则不变:便于数据分拣、分域;不过为了更好的执行,在此之前,我们需要约定日志组件为logback + sl4j;因为我们会使用logback中的MDC机制,来打印更多的运行时信息。

%d{yyyy-MM-dd/HH:mm:ss.SSS}|%X{localIp}|%X{requestId}|%X{requestSeq}|^_^|uid:%X{uid}|^_^|[%t]|%-5level|%logger{50} %line - %m%n

整个过程中,我们将request_id从nginx传递到tomcat,在传递到java应用内部,主要是为后期的请求追踪平台做铺垫,同时我们排查问题也将更加容易。需要注意,%X{requestId}和%X{requestSeq}都是经过MDC Filter进行分装后的。

在第二个域中,允许每个项目自定义各自的日志字段,为K-V模式,比如“uid:10010|orderId:10000”,K-V之间通过“:”分割,此后我们日志分析组件可以将它们解析成map并保存,比如保存在ES中。之所以这么做的原因是,每个业务系统需要打印的自定义字段各有不同,这对后续的数据分析和统计组件有较大的挑战,为了简化后续操作,我们将用户自定义字段部分结构松耦合。

在上文中,我们还提到业务日志的大小问题,这就需要采用一定的rolling策略,我们约定所有项目的logback组件的版本不低于1.1.7,并统一rolling策略:

${LOG_HOME}/order-center.log

${LOG_HOME}/order-center.log.%d{yyyy-MM-dd}.%i

256MB

15

32GB

….

4、基础数据平台规划

1)基于Flume组件,对全网项目的日志文件进行收集,包括历史文件(每天rotate生成的、rolling生成的文件)和实时日志信息(tail);将日志文件统一保存在一个或者多个堡垒机(group server)上,并将日志按照项目、时间进行归类。

2)业务系统通常是分布式部署,一个project部署在多个机器上,每个机器都会产生新的日志信息,如果遇到线上问题,排查期间需要访问多个机器,为了解决这个问题,我们将每个项目实时产生的日志信息,统一汇总在堡垒机上一个文件中,比如:堡垒机上的/order-center/2017-10-11/access.log.tail,此文件保存了order-center项目中2017-10-11,多个tomcat实时的日志,它们混合在一起。

3)Flume将实时日志转发到kafka中,其他数据统计、分析系统通过kafka消费数据。此外我们的Flume将采用“多层”架构设计,每个application宿主机器上部署一个Flume agent,同一个项目的agent将数据发给一个Flume collector(也是一个Flume agent),并统一由collector对日志信息进行分类、本地存储、Filter、以及转发给kafka等。

4)基于storm + kafka对实时日志信息进行分析,并根据规则匹配日志内容,当遇到“业务异常”、“流量异常”等情况是,触发报警,并将相应的信息进行整理,形成traceing link并展示给相关人员。


以上所述就是小编给大家介绍的《nginx/tomcat日志格式规范》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Scalable Internet Architectures

Scalable Internet Architectures

Theo Schlossnagle / Sams Publishing / 2006-7-31 / USD 49.99

As a developer, you are aware of the increasing concern amongst developers and site architects that websites be able to handle the vast number of visitors that flood the Internet on a daily basis. Sc......一起来看看 《Scalable Internet Architectures》 这本书的介绍吧!

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具