将PostgreSQL日志输出为Prometheus指标本文讨论使用日志作为数据源生成Prometheus指标。如果现有出口商提供的指标不能满足要求,或出口商因授权原因无法对外公开,??可参考本文提供的方法。写这篇文章的原因是我们的一位客户希望能够及时获得有关从应用程序到PostgreSQLv14数据库的失败查询的信息。同时,我们必须在不对应用程序代码进行任何更改的情况下实施此监控。在查看了现有的PostgreSQL导出器之后,我们找不到任何合适的指标来发送错误报告,因此我们决定自己创建一个新的。1.准备日志以供进一步使用从技术角度来看,步骤大致是:解析日志文件,从数据中提取指标,输出到Prometheus,设置警报。较早的PostgreSQL版本(版本15之前)不支持JSON结构化日志格式。生产环境不建议安装第三方模块,我们也建议将日志数据存储为CSV格式。但是,我们可以使用配置文件来根据需要格式化输出。我们的客户使用如下日志格式:postgresql.conflog_line_prefix='%m%p%u@%dfrom%h[vxid:%vtxid:%x][%i]'`描述如下:%m是时间戳,包括毫秒;%p——进程号;%u-用户名;%d-数据库名称。请参阅PostgreSQL文档(https://www.postgresql.org/docs/14/runtime-config-logging.html),了解有关其他变量的用途以及可写入日志的其他信息的更多信息。结果如下:2022-05-1207:33:54.285UTC2672031@from[vxid:txid:0][]LOG:checkpointcomplete:wrote64buffers(0.0%);添加了0个WAL文件,删除了0个,回收了10个;写入=6.266秒,同步=0.004秒,总计=6.285秒;同步文件=10,lnotallow=0.003s,平均=0.001s;距离=163840kB,估计=163844kB2。我们试图找到最好的解决方案fluentd(https://docs.fluentd.org/)、Promtail(https://grafana.com/docs/loki/latest/clients/promtail/)和exporter(https:///vector.dev/docs/)从日志中检索指标并将它们发送到Prometheus。Fluentd有一个广泛的插件系统来适应所有用例。例如,fluent-plugin-prometheus(https://github.com/fluent/fluent-plugin-prometheus)将数据转换成度量格式并交付给Prometheus。但是,自从v2.0.0发布后,该项目的开发进展缓慢。出于这个原因,我们这次决定走另一条路——尽管我们真的很喜欢fluentd并且经常使用它。我们尝试的第一个工具是Promtail。它具有解析文本日志(包括多行日志)、基于任务处理它们(包括提取指标)以及基于指定参数过滤内容的能力。为了进行测试,我们创建了一个配置文件来计算日志行数。以下是日志处理阶段的示例:pipeline_stages:-multiline:firstline:'^\[\d{4}-\d{2}-\d{2}\d{1,2}:\d{2}:\d{2}\]'-正则表达式:表达式:'^(?P\[\d{4}-\d{2}-\d{2}\d{1,2}:\d{2}:\d{2}\])(?P(?s:.*))$'-指标:log_lines_total:类型:计数器描述:“日志行总数”前缀:pg_custom_max_idle_duration:24h配置:match_all:trueaction:inclog_bytes_total:type:Counterdescription:"totalbytesofloglines"prefix:pg_custom_max_idle_duration:24hconfig:match_all:truecount_entry_bytes:trueaction:add配置工作正常;但是,我们错过了一个关键点。Promtail需要Loki(Grafana开发的日志聚合工具)的地址作为强制配置参数。如果没有设置这个参数,它根本不会启动。我们认为同时安装Loki是不切实际的。注意。如果您仍然想使用Promtail,您可以将Loki地址替换为能够为任何请求提供200响应代码的任何Web服务器(例如nginx)的地址。但是,我们不建议在生产环境中使用此解决方法。终于轮到Vector了。这对我们来说效果很好。3.Vector:解析日志并输出到PrometheusVector必须安装在需要解析的日志文件所在的主机上,这样才能将日志输出到Prometheus。安装完成后,进行相应的配置。你可以使用,例如,Ansible来做这一点:#playbook-vector.yaml----name:Setupvectorhosts:-pgbecome:yesvars:arch:amd64version:0.18.1vector_template:files/40-vector.tomlvector_config_file:/etc/vector/vector.tomltasks:-name:Setupinstallvectorbecome:yesapt:deb:"https://packages.timber.io/vector/{{版本}}/vector-{{version}}-{{arch}}.deb"install_recommends:yesnotify:-restartvector-name:Copyconfigcopy:src:"{{vector_template}}"dest:"{{vector_config_file}}"mode:0644所有者:vectorgroup:vectornotify:restartvector-name:StartVectorservice:state:startedenabled:yesname:vectorhandlers:-name:restartvectorservice:state:restarteddaemon_reload:yesname:vectorVector配置存储在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_beforemode意味着Vector会将condition_pattern之后(而非开头)的所有行视为一条消息。您还可以使用其他multiline.mode值。例如,half_withpattern包括所有连续的行,直到并包括与condition_pattern消息匹配的第一行。然后使用VRL(https://vector.dev/docs/reference/vrl)解析消息:#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+))从(?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(."请重试设置")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"输入=["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}}"最后一步是发布导出器。Prometheus将使用它来抓取指标。[sinks.postgres_export_metric]type="prometheus_exporter"inputs=["postgres_metric"]address="0.0.0.0:9598"default_namespace="pg_log"4.根据检索到的指标设置警报,以便Prometheus从新的导出器指标中获取,我们现在必须设置常规目标:scrape_configs:-job_name:custom-pg-log-exporterstatic_configs:-targets:['10.10.10.2:9598','10.10.10.3:9598','10.10.10.4:9598']下一步是创建Alertmanager将根据其路由设置处理的基于度量的规则:-alert:PgErrorCountChangeWarningexpr:|increase(pg_log_error_total{level="ERROR"}[30m])>0for:10mlabels:severity:warningannotations:summary:pg主机{{$labels.host}}日志中的错误数量已更改为{{$价值}}描述:|{{$labels.host}}服务器上的PostgreSQL日志中存在错误。-警报:PgErrorCountChangeCriticalexpr:|增加(pg_log_error_total{level="FATAL"}[30m])>0for:10mlabels:severity:critical注释:摘要:pg主机{{$labels.host}}日志中的致命错误数量已更改为{{$value}}描述:|{{$labels.host}}服务器上的PostgreSQL日志中存在致命错误。此处的pg_log_error_total计算向量时间序列的30分钟增量,其值大于零表示计数器已更改,导致发送警报给用户。然后用户可以检查PostgreSQL日志以找出问题的原因。5.结论因此,我们使用了一个简单的错误计数器来说明如何设置基于日志文件的指标收集。如果现有导出器不提供我们想要的指标,并且无法更改应用程序代码,这可能是一个相对简单的解决方案。我们的选择受到Vector的简单配置和广泛功能的影响,使其成为各种任务的理想选择。此外,其高性能(https://medium.com/ibm-cloud/log-collectors-performance-benchmarking-8c5218a08fea)意味着可用资源得到有效利用。vectortopCli工具有助于调试日志记录管道和查看Vector的指标。它在漂亮的TUI界面中显示信息。Vector不仅限于基本的计数器功能——它还可以解析日志以查找缓慢的数据库查询。然后,您可以使用VRL处理结果,聚合(https://vector.dev/docs/reference/configuration/transforms/aggregate/)它们,将它们转换为指标,然后在Grafana中显示前10个查询。它还可以通过处理连接日志和根据获得的数据创建指标来证明对安全审计很有用。换句话说,Vector有很多应用场景——这完全取决于用户的需求。原文:https://blog.palark.com/vector-to-export-pgsql-logs-into-prometheus/
