五分鐘了解 LogQL 用法
受PromQL的啟發(fā),Loki也有自己的LogQL查詢語(yǔ)句。根據(jù)官方的說(shuō)法,它就像一個(gè)分布式的grep日志聚合查看器。和PromeQL一樣,LogQL也是使用標(biāo)簽和運(yùn)算符進(jìn)行過(guò)濾,它主要分為兩個(gè)部分:
log stream selector (日志流選擇器)
filter expression (過(guò)濾器表達(dá)式)
我們用這兩部分就可以在Loki中組合出我們想要的功能,通常情況下我們可以拿來(lái)做如下功能
根據(jù)日志流選擇器查看日志內(nèi)容
通過(guò)過(guò)濾規(guī)則在日志流中計(jì)算相關(guān)的度量指標(biāo)
log stream selector
日志流選擇器這部分和PromQL的語(yǔ)法一樣,主要也是通過(guò)采集上來(lái)的日志label來(lái)確定你要查詢的日志流。通常label的匹配運(yùn)算支持以下幾種:
=: 完全匹配
!=: 不匹配
=~: 正則表達(dá)式匹配
!~: 正則表達(dá)式不匹配
舉個(gè)例子
{name=~"mysql.+", env="prod"}
{name!~"mysql.+", env="prod"}
{name!~`mysql-\d+`,env="prod"}
以上語(yǔ)句都可以查出所有與之匹配的日志內(nèi)容
filter expression
在查看全文的日志時(shí),通常會(huì)用grep等一些工具來(lái)查找我們關(guān)心的日志內(nèi)容。LogQL的表達(dá)式就是干這個(gè)的。當(dāng)前,過(guò)濾的表達(dá)式主要支持如下4種:
|=:日志行包含的字符串
!=:日志行不包含的字符串
|~:日志行匹配正則表達(dá)式
!~:日志行與正則表達(dá)式不匹配
舉個(gè)例子
{job="mysql"} |= "error"
{name="kafka"} |~ "tsdb-ops.*io:2003"
{name="cassandra"} |~ `error=\w+`
{instance=~"kafka-[23]",name="kafka"} != "kafka.server:type=ReplicaManager"
如果要進(jìn)行多次匹配的話,我們可以也可以像在linux用管道的方式追加規(guī)則:
{job="mysql"} |= "error" != "timeout"
日志度量
LogQL同樣支持通過(guò)函數(shù)方式將日志流進(jìn)行度量,通常我們可以用它來(lái)計(jì)算消息的錯(cuò)誤率或者排序一段時(shí)間內(nèi)的應(yīng)用日志輸出Top N。
區(qū)間向量
LogQL同樣也支持有限的區(qū)間向量度量語(yǔ)句,使用方式也和PromQL類似,常用函數(shù)主要是如下4個(gè):
rate: 計(jì)算每秒的日志條目
count_over_time: 對(duì)指定范圍內(nèi)的每個(gè)日志流的條目進(jìn)行計(jì)數(shù)
bytes_rate: 計(jì)算日志流每秒的字節(jié)數(shù)
bytes_over_time: 對(duì)指定范圍內(nèi)的每個(gè)日志流的使用的字節(jié)數(shù)
舉個(gè)例子:
#計(jì)算nginx的qps
rate({filename="/var/log/nginx/access.log"}[5m]))
#計(jì)算kernel過(guò)去5分鐘發(fā)生oom的次數(shù)
count_over_time({filename="/var/log/message"} |~ "oom_kill_process" [5m]))
聚合函數(shù)
LogQL也支持聚合運(yùn)算,我們可用它來(lái)聚合單個(gè)向量?jī)?nèi)的元素,從而產(chǎn)生一個(gè)具有較少元素的新向量,當(dāng)前支持的聚合函數(shù)如下:
sum:求和
min:最小值
max:最大值
avg:平均值
stddev:標(biāo)準(zhǔn)差
stdvar:標(biāo)準(zhǔn)方差
count:計(jì)數(shù)
bottomk:最小的k個(gè)元素
topk:最大的k個(gè)元素
聚合函數(shù)通常我們用如下表達(dá)式描述:
([parameter,] ) [without|by ( 對(duì)于需要對(duì)標(biāo)簽進(jìn)行分組時(shí),我們可以用without或者by來(lái)區(qū)分,比如
#計(jì)算nginx的qps,并按照pod_name來(lái)分組
sum(rate({filename="/var/log/nginx/access.log"}[5m])) by (pod_name)
只有在使用bottomk和topk函數(shù)時(shí),我們可以對(duì)函數(shù)輸入相關(guān)的參數(shù),比如
#計(jì)算nginx的qps最大的前5個(gè),并按照pod_name來(lái)分組
topk(5,sum(rate({filename="/var/log/nginx/access.log"}[5m])) by (pod_name))
數(shù)學(xué)計(jì)算
有同學(xué)要問(wèn)了,Loki存的不是日志嗎?都是文本,怎么計(jì)算啊?顯然LogQL中的數(shù)學(xué)運(yùn)算還是面向區(qū)間向量操作的。LogQL中的支持的二進(jìn)制運(yùn)算符如下:
+:加法
-:減法
*:乘法
/:除法
%:求模
:?求冪
比如我們要找到某個(gè)業(yè)務(wù)日志里面的錯(cuò)誤率,就可以按照如下方式計(jì)算:
#計(jì)算日志內(nèi)的錯(cuò)誤率
sum(rate({app="foo", level="error"}[1m])) / sum(rate({app="foo"}[1m]))
集合運(yùn)算
集合運(yùn)算僅在區(qū)間向量范圍內(nèi)有效,當(dāng)前支持
and:并且
or:或者
unless:排除
小白當(dāng)前還沒(méi)找到LogQL里面集合運(yùn)算的案例,暫且跳過(guò)
比較運(yùn)算
LogQL支持的比較運(yùn)算符合PromQL一樣,均為以下內(nèi)容:
==:等于
!=:不等于
>:大于
>=: 大于或等于
<:小于
<=: 小于或等于
通常我們使用區(qū)間向量計(jì)算后會(huì)做一個(gè)閾值的比較,這對(duì)應(yīng)告警是非常有用的,比如:
# 統(tǒng)計(jì)5分鐘內(nèi)error級(jí)別日志條目大于10的情況
count_over_time({app="foo", level="error"}[5m]) > 10
當(dāng)然我們也可以通過(guò)布爾計(jì)算來(lái)表達(dá),比如:
# 統(tǒng)計(jì)5分鐘內(nèi)error級(jí)別日志條目大于10為真,反正則為假
count_over_time({app="foo", level="error"}[5m]) > bool 10
這部分后面結(jié)合Loki ruler使用會(huì)有更多的使用場(chǎng)景,建議配合《Loki告警的正確姿勢(shì)》一起食用
運(yùn)算優(yōu)先級(jí)
LogQL的運(yùn)算優(yōu)先級(jí)也保持了常規(guī)的數(shù)學(xué)操作順序,即如下規(guī)則:
^
*, /, %
+, -
==,!=, <=, <, >=, >
and, unless
or

END
?點(diǎn)擊屏末?|?閱讀原文?|?即刻學(xué)習(xí)