日志分析
日志分析在web系统中故障排查、性能分析方面有着非常重要的作用。该工具的侧重点不是通常的PV,UV等展示,而是在指定时间段内提供细粒度(最小分钟级别,即一分钟内的日志做抽象和汇总)的异常定位和性能分析。
环境安装
Python 3.4+
pymongo 3.4.0+
MongoDB server
先明确几个术语
指请求中不包含参数的部分; 指原始的请求,包含参数或者无参数; 指请求中的参数部分。(参照nginx中的定义)
和 是指对uri和args进行抽象处理后的字符串(以便分类),例如:
经抽象处理转换为 "/sub/*/*/*", "channel=*&version=*"
特点
提供一个日志分析的总入口:经由此入口,可查看某站点所有 server 产生日志的汇总分析;亦可根据 和 两个维度进行过滤
支持对 requesturi,IP 和 responsecode 进行分析,基于 、 、 三个大维度进行分析;另外不同子项又各有特点
(核心思想)以某一类uri 或其对应的各类args 为维度进行分析,即对 requesturi 进行抽象处理将其分为 uriabs 和 args_abs 两部分
3中提到的抽象归类思想,默认抽象方法可满足大部分需求;另外也提供了定制抽象规则的选项,基于此可灵活指定请求中的任何部分是否要抽象处理
requesturi 分析能直观展示哪类请求数量多、哪类请求耗时多、哪类请求占流量;另外可展示某一类请求在不同粒度里(minute, tenmin, hour, day)各指标随时间的分布变化;也可以针对某一 uriabs 分析其不同 argsabs 各指标的分布
IP 分析将所有请求分为3种来源(fromcdn/proxy, fromreverseproxy, fromclientdirectly),三种来源各自展示其访问量前 N 的 IP 地址;并且可展示某一 IP 访问的各指标随时间的分布;也可针对某一 IP 分析其产生的不同 uriabs 各指标的分布
通过4分位数概念以实现对 和 更准确的描述,因为对于日志中的响应时间,算数平均值的参考意义不大
高性能:本着谁产生的日志谁处理的思想,日志分析脚本loganalyse要在web服务器上定时运行,因而loganalyse的高效率低资源也是重中之重。经测试,在笔者的服务器上(磁盘:3*7200rpm组RAID5,千兆局域网),对于不同的日志文件,处理速度在20000行/s~30000行/s之间
实现思路
分析脚本( )部署到各台 web server,并通过 crontab 设置定时运行。 利用python的re模块通过正则表达式对日志进行分析处理,取得 、 、 、 、 、 、 等信息并进行初步加工然后存储进MongoDB。查看脚本( )作为入口即可对所有web server的日志进行分析查看,至于实时性,取决于web server上 脚本的执行频率。
前提规范
日志格式决定了代码中的正则表达式,是可根据自己情况参考 中的正则定义进行定制的)。项目中预定义的日志格式对应如下:
对于其他格式的 nginx 日志或者 Apache 日志,按照如上原则,稍作就可以使用该工具分析处理。
对于异常日志的处理
如果想靠空格或双引号来分割各段的话,主要问题是面对各种不规范的记录时(原因不一而足,而且也是样式繁多),无法做到将各种异常都考虑在内,所以项目中采用了 模块而不是简单的 函数的原因。代码里对一些“可以容忍”的异常记录通过一些判断逻辑予以处理;对于“无法容忍”的异常记录则返回空字符串并将日志记录于文件。
其实对于上述的这些不规范的请求,最好的办法是在nginx中定义日志格式时,用一个特殊字符作为分隔符,例如“|”。这样就不需要re模块,直接字符串分割就能正确的获取到各段(性能会好些)。
log_show.py使用说明:
帮助信息
所有示例均可通过 , , 参数对 和 进行过滤
request子命令
对指定站点今日已入库的数据进行分析
通过上例可观察指定时间内(默认当天0时至当前时间)hits/bytes/time三个维度的排名以及响应时间和响应大小的分布情况。例如,看到某个uriabs只有比较少的hits确产生了比较大的bytes或耗费了较多的time,那么该uriabs是否值得关注一下呢。
ip子命令
显示基于ip地址的分析结果
IP分析的思想是将请求按来源归为三大类:Fromcdn/Proxy,Fromreverseproxy,Fromclient_directly,然后各自分类内按请求次数对IP地址进行排序
distribution 子命令
对 “所有request” 或 “指定uri/request_uri” 按 “分/十分/时/天” 为粒度进行聚合统计
对 “指定IP” 按 “分/十分/时/天” 为粒度进行聚合统计
适用场景:查看request/IP随时间在各聚合粒度内各项指标的变化情况,例如针对某个uri发现其请求数(或带宽)变大,则可通过 子命令观察是某一段时间突然变大呢,还是比较平稳的变大
通过上例,可展示"/view/*/*.json"在指定时间段内的分布情况,包括hits/bytes/time总量以及每个粒度内个指标相对于总量的占比;该子命令亦能展示各指标随时间的“趋势”。
说明: minute字段为指定的聚合(group)粒度,1803091654 表示“18年03月09日16时54分”
可通过 参数指定聚合的粒度(minute/tenmin/hour/day)
子命令后可以跟具体的uri/requesturi(显示该uri/request_uri以指定粒度随时间的分布)或不跟uri(显示所有请求以指定粒度随时间的分布)
detail 子命令:
对某一uri进行详细分析,查看其不同参数(args)的各项指标分布
对某一IP进行详细分析,查看其产生的请求在不同uri_abs间的分布情
适用场景:比如定位到某一类型的uriabs在某方面(hits/bytes/time)有异常,就可以通过detail子命令对该类uriabs进行更近一步的分析,精确定位到是哪种参数(args_abs)导致的异常;或者观察到某个IP访问异常,可以再深入一下该IP是泛泛的访问呢,还是只对某些uri感兴趣。
通过上例可观察到"/recommend/update"这个uri所对应的不同参数各个指标的情况。另外还有一个附带的发现:开发在书写参数时相同的参数组合没有按同一个顺序书写,虽不影响功能,但在精准的进行应用性能监控的时候会造成一定困扰。
说明: 子命令后跟随uri(不含参数,含参数的话将忽略参数)
loganalyse.py部署说明:该脚本的设计目标是将其放到web server的的计划任务里,定时(例如每30分钟或10分钟,自定义)执行,在需要时通过logshow.py进行分析即可。
Note
其中 和 是对uri和args进行抽象化(抽象出特定的请求模式,即将请求分类看待)处理之后的结果,默认规则如下
uri:将request_uri以"/"和"."分割为几段,若某一段全部由数字组成则将其抽象为一个"*"
args:将所有的value替换成"*"
中还有一些其他有趣的函数
本文作者
❈
jkklee,6年运维老司机一枚,擅长复杂场景下的故障排查,性能优化。目前比较侧重于将自己这些年的运维积累转化成通用易用的各种工具,希望能帮到更多的运维同胞。
本文项目GitHub地址,欢迎star和fork:
https://github.com/jkklee/web_log_analyse
❈
领取专属 10元无门槛券
私享最新 技术干货