fix(langfuse): warn once per invalid HERMES_LANGFUSE_MAX_DEPTH value, not per payload

#116713 parsed HERMES_LANGFUSE_MAX_DEPTH inside `_safe_value`, i.e. once per
captured prompt, response, tool input and tool output. With an invalid value
(`abc`) every captured field logged the same "Invalid ... Falling back to 4"
WARNING for the life of the process — one multi-tool turn fills agent.log.

Resolve the depth in `_resolve_max_depth`, an lru_cache keyed on the raw env
string: the warning fires once per distinct bad value, a changed env var is
still picked up by a long-lived process (mirrors `_capture_mode`, which also
reads per call and warns once), and valid values skip the int() parse after
the first call.

Follow-up to #116713 (independent review finding).
This commit is contained in:
teknium1
2026-09-20 00:08:10 -07:00
committed by Teknium
parent b5c0bd6d95
commit 34b475e2ce
2 changed files with 36 additions and 8 deletions

View File

@@ -10,6 +10,7 @@ from __future__ import annotations
import atexit
import contextlib
import functools
import json
import logging
import os
@@ -383,18 +384,26 @@ def _normalize_payload(value: Any, *, tool_name: str = "", args: Any = None) ->
return normalized
@functools.lru_cache(maxsize=8)
def _resolve_max_depth(configured_depth: str) -> int:
"""Parse ``HERMES_LANGFUSE_MAX_DEPTH``; an invalid value warns ONCE per distinct value.
Cached on the raw string (not at import) so a long-lived process still picks up a changed
env var, while a bad value no longer logs one warning per captured prompt/tool payload."""
try:
max_depth = int(configured_depth)
if max_depth < 0:
raise ValueError
return max_depth
except ValueError:
logger.warning("Invalid HERMES_LANGFUSE_MAX_DEPTH=%r; use a non-negative integer. Falling back to 4.", configured_depth)
return 4
def _safe_value(value: Any, *, max_chars: Optional[int] = None, depth: int = 0,
parse_json_strings: bool = False, max_depth: Optional[int] = None) -> Any:
max_chars = max_chars if max_chars is not None else int(_env("HERMES_LANGFUSE_MAX_CHARS", "12000") or "12000")
if max_depth is None:
configured_depth = _env("HERMES_LANGFUSE_MAX_DEPTH", "4") or "4"
try:
max_depth = int(configured_depth)
if max_depth < 0:
raise ValueError
except ValueError:
logger.warning("Invalid HERMES_LANGFUSE_MAX_DEPTH=%r; use a non-negative integer. Falling back to 4.", configured_depth)
max_depth = 4
max_depth = _resolve_max_depth(_env("HERMES_LANGFUSE_MAX_DEPTH", "4") or "4")
if depth > max_depth:
return "<max-depth>"
if value is None or isinstance(value, (int, float, bool)):

View File

@@ -49,3 +49,22 @@ def test_invalid_max_depth_warns_and_preserves_default_capture(monkeypatch, capl
assert len(caplog.records) == 1
assert "HERMES_LANGFUSE_MAX_DEPTH" in caplog.text
assert "non-negative integer" in caplog.text
def test_invalid_max_depth_warns_once_per_value_not_per_payload(monkeypatch, caplog):
"""A bad ``HERMES_LANGFUSE_MAX_DEPTH`` must not log one warning per captured prompt/tool payload
for the life of the process; a changed (still bad) value gets its own single warning."""
plugin = importlib.import_module("plugins.observability.langfuse")
monkeypatch.setenv("HERMES_LANGFUSE_CAPTURE", "full")
monkeypatch.setenv("HERMES_LANGFUSE_MAX_DEPTH", "abc")
payload = {"result": {"data": [{"index": 0}]}}
for _ in range(5):
plugin._capture_content(payload)
plugin._capture_content(payload, tool_result_of=("example", {}))
assert sum("HERMES_LANGFUSE_MAX_DEPTH" in r.getMessage() for r in caplog.records) == 1
monkeypatch.setenv("HERMES_LANGFUSE_MAX_DEPTH", "-7")
for _ in range(3):
plugin._capture_content(payload)
assert sum("HERMES_LANGFUSE_MAX_DEPTH" in r.getMessage() for r in caplog.records) == 2