mirror of
https://github.com/Alkatrazz24/Funk-lab.git
synced 2026-07-09 01:14:42 +02:00
BrokenPipeError corrigé : send_response(200) envoyé avant subprocess. ask-agent lancé en threading.Thread daemon — AlertManager n'attend plus. NO_COLOR=1 + TERM=dumb pour éviter les codes ANSI dans les logs. docs: alertmanager-webhook.md — architecture, flux, test, dépannage Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
95 lines
3.3 KiB
Python
95 lines
3.3 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
AlertManager webhook → ask-agent monitor
|
|
Reçoit les alertes Prometheus et les délègue au profil monitor de Hermes.
|
|
"""
|
|
import json
|
|
import os
|
|
import subprocess
|
|
import logging
|
|
import threading
|
|
from http.server import HTTPServer, BaseHTTPRequestHandler
|
|
from datetime import datetime
|
|
|
|
logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)s %(message)s')
|
|
log = logging.getLogger(__name__)
|
|
|
|
PORT = int(os.environ.get("WEBHOOK_PORT", 9093))
|
|
|
|
|
|
def format_alert(alert: dict) -> str:
|
|
name = alert.get("labels", {}).get("alertname", "unknown")
|
|
severity = alert.get("labels", {}).get("severity", "unknown")
|
|
instance = alert.get("labels", {}).get("instance", "unknown")
|
|
summary = alert.get("annotations", {}).get("summary", "")
|
|
description = alert.get("annotations", {}).get("description", "")
|
|
status = alert.get("status", "firing")
|
|
return f"[{status.upper()}] {name} — severity={severity} instance={instance}\n{summary}\n{description}".strip()
|
|
|
|
|
|
class WebhookHandler(BaseHTTPRequestHandler):
|
|
def do_POST(self):
|
|
if self.path != "/webhook":
|
|
self.send_response(404)
|
|
self.end_headers()
|
|
return
|
|
|
|
length = int(self.headers.get("Content-Length", 0))
|
|
body = self.rfile.read(length)
|
|
|
|
try:
|
|
payload = json.loads(body)
|
|
except json.JSONDecodeError:
|
|
log.error("Invalid JSON payload")
|
|
self.send_response(400)
|
|
self.end_headers()
|
|
return
|
|
|
|
alerts = payload.get("alerts", [])
|
|
firing = [a for a in alerts if a.get("status") == "firing"]
|
|
resolved = [a for a in alerts if a.get("status") == "resolved"]
|
|
|
|
if not alerts:
|
|
self.send_response(200)
|
|
self.end_headers()
|
|
return
|
|
|
|
lines = [f"Alertes Prometheus reçues à {datetime.now().strftime('%H:%M:%S')} :"]
|
|
for a in firing:
|
|
lines.append(format_alert(a))
|
|
for a in resolved:
|
|
lines.append(format_alert(a))
|
|
|
|
message = "\n".join(lines) + "\n\nAnalyse ces alertes : sont-elles critiques ? Quelles actions recommandes-tu ?"
|
|
|
|
log.info(f"Forwarding {len(firing)} firing + {len(resolved)} resolved alerts to ask-agent monitor")
|
|
|
|
self.send_response(200)
|
|
self.end_headers()
|
|
self.wfile.write(b"ok")
|
|
|
|
def run_agent():
|
|
try:
|
|
env = {**os.environ, "NO_COLOR": "1", "TERM": "dumb"}
|
|
result = subprocess.run(
|
|
["/usr/local/bin/ask-agent", "monitor", message],
|
|
capture_output=True, text=True, timeout=120, env=env
|
|
)
|
|
log.info(f"ask-agent response: {result.stdout[:200]}")
|
|
if result.returncode != 0:
|
|
log.error(f"ask-agent stderr: {result.stderr[:200]}")
|
|
except subprocess.TimeoutExpired:
|
|
log.error("ask-agent timed out")
|
|
except Exception as e:
|
|
log.error(f"ask-agent error: {e}")
|
|
|
|
threading.Thread(target=run_agent, daemon=True).start()
|
|
|
|
def log_message(self, format, *args):
|
|
pass # silence HTTP access logs
|
|
|
|
|
|
if __name__ == "__main__":
|
|
log.info(f"AlertManager webhook listening on :{PORT}")
|
|
server = HTTPServer(("0.0.0.0", PORT), WebhookHandler)
|
|
server.serve_forever()
|