40-clients/ucepsa/edge-oee-demo/grafana/scripts/patch_machine_dashboard_pareto_clean.py
2026-06-25 18:51:33 +02:00

115 lines
3.0 KiB
Python
Executable File

#!/usr/bin/env python3
import base64
import json
import sys
import urllib.error
import urllib.request
from pathlib import Path
BASE_URL = "http://127.0.0.1:3000"
DASHBOARD_UID = "ucepsa-edge-oee-machine"
def read_env(path=".env"):
env = {}
p = Path(path)
if not p.exists():
return env
for raw in p.read_text().splitlines():
line = raw.strip()
if not line or line.startswith("#") or "=" not in line:
continue
key, value = line.split("=", 1)
env[key.strip()] = value.strip().strip('"').strip("'")
return env
env = read_env()
user = env.get("GRAFANA_ADMIN_USER", "admin")
password = env.get("GRAFANA_ADMIN_PASSWORD")
if not password:
print("ERROR: no encuentro GRAFANA_ADMIN_PASSWORD en .env", file=sys.stderr)
sys.exit(1)
token = base64.b64encode(f"{user}:{password}".encode()).decode()
def api(method, path, payload=None):
data = None
headers = {
"Authorization": f"Basic {token}",
"Content-Type": "application/json",
"Accept": "application/json",
}
if payload is not None:
data = json.dumps(payload).encode("utf-8")
req = urllib.request.Request(
BASE_URL + path,
data=data,
headers=headers,
method=method,
)
try:
with urllib.request.urlopen(req, timeout=30) as resp:
body = resp.read().decode("utf-8")
return json.loads(body) if body else {}
except urllib.error.HTTPError as e:
print("HTTP ERROR:", e.code, e.read().decode("utf-8"), file=sys.stderr)
raise
def walk_panels(panels):
for p in panels or []:
yield p
for child in walk_panels(p.get("panels", [])):
yield child
doc = api("GET", f"/api/dashboards/uid/{DASHBOARD_UID}")
dashboard = doc["dashboard"]
meta = doc.get("meta", {})
changed = 0
for panel in walk_panels(dashboard.get("panels", [])):
if panel.get("title") in ("Pareto causas de paro", "Pareto causas clasificadas"):
panel["title"] = "Pareto causas clasificadas por minutos"
for target in panel.get("targets", []):
target["rawSql"] = """
SELECT
cause_name AS "Causa",
ROUND(SUM(duration_min)::numeric, 2) AS "Minutos"
FROM mv_reports_ucepsa_demo.machine_stops_grafana
WHERE machine_id = '$machine_id'
AND classification_status = 'CLASSIFIED'
AND status = 'CLOSED'
GROUP BY cause_name
ORDER BY SUM(duration_min) DESC
LIMIT 10
"""
target["format"] = "table"
panel.setdefault("fieldConfig", {}).setdefault("defaults", {})["unit"] = "min"
changed += 1
payload = {
"dashboard": dashboard,
"overwrite": True,
"message": "Clean stop cause pareto panel",
}
if meta.get("folderUid"):
payload["folderUid"] = meta["folderUid"]
result = api("POST", "/api/dashboards/db", payload)
print(f"Paneles modificados: {changed}")
print("Dashboard actualizado:")
print(BASE_URL + result.get("url", f"/d/{DASHBOARD_UID}"))