Attribute API-key traffic on the lifecycle rows it creates
The overlay opens on API-key traffic only, and record_lifecycle never set that flag. Auto-switch and auto-download run before the endpoint opens its request row, so a switch or a download that is refused never reaches api_monitor.start and its lifecycle row is the whole trace of the request. The monitor therefore stayed shut on exactly the failures automatic observability is for. The row now carries the attribution: a load takes it from the request that drove it, and auto-download passes it directly, since only an API request reaches that path at all. A manual unload and an idle unload are not API traffic and stay unattributed, so neither pops the overlay.
This commit is contained in:
parent
9df8bedda2
commit
384a55de43
4 changed files with 36 additions and 1 deletions
|
|
@ -173,6 +173,7 @@ class ApiMonitor:
|
|||
model: str,
|
||||
reason: Optional[str] = None,
|
||||
running: bool = False,
|
||||
via_api_key: bool = False,
|
||||
) -> str:
|
||||
"""Record a model load/unload alongside the request traffic that caused it.
|
||||
|
||||
|
|
@ -199,6 +200,11 @@ class ApiMonitor:
|
|||
event = event,
|
||||
reason = reason,
|
||||
shared = True,
|
||||
# The overlay opens on API-key traffic only. A switch or download that
|
||||
# is refused never reaches api_monitor.start, so this row is the whole
|
||||
# trace of it, and without the attribution the monitor stayed shut on
|
||||
# exactly the failures it exists to surface.
|
||||
via_api_key = via_api_key,
|
||||
)
|
||||
with self._lock:
|
||||
self._entries.appendleft(entry)
|
||||
|
|
|
|||
|
|
@ -777,7 +777,8 @@ async def _dispatch(
|
|||
return busy
|
||||
|
||||
monitor_id = api_monitor.record_lifecycle(
|
||||
event = "download", model = label, reason = "api", running = True
|
||||
# Only an API request reaches auto-download, hence reason "api".
|
||||
event = "download", model = label, reason = "api", running = True, via_api_key = True
|
||||
)
|
||||
with _lock:
|
||||
if _active is active:
|
||||
|
|
|
|||
|
|
@ -5321,6 +5321,9 @@ async def _load_model_impl(
|
|||
event = "load",
|
||||
model = _lifecycle_model_label(request.model_path, request.gguf_variant),
|
||||
running = True,
|
||||
# Auto-switch loads run before the endpoint opens its request row, so a
|
||||
# load that fails there leaves this as the only trace of API traffic.
|
||||
via_api_key = _request_used_api_key(fastapi_request),
|
||||
)
|
||||
|
||||
native_grant_backed = False
|
||||
|
|
|
|||
|
|
@ -517,3 +517,28 @@ def test_hidden_shared_ids_do_not_outlive_their_entries():
|
|||
for i in range(5):
|
||||
monitor.record_lifecycle(event = "unload", model = f"org/M{i}")
|
||||
assert not monitor._hidden_shared.get("alice")
|
||||
|
||||
|
||||
def test_an_api_triggered_lifecycle_row_carries_the_attribution():
|
||||
"""The overlay opens on API-key traffic only. An auto-switch or auto-download
|
||||
that is refused never reaches api_monitor.start, so the lifecycle row is the
|
||||
whole trace of that request; without the attribution the monitor stayed shut
|
||||
on exactly the failures it exists to surface."""
|
||||
monitor = ApiMonitor(max_entries = 5)
|
||||
|
||||
api_load = monitor.record_lifecycle(
|
||||
event = "load", model = "org/Repo-GGUF", running = True, via_api_key = True
|
||||
)
|
||||
monitor.record_lifecycle(event = "unload", model = "org/Repo-GGUF", reason = "idle")
|
||||
|
||||
rows = {e["id"]: e for e in monitor.snapshot()}
|
||||
assert rows[api_load]["via_api_key"] is True
|
||||
# A background unload is not API traffic and must not pop the overlay.
|
||||
idle = [e for e in rows.values() if e["event"] == "unload"]
|
||||
assert idle and all(e["via_api_key"] is False for e in idle)
|
||||
|
||||
# The failure path keeps it: failing the row must not drop the attribution.
|
||||
monitor.fail(api_load, error = "auto-switch refused")
|
||||
after = {e["id"]: e for e in monitor.snapshot()}
|
||||
assert after[api_load]["via_api_key"] is True
|
||||
assert after[api_load]["status"] == "error"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue