ToB企服应用市场:ToB评测及商务社交产业平台
标题:
Grafana系列-Loki-基于日志实现告警
[打印本页]
作者:
笑看天下无敌手
时间:
2024-2-12 12:00
标题:
Grafana系列-Loki-基于日志实现告警
系列文章
Loki 系列文章
前言
实际应用中除了基于 Metrics 告警, 往往还有基于日志的告警需求, 可以作为基于 Metrics 告警之外的一个补充. 典型如基于 NGINX 日志的错误率告警.本文将介绍如何基于 Loki 实现基于日志的告警.
本文我们基于以下 2 类实际场景进行实战演练:
基于 NGINX 日志的错误率告警
基于 Nomad 日志的心跳异常告警(关于 Nomad 的介绍, 可以参见这篇文章:
《大规模 IoT 边缘容器集群管理的几种架构 -2-HashiCorp 解决方案 Nomad》
)
基于日志告警的应用场景
基于日志告警的广泛应用于如下场景:
黑盒监控
对于不是我们开发的组件, 如云厂商/第三方的负载均衡器和无数其他组件(包括开源组件和封闭第三方组件)支持我们的应用程序,但不会公开我们想要的指标。有些根本不公开任何指标。 Loki 的警报和记录规则可以生成有关系统状态的指标和警报,并通过使用日志将组件带入我们的可观察性堆栈中。这是一种将高级可观察性引入遗留架构的极其强大的方法。
事件告警
有时,您想知道某件事情是否已经发生。根据日志发出警报可以很好地解决这个问题,例如查找身份验证凭据泄露的示例:
- name: credentials_leak
rules:
- alert: http-credentials-leaked
annotations:
message: "{{ $labels.job }} is leaking http basic auth credentials."
expr: 'sum by (cluster, job, pod) (count_over_time({namespace="prod"} |~ "http(s?)://(\\w+):(\\w+)@" [5m]) > 0)'
for: 10m
labels:
severity: critical
复制代码
关于 Nomad 的就属于这类场景.
技术储备
Loki 告警
Grafana Loki 包含一个名为 ruler 的组件。Ruler 负责持续评估一组可配置查询并根据结果执行操作。其支持两种规则:alerting 规则和 recording 规则。
Loki Alering 规则
Loki 的告警规则格式几乎与 Prometheus 一样. 这里举一个完整的例子:
groups:
- name: should_fire
rules:
- alert: HighPercentageError
expr: |
sum(rate({app="foo", env="production"} |= "error" [5m])) by (job)
/
sum(rate({app="foo", env="production"}[5m])) by (job)
> 0.05
for: 10m
labels:
severity: page
annotations:
summary: High request latency
- name: credentials_leak
rules:
- alert: http-credentials-leaked
annotations:
message: "{{ $labels.job }} is leaking http basic auth credentials."
expr: 'sum by (cluster, job, pod) (count_over_time({namespace="prod"} |~ "http(s?)://(\\w+):(\\w+)@" [5m]) > 0)'
for: 10m
labels:
severity: critical
复制代码
Loki LogQL 查询
Loki 日志查询语言 (LogQL) 是一种查询语言,用于从 Loki 中检索日志。LogQL 与 Prometheus 非常相似,但有一些重要的区别。
LogQL 快速上手
所有 LogQL 查询都包含日志流选择器(
log stream selector
)。如下图:
可选择在日志流选择器后添加日志管道(
log pipeline
)。日志管道是一组阶段表达式,它们串联在一起并应用于选定的日志流。每个表达式都可以过滤、解析或更改日志行及其各自的标签。
以下示例显示了正在运行的完整日志查询:
{container="query-frontend",namespace="loki-dev"}
|= "metrics.go"
| logfmt
| duration > 10s
and throughput_mb < 500
复制代码
该查询由以下部分组成:
日志流选择器 {container="query-frontend",namespace="loki-dev"} ,其目标是 loki-dev 命名空间中的 query-frontend 容器。
日志管道 |= "metrics.go" | logfmt | duration > 10s and throughput_mb < 500 它将过滤掉包含单词 metrics.go 的日志,然后解析每个日志行以提取更多标签并使用它们进行过滤。
解析器表达式
为了进行告警, 我们往往需要在告警之前对
非结构化日志
进行解析, 解析后会获得更精确的字段信息(称为label), 这就是为什么我们需要使用解析器表达式.
解析器表达式可从日志内容中解析和提取标签(label)。这些提取的标签可用于使用标签过滤表达式进行过滤,或用于 metrics 汇总。
如果原始日志流中已经存在提取的标签 key名称(典型如: level),提取的标签 key 将以 _extracted 关键字为后缀,以区分两个标签。你也可以使用
标签格式表达式
强行覆盖原始标签。不过,如果提取的键出现两次,则只保留第一个标签值。
Loki 支持
JSON
、
logfmt
、
pattern
、
regexp
和
unpack
解析器。
今天我们重点介绍下 logfmt, pattern 和 regexp 解析器。
logfmt 解析器
logfmt 解析器可以以两种模式运行:
不带参数
可以使用 | logfmt 添加 logfmt 解析器,并将从 logfmt 格式的日志行中提取所有键和值。
例如以下日志行:
at=info method=GET path=/ host=grafana.net fwd="124.133.124.161" service=8ms status=200
复制代码
将提取到以下标签:
"at" => "info"
"method" => "GET"
"path" => "/"
"host" => "grafana.net"
"fwd" => "124.133.124.161"
"service" => "8ms"
"status" => "200"
复制代码
带参数
与 JSON 解析器类似,在管道中使用 | logfmt label="expression", another="expression" 将导致只提取标签指定的字段。
例如, | logfmt host, fwd_ip="fwd" 将从以下日志行中提取标签 host 和 fwd :
at=info method=GET path=/ host=grafana.net fwd="124.133.124.161" service=8ms status=200
复制代码
并将 fwd 重命名为 fwd_ip:
"host" => "grafana.net"
"fwd_ip" => "124.133.124.161"
复制代码
Pattern 解析器
Pattern 解析器允许通过定义模式表达式(| pattern "")从日志行中明确提取字段。该表达式与日志行的结构相匹配。
典型如 NGINX 日志:
0.191.12.2 - - [10/Jun/2021:09:14:29 +0000] "GET /api/plugins/versioncheck HTTP/1.1" 200 2 "-" "Go-http-client/2.0" "13.76.247.102, 34.120.177.193" "TLSv1.2" "US" ""
复制代码
该日志行可以用表达式解析:
<ip> - - <_> "<method> <uri> <_>" <status> <size> <_> "<agent>" <_>
复制代码
提取出这些字段:
"ip" => "0.191.12.2"
"method" => "GET"
"uri" => "/api/plugins/versioncheck"
"status" => "200"
"size" => "2"
"agent" => "Go-http-client/2.0"
复制代码
Pattern 表达式由捕获(captures )和文字组成。
捕获是以 字符分隔的字段名。 定义字段名 example。未命名的捕获显示为 。未命名的捕获会跳过匹配的内容。
Regular Expression 解析器
logfmt 和 json 会隐式提取所有值且不需要参数,而 regexp 解析器则不同,它只需要一个参数 | regexp "",即使用
Golang RE2 语法
的正则表达式。
正则表达式必须包含至少一个命名子匹配(例如 (?Pre) ),每个子匹配将提取不同的标签。
例如,解析器 | regexp "(?P\\w+) (?P[\\w|/]+) \\((?P\\d+?)\\) (?P.*)" 将从以下行中提取:
POST /api/prom/api/v1/query_range (200) 1.5s
复制代码
到这些标签:
"method" => "POST"
"path" => "/api/prom/api/v1/query_range"
"status" => "200"
"duration" => "1.5s"
复制代码
实战演练
<blockquote>
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/)
Powered by Discuz! X3.4