init stacks
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -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
|
||||
Reference in New Issue
Block a user