From 041dad2c9322fa9083a74929f1482cc4a0592a11 Mon Sep 17 00:00:00 2001 From: Magnus Root Date: Thu, 4 Jun 2026 12:06:21 +0300 Subject: [PATCH] Fix alerts --- LICENSE | 0 README.md | 0 alert_rules_template.json | 344 ++++++++++++++++++++++++++++++++++++-- dashboard_template.json | 0 4 files changed, 326 insertions(+), 18 deletions(-) mode change 100644 => 100755 LICENSE mode change 100644 => 100755 README.md mode change 100644 => 100755 alert_rules_template.json mode change 100644 => 100755 dashboard_template.json diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/alert_rules_template.json b/alert_rules_template.json old mode 100644 new mode 100755 index 5f1b617..00c3ecb --- a/alert_rules_template.json +++ b/alert_rules_template.json @@ -141,7 +141,11 @@ } ], "annotations": { - "summary": "🟡 {{ $labels.instance }}: диск / заполнен на {{ $values.\"Занято в /\".Value | printf \"%.1f\" }}% (порог 75%)" + "summary": "🟡 {{ $labels.instance }}: диск / заполнен {{ (index $values \"Занято в /\").Value | printf \"%.1f\" }}% (порог 75%)", + "circle": "🟡", + "alert_text": "диск / заполнен", + "value_key": "Занято в /", + "threshold": "75%" }, "ruleGroup": "[SYSTEM]" }, @@ -220,7 +224,11 @@ } ], "annotations": { - "summary": "🟡 {{ $labels.instance }}: диск /var/log заполнен на {{ $values.\"Занято в /var/log\".Value | printf \"%.1f\" }}% (порог 75%)" + "summary": "🟡 {{ $labels.instance }}: диск /var/log заполнен {{ (index $values \"Занято в /var/log\").Value | printf \"%.1f\" }}% (порог 75%)", + "circle": "🟡", + "alert_text": "диск /var/log заполнен", + "value_key": "Занято в /var/log", + "threshold": "75%" }, "ruleGroup": "[SYSTEM]" }, @@ -299,7 +307,11 @@ } ], "annotations": { - "summary": "🔴 {{ $labels.instance }}: диск / заполнен на {{ $values.\"Занято в /\".Value | printf \"%.1f\" }}% (порог 90%)" + "summary": "🔴 {{ $labels.instance }}: диск / заполнен {{ (index $values \"Занято в /\").Value | printf \"%.1f\" }}% (порог 90%)", + "circle": "🔴", + "alert_text": "диск / заполнен", + "value_key": "Занято в /", + "threshold": "90%" }, "ruleGroup": "[SYSTEM]" }, @@ -378,7 +390,11 @@ } ], "annotations": { - "summary": "🔴 {{ $labels.instance }}: диск /var/log заполнен на {{ $values.\"Занято в /var/log\".Value | printf \"%.1f\" }}% (порог 90%)" + "summary": "🔴 {{ $labels.instance }}: диск /var/log заполнен {{ (index $values \"Занято в /var/log\").Value | printf \"%.1f\" }}% (порог 90%)", + "circle": "🔴", + "alert_text": "диск /var/log заполнен", + "value_key": "Занято в /var/log", + "threshold": "90%" }, "ruleGroup": "[SYSTEM]" }, @@ -456,7 +472,11 @@ } ], "annotations": { - "summary": "⚪ {{ $labels.instance }}: CPU загружен на {{ $values.\"Занято CPU\".Value | printf \"%.1f\" }}% (порог 35%)" + "summary": "⚪ {{ $labels.instance }}: CPU загружен {{ (index $values \"Занято CPU\").Value | printf \"%.1f\" }}% (порог 35%)", + "circle": "⚪", + "alert_text": "CPU загружен", + "value_key": "Занято CPU", + "threshold": "35%" }, "ruleGroup": "[SYSTEM]" }, @@ -534,7 +554,11 @@ } ], "annotations": { - "summary": "🟡 {{ $labels.instance }}: CPU загружен на {{ $values.\"Занято CPU\".Value | printf \"%.1f\" }}% (порог 45%)" + "summary": "🟡 {{ $labels.instance }}: CPU загружен {{ (index $values \"Занято CPU\").Value | printf \"%.1f\" }}% (порог 45%)", + "circle": "🟡", + "alert_text": "CPU загружен", + "value_key": "Занято CPU", + "threshold": "45%" }, "ruleGroup": "[SYSTEM]" }, @@ -612,7 +636,11 @@ } ], "annotations": { - "summary": "🔴 {{ $labels.instance }}: CPU загружен на {{ $values.\"Занято CPU\".Value | printf \"%.1f\" }}% (порог 75%)" + "summary": "🔴 {{ $labels.instance }}: CPU загружен {{ (index $values \"Занято CPU\").Value | printf \"%.1f\" }}% (порог 75%)", + "circle": "🔴", + "alert_text": "CPU загружен", + "value_key": "Занято CPU", + "threshold": "75%" }, "ruleGroup": "[SYSTEM]" }, @@ -690,7 +718,11 @@ } ], "annotations": { - "summary": "⚪ {{ $labels.instance }}: RAM занята на {{ $values.\"Занято RAM\".Value | printf \"%.1f\" }}% (порог 35%)" + "summary": "⚪ {{ $labels.instance }}: RAM занята {{ (index $values \"Занято RAM\").Value | printf \"%.1f\" }}% (порог 35%)", + "circle": "⚪", + "alert_text": "RAM занята", + "value_key": "Занято RAM", + "threshold": "35%" }, "ruleGroup": "[SYSTEM]" }, @@ -768,7 +800,11 @@ } ], "annotations": { - "summary": "🟡 {{ $labels.instance }}: RAM занята на {{ $values.\"Занято RAM\".Value | printf \"%.1f\" }}% (порог 45%)" + "summary": "🟡 {{ $labels.instance }}: RAM занята {{ (index $values \"Занято RAM\").Value | printf \"%.1f\" }}% (порог 45%)", + "circle": "🟡", + "alert_text": "RAM занята", + "value_key": "Занято RAM", + "threshold": "45%" }, "ruleGroup": "[SYSTEM]" }, @@ -846,7 +882,11 @@ } ], "annotations": { - "summary": "🔴 {{ $labels.instance }}: RAM занята на {{ $values.\"Занято RAM\".Value | printf \"%.1f\" }}% (порог 75%)" + "summary": "🔴 {{ $labels.instance }}: RAM занята {{ (index $values \"Занято RAM\").Value | printf \"%.1f\" }}% (порог 75%)", + "circle": "🔴", + "alert_text": "RAM занята", + "value_key": "Занято RAM", + "threshold": "75%" }, "ruleGroup": "[SYSTEM]" }, @@ -924,7 +964,11 @@ } ], "annotations": { - "summary": "🔴 {{ $labels.instance }}: CPU загружен на {{ $values.\"Занято CPU\".Value | printf \"%.1f\" }}% (порог 90%)" + "summary": "🔴 {{ $labels.instance }}: CPU загружен {{ (index $values \"Занято CPU\").Value | printf \"%.1f\" }}% (порог 90%)", + "circle": "🔴", + "alert_text": "CPU загружен", + "value_key": "Занято CPU", + "threshold": "90%" }, "ruleGroup": "[SYSTEM]" }, @@ -1002,7 +1046,11 @@ } ], "annotations": { - "summary": "🔴 {{ $labels.instance }}: RAM занята на {{ $values.\"Занято RAM\".Value | printf \"%.1f\" }}% (порог 90%)" + "summary": "🔴 {{ $labels.instance }}: RAM занята {{ (index $values \"Занято RAM\").Value | printf \"%.1f\" }}% (порог 90%)", + "circle": "🔴", + "alert_text": "RAM занята", + "value_key": "Занято RAM", + "threshold": "90%" }, "ruleGroup": "[SYSTEM]" }, @@ -1017,7 +1065,11 @@ "folderUID": "", "ruleGroup": "[SYSTEM]", "annotations": { - "summary": "⚪ {{ $labels.instance }}: нагрузка на bond0 {{ $values.\"Total\".Value | printf \"%.2f\" }} Гбит/с (порог 35% от 25 Гбит/с)" + "summary": "⚪ {{ $labels.instance }}: нагрузка на bond0 {{ (index $values \"Total\").Value | printf \"%.1f\" }}% (порог 35% от 25 Гбит/с)", + "circle": "⚪", + "alert_text": "нагрузка на bond0", + "value_key": "Total", + "threshold": "35% от 25 Гбит/с" }, "data": [ { @@ -1097,7 +1149,11 @@ "folderUID": "", "ruleGroup": "[SYSTEM]", "annotations": { - "summary": "🟡 {{ $labels.instance }}: нагрузка на bond0 {{ $values.\"Total\".Value | printf \"%.2f\" }} Гбит/с (порог 45% от 25 Гбит/с)" + "summary": "🟡 {{ $labels.instance }}: нагрузка на bond0 {{ (index $values \"Total\").Value | printf \"%.1f\" }}% (порог 45% от 25 Гбит/с)", + "circle": "🟡", + "alert_text": "нагрузка на bond0", + "value_key": "Total", + "threshold": "45% от 25 Гбит/с" }, "data": [ { @@ -1177,7 +1233,11 @@ "folderUID": "", "ruleGroup": "[SYSTEM]", "annotations": { - "summary": "🔴 {{ $labels.instance }}: нагрузка на bond0 {{ $values.\"Total\".Value | printf \"%.2f\" }} Гбит/с (порог 75% от 25 Гбит/с)" + "summary": "🔴 {{ $labels.instance }}: нагрузка на bond0 {{ (index $values \"Total\").Value | printf \"%.1f\" }}% (порог 75% от 25 Гбит/с)", + "circle": "🔴", + "alert_text": "нагрузка на bond0", + "value_key": "Total", + "threshold": "75% от 25 Гбит/с" }, "data": [ { @@ -1254,7 +1314,11 @@ "no_data_state": "NoData", "exec_err_state": "Error", "annotations": { - "summary": "🔴 Контейнер {{ index $labels `name` }} на хосте {{ index $labels `instance` }} упал. Текущее значение: {{ $values.A.Value }}" + "summary": "🔴 {{ $labels.instance }}: контейнер упал {{ (index $values \"A\").Value | printf \"%.1f\" }}% (порог )", + "circle": "🔴", + "alert_text": "контейнер упал", + "value_key": "A", + "threshold": "" }, "data": [ { @@ -1399,10 +1463,254 @@ } ], "annotations": { - "summary": "🔴 {{ $labels.instance }}: служба angie.service не активна" + "summary": "🔴 {{ $labels.instance }}: служба angie.service не активна", + "circle": "🔴", + "alert_text": "служба angie.service не активна", + "value_key": "", + "threshold": "" }, "ruleGroup": "[SYSTEM]" }, + { + "uid": "blackbox_tcp_80", + "title": "[SYS] TCP Port 80 Unavailable", + "condition": "Превышение", + "for": "15s", + "no_data_state": "NoData", + "exec_err_state": "Error", + "isPaused": true, + "folderUID": "", + "ruleGroup": "[SYSTEM]", + "annotations": { + "summary": "🔴 Хост {{ $labels.host }} ({{ $labels.instance }}): недоступен TCP порт 80" + }, + "data": [ + { + "refId": "A", + "relativeTimeRange": { + "from": 60, + "to": 0 + }, + "datasourceUid": "deibaq3pwytxce", + "model": { + "datasource": { + "type": "prometheus", + "uid": "deibaq3pwytxce" + }, + "editorMode": "code", + "expr": "probe_success{job=\"blackbox_tcp\",instance=~\".*:80\"}", + "instant": true, + "intervalMs": 1000, + "legendFormat": "{{host}}", + "maxDataPoints": 43200, + "range": false, + "refId": "A" + } + }, + { + "refId": "Превышение", + "relativeTimeRange": { + "from": 0, + "to": 0 + }, + "datasourceUid": "__expr__", + "model": { + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "lt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "Превышение" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "datasource": { + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "A", + "intervalMs": 1000, + "maxDataPoints": 43200, + "refId": "Превышение", + "type": "threshold" + } + } + ] + }, + { + "uid": "blackbox_tcp_443", + "title": "[SYS] TCP Port 443 Unavailable", + "condition": "Превышение", + "for": "15s", + "no_data_state": "NoData", + "exec_err_state": "Error", + "isPaused": true, + "folderUID": "", + "ruleGroup": "[SYSTEM]", + "annotations": { + "summary": "🔴 Хост {{ $labels.host }} ({{ $labels.instance }}): недоступен TCP порт 443" + }, + "data": [ + { + "refId": "A", + "relativeTimeRange": { + "from": 60, + "to": 0 + }, + "datasourceUid": "deibaq3pwytxce", + "model": { + "datasource": { + "type": "prometheus", + "uid": "deibaq3pwytxce" + }, + "editorMode": "code", + "expr": "probe_success{job=\"blackbox_tcp\",instance=~\".*:443\"}", + "instant": true, + "intervalMs": 1000, + "legendFormat": "{{host}}", + "maxDataPoints": 43200, + "range": false, + "refId": "A" + } + }, + { + "refId": "Превышение", + "relativeTimeRange": { + "from": 0, + "to": 0 + }, + "datasourceUid": "__expr__", + "model": { + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "lt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "Превышение" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "datasource": { + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "A", + "intervalMs": 1000, + "maxDataPoints": 43200, + "refId": "Превышение", + "type": "threshold" + } + } + ] + }, + { + "uid": "blackbox_icmp", + "title": "[SYS] ICMP Unavailable", + "condition": "Превышение", + "for": "15s", + "no_data_state": "NoData", + "exec_err_state": "Error", + "isPaused": true, + "folderUID": "", + "ruleGroup": "[SYSTEM]", + "annotations": { + "summary": "🔴 Хост {{ $labels.host }} ({{ $labels.instance }}): недоступен по ICMP (ping)" + }, + "data": [ + { + "refId": "A", + "relativeTimeRange": { + "from": 60, + "to": 0 + }, + "datasourceUid": "deibaq3pwytxce", + "model": { + "datasource": { + "type": "prometheus", + "uid": "deibaq3pwytxce" + }, + "editorMode": "code", + "expr": "probe_success{job=\"blackbox_icmp\",host=~\".+\"}", + "instant": true, + "intervalMs": 1000, + "legendFormat": "{{host}}", + "maxDataPoints": 43200, + "range": false, + "refId": "A" + } + }, + { + "refId": "Превышение", + "relativeTimeRange": { + "from": 0, + "to": 0 + }, + "datasourceUid": "__expr__", + "model": { + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "lt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "Превышение" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "datasource": { + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "A", + "intervalMs": 1000, + "maxDataPoints": 43200, + "refId": "Превышение", + "type": "threshold" + } + } + ] + }, { "uid": "shm_usage_75pct", "title": "[Docker] SHM Usage 75%", @@ -1610,6 +1918,6 @@ ], "contact_point": { "receiver_name": "tg+mail+mattermost PTAF Grafana", - "message_template": "{{ range .Alerts }}{{ if eq .Status \"firing\" }}🔴 Firing{{ else }}✅ Resolved{{ end }}\n{{ if .Annotations.client_domain }}{{ if eq .Annotations.severity \"warning\" }}🟡 {{ .Annotations.client_domain }} — {{ if .Annotations.code_field }}{{ .Annotations.code_field }}{{ end }} кодов ответа{{ if index .Values \"_Reduce\" }} на WAF {{ index .Values \"_Reduce\" | printf \"%.0f\" }} {{ if .Annotations.value_unit }}{{ .Annotations.value_unit }}{{ end }}{{ end }} {{ if .Annotations.field_info }}{{ .Annotations.field_info }}{{ end }}\n{{ if .Annotations.threshold_count }}Пороговое значение {{ .Annotations.threshold_count }}\n{{ end }}{{ else }}{{ if eq .Status \"firing\" }}🔴 {{ .Annotations.client_domain }} — {{ .Annotations.code_field }} ошибок > {{ .Annotations.threshold_value }}% держится > {{ .Annotations.for_duration }}.\nТекущее значение: {{ if index .Values \"Значение\" }}{{ index .Values \"Значение\" | printf \"%.2f\" }}%{{ end }}{{ if index .Values \"_Reduce\" }}{{ index .Values \"_Reduce\" | printf \"%.2f\" }}%{{ end }} {{ if .Annotations.field_info }}{{ .Annotations.field_info }}{{ end }}\n{{ else }}🔴 {{ .Annotations.client_domain }} — {{ .Annotations.code_field }} ошибок < {{ .Annotations.threshold_value }}%.\n{{ end }}{{ end }}{{ else }}{{ if .Annotations.summary }}{{ .Annotations.summary }}\n{{ end }}{{ end }}{{ if eq .Status \"firing\" }}Время сработки алерта: {{ .StartsAt.Format \"2006-01-02 15:04:05 UTC\" }}{{ else }}Время разрешения алерта: {{ .EndsAt.Format \"2006-01-02 15:04:05 UTC\" }}{{ end }}\n{{ if eq .Status \"firing\" }}{{ if .Annotations.runbook }}\nНеобходимо {{ .Annotations.runbook }}\n{{ end }}{{ end }}{{ end }}" + "message_template": "{{ range .Alerts }}{{ if eq .Status \"firing\" }}🔴 Firing{{ else }}✅ Resolved{{ end }}\n{{ if .Annotations.client_domain }}{{ if .Annotations.value_unit }}🟡 {{ .Annotations.client_domain }}{{ if index .Values \"_Reduce\" }} — {{ .Annotations.code_field }} кодов ответа на WAF {{ index .Values \"_Reduce\" | printf \"%.0f\" }} {{ .Annotations.value_unit }}{{ end }} {{ if .Annotations.field_info }}{{ .Annotations.field_info }}{{ end }}\n{{ if .Annotations.threshold_count }}Пороговое значение {{ .Annotations.threshold_count }}\n{{ end }}{{ else }}{{ if eq .Status \"firing\" }}{{ if eq .Annotations.severity \"warning\" }}🟡{{ else }}🔴{{ end }} {{ .Annotations.client_domain }} — {{ .Annotations.code_field }} ошибок > {{ .Annotations.threshold_value }}% держится > {{ .Annotations.for_duration }}.\nТекущее значение: {{ if index .Values \"Значение\" }}{{ index .Values \"Значение\" | printf \"%.2f\" }}%{{ end }}{{ if index .Values \"_Reduce\" }}{{ index .Values \"_Reduce\" | printf \"%.2f\" }}%{{ end }} {{ if .Annotations.field_info }}{{ .Annotations.field_info }}{{ end }}\n{{ else }}{{ if eq .Annotations.severity \"warning\" }}🟡{{ else }}🔴{{ end }} {{ .Annotations.client_domain }} — {{ .Annotations.code_field }} ошибок < {{ .Annotations.threshold_value }}%.\n{{ end }}{{ end }}{{ else }}{{ if .Annotations.circle }}{{ .Annotations.circle }} {{ .Labels.instance }}: {{ .Annotations.alert_text }}{{ if .Annotations.value_key }} {{ index .Values .Annotations.value_key | printf \"%.1f\" }}% (порог {{ .Annotations.threshold }}){{ end }}\n{{ else }}{{ if .Annotations.summary }}{{ .Annotations.summary }}\n{{ end }}{{ end }}{{ end }}{{ if eq .Status \"firing\" }}Время сработки алерта: {{ .StartsAt.Format \"2006-01-02 15:04:05 UTC\" }}{{ else }}Время разрешения алерта: {{ .EndsAt.Format \"2006-01-02 15:04:05 UTC\" }}{{ end }}\n{{ if eq .Status \"firing\" }}{{ if .Annotations.runbook }}\nНеобходимо {{ .Annotations.runbook }}\n{{ end }}{{ end }}{{ end }}" } } \ No newline at end of file diff --git a/dashboard_template.json b/dashboard_template.json old mode 100644 new mode 100755