如何用LogQL在幾秒內(nèi)查詢TB級(jí)的日志
時(shí)間:2021-09-07 11:27:34
手機(jī)看文章
掃描二維碼
隨時(shí)隨地手機(jī)看文章
[導(dǎo)讀]LogQL在很大程度上受Prometheus的PromQL啟發(fā)。但是,當(dāng)涉及到在過濾海量日志時(shí),我們就像面臨在大海撈針一樣復(fù)雜。LogQL是Loki特有的語句,在本文中,我們將提供LogQL的快速過濾器查詢技巧,這些查詢可以在幾秒鐘內(nèi)過濾掉數(shù)TB的數(shù)據(jù)。在Loki中,我們可以使用...
LogQL在很大程度上受Prometheus的PromQL啟發(fā)。但是,當(dāng)涉及到在過濾海量日志時(shí),我們就像面臨在大海撈針一樣復(fù)雜。LogQL是Loki特有的語句,在本文中,我們將提供LogQL的快速過濾器查詢技巧,這些查詢可以在幾秒鐘內(nèi)過濾掉數(shù)TB的數(shù)據(jù)。在Loki中,我們可以使用三種類型的過濾器:

Label matchers
Label matchers(標(biāo)簽匹配器)是你的第一道防線,是大幅減少你搜索的日志數(shù)量(例如,從100TB到1TB)的最好方法。當(dāng)然,這意味著你需要在的日志采集端上有良好的標(biāo)簽定義規(guī)范。基本上,標(biāo)簽應(yīng)該定義的類型包括,工作負(fù)載、集群、命名空間和容器等,這樣你就可以在多個(gè)不同的維度上對(duì)數(shù)據(jù)進(jìn)行切分。比如說- 一個(gè)應(yīng)用在多個(gè)集群上運(yùn)行
- 落在多個(gè)k8s集群命名空間的開發(fā)環(huán)境
- 生產(chǎn)環(huán)境的命名空間
=
匹配器(例如,{cluster="us-central1"})
。否則,你將不得不提取整個(gè)索引數(shù)據(jù)。但有一個(gè)例外。如果匹配器包含一個(gè)或多個(gè)字元,比如{container=~"promtail|agent"}
,同時(shí)只有一個(gè)單一的regex匹配器,Loki可以自行優(yōu)化查詢
下面就是一些實(shí)用的樣例:好例子:{cluster="us-central1"}
{container="istio"}
{cluster="us-central1",?container=~"agent|promtail"}
壞例子:{job=~".*/queue"}
{namespace!~"dev-.*"}
Line filters
Line filters(行過濾器)是您的第二個(gè)好朋友,因?yàn)樗鼈儓?zhí)行過程超級(jí)快。它允許你過濾包含(|=
)或不包含(!=
)字符串的日志,你也可以使用正則來匹配(|~
)或不匹配(!~
)日志,但你應(yīng)該把它們放在標(biāo)簽匹配器之后
。現(xiàn)在,當(dāng)我們將這些過濾器連起來使用時(shí),要注意過濾器的順序
。先用那些能過濾最多日志的過濾器,然后再使用正則,它比=
和!=
慢。但有一個(gè)例外。|~ "error|fatal "
可以被Loki優(yōu)化掉 實(shí)際上這兩個(gè)字符串被loki自動(dòng)過濾掉了,所以不會(huì)執(zhí)行正則匹配
一個(gè)好的方法是先添加一個(gè)符合你要找的東西的過濾器,例如,|= "err"
。然后再添加越來越多的不等式來過濾你不想要的東西,直到最終得到類似于下面這樣的結(jié)果|=?"err"?!=?"timeout"?!=?"cancelled"?|~?"failed.*"?!=?"memcached"
現(xiàn)在,如果你意識(shí)到你的大部分錯(cuò)誤來自memcached,那么就把它移到第一個(gè)位置!=?"memcached"?|=?"err"?!=?"timeout"?!=?"cancelled"?|~?"failed.*"
這樣一來,后續(xù)過濾器的執(zhí)行次數(shù)就會(huì)減少。除此之外,行過濾器也很適合查找IP、TraceID、UUID等類型的日志。比如下面這個(gè)也一個(gè)很好的查詢方式{namespace="prod"}?|=?"traceID=2e2er8923100"
如果你想讓這個(gè)traceID的所有日志都符合某個(gè)regex,可以在ID過濾器后面加上|~ "/api/v. /query"
,這樣就不會(huì)對(duì)prod命名空間的每個(gè)pod中去添加查詢。Label filters
Label filters(標(biāo)簽過濾器)提供了更復(fù)雜的計(jì)算功能(duration,numerical等),但是它們通常需要先提取標(biāo)簽,然后再將標(biāo)簽值轉(zhuǎn)換為另一種類型。這意味著它們通常是最慢的,因此我們應(yīng)該最后使用它們。實(shí)際上我們可以在不提取標(biāo)簽的情況下使用標(biāo)簽過濾器(使用盡管|json
或|logfmt
等解析器)。標(biāo)簽過濾器也可以在索引標(biāo)簽上工作。例如,{job="ingress/nginx"}。| status_code >= 400 and cluster="us-central2"
可以正常工作,但你真正應(yīng)該問自己的是,你是否需要將 status_code 作為索引標(biāo)簽。一般來說,你不應(yīng)該,但你可以考慮提取 status_code 作為標(biāo)簽,這可以將大批量的流(每秒超過一千行)分解成獨(dú)立的流。
| json
和| logfmt
解析器很快,但是解析| regex
卻很慢。這就是為什么在使用解析器時(shí),我總是在它前面加上一個(gè)行過濾器。例如,在我的Go應(yīng)用程序(包括Loki)中,我的所有日志均支持顯示文件名和行號(hào)(此處為caller=metrics.go:83
)level=info?ts=2020-12-07T21:03:22.885781801Z?caller=metrics.go:83?org_id=29?traceID=4078dafcbc079822?latency=slow?query="{cluster=\"ops-tools1\",job=\"loki-ops/querier\"}?!=?\"logging.go\"?!=?\"metrics.go\"?|=?\"recover\""?query_type=filter?range_type=range?length=168h0m1s?step=5m0s?duration=54.82511258s?status=200?throughput=8.3GB?total_bytes=454GB
因此,當(dāng)我們想過濾緩慢的請(qǐng)求時(shí),應(yīng)該先對(duì)記錄文件和行號(hào)
進(jìn)行過濾,然后再進(jìn)行解析,最后再將提取的標(biāo)簽進(jìn)行比較。{namespace="loki-ops",container="query-frontend"}?
|=?"caller=metrics.go:83"?
|?logfmt?
|?throughput?>?1GB?and?duration?>?10s?and?org_id=29