基于SQL的日志分析工具myselect
基本介紹
程序開發者常常要分析程序日志,包括自己打印的日志及使用的其他軟件打印的日志,如php,nginx日志等,linux環境下分析日志有一些內置命令能夠使用,如grep,sort,uniq,awk等,當中最強大的是awk,是作為一門小巧的文本處理語言存在的,但由于它是一門語言,功能強大,但在命令行下使用并不那么方便,由于awk是面向計算而不是面向統計的。awk能夠定義變量,能夠進行計算,命令行下就是一個包括隱式for循環的語言。
awk假設非常長時間不用,它的一些語法就忘了,要分析線上日志時就想假設能用sql分析該多好,確實,sql(結構化查詢語言)是一門真正面向統計的語言,包含HIVE也是用它,于是最近開發了一個基于sql的日志分析器,能夠用類sql語法分析日志,以下稱它為myselect。
myselect是一個簡化日志分析的工具,相信它已經覆蓋了大部分awk能完畢的日志分析功能,當然特殊情況下還是須要用到awk等。myselect把要分析日志文件當成一個數據庫,里面的日志行當作數據庫記錄,從而對里面的日志數據進行統計分析。以下看看myselect與awk等其他命令在使用上的對照。
以分析ngnix日志為例,以下這條日志是我們線上web機器的一條日志
198.52.103.14 - - [29/Jun/2014:00:17:11 +0800] "GET /q/1403060495509100 HTTP/1.1" 200 26788 "http://wenda.so.com/q/1403060495509100" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727)" 221 0.532
第一個字段是IP,假設要知道來源ip最多的是哪些,用 awk等其他命令實現例如以下
$?awk '{ print $1}' accesstest.log | sort | uniq -c | sort -k1nr | less?
14 111.13.65.251?
13 10.141.88.248?
12 10.141.88.239?
10 10.141.88.250?
9 121.226.135.115?
8 10.141.88.241?
8 10.141.88.249?
8 222.74.246.190?
7 211.149.165.150?
6 119.138.167.213
甚至全然單純使用awk都能夠實現以上功能,但有其他更好用的命令這樣顯得不是必需了
myselect怎樣實現以上功能? myselect將日志行看成多個字段,字段間以空格分隔,在雙引號中的全部字符是算作一個字段的,即使當中包含空格,這點與awk純粹以空格分隔是不同的,這使我們處理日志也更方便。能夠通過例如以下命令查看某一日志行各字段值:
$?myselect -s '198.52.103.14 - - [29/Jun/2014:00:17:11 +0800] "GET /q/1403060495509100 HTTP/1.1" 200 26788 "http://wenda.so.com/q/1403060495509100" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727)" 221 0.532'
**log fields**?
$1 ??198.52.103.14?
$2 ??-?
$3 ??-?
$4 ??[29/Jun/2014:00:17:11?
$5 ??+0800]?
$6 ??GET /q/1403060495509100 HTTP/1.1?
$7 ??200?
$8 ??26788?
$9 ??http://wenda.so.com/q/1403060495509100?
$10 ??Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727)?
$11 ??221?
$12 ??0.532
-s選項將日志行各字段值打印出來,接下來能夠依據相應字段進行計算,例如以下
$?myselect 'select count($1),$1 from accesstest.log group by?$1 order by count($1) desc limit 10'?
14 111.13.65.251?
13 10.141.88.248?
12 10.141.88.239?
10 10.141.88.250?
9 121.226.135.115?
8 10.141.88.241?
8 10.141.88.249?
8 222.74.246.190?
7 211.149.165.150?
6 61.174.51.174
結果全然一樣
還有一個經常使用的需求是查看每分鐘的流量,并觀察流量異常的情況,用awk等命令例如以下:
$?awk '{ print gensub(/.*2014:(.+):.*+0800].*/,"\\1","g")}' access_wenda.qihoo.com_log | uniq -c | grep -v Windows | less?
1567 00:17?
1597 00:17?
933 00:18?
3045 00:18?
1605 00:19?
294 00:19?
2021 00:19?
1315 00:20?
666 00:20?
1875 00:20?
3679 00:21?
1172 00:22?
479 00:22?
2094 00:22?
1352 00:23?
51 00:23?
37 00:23
grep -v Windows是為了過濾掉一些亂碼行,在awk我們須要通過gensub獲得子的字段,如這里的分鐘值,而在myselect也有相同的功能的函數regsub($1,pattern,replace),用myselect 完畢相同的需求例如以下:
$?myselect 'select regsub($4, /.*2014:(.+):\d{2}.*/,\1),count($1) from access_wenda.qihoo.com_log group by regsub($4, /.*2014:(.+):\d{2}.*/,\1) order by count($1)desc limit 10'
regsub($4, /.*2014:(.+):\d{2}.*/,\1),我們對第4個字段使用正則獲得分鐘值。
再比方我們要計算網絡請求平均耗時,用awk能夠實現,但過程比較復雜,須要定義變量并進行計算,而用myselect 僅僅須要 利用 avg函數較為簡單計算出來,例如以下
$?myselect 'select avg($12) from access_wenda.qihoo.com_log'
從以上的對照中,能夠發現myselect是以寫sql方法進行統計,不但好記,并且分析思路比較直觀,不像awk須要一堆命令進行配合。
或許你會說把日志放到數據庫再分析也一樣,只是這個過程太麻煩了,不如直接對文件用SQL分析。
myselect 使用
安裝myselect 程序后,能夠查看用法
$?myselect -h?
usage:?
myselect 'sql sentence'; 用 sql進行統計分析?
myselect -s 'log line';對日志行按空格進行切割編號?
myselect -n 'log line' 'sql sentence'; 對日志行用sql進行解析?
myselect -p 'sql sentence'; 查看sql語法解析結果?
myselect -c 'sql sentence'; 查看sql計算過程
統計分析基本使用例如以下
$ myselect 'sql語句'
sql語句語法基本與普通數據庫查詢select語句一致,不區分大寫和小寫(當然,文件名稱是區分大寫和小寫的),支持自由格式,僅僅有小部分不同,我們有理由相信sql語言在統計分析上一定是眼下最優的語言,基本照著它來實現即可了。
sql語句 = SELECT?
select_expr [, select_expr ...]?
[FROM file_name?
[WHERE where_condition]?
[GROUP BY {col_name | expr }?
[HAVING where_condition]?
[ORDER BY {col_name | expr }?
[ASC | DESC]]?
[LIMIT {[offset,] row_count }]
簡單說明例如以下:
select_expr
能夠包含字段編號如$1,$2,字段以空格分隔,也能夠包含函數,函數分兩類?
字符串處理函數:
- strsub($1,2,3) 截取子字符串
- regsub($1,/(.):(.+):(.)/i,\2) 按正則替換子字符串
字符串函數能夠用在不論什么字段能夠出現的地方,它的參數也包含了字段編號
聚合函數:
- count
- sum
- agv
- max
- min
意義與普通sql一樣。
where_condition
用and 連接起來的關系表達式,眼下還不支持or, 支持例如以下的操作符?
=,!=,>,<,>=,<=,like,rlike?
like表示是否包含對應字符串,rlike表示正則匹配對應模式
原計劃myselect用go語言實現,并看了一遍go手冊,但在我們組內技術期刊投稿截止之前的非常短時間里無法用一門剛看的語言來實現它,轉而先用php實現一個了版本號,而且基本可用,眼下實現的php版本號實現了基本的sql select 語句語法,像askeyword及or邏輯操作符還沒有實現,但這不重要。在日志文件非常大時,php實現的版本號在性能以及內存占用上都無法非常好滿足要求,但相信不久就會有go語言實現的高可用版本號。
對于不熟悉awk或一下無法記起awk語法細節的人來說,在須要分析日志時myselect能夠非常好實現我們的需求,sql語言大家都應該是非常熟悉的。
本工具源代碼已放到到了 github ? https://github.com/micweaver/myselect
基本實現算法在里面,接下來要翻譯成go語言實現,go語言能非常好的滿足我們對性能及內存占用的需求,當然極大的日志你要借助于hadoop,hive等分布式計算工具
轉載于:https://www.cnblogs.com/yxwkf/p/3860261.html
總結
以上是生活随笔為你收集整理的基于SQL的日志分析工具myselect的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ci框架(二)
- 下一篇: SQL:认识数据库约束