init stacks

This commit is contained in:
tan-docker
2026-03-21 14:12:55 +01:00
commit d3e8da2e25
1919 changed files with 200787 additions and 0 deletions
@@ -0,0 +1,31 @@
def analyze(metrics: dict):
alerts = []
if metrics.get("cpu"):
cpu = float(metrics["cpu"][0]["value"][1])
if cpu > 85:
alerts.append({
"title": "CPU élevée",
"cause": f"{cpu:.1f} %",
"severity": "warning",
})
if metrics.get("memory"):
mem = float(metrics["memory"][0]["value"][1])
if mem > 90:
alerts.append({
"title": "Mémoire saturée",
"cause": f"{mem:.1f} %",
"severity": "critical",
})
if metrics.get("containers_down"):
down = int(float(metrics["containers_down"][0]["value"][1]))
if down > 0:
alerts.append({
"title": "Containers arrêtés",
"cause": f"{down} détecté(s)",
"severity": "critical",
})
return alerts
@@ -0,0 +1,14 @@
from api.connectors.prometheus import (
get_cpu_usage,
get_memory_usage,
get_disk_usage,
get_container_down,
)
def collect_metrics():
return {
"cpu": get_cpu_usage(),
"memory": get_memory_usage(),
"disk": get_disk_usage(),
"containers_down": get_container_down(),
}
@@ -0,0 +1,44 @@
import yaml
with open("correlation/rules.yaml") as f:
RULES = yaml.safe_load(f)
def correlate(alert):
service = alert["service"]
rules = RULES["services"].get(service, {})
return {
"service": service,
"severity": alert["severity"],
"metrics": alert["metrics"],
"depends_on": rules.get("depends_on", []),
"impact": rules.get("impact", [])
}
def evaluate(rules: list, metrics: dict):
incidents = []
for rule in rules:
matched = True
for metric, condition in rule["when"].items():
value = metrics.get(metric)
if value is None:
matched = False
break
if "gt" in condition and value <= condition["gt"]:
matched = False
if "lt" in condition and value >= condition["lt"]:
matched = False
if matched:
incidents.append({
"id": rule["id"],
"severity": rule["severity"],
"impact": rule["impact"],
"metrics": metrics,
})
return incidents
@@ -0,0 +1,14 @@
import yaml
from pathlib import Path
RULES_FILE = Path(__file__).parent / "rules.yaml"
def load_rules():
if not RULES_FILE.exists():
return []
with RULES_FILE.open("r") as f:
data = yaml.safe_load(f) or {}
return data.get("rules", [])
@@ -0,0 +1,34 @@
services:
jellyfin:
depends_on:
- tdarr
- cpu
impact:
- media
- nextcloud
nextcloud:
depends_on:
- database
- redis
rules:
- id: cpu_ram_pressure
description: CPU élevé + mémoire sous pression
when:
cpu:
gt: 80
for: 5m
memory_available:
lt: 15
impact: "Risque fort de ralentissement général"
severity: high
- id: io_wait_saturation
description: IO wait élevé
when:
io_wait:
gt: 20
for: 3m
impact: "Disque saturé, latences applicatives"
severity: high