[date: 2018-07-24 00:57] [visits: 6]

从文本日志中提取信息

上一篇文章讲述了自己的一次性能优化经历,其中有提到由于系统没有监控模块,故障后只能从访问日志中提取信息,这次我就跟大家分享一下从文本访问日志中提取信息的小技巧。

主要是借助Linux shell中强大的管道功能以及文本处理工具cat、grep、sed、awk等,我忘了自己是何时喜欢上这种复古的方式和工具,但在用的时候是真心感叹Linux以及老一辈程序员的伟大。给大家推荐一本书:《Unix编程艺术》,里面讲了Unix文化、哲学等通用主题,很老很古典。

日志格式

访问日志是自己输出的,其格式如下:

{date} {time} {ip} {method} {url} {code} {delay}

示例:

2018-07-23 22:00:00 14.16.177.102 PUT /fsfl/api/client/user/update 200 7ms
2018-07-23 22:00:00 27.187.169.116 GET /fsfl/api/client/user/detail 200 8ms
2018-07-23 22:00:00 122.243.239.240 GET /fsfl/api/client/star/time-history 200 2ms

后面所有的操作命令皆是以此格式的日志文件作为输入,文件名叫access.log

访问量

从日志文件中统计访问量是最简单的,只需一行命令:

cat access.log |wc -l

cat用来将整个文本文件输出到标准输出,wc用来统计文本文件的行数、字符数信息等,在这里用一个管道连起来并使用l参数,得到的就是access.log文件的行数,即访问量

某一日的访问数:

cat access.log |grep '2018-07-15' |wc -l

grep主要用来对文本文件进行按行过滤,这里体现的是其管道用法,匹配access.log中的指定日期行,然后经过wc -l的到就是2018-07-15这一天的访问量

峰值QPS

统计QPS峰值主要是借助awk这个老古董,如统计2018-07-15日18-19点时段的峰值QPS:

cat access.log |grep '2018-07-15 18' |awk '{count[$2]++} END {for(i in count) {print i,count[i] |"sort -r -n -k 2"}}' |head -n 5

这些命令真要详细介绍,每一个估计都可以写一篇或几篇文章,所以都略过吧...

输出结果:

18:02:50 12
18:24:52 11
18:37:06 10
18:48:26 10
18:52:37 10

这命令随便改一下就可统计一天的QPS峰值,具体输出几行也是一个参数而已,有兴趣的朋友去学一学Linux下这些文本处理工具,保你不后悔。

平均响应时长与超过1s的数量

依旧是awk,统计2018-07-15日18-19点时段的平均响应时长与超过1s的数量:

cat access.log |grep '2018-07-15 18' |awk '{print $7}' |sed s/ms// |awk '{sum += $1; if($1 > 1000) {timeout += 1}} END {print "avg:", sum/NR, ":", timeout, timeout/NR}'

不解释,感兴趣的朋友去搜索每个命令进行学习

输出结果:

avg: 23.4577
timeout: 4 0.0005097

这里把对时间的grep改一下可以变成按URL统计,非常方便。

非200的请求

非200的请求,一般是出错请求,这里也可以写成4xx或者5xx的匹配模式,随你发挥,以下命令统计18-19点时间段非200的请求数:

cat access.log |grep '2018-07-15 18' |awk '{print $6}' |grep -v 200 |wc -l

grep -v,即--invert-match,过滤不匹配的行

访问前十的URl

不多说,上命令:

cat access.log |awk '{print $5}' |awk '{count[$1]++} END {for(i in count) {print i, count[i] |"sort -r -n -k 2"}}' |head -n 10

输出结果:

/fsfl/api/client/user/detail 292348
/fsfl/api/client/user/update 99994
/fsfl/api/client/complex/home?size=50 98038
/fsfl/api/client/star/time-history 73024
/fsfl/api/client/star/week-items?page=0&size=20 66190
/fsfl/api/client/star/week-detail/16523?size=20 49272
/fsfl/api/client/user/check-state 41542
/fsfl/api/client/user/check-in 32022
/fsfl/api/client/star/support/16523 30603
/fsfl/api/client/user/share-award 27524

总结

不难发现,上面的命令基本上是在用同一种方式在提取信息,也就是cat、grep、sed、awk组合运用,真尼玛优雅,这篇文章的作用就是展示一下Linux下这些古董遗留的力量,祝大家have fun。

后记

上面的过程再优雅也还是较繁琐,尤其是在运用不熟练的情况下,所以在文章写完后再给大家推荐一个小工具:goaccess,也是用来从日志中提取各种信息,但用起来相对简单,不用那么繁琐,而且它会把信息以各种可能的方式展示出来,当你发现它没有呈现给你想要的数据时,再考虑用原始的方式去提取。

goaccess使用示例:

goaccess -f access.log --date-format='%d/%b/%Y' --time-format='%H:%M:%S' --log-format='%h %^ %^ [%d:%t %^] "%r" %s %b "%R" "%u"' > report.html

这里是对nginx的默认访问日志提取,完成后打开report.html,你会吃惊的

这里涉及date format、time format以及log format的指定,针对不同的日志格式可能需要做些小修改,具体内容可以自行搜索。