Files
boc/life-weather/monitor.py
T
Bernt aee0f09db8 landvex: Fixar och tester klara för alla komponenter
- Datafabrik: Dockerfile fix, agentorkestrering fungerar
- Vision: Identify-modell, FAISS, OCR alla testade
- API: Alla 7 integrationstester passerade
- Upplösare: Entitetsupplösning verifierad
2026-07-05 06:41:32 +00:00

133 lines
3.9 KiB
Python

#!/usr/bin/env python3
"""
LIFE Runtime Monitor
Samlar operativa mätvärden under burn-in
"""
import sqlite3
import json
import time
from datetime import datetime, timedelta
from pathlib import Path
DB_PATH = "/home/bernt/.openclaw/workspace/rivp-pilot-1/rivp.db"
LOG_DIR = Path("/home/bernt/.openclaw/workspace/life-weather/logs")
METRICS_FILE = Path("/home/bernt/.openclaw/workspace/life-weather/metrics.json")
def collect_metrics():
"""Samla mätvärden från databasen"""
conn = sqlite3.connect(DB_PATH)
c = conn.cursor()
metrics = {
"timestamp": datetime.now().isoformat(),
"pipeline": {},
"observations": {},
"system": {}
}
# Pipeline-mätvärden
c.execute("SELECT COUNT(*) FROM weather_observations")
total_obs = c.fetchone()[0]
c.execute("""
SELECT COUNT(*) FROM weather_observations
WHERE created_at > datetime('now', '-1 hour')
""")
obs_last_hour = c.fetchone()[0]
# Dubbletter
c.execute("""
SELECT road_id, observation_type, timestamp, COUNT(*) as cnt
FROM weather_observations
GROUP BY road_id, observation_type, timestamp
HAVING cnt > 1
""")
duplicates = len(c.fetchall())
# Reality Latency
c.execute("""
SELECT MAX(created_at) FROM weather_observations
""")
last_obs = c.fetchone()[0]
if last_obs:
last_time = datetime.fromisoformat(last_obs)
latency_minutes = (datetime.now() - last_time).total_seconds() / 60
else:
latency_minutes = None
metrics["observations"] = {
"total": total_obs,
"last_hour": obs_last_hour,
"duplicates": duplicates,
"reality_latency_minutes": round(latency_minutes, 1) if latency_minutes else None
}
# System-mätvärden (från loggar)
log_file = LOG_DIR / "scheduler.log"
if log_file.exists():
with open(log_file) as f:
lines = f.readlines()
# Räkna fel
errors = [l for l in lines if "ERROR" in l]
warnings = [l for l in lines if "WARNING" in l]
metrics["pipeline"] = {
"total_runs": len([l for l in lines if "WEATHER JOB STARTAR" in l]),
"errors": len(errors),
"warnings": len(warnings)
}
conn.close()
# Spara mätvärden
if METRICS_FILE.exists():
with open(METRICS_FILE) as f:
history = json.load(f)
else:
history = []
history.append(metrics)
# Behåll senaste 168 timmar (7 dagar)
cutoff = datetime.now() - timedelta(hours=168)
history = [h for h in history if datetime.fromisoformat(h["timestamp"]) > cutoff]
with open(METRICS_FILE, 'w') as f:
json.dump(history, f, indent=2)
return metrics
def print_status():
"""Skriv ut aktuell status"""
metrics = collect_metrics()
print("=" * 60)
print("LIFE RUNTIME STATUS")
print("=" * 60)
print(f"Tid: {metrics['timestamp']}")
print()
print("OBSERVATIONER:")
print(f" Total: {metrics['observations']['total']}")
print(f" Senaste timmen: {metrics['observations']['last_hour']}")
print(f" Dubbletter: {metrics['observations']['duplicates']}")
print(f" Reality Latency: {metrics['observations']['reality_latency_minutes']} min")
print()
print("PIPELINE:")
print(f" Körningar: {metrics['pipeline'].get('total_runs', 0)}")
print(f" Fel: {metrics['pipeline'].get('errors', 0)}")
print(f" Varningar: {metrics['pipeline'].get('warnings', 0)}")
print()
# Beräkna success rate
total = metrics['pipeline'].get('total_runs', 0)
errors = metrics['pipeline'].get('errors', 0)
if total > 0:
success_rate = ((total - errors) / total) * 100
print(f" Success Rate: {success_rate:.1f}%")
print("=" * 60)
if __name__ == "__main__":
print_status()