ffmpeg fix
This commit is contained in:
88
cht/telemetry.py
Normal file
88
cht/telemetry.py
Normal file
@@ -0,0 +1,88 @@
|
||||
"""Session telemetry — lightweight event/metric log for post-run analysis.
|
||||
|
||||
Writes a JSON-lines file (one event per line) to the session directory.
|
||||
Each event has a timestamp, type, and payload. Designed to be grep-friendly.
|
||||
|
||||
Usage:
|
||||
tel = Telemetry(session_dir)
|
||||
tel.event("scene_threshold_changed", {"from": 0.10, "to": 0.15})
|
||||
tel.metric("scene_detection", {"start": 120.0, "end": 135.0, "frames_found": 3, "elapsed_ms": 1200})
|
||||
tel.close()
|
||||
"""
|
||||
|
||||
import json
|
||||
import logging
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Telemetry:
|
||||
def __init__(self, session_dir: Path):
|
||||
self._path = session_dir / "telemetry.jsonl"
|
||||
self._start = time.monotonic()
|
||||
self._wall_start = time.time()
|
||||
self._file = None
|
||||
self._log_handler = None
|
||||
try:
|
||||
session_dir.mkdir(parents=True, exist_ok=True)
|
||||
self._file = open(self._path, "a")
|
||||
except Exception as e:
|
||||
log.warning("Telemetry init failed: %s", e)
|
||||
|
||||
# Also save full logs to session directory
|
||||
try:
|
||||
log_path = session_dir / "session.log"
|
||||
handler = logging.FileHandler(str(log_path), mode="a")
|
||||
handler.setLevel(logging.DEBUG)
|
||||
handler.setFormatter(logging.Formatter(
|
||||
"%(asctime)s %(levelname)-7s %(name)s: %(message)s",
|
||||
datefmt="%H:%M:%S",
|
||||
))
|
||||
logging.getLogger().addHandler(handler)
|
||||
self._log_handler = handler
|
||||
except Exception as e:
|
||||
log.warning("Log file handler failed: %s", e)
|
||||
|
||||
self.event("session_start", {"session_dir": str(session_dir)})
|
||||
|
||||
def event(self, name: str, data: dict | None = None) -> None:
|
||||
"""Log a discrete event (setting change, mode switch, user action)."""
|
||||
self._write("event", name, data or {})
|
||||
|
||||
def metric(self, name: str, data: dict) -> None:
|
||||
"""Log a measurement (processing time, frame count, etc)."""
|
||||
self._write("metric", name, data)
|
||||
|
||||
def _write(self, kind: str, name: str, data: dict) -> None:
|
||||
if not self._file:
|
||||
return
|
||||
entry = {
|
||||
"t": round(time.monotonic() - self._start, 3),
|
||||
"wall": round(time.time(), 3),
|
||||
"kind": kind,
|
||||
"name": name,
|
||||
**data,
|
||||
}
|
||||
try:
|
||||
self._file.write(json.dumps(entry) + "\n")
|
||||
self._file.flush()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def close(self) -> None:
|
||||
self.event("session_end", {})
|
||||
if self._log_handler:
|
||||
logging.getLogger().removeHandler(self._log_handler)
|
||||
try:
|
||||
self._log_handler.close()
|
||||
except Exception:
|
||||
pass
|
||||
self._log_handler = None
|
||||
if self._file:
|
||||
try:
|
||||
self._file.close()
|
||||
except Exception:
|
||||
pass
|
||||
self._file = None
|
||||
Reference in New Issue
Block a user