fix: экспорт всех текущих проблем в Zabbix + совместимость шаблона с Zabbix 5.0

collect_and_alert теперь экспортирует ВСЕ текущие проблемные DAG-и,
а не только новые — Zabbix видит проблему пока DAG не починен.

Zabbix XML шаблон: version 5.0, убраны tags, preprocessing params,
triggers/graphs вынесены на верхний уровень, history 7d / trends 365d.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maksim Totmin
2026-04-09 10:11:27 +07:00
co-authored by Claude Opus 4.6
parent 289c308fcb
commit f3e1ad7df3
2 changed files with 138 additions and 219 deletions
+42 -42
View File
@@ -211,54 +211,54 @@ class ActionHandler:
return "needs_alert"
def collect_and_alert(self, issues: list[DagIssue]):
"""Export alerts for issues that need alerting.
"""Export all current issues and mark new ones as alerted.
Filters to only unalerted issues, builds JSON payload,
writes to file for Zabbix agent, and marks as alerted in state.
Always exports the full list of current problems so Zabbix sees them
until they are resolved. Only logs warnings for newly discovered issues.
"""
to_alert = []
# Build export payload for ALL current issues
all_problems = []
new_issues = []
for issue in issues:
entry = self._state.ensure_entry(issue.dag_id, issue.dag_run_id)
alert_data = {
"dag_id": issue.dag_id,
"dag_run_id": issue.dag_run_id,
"issue_type": issue.issue_type,
"status": issue.state,
"duration_seconds": issue.duration_seconds,
"error_info": issue.error_info,
"retry_count": entry["retry_count"],
}
all_problems.append(alert_data)
if not self._state.is_alerted(issue.dag_id, issue.dag_run_id):
entry = self._state.ensure_entry(issue.dag_id, issue.dag_run_id)
alert_data = {
"dag_id": issue.dag_id,
"dag_run_id": issue.dag_run_id,
"issue_type": issue.issue_type,
"status": issue.state,
"duration_seconds": issue.duration_seconds,
"error_info": issue.error_info,
"retry_count": entry["retry_count"],
}
to_alert.append(alert_data)
logger.debug(
"Issue queued for alert: %s/%s type=%s retries=%d",
issue.dag_id, issue.dag_run_id,
issue.issue_type, entry["retry_count"],
)
new_issues.append(issue)
if not to_alert:
# Write empty list to clear Zabbix trigger
if not all_problems:
self._exporter.export_problems([])
logger.info("No issues to alert, exported empty problem list")
logger.info("No issues, exported empty problem list")
return
logger.warning(
"Exporting %d problematic DAG runs for Zabbix: %s",
len(to_alert),
", ".join(
f"{p['dag_id']}/{p['dag_run_id']}({p['issue_type']})"
for p in to_alert
),
# Log new issues at warning level
if new_issues:
logger.warning(
"New problematic DAG runs: %s",
", ".join(
f"{i.dag_id}/{i.dag_run_id}({i.issue_type})"
for i in new_issues
),
)
logger.debug("Alert payload:\n%s", json.dumps(all_problems, indent=2, ensure_ascii=False))
self._exporter.export_problems(all_problems)
# Mark new issues as alerted
for issue in new_issues:
self._state.mark_alerted(issue.dag_id, issue.dag_run_id)
logger.debug("Marked as alerted: %s/%s", issue.dag_id, issue.dag_run_id)
logger.info(
"Exported %d issues to problems file (%d new)",
len(all_problems), len(new_issues),
)
# Log full alert payload at debug level
logger.debug("Alert payload:\n%s", json.dumps(to_alert, indent=2, ensure_ascii=False))
self._exporter.export_problems(to_alert)
for issue in issues:
if not self._state.is_alerted(issue.dag_id, issue.dag_run_id):
self._state.mark_alerted(issue.dag_id, issue.dag_run_id)
logger.debug("Marked as alerted: %s/%s", issue.dag_id, issue.dag_run_id)
logger.info("Exported %d issues to problems file for Zabbix agent", len(to_alert))