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:
@@ -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)):
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user