通常,日志文件都是文本格式,其中的内容是非结构化的文本串。这就使得我们查询日志信息时,一般只能使用文本编辑软件的搜索功能,输入关键字后,靠眼力去侦查每处匹配结果。在日志量不大,或者只是偶尔查一下时,这么操作倒也无妨。不过,再简单的事情也怕多次重复。如果需要频繁查询,量变就可能引起质变。如果每次还都要靠人工搜索,那么就算有再好的视力,也会有头晕目眩的时候。因此,想要轻松查询日志,就必须找到一款合适的工具,有了合适的工具,就可以一边喝着咖啡,一边轻弹条件回车就行了。
工具里面,首先想到的,就是利用各种计算机开发语言,外加关系数据库。但这类工具开发过程繁琐,还需要准备好多工作环境,包括配置语言开发环境,安装数据库服务,安装数据库查询应用等。
对于这么“重”的方案,我们果断撇开。因为今天就要介绍一个轻巧方便的工具——集算器,利用集算器,可以将文本日志变成结构化数据,然后就可以使用我们熟悉的 SQL 式查询了。
这里,我们利用到了集算语言 (Structured Process Language,简称 SPL) 的两大优点:
- 将日志内容结构化为数据表结构,SPL 远比常用开发语言简单、易用、直观。
- SPL 支持直接对结构化的文件进行 SQL 查询,不再需要安装配置第三方数据库软件。
下面就是具体的实施过程。
1、日志结构分析
不同的日志文件,其内容格式五花八门,每一个看上去都杂乱无章。但对于某个特定的具体的日志来说,它一定会有它自己的结构。拿到日志文件后,首先要做的就是分析日志内容,提炼数据结构,总结出可以结构化的字段。
作为示例,我们用腾讯视频软件下的一个启动日志来做案例。如果你也用过腾讯视频,就可以利用下面的代码来体验和学习,分析一下自己的使用行为了。这个日志文件,位于当前用户的 AppData 路径下,并且以 QQLive.exe[Main] 开头。在我的机器上,这个文件就是:
C:\Users\[Joancy]\AppData\Roaming\Tencent\QQLive\Log\QQLive.exe[Main][2018-8-3 21-5-35-557][12164].log
上述路径中 [Joancy] 是我的 Windows 登录用户名,在你的机器中,将会是你的用户名。QQLive.exe[Main]开头的日志文件有很多,随便取一个就可以。
下面就是这个日志文件中的两行:
[18-07-19 14:35:06][9416]-[31ms][QQLiveMainModule.dll][CQQLiveModule::ParsCommandLine] cmd=”C:\Program Files (x86)\Tencent\QQLive\QQLive.exe” -system_startup
[18-07-19 14:35:08][9416]-[2266ms][HttpModule.dll][CDownloadMgr::AddTask]keyid = 1,url = http://182.254.116.117/d?dn=vv.video.qq.com.&ttl=1
可以看到,这个日志的内容比较规整,一行一条记录。每行中一对中括号中的内容为一节,对应一个字段。只是最后的两节有点特殊,其中倒数第二节可以省略,而最后一节没用中括号括起来。这样,我们就可以整理出日志表的数据结构如下,并且把第一行内容作为对应的示例:
字段名 | 类型 | 分节内容 | |
---|---|---|---|
1 | 记录时间 | DateTime | [18-07-19 14:35:06] |
2 | 线程编号 | Integer | [9416] |
3 | 加载时刻 | Integer | [31ms] |
4 | 加载模块 | String | [QQLiveMainModule.dll] |
5 | 加载函数 | String | [CQQLiveModule::ParsCommandLine] |
6 | 日志内容 | String | cmd=”C:\Program Files (x86)\Tencent\QQLive\QQLive.exe” -system_startup |
表(1)
解析各个字段时,需要注意:
1) 记录时间: 由于年份只有两位,所以在转成日期时间类型时,需要指定相匹配的日期格式,否则 18 就会被当成公元 18 年,而不是 2018 年了。具体的操作方法是打开集算器菜单中的选项,在弹出的窗口中点击环境页面,设置属性‘日期时间格式’为‘yy-MM-dd HH??ss’。
2) 加载时刻: 描述的是程序自从启动后,当前模块从启动后历经的毫秒数。由于字串后面有单位‘ms’,因此需要在转换为整数前先去掉这个单位。
3) 加载函数: 这个字段不一定有,所以需要在分析结构时进行判断,没有该字段时,需要插入空值。
2、结构化实施
如果采用数据库来存储结构化后的日志数据,首先需要安装和配置数据库,然后安装合适的数据库查询应用程序,这个过程可能会比较麻烦。如果利用现成的生产数据库,那么首先可能更新不方便,其次更重要的,会影响生产系统的性能。
而利用集算器,由于 SPL 支持直接对结构化的文件进行 SQL 查询,那就简单了,只需将结构化后的内容保存到文件就行了。
下面开始编程。在集算器设计器中,新建文件,设定它的网格参数为‘fileName’,用于指定需要转换的日志文件,然后把文件保存为 convert.dfx。具体的实现脚本如下:
A | B | C | D | |
---|---|---|---|---|
1 | =create(记录时间, 线程编号, 加载时刻, 加载模块, 加载函数, 日志内容) | |||
2 | =file@s(fileName:”UTF-8″) | =A2.read@n() | ||
3 | for B2 | if len(trim(A3))==0 | next | |
4 | =[] | |||
5 | for 4 | =substr@l(A3,”]”) | >A3=substr(A3,”]”) | |
6 | =substr(C5,”[“) | |||
7 | if B5==3 | >C6=substr@l(C6,”ms”) | ||
8 | =parse(C6) | =B4=B4|C8 | ||
9 | if left(A3,1)==”[“ | =substr@l(A3,”]”) | >A3=substr(A3,”]”) | |
10 | =substr(C9,”[“) | =parse(C10) | ||
11 | =B4=B4|D10 | |||
12 | else | =B4.insert(5,null) | ||
13 | =B4=B4|A3 | |||
14 | >A1.record(B4) | |||
15 | =A2.name |