Studio: add option to disable the in-memory API monitor (#7156)

---------

Co-authored-by: oobabooga <112222186+oobabooga@users.noreply.github.com>
This commit is contained in:
Gaurav Dubey 2026-07-28 07:17:24 +05:30 committed by GitHub
commit 36e83de336
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 78 additions and 2 deletions

View file

@ -5,6 +5,7 @@
from __future__ import annotations
import os
import threading
import time
import uuid
@ -18,6 +19,14 @@ _MAX_PROMPT_CHARS = 12000
_MAX_REPLY_CHARS = 12000
_PREVIEW_CHARS = 360
# Opt-in startup kill switch for Studio's in-memory API monitor.
_DISABLE_ENV = "UNSLOTH_STUDIO_DISABLE_API_MONITOR"
_TRUE_VALUES = frozenset({"1", "true", "yes", "on"})
def _api_monitor_disabled() -> bool:
return os.environ.get(_DISABLE_ENV, "").strip().lower() in _TRUE_VALUES
def _trim(text: Optional[str], limit: int) -> str:
if not text:
@ -104,10 +113,16 @@ class ApiMonitorEntry:
class ApiMonitor:
def __init__(self, max_entries: int = _MAX_ENTRIES):
def __init__(
self,
max_entries: int = _MAX_ENTRIES,
*,
enabled: bool = True,
):
self._entries: deque[ApiMonitorEntry] = deque()
self._max_entries = max(0, max_entries)
self._lock = threading.Lock()
self._enabled = enabled
def start(
self,
@ -119,6 +134,8 @@ class ApiMonitor:
context_length: Optional[int] = None,
subject: Optional[str] = None,
) -> str:
if not self._enabled:
return ""
now = time.time()
entry = ApiMonitorEntry(
id = f"apireq_{uuid.uuid4().hex[:12]}",
@ -152,6 +169,8 @@ class ApiMonitor:
:meth:`fail`; an unload is terminal on arrival. Rows are shared (visible to
every subject) and share the request retention budget.
"""
if not self._enabled:
return ""
now = time.time()
entry = ApiMonitorEntry(
id = f"apievt_{uuid.uuid4().hex[:12]}",
@ -392,4 +411,4 @@ class ApiMonitor:
self._entries = kept
api_monitor = ApiMonitor()
api_monitor = ApiMonitor(enabled = not _api_monitor_disabled())

View file

@ -260,6 +260,63 @@ def test_api_monitor_append_reply_exact_cap_then_more_marks_truncated():
assert len(reply) == m._MAX_REPLY_CHARS and reply.endswith("...")
def test_api_monitor_disabled_is_noop():
monitor = ApiMonitor(max_entries = 3, enabled = False)
request_id = monitor.start(
endpoint = "/v1/chat/completions",
method = "POST",
model = "local-model",
prompt = "user: hello",
context_length = 100,
)
load_id = monitor.record_lifecycle(
event = "load",
model = "local-model",
running = True,
)
unload_id = monitor.record_lifecycle(
event = "unload",
model = "local-model",
)
assert request_id == load_id == unload_id == ""
# Every mutator must be a safe no-op on the falsy id.
monitor.append_reply(request_id, "hi")
monitor.set_reply(request_id, "hi")
monitor.set_usage(request_id, prompt_tokens = 4, completion_tokens = 6)
monitor.relabel(load_id, "renamed-model")
monitor.set_progress(load_id, 50)
monitor.finish(load_id)
monitor.fail_open(load_id, "boom")
monitor.fail(request_id, "boom")
monitor.discard(unload_id)
assert monitor.snapshot() == []
assert monitor.active_count() == 0
assert monitor.get(request_id) is None
def test_api_monitor_disable_env_var_truthy(monkeypatch):
import core.inference.api_monitor as m
for value in ("1", "true", "yes", "on", "TRUE", "On", " yes "):
monkeypatch.setenv(m._DISABLE_ENV, value)
assert m._api_monitor_disabled() is True, value
def test_api_monitor_disable_env_var_falsy(monkeypatch):
import core.inference.api_monitor as m
for value in ("", "0", "false", "no", "off", "disabled"):
monkeypatch.setenv(m._DISABLE_ENV, value)
assert m._api_monitor_disabled() is False, value
def test_api_monitor_disable_env_var_unset(monkeypatch):
import core.inference.api_monitor as m
monkeypatch.delenv(m._DISABLE_ENV, raising = False)
assert m._api_monitor_disabled() is False
# ── model lifecycle rows (load / unload) ────────────────────────────