fix(unraid): expose sanitized inference error detail

This commit is contained in:
Codex
2026-08-15 09:42:46 -07:00
parent 6eff349f02
commit 89da9c782b
@@ -41,6 +41,7 @@ class State:
self.inference_fault = False self.inference_fault = False
self.ws_source_ok = False self.ws_source_ok = False
self.error_code: str | None = None self.error_code: str | None = None
self.error_detail: str | None = None
self.frame_id = 0 self.frame_id = 0
self.messages = 0 self.messages = 0
self.frames_dropped = 0 self.frames_dropped = 0
@@ -97,7 +98,8 @@ def health():
"last_frame_age_ms": round(age, 3) if age is not None else None, "last_frame_age_ms": round(age, 3) if age is not None else None,
"actual_width": state.width or None, "actual_height": state.height or None}, "actual_width": state.width or None, "actual_height": state.height or None},
"models": {"detector_ready": state.models_ready, "pose_ready": state.models_ready}, "models": {"detector_ready": state.models_ready, "pose_ready": state.models_ready},
"error_code": state.error_code, "uptime_seconds": round(time.monotonic() - state.started, 1)} "error_code": state.error_code, "error_detail": state.error_detail,
"uptime_seconds": round(time.monotonic() - state.started, 1)}
@app.get("/v1/capabilities", dependencies=[Depends(authorized)]) @app.get("/v1/capabilities", dependencies=[Depends(authorized)])
@@ -144,14 +146,16 @@ def inference_worker(loop: asyncio.AbstractEventLoop) -> None:
threshold = float(os.getenv("DETECTION_THRESHOLD", ".35")); max_people = int(os.getenv("MAX_PEOPLE", "4")) threshold = float(os.getenv("DETECTION_THRESHOLD", ".35")); max_people = int(os.getenv("MAX_PEOPLE", "4"))
try: try:
models.load(); state.models_ready = True; LOG.info("official detector and pose checkpoints loaded") models.load(); state.models_ready = True; LOG.info("official detector and pose checkpoints loaded")
except Exception: except Exception as exc:
state.inference_fault = True; state.error_code = "MODEL_LOAD_FAILED"; LOG.exception("model loading failed"); return state.inference_fault = True; state.error_code = "MODEL_LOAD_FAILED"
state.error_detail = f"{type(exc).__name__}: {str(exc)[:240]}"; LOG.exception("model loading failed"); return
while True: while True:
frame = frames.get(); started_ns = time.time_ns(); perf = time.perf_counter_ns() frame = frames.get(); started_ns = time.time_ns(); perf = time.perf_counter_ns()
try: try:
people, det_ms, pose_ms = models.infer(frame.pixels, threshold, max_people) people, det_ms, pose_ms = models.infer(frame.pixels, threshold, max_people)
finished_ns = time.time_ns(); total_ms = (time.perf_counter_ns() - perf) / 1e6 finished_ns = time.time_ns(); total_ms = (time.perf_counter_ns() - perf) / 1e6
state.frame_id += 1; state.cuda_inference_ok = True; state.inference_fault = False; state.error_code = None state.frame_id += 1; state.cuda_inference_ok = True; state.inference_fault = False
state.error_code = None; state.error_detail = None
msg = {"schema": "tail2.pose.v1", "stream_id": config["stream_id"], "session_id": state.session_id, msg = {"schema": "tail2.pose.v1", "stream_id": config["stream_id"], "session_id": state.session_id,
"frame_id": state.frame_id, "source_received_unix_ns": frame.received_ns, "frame_id": state.frame_id, "source_received_unix_ns": frame.received_ns,
"inference_started_unix_ns": started_ns, "inference_finished_unix_ns": finished_ns, "inference_started_unix_ns": started_ns, "inference_finished_unix_ns": finished_ns,
@@ -164,8 +168,9 @@ def inference_worker(loop: asyncio.AbstractEventLoop) -> None:
"error": None} "error": None}
state.inference_ms.append(total_ms); state.messages += 1; state.ws_source_ok = True state.inference_ms.append(total_ms); state.messages += 1; state.ws_source_ok = True
hub.publish_on_loop(loop, msg) hub.publish_on_loop(loop, msg)
except Exception: except Exception as exc:
state.inference_fault = True; state.error_code = "INFERENCE_FAILED"; LOG.exception("inference failed") state.inference_fault = True; state.error_code = "INFERENCE_FAILED"
state.error_detail = f"{type(exc).__name__}: {str(exc)[:240]}"; LOG.exception("inference failed")
@app.on_event("startup") @app.on_event("startup")
@@ -178,4 +183,3 @@ async def startup() -> None:
if __name__ == "__main__": if __name__ == "__main__":
uvicorn.run(app, host=os.getenv("API_BIND", "0.0.0.0"), port=int(os.getenv("API_PORT", "18120")), uvicorn.run(app, host=os.getenv("API_BIND", "0.0.0.0"), port=int(os.getenv("API_PORT", "18120")),
access_log=False, ws_max_size=65536) access_log=False, ws_max_size=65536)