使用 Vector 将 PostgreSQL 日志输出为 Prometheus 指标

网友投稿 1147 2023-04-16

使用 Vector 将 *** 日志输出为 Prometheus 指标

使用 Vector 将 *** 日志输出为 Prometheus 指标

​本文讨论使用日志作为数据源生成 Prometheus 指标。如果现有 exporters 提供的指标无法满足需求,或者 exporter 因授权原因无法对外公开,则可以参考本文提供的方式。

写本文的原因是,我们的一位客户希望能够及时获取有关从应用程序到 *** v14 数据库的失败查询的信息。同时,我们必须在不对应用程序代码进行任何更改的情况下实现此监控。在查看现有的 *** exporter后,我们未能找到任何能够发送错误报告的合适指标,因此我们决定自己新建一个。

1.准备日志以供进一步使用

从技术角度来看,步骤大致为:解析日志文件、从数据中提取指标、将其输出到 Prometheus 以及设置告警。早期的 *** 版本(15 版本之前)不支持 JSON 结构化日志格式。在生产环境中安装第三方模块并不推荐,我们也与推荐以 CSV 格式存储日志数据。但是,我们能够根据需要使用配置文件来格式化输出。我们的客户使用了以下日志格式:

postgresql.conf log_line_prefix = '%m %p %u@%d from %h [vxid:%v txid:%x] [%i] '`

描述如下:

%m是一个时间戳,包括毫秒;%p– 进程号;%u- 用户名;%d- 数据库名称。

有关其他变量的用途以及可以写入日志的其他信息的更多信息,请参阅 *** 文档

结果如下:

2.寻找最佳解决方案

我们尝试的第一个工具是 Promtail。它具有解析文本日志(包括多行日志)、基于任务处理它们(包括提取指标)以及基于指定参数过滤内容的能力。

为了进行测试,我们创建了一个配置文件来计算日志行数。

这是日志处理阶段的示例:

pipeline_stages: - multiline: firstline: '^\[\d{4}-\d{2}-\d{2} \d{1,2}:\d{2}:\d{2}\]' - regex: expression: '^(?P\[\d{4}-\d{2}-\d{2} \d{1,2}:\d{2}:\d{2}\]) (?P(?s:.*))$' - metrics: log_lines_total: type: Counter description: "total number of log lines" prefix: pg_custom_ max_idle_duration: 24h config: match_all: true action: inc log_bytes_total: type: Counter description: "total bytes of log lines" prefix: pg_custom_ max_idle_duration: 24h config: match_all: true count_entry_bytes: true action: add

配置工作正常;然而,我们错过了一个关键点。Promtail需要Loki(Grafana开发的日志聚合工具)的地址作为强制配置参数。没有这个参数集,它根本不会启动。我们认为同时安装 Loki 是不切实际的。

注意。如果您仍然想使用 Promtail,您可以将 Loki 地址替换为任何能够为任何请求提供 200 响应代码的 Web 服务器(例如,nginx)的地址。但是,我们不建议在生产环境中使用此解决方法。

终于轮到 Vector 了。这对我们来说效果很不错。

3.Vector:解析日志并输出到 Prometheus

Vector 必须安装在要解析的日志文件所在的主机上,以便将日志输出到 Prometheus。安装完成后,进行相应的配置。你可以使用,例如,Ansible 来做到这一点:

Vector 配置存储在 TOML 文件中。在此文件中指定日志文件的位置及其类型:

# vector.toml[sources.postgres_logs.multiline]start_pattern = '^\d{4}-[0-1]\d-[0-3]\d \d+:\d+:\d+\.\d+ [A-Z]{3}'mode = "halt_before"condition_pattern = '^\d{4}-[0-1]\d-[0-3]\d \d+:\d+:\d+\.\d+ [A-Z]{3}'timeout_ms = 1000

请注意,halt_before​mode 意味着 Vector 会将跟在condition_pattern(并且不以后者开头)之后的所有行视为单个消息。

您也可以使用其他multiline.mode​值。例如,该half_with​模式包括所有连续的行,直到并包括与condition_pattern消息中匹配的第一行。

# vector.toml[transforms.postgres_remap]type = "remap"inputs = [ "postgres_logs" ]source = """. |= parse_regex!(.message, r'^(?P\\d{4}-[0-1]\\d-[0-3]\\d \\d+:\\d+:\\d+\\.\\d+ [A-Z]{3}) (?P\\d+) (?P(\\[\\w+\\]@\\w+|@|\\w+@\\w+)) from (?P(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|\\[\\w+\\]|\\s*)) (?P\\[\\w+:.+:\\d+\\]) (?P(\\[\\]|\\[\\w.+\\])) (?P.*[A-Z]): (?P.*)$')del(.timestamp)message_parts, err = split(.message, ", ", limit: 2)structured = parse_key_value(message_parts[1], key_value_delimiter: ":", field_delimiter: ",") ?? {}message = message_parts[0]. = merge(., structured)del(."please try the setup again")del(.message)"""

在这里,我们:

指定日志源;设置一个正则表达式来解析日志消息;删除了不必要的字段;使用“,”分隔符拆分消息;将结果保存到map数组中,对其进行处理,并获得 JSON 输出,以便我们可以继续操作其字段。

现在让我们过滤掉错误消息:

# vector.toml[transforms.postgres_filter]type = "filter"inputs = [ "postgres_remap" ]condition = '.level == "ERROR" || .level == "FATAL"'

此配置将在指标中包含ERROR和FATAL消息。

接下来,根据过滤的日志消息创建一个指标。设置要使用的指标类型和字段,适当地命名,并附加额外的标签。

# vector.toml[transforms.postgres_metric]type = "log_to_metric"inputs = [ "postgres_filter" ] [[transforms.postgres_metric.metrics]] type = "counter" field = "level" name = "error_total" namespace = "pg_log" [transforms.postgres_metric.metrics.tags] level = "{{level}}" host = "{{host}}"

最后一步是发布 exporter。Prometheus 将使用它来抓取指标。

[sinks.postgres_export_metric]type = "prometheus_exporter"inputs = [ "postgres_metric" ]address = "0.0.0.0:9598"default_namespace = "pg_log"

4.根据检索到的指标设置警报

为了让 Prometheus 能够从新 exporter 器中抓取指标,我们现在必须设置常规目标:

scrape_configs: - job_name: custom-pg-log-exporter static_configs: - targets: ['10.10.10.2:9598', '10.10.10.3:9598', '10.10.10.4:9598']

下一步是创建基于指标的规则,Alertmanager 将根据其路由设置处理该规则:

- alert: PgErrorCountChangeWarning expr: | increase(pg_log_error_total{level="ERROR"}[30m]) > 0 for: 10m labels: severity: warning annotations: summary: The amount of errors in pg host {{$labels.host}} log has changed to {{$value}} description: | There are errors in the *** logs on the {{$labels.host}} server.- alert: PgErrorCountChangeCritical expr: | increase(pg_log_error_total{level="FATAL"}[30m]) > 0 for: 10m labels: severity: critical annotations: summary: The amount of fatal errors in pg host {{$labels.host}} log has changed to {{$value}} description: | There are fatal errors in the *** logs on the {{$labels.host}} server.

pg_log_error_total这里计算向量时间序列30分钟的增量。其值大于零意味着计数器已更改,从而导致向用户发送警报。然后用户可以检查 *** 日志以找出问题的原因。

5.结论

因此,我们使用了一个简单的错误计数器来说明如何根据日志文件设置指标收集。如果现有的 exporter 没有提供我们想要的指标,并且没有办法更改应用程序代码,这可以作为一个相对简单的解决方案。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:MySQL:两张表编码方式不一致,关联查询一定会导致索引失效吗?
下一篇:怎样快速地迁移 MySQL 中的数据?
相关文章