?本文討論使用日志作為數據源生成 Prometheus 指標。如果現有 exporters 提供的指標無法滿足需求,或者 exporter 因授權原因無法對外公開,則可以參考本文提供的方式。
寫本文的原因是,我們的一位客戶希望能夠及時獲取有關從應用程序到 PostgreSQL v14 數據庫的失敗查詢的信息。同時,我們必須在不對應用程序代碼進行任何更改的情況下實現此監控。在查看現有的 PostgreSQL exporter后,我們未能找到任何能夠發送錯誤報告的合適指標,因此我們決定自己新建一個。
1.準備日志以供進一步使用
從技術角度來看,步驟大致為:解析日志文件、從數據中提取指標、將其輸出到 Prometheus 以及設置告警。早期的 PostgreSQL 版本(15 版本之前)不支持 JSON 結構化日志格式。在生產環境中安裝第三方模塊并不推薦,我們也與推薦以 CSV 格式存儲日志數據。但是,我們能夠根據需要使用配置文件來格式化輸出。我們的客戶使用了以下日志格式:
postgresql.conf log_line_prefix = '%m %p %u@%d from %h [vxid:%v txid:%x] [%i] '`描述如下:
- %m是一個時間戳,包括毫秒;
- %p– 進程號;
- %u- 用戶名;
- %d- 數據庫名稱。
有關其他變量的用途以及可以寫入日志的其他信息的更多信息,請參閱 PostgreSQL 文檔
(https://www.postgresql.org/docs/14/runtime-config-logging.html)。
結果如下:
2022-05-12 07:33:54.285 UTC 2672031 @ from [vxid: txid:0] [] LOG: checkpoint complete: wrote 64 buffers (0.0%); 0 WAL file(s) added, 0 removed, 10 recycled; write=6.266
s, sync=0.004 s, total=6.285 s; sync files=10, lnotallow=0.003 s, average=0.001 s; distance=163840 kB, estimate=163844 kB
2.尋找最佳解決方案
我們嘗試了 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}\]'
- 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 來做到這一點:
# playbook-vector.yaml
---
- name: Setup vector
hosts:
- pg
become: yes
vars:
arch: amd64
version: 0.18.1
vector_template: files/40-vector.toml
vector_config_file: /etc/vector/vector.toml
tasks:
- name: Setup install vector
become: yes
apt:
deb: "https://packages.timber.io/vector/` version `/vector-` version `-` arch `.deb"
install_recommends: yes
notify:
- restart vector
- name: Copy config
copy:
src: "` vector_template `"
dest: "` vector_config_file `"
mode: 0644
owner: vector
group: vector
notify: restart vector
- name: Start Vector
service:
state: started
enabled: yes
name: vector
handlers:
- name: restart vector
service:
state: restarted
daemon_reload: yes
name: vector
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消息中匹配的第一行。
然后使用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+)) 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 PostgreSQL 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 PostgreSQL logs on the {{$labels.host}} server.
pg_log_error_total這里計算向量時間序列30分鐘的增量。其值大于零意味著計數器已更改,從而導致向用戶發送警報。然后用戶可以檢查 PostgreSQL 日志以找出問題的原因。
5.結論
因此,我們使用了一個簡單的錯誤計數器來說明如何根據日志文件設置指標收集。如果現有的 exporter 沒有提供我們想要的指標,并且沒有辦法更改應用程序代碼,這可以作為一個相對簡單的解決方案。
我們的選擇受到 Vector 的簡單配置和廣泛功能的影響,使其成為各種任務的理想選擇。此外,其高性能 (https://medium.com/ibm-cloud/log-collectors-performance-benchmarking-8c5218a08fea) 意味著可用資源得到有效利用。vector top Cli工具有助于調試日志管道和查看 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/?