Python老司机带你快速搞定日志分析工具
标题说明一切,原文地址:jkklee/web_log_analyse,觉得文章不错请给原作者一个star哦~
日志分析在web系统中故障排查、性能分析方面有着非常重要的作用。该工具的侧重点不是通常的PV,UV等展示,而是在指定时间段内提供细粒度(最小分钟级别,即一分钟内的日志做抽象和汇总)的异常定位和性能分析。
更多Python视频、源码、资料加群531509025免费获取
环境安装
- Python 3.4+
- pymongo 3.4.0+
- MongoDB server
先明确几个术语
uri
指请求中不包含参数的部分; request_uri
指原始的请求,包含参数或者无参数; args
指请求中的参数部分。(参照nginx中的定义)
uri_abs
和 args_abs
是指对uri和args进行抽象处理后的字符串(以便分类),例如:
"/sub/0/100414/4070?channel=ios&version=1.4.5"
经抽象处理转换为 uri_abs:
"/sub/*/*/*", args_abs:
"channel=*&version=*"
特点
- 提供一个日志分析的总入口:经由此入口,可查看某站点所有 server 产生日志的汇总分析;亦可根据
时间段
和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之间
实现思路
分析脚本( log_analyse.py
)部署到各台 web server,并通过 crontab 设置定时运行。 log_analyse.py
利用python的re模块通过正则表达式对日志进行分析处理,取得 uri
、 args
、 时间当前
、 状态码
、 响应大小
、 响应时间
、 server name
等信息并进行初步加工然后存储进MongoDB。查看脚本( log_show.py
)作为入口即可对所有web server的日志进行分析查看,至于实时性,取决于web server上 log_analyse.py
脚本的执行频率。
前提规范
- 各台server的日志文件按统一路径存放
- 日志格式、日志命名规则保持一致(代码中规定格式为xxx.access.log)
- 每天的0点日志切割
日志格式决定了代码中的正则表达式,是可根据自己情况参考 analyse_config.py
中的正则定义进行定制的)。项目中预定义的日志格式对应如下:
log_format access '$remote_addr - [$time_local] "$request" '
'$status $body_bytes_sent $request_time "$http_referer" '
'"$http_user_agent" - $http_x_forwarded_for';
对于其他格式的 nginx 日志或者 Apache 日志,按照如上原则,稍作就可以使用该工具分析处理。
对于异常日志的处理
如果想靠空格或双引号来分割各段的话,主要问题是面对各种不规范的记录时(原因不一而足,而且也是样式繁多),无法做到将各种异常都考虑在内,所以项目中采用了 re
模块而不是简单的 split()
函数的原因。代码里对一些“可以容忍”的异常记录通过一些判断逻辑予以处理;对于“无法容忍”的异常记录则返回空字符串并将日志记录于文件。
其实对于上述的这些不规范的请求,最好的办法是在nginx中定义日志格式时,用一个特殊字符作为分隔符,例如“|”。这样就不需要re模块,直接字符串分割就能正确的获取到各段(性能会好些)。
log_show.py使用说明:
帮助信息
[ljk@demo ~]$ log_show --help
Usage:log_show <site_name> [options] request [distribution [<request>]|detail <uri>]log_show <site_name> [options] ip [distribution <ip>|detail <ip>]log_show <site_name> [options] error [distribution <error_code>|detail <error_code>]
Options:
-h --help Show this screen.
-f --from <start_time> Start time. Format: %y%m%d[%H[%M]], %H and %M is optional
-t --to <end_time> End time. Format is same as --from
-l --limit <num> Number of lines in output, 0 means no limit. [default: 5]
-s --server <server> Web server hostname
-g --group_by <group_by> Group by every minute, every ten minutes, every hour or every day,valid values: "minute", "ten_min", "hour", "day". [default: hour]distribution Show distribution(about hits,bytes,time,etc) of:all or specific 'request', the specific 'ip', the specific 'error_code' in every period.
Period is specific by --group_bydetail Show details of:detail 'args' analyse of the specific 'uri'(if it has args);detail 'uri' analyse of the specific 'ip' or 'error_code'
Notice: it's best to put 'request_uri', 'uri' and 'ip' in quotation marks.
所有示例均可通过 -f
, -t
, -s
参数对 起始时间
和 指定server
进行过滤
request子命令
对指定站点今日已入库的数据进行分析
[ljk@demo ~]$ log_show api request -l 3
====================
Total_hits:999205 invalid_hits:581
====================hits percent time_distribution(s) bytes_distribution(B) uri_abs
430210 43.06% %25<0.01 %50<0.03 %75<0.06 %100<2.82 %25<42 %50<61 %75<63 %100<155 /api/record/getR
183367 18.35% %25<0.02 %50<0.03 %75<0.06 %100<1.73 %25<34 %50<196 %75<221 %100<344 /api/getR/com/*/*/*
102299 10.24% %25<0.02 %50<0.02 %75<0.05 %100<1.77 %25<3263 %50<3862 %75<3982 %100<4512 /view/*/*/*/*.js
====================
Total_bytes:1.91 GB
====================bytes percent time_distribution(s) bytes_distribution(B) uri_abs1.23 GB 64.61% %25<0.03 %50<0.04 %75<0.1 %100<1.96 %25<2549 %50<17296 %75<31054 %100<691666 /api/NewCom/list
319.05 MB 16.32% %25<0.02 %50<0.02 %75<0.05 %100<1.77 %25<3263 %50<3862 %75<3982 %100<4512 /view/*/*/*/*.js
167.12 MB 8.55% %25<0.15 %50<0.19 %75<0.55 %100<2.93 %25<2791 %50<3078 %75<3213 %100<11327 /api/getR/com/*/*
====================
Total_time:117048s
====================
cum. time percent time_distribution(s) bytes_distribution(B) uri_abs
38747 33.10% %25<0.01 %50<0.03 %75<0.06 %100<2.82 %25<42 %50<61 %75<63 %100<155 /api/record/getR
22092 18.87% %25<0.02 %50<0.03 %75<0.06 %100<1.73 %25<34 %50<196 %75<221 %100<344 /api/getR/com/*/*/*
17959 15.34% %25<0.15 %50<0.19 %75<0.55 %100<2.93 %25<2791 %50<3078 %75<3213 %100<11327 /api/getRInfo/com/*/*
通过上例可观察指定时间内(默认当天0时至当前时间)hits/bytes/time三个维度的排名以及响应时间和响应大小的分布情况。例如,看到某个uriabs只有比较少的hits确产生了比较大的bytes或耗费了较多的time,那么该uriabs是否值得关注一下呢。
ip子命令
显示基于ip地址的分析结果
[ljk@demo ~]$ log_show.py api ip -l 2
====================
From_cdn/Proxy: hits hits(%) bytes bytes(%) time(%)
==================== 199870 99.94 570.51 MB 99.99 99.99
Last_cdn_ipxxx.57.xxx.189 1914 0.96 696.18 KB 0.12 0.68xxx.206.xxx.154 1741 0.87 1.56 MB 0.27 0.98
User_ip_via_cdnxxx.249.xxx.56 787 0.39 154.82 KB 0.03 0.23xxx.60.xxx.86 183 0.09 1.05 MB 0.18 0.13
====================
From_reverse_proxy: hits hits(%) bytes bytes(%) time(%)
==================== 66 0.03 68.83 KB 0.01 0.01
User_ip_via_proxyxxx.188.xxx.21 2 0.00 1.53 KB 0.00 0.00xxx.5.xxx.4 2 0.00 324.00 B 0.00 0.00
====================
From_client_directly: hits hits(%) bytes bytes(%) time(%)
==================== 64 0.03 8.32 KB 0.00 0.00
Remote_addr
192.168.1.202 29 0.01 58.00 B 0.00 0.00
192.168.1.200 29 0.01 58.00 B 0.00 0.00
IP分析的思想是将请求按来源归为三大类:Fromcdn/Proxy,Fromreverseproxy,Fromclient_directly,然后各自分类内按请求次数对IP地址进行排序
distribution 子命令
- 对 “所有request” 或 “指定uri/request_uri” 按 “分/十分/时/天” 为粒度进行聚合统计
- 对 “指定IP” 按 “分/十分/时/天” 为粒度进行聚合统计
适用场景:查看request/IP随时间在各聚合粒度内各项指标的变化情况,例如针对某个uri发现其请求数(或带宽)变大,则可通过 distribution
子命令观察是某一段时间突然变大呢,还是比较平稳的变大
# 示例1: 分析指定request的分布情况, 指定按minute进行分组聚合, 默认显示5行
[ljk@demo ~]$ python log_show.py api request distribution "/view/*/*.json" -g minute
====================
uri_abs: /view/*/*.json
Total_hits: 17130 Total_bytes: 23.92 MB
====================minute hits hits(%) bytes bytes(%) time_distribution(s) bytes_distribution(B)
1803091654 1543 9.01% 2.15 MB 8.98% %25<0.03 %50<0.03 %75<0.05 %100<1.07 %25<1532 %50<1593 %75<1645 %100<1982
1803091655 1527 8.91% 2.13 MB 8.88% %25<0.03 %50<0.04 %75<0.05 %100<1.04 %25<1538 %50<1592 %75<1642 %100<2143
1803091656 1464 8.55% 2.05 MB 8.57% %25<0.03 %50<0.04 %75<0.05 %100<1.03 %25<1536 %50<1592 %75<1642 %100<1952
1803091657 1551 9.05% 2.15 MB 8.97% %25<0.02 %50<0.03 %75<0.04 %100<0.89 %25<1534 %50<1594 %75<1639 %100<1977
1803091658 1458 8.51% 2.06 MB 8.61% %25<0.02 %50<0.03 %75<0.04 %100<2.35 %25<1540 %50<1596 %75<1644 %100<2146
通过上例,可展示"/view/*/*.json"在指定时间段内的分布情况,包括hits/bytes/time总量以及每个粒度内个指标相对于总量的占比;该子命令亦能展示各指标随时间的“趋势”。
说明: minute字段为指定的聚合(group)粒度,1803091654 表示“18年03月09日16时54分”
可通过 -g
参数指定聚合的粒度(minute/tenmin/hour/day)
distribution
子命令后可以跟具体的uri/requesturi(显示该uri/request_uri以指定粒度随时间的分布)或不跟uri(显示所有请求以指定粒度随时间的分布)
# 示例2: 分析指定IP产生的请求数/带宽随时间分布情况, 默认聚合粒度为hour
[ljk@demo ~]$ python log_show.py api ip -t 180314 distribution "140.206.109.174" -l 0
====================
IP: 140.206.109.174
Total_hits: 10999 Total_bytes: 4.83 MB
====================hour hits hits(%) bytes bytes(%)
18031306 1273 11.57% 765.40 KB 15.47%
18031307 2133 19.39% 1004.74 KB 20.31%
18031308 2211 20.10% 1.00 MB 20.74%
18031309 2334 21.22% 1.05 MB 21.72%
18031310 2421 22.01% 850.79 KB 17.20%
18031311 627 5.70% 226.30 KB 4.57%
说明: hour字段表示默认的聚合粒度,18031306表示“18年03月13日06时”
-l 0 表示不限制输出行数(即输出所有结果)
detail 子命令:
- 对某一uri进行详细分析,查看其不同参数(args)的各项指标分布
- 对某一IP进行详细分析,查看其产生的请求在不同uri_abs间的分布情
适用场景:比如定位到某一类型的uriabs在某方面(hits/bytes/time)有异常,就可以通过detail子命令对该类uriabs进行更近一步的分析,精确定位到是哪种参数(args_abs)导致的异常;或者观察到某个IP访问异常,可以再深入一下该IP是泛泛的访问呢,还是只对某些uri感兴趣。
# 示例1:
[ljk@demo ~]$ python log_show.py api -f 180201 request detail "/recommend/update" -l 3
====================
uri_abs: /recommend/batchUpdate
Total_hits: 10069 Total_bytes: 7.62 MB
====================hits hits(%) bytes bytes(%) time(%) time_distribution(s) bytes_distribution(B) args_abs
4568 45.37% 3.46 MB 45.44% 47.96% %25<0.04 %50<0.06 %75<0.07 %100<0.47 %25<755 %50<795 %75<845 %100<1484 uid=*&category_id=*&channel=*&version=*
4333 43.03% 3.25 MB 42.64% 42.30% %25<0.03 %50<0.05 %75<0.07 %100<0.48 %25<752 %50<791 %75<840 %100<1447 category_id=*&channel=*&uid=*&version=*
389 3.86% 314.15 KB 4.03% 0.88% %25<0.02 %50<0.03 %75<0.04 %100<0.06 %25<766 %50<802 %75<850 %100<1203 category_id=*&channel=*&version=*
通过上例可观察到"/recommend/update"这个uri所对应的不同参数各个指标的情况。另外还有一个附带的发现:开发在书写参数时相同的参数组合没有按同一个顺序书写,虽不影响功能,但在精准的进行应用性能监控的时候会造成一定困扰。
说明: detail
子命令后跟随uri(不含参数,含参数的话将忽略参数)
# 示例2: 观察某个IP分别产生了多少种请求, 每种请求的(hits/bytes/time)指标
[ljk@demo ~]$ python log_show.py m -t 180314 ip detail "1.2.3.4"
====================
IP: 140.206.109.174
Total_hits: 10999 Total_bytes: 4.83 MB
====================hits hits(%) bytes bytes(%) time(%) uri_abs
10536 95.79% 405.47 KB 8.19% 92.01% /introduction/watch
147 1.34% 1.90 MB 39.31% 1.93% /view/*/*.html138 1.25% 407.42 KB 8.23% 2.41% /chapinfo/*/*.html
42 0.38% 644.88 KB 13.03% 1.38% /info/*.html
30 0.27% 229.98 KB 4.65% 1.14% /classify/*.json
loganalyse.py部署说明: 该脚本的设计目标是将其放到web server的的计划任务里,定时(例如每30分钟或10分钟,自定义)执行,在需要时通过logshow.py进行分析即可。
*/15 * * * * export LANG=zh_CN.UTF-8;python3 /home/ljk/log_analyse.py &> /tmp/log_analyse.log
Note
- 其中
uri_abs
和args_abs
是对uri和args进行抽象化(抽象出特定的请求模式,即将请求分类看待)处理之后的结果,默认规则如下
uri:将request_uri以"/"和"."分割为几段,若某一段全部由数字组成则将其抽象为一个"*"
args:将所有的value替换成"*" common/common.py
中还有一些其他有趣的函数
Python老司机带你快速搞定日志分析工具相关推荐
- 苹果怎么批量删除联系人?老司机带你轻松搞定!
苹果怎么批量删除联系人?很多刚刚换到苹果手机的人都会有这样的疑惑,苹果手机删除联系人的时候不能多选,每次删除多个联系人都要一个个手动删除,非常麻烦,有什么简便方法来批量删除联系人么?答案当然是有的,今 ...
- 老司机带你快速实现Python下载与安装
目录 一.新手下载与安装Python的步骤: 二.老司机下载与安装Python的步骤: 先来看一下新手是怎么下载安装的: 一.新手下载与安装Python的步骤: 1.打开Python官网:https: ...
- 用 Python 帮运营妹纸快速搞定 Excel 文档
Microsoft Office 被广泛用于商务和运营分析中, 其中 Excel 尤其受欢迎.Excel 可以用于存储表格数据.创建报告.图形趋势等.在深入研究用 Python 处理 Excel 文档 ...
- 老司机带你快速熟悉Swift 4.1(一)
简单学 1.我的第一个Swift程序 传统表明,用新语言编写的第一个程序应该在屏幕上打印"Hello,world!".在Swift中,这可以在一行中完成: 在Swift中,这行代码 ...
- python老司机带你玩玩炫酷的3D渲染,酷毙了!
自从学会了turtle模块后,画了不少简笔画.像小猪佩奇.哆啦A梦等等,但是这些依然不能让身边人感受到python的强大,依然是每次装逼必被打脸.就像你用turtle画了这个 别人拿出了这个 怎么办? ...
- 金士顿固态硬盘不认盘修复_#原创新人#老司机带你玩转PC,故障之SSD篇 篇一:金士顿 V300 240G SATA3 固态硬盘 丢盘掉速解决记录...
#原创新人#老司机带你玩转PC,故障之SSD篇 篇一:金士顿 V300 240G SATA3 固态硬盘 丢盘掉速解决记录 2016-10-25 11:14:08 12点赞 72收藏 23评论 小编注: ...
- 纵剑仙界一直显示连接服务器,纵剑仙界h5新手指引 老司机带你少走弯路
纵剑仙界h5新手指引,老司机带你少走弯路.新手初来乍到,不知道该做什么怎么办?别怕!让小编来手把手教你玩转纵剑仙界! 在<纵剑仙界>手游中,等级是一个非常重要的因素.除了转生.装备高阶装备 ...
- 怎么做95置信区间图_这种动态的OD图怎么做?简单3步快速搞定
之前在视频号中发过一个单车的出行数据可视化效果. 动态展示了某天单车不同时段的运行情况,这种动态的OD可视化效果是如何制作的呢?使用的是kepler.gl进行制作的,其实非常简单,3步即可快速搞定. ...
- 老司机带你从源码开始撸Spring生命周期!!!
导读 Spring在Java Web方面有着举足轻重的地位,spring的源码设计更是被很多开发者所惊叹,巧妙的设计,精细的构思,都注定他的地位.今天陈某大言不惭的带你来从源码角度解析Spring的生 ...
最新文章
- UIView及其分类的属性方法定义
- 程序员的浪漫:女神节专用开源项目
- 2022年跨境卖家如何布局海外市场?东南亚“钱”景可观
- 上天入海又怎样?阿里的运动达人纷纷表示不服
- 链表之单链表的反转总结
- mr图像翻转的原因_MRI图像常见问题及对策
- webstorm apache设置 很方便啦
- linux 一次执行多条命令
- git(10)---GIT对象模型
- 2020-08-21 第一次面试小结
- 局域网在线计算机扫描仪,局域网内也共享扫描仪
- 家庭电信网弄外网唤醒并远程内网电脑
- 不定积分24个基本公式整理
- DRM2.0 的身份认证过程
- 数据库服务:数据库表空间扩容
- mysql数据库SQL语句介绍
- 2022非常全的接口测试面试题及参考答案-软件测试工程师没有碰到算我输~
- Java接口练习:求圆柱体和圆锥体的表面积和体积
- ToggleSwitch控件介绍
- 失业下的深圳中年:没有人活的容易,生活仍得继续...
热门文章
- 国外人经常上的网站,即全球各个领域最大的互联网网站
- Linux系统 ISO下载
- Html创建动画的基本过程,动画视频制作基本的流程
- 【R语言】使用nnet过程中报错Error in eval(predvars, data, env) : object ‘naulong‘ not found
- 出现You are using pip version 19.0.3, however version 20.0.2 is available.怎么办
- 浏览器DNS解析过程
- JavaWEB(项目分析用户登录发布新闻)
- 豆瓣电台 for WP7 客户端开源
- 罗密欧与朱丽叶的迷宫问题
- MAX7219芯片 共阴LED驱动器 详细介绍