项目依赖
在Starter项目里,打开Nuget包管理器,搜索并安装NLog.Targets.Seq(也可以非侵入式依赖,直接拷贝dll文件到对应程序文件夹内也可) 以下两种方式配合修改配置均可引入Seq
Nuget引用NLog.Targets.Seq
在应用位置植入NLog.Targets.Seq.dll
修改NLog.config加入以下配置块
在<nlog>
标签里添加
<extensions>
<add assembly="NLog.Targets.Seq"/>
</extensions>
在<targets>
标签里添加
<target name="seq" xsi:type="BufferingWrapper" bufferSize="1000" flushTimeout="2000">
<target xsi:type="Seq" serverUrl="http://具体IP:5341" apiKey="xxx" />
</target>
在<rules>
标签里添加
<logger name="*" minlevel="Info" writeTo="seq" />
通用词语定义
所有通用key均以小写拼写,多个字母以_分隔(下划线) 约定俗成的key
- app: 具体服务应用(his、mam、mdm等)
- env: 服务环境(dev、test、pre、prod)
基本搜索
搜索表达式
下面介绍常用的搜索方式。
字符串模糊检索
直接输入字符串,所有匹配字符串的都会检索出来,这种写法不会区分大小写。同时支持使用'和”
key检索
通过预先定义好key-value键值对来检索,一般用于区分环境和应用程序。
这里展示了在对应系统的ApiKey位置加入对应的key-value
逻辑运算符
支持常见的逻辑运算符,如and、or、not等,也支持他们的简写语法(command语法)
逻辑运算符 | Command语法 |
---|---|
and | && |
or | || |
not | ! |
同时还支持常见sql运算符
<>、<、<=、>、>=、==、!=
如下图
查询不是his系统的日志
内置属性
Seq支持许多内置属性,像是@Level等
常用属性如下
内置属性名 | 作用 |
---|---|
@Level | 日志级别(Info、Warn、Error等) |
@Timestamp | 日志记录时间,时间戳格式 |
@Message | 日志信息 |
@Exception | 日志如果包含异常信息和堆栈信息,会记录到这里面 |
@Data | 日志结构 |
@Property | 日志附带属性 |
字符串常见检索方式
like和% 这一点与SQL几乎一样,字符串可支持这样检索。
ci 忽略大小写
正则表达式
支持复杂的正则表达式,具体正则表达式可以参考这个链接菜鸟教程-正则表达式
数据类型
Seq支持多种数据类型,如下
- 'single quoted'- 字符串;引号字符可以通过加倍来转义:''Can''t'(两个引号即可转义一个引号,这一点与SQL一致)
- 123, , - 数字,内部表示为 128 位十进制值0.450xc0ffee
- 30d, - 持续时间,像是8h,1h15m,1m15s等等
- true和false,布尔值
- [1, 'test', true]- 具有从零开始的数字索引的数组[0]
- {ace: 1, 'beta gamma': 23}- 带有字符串或标识符键的对象文字,Json对象等
- null,可以检测用于日志是否为空
常用表达式
- IN表达式
用于检索包含在多种数据(数组)的数据
- 条件表达式
Seq同时支持
if then else
的条件语法结构,在后续的Select表达式中常用。
快速筛选同类型日志
在实际日志使用中,我们的日志往往很多是结构化的。如下图。
它们的结构化方式都是RemoveUnhealthyAddress Timer 耗时:{耗时}
如果我们要定位同类型日志时,可以使用EventType(事件类型),在Seq中点开日志详情,即可获取EventType。
可以在Type下点击 Find 来查看这个类型下的所有日志。记录该EventType即可在后续日志查询中使用该EventType快速定位。
使用时间来定位日志
时间戳和日期时间
支持常见的时间戳定位
同时也支持常见的时间格式查询,注意一点,初始未设置的Seq默认时间用的是格林威治时间,换算成北京时要-8h
时间范围和时间运算符
在Seq中支持时间范围标记,Seq的最小单位时是100纳秒(Ticks)
时间范围可以指定为任意整数天 ( d)、小时 (h )、分钟 (m )、秒 (s ) 和毫秒 ( ms),并且这些可以链接在一起以表示更复杂的持续时间,例如.1h30m
例如,之前我们谈到要减8小时变成北京时,就可以在这里操作
同时Seq支持大量的时间运算符和比较符,除了最常见的=之外还有
运算符:+、-、*、/
(常见的加减乘除)
比较符:<>、<、<=、>、>=
(不等于、小于、小于等于、大于、大于等于)
同时还支持获取当前时间,使用方法Now(),例如我这里获取最近1分15秒内的日志
定位Seq时间
有时,Seq时间并不一定就是格林威治时间,我们需要定位Seq服务器的时间。
可以使用Select ToTimeString(Now())
或者Select ToIsoString(Now())
的形式来定位当前Seq时间
可根据Seq时间来决定实际的时间查询方式。
获取具体时区误差 时区代码表参考:维基-时区表
注:北京时间是Asia/Shanghai
由于过于复杂, 推荐还是使用-8h的操作,只有在需要进行时区操作和划算的时候才推荐使用此功能
DatePart(时间部分)
需要通过某个时间部分来定位日志,比如要定位所有六月的日志、所有星期三的日志、所有12号的日志
例如定位周三的日志:
DatePart(时间,时间部分,误差值)
时间部分 | 描述 |
---|---|
date | 表示 0:00(午夜 AM)的日期/时间,以刻度为单位 |
time | 从午夜 AM 到指定的持续时间,以刻度为单位 |
year | 年份部分为整数,例如 2021-01-05,这里的部分就是2021 |
month | 月份部分,例如 2021-01-05,这里的部分就是1 |
day | 天部分,例如 2021-01-05,这里的部分就是5 |
hour | (24 小时制)的小时部分,例如 13 表示下午 1 点,2021-01-05 11:03:54的hour部分就是11 |
minute | 分钟,例如2021-01-05 11:03:54的hour部分就是3 |
second | 秒,例如2021-01-05 11:03:54的hour部分就是54 |
weekday | 星期几,星期日=0,星期一=1,…… |
复杂查询
在复杂查询下,更多细节推荐查阅官方文档:官方文档
函数
Seq支持很多函数来辅助日志分析,我们在使用中常常不需要关注所有的函数列表,官方提供了一份常用的函数表:函数表
这里写几个最常用的函数用法
DateTime(str)
尝试将字符串转换为日期时间。如果无法正确解析,将返回null;正确解析则返回这个时间的Seq时间单位。
DatePart(datetime, part, offset)
获取日期时间部分,用于获取日期时间的一部分。在[[Seq#DatePart(时间部分)|前面的时间部分]]有讨论过。
Now()
获取当前时间的时间单位,返回Seq时间单位
Round(value, places)
四舍五入指定的小数位,value是传入值,places是最终保留小数位
Substring(str, start, length)
切割字符串,在复杂查询中极其常用的函数。常配合Length一同使用。
ToIsoString(datetime)
获取Iso-8601时间(也就是我们最常见的时间格式),需要传入Seq时间单位。
ToJson(arg)
将对象值转换为Json。
FromJson(json)
将Json转换为对象,序列化后即可直接从中取出字段使用。该函数消耗较大,尽量慎用。
ToNumber(str)
将字符串解析为数字。如果无法解析直接返回null。数字类型即可在Seq中做数字计算和比较。常用于耗时统计和筛选。
查询
在Seq下,全面支持SQL语法。像select、from等关键字与SQL使用一致。
select [<column> [as <label>],] //查询那些列,as即别名
[from stream //从哪里获取数据,最常用的即是stream
[where <predicate>] //Where条件
[group by [time(<d>)|<grouping>,]] //分组
[having <predicate>] //Having条件
[order by [time|<label>] [asc|desc]] //排序
[limit <n>] //Top多少条
[for refresh]]
聚合函数
与SQL一样,Seq也支持聚合函数来辅助统计和分析日志。 这里只谈到常用的聚合函数,更多资料参考官方文档-聚合函数
Count()
使用Count可以快速确认有多少符合条件的日志数
`select count(*) from stream where @Level='Error'
Distinct()
去除重复日志
`select distinct(@Message) from stream where @Level='Error'
Sum()
统计符合条件的字段/值之和
`select sum(1) from stream where @Level='Error' group by app
变量和Seq分组
待更新
一些应用场景
查询指定应用下近1个小时内的报错日志
select * from stream where @Level='Error' and @Timestamp > now()-1h and app='his'
复杂查询,查询指定日志信息,耗时>x值的
报表