Skip to content

Commit 57c90d7

Browse files
NiteshDhanpalclaude
andcommitted
feat(tracing): honor SGP_OBS_CORRELATE_BUSINESS at the Correlator construction
Pass the flag into the sgp_obs Correlator that _begin_obs builds for every adk business span, so the opt-out actually takes effect on the primary correlation path. Behavior lives in sgp_obs (scaleapi#158071); this is the construction pass-through. Version-resilient (_build_correlator): an installed sgp_obs that predates the `correlate_business` parameter raises TypeError on the kwarg, so we fall back to the no-arg form and correlation stays always-on rather than dying. The flag takes effect once the sgp-obs pin is bumped to the release that wired it (0.5.0). Confirmed against the currently-pinned 0.3.0: fallback, no crash. Test: env parsing + no-crash fallback + (when supported) the flag reaching the Correlator instance. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 6122e82 commit 57c90d7

2 files changed

Lines changed: 61 additions & 1 deletion

File tree

src/agentex/lib/core/tracing/trace.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,26 @@ def _obs_mode() -> ObsMode:
4949
return ObsMode.OTEL if (os.getenv("SGP_OBS_MODE") or "").strip().lower() == "lgtm" else ObsMode.DD_ONLY
5050

5151

52+
def _correlate_business() -> bool:
53+
"""``SGP_OBS_CORRELATE_BUSINESS`` — default True. Read from the env directly
54+
(mirroring ``_obs_mode``) rather than sgp_obs.TracingConfig, so we don't depend
55+
on a specific config-field surface. When false, the Correlator opens the obs
56+
span but writes NO business<->obs correlation in either direction."""
57+
return (os.getenv("SGP_OBS_CORRELATE_BUSINESS") or "true").strip().lower() not in ("false", "0", "no")
58+
59+
60+
def _build_correlator() -> Correlator:
61+
"""Construct the Correlator, honoring SGP_OBS_CORRELATE_BUSINESS when the
62+
installed sgp_obs supports it. Version-resilient: an sgp_obs that predates the
63+
``correlate_business`` parameter raises TypeError on the kwarg — fall back to
64+
the no-arg form so correlation keeps working (always-on) instead of dying. The
65+
flag takes effect once sgp_obs is bumped to the release that wired it."""
66+
try:
67+
return Correlator(_OTEL, _DDTRACE, _obs_mode(), correlate_business=_correlate_business())
68+
except TypeError: # sgp_obs predates the flag; correlation stays always-on
69+
return Correlator(_OTEL, _DDTRACE, _obs_mode())
70+
71+
5272
def _close_obs(handle: ObsSpanHandle | None, error: dict[str, str] | None = None) -> None:
5373
"""Close a wrapper span (best-effort), marking it errored when the business span
5474
carried an error. Safe on ``None``; obs must never fail the app path."""
@@ -159,7 +179,7 @@ def _begin_obs(
159179
is_dispatch_boundary=_sgp_temporal.in_dispatch_boundary(),
160180
)
161181
try:
162-
handle, edge = Correlator(_OTEL, _DDTRACE, _obs_mode()).begin(req)
182+
handle, edge = _build_correlator().begin(req)
163183
except Exception: # pragma: no cover - obs must never break the business span
164184
return None, {}
165185
return handle, edge.as_metadata()
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
"""SDK side of SGP_OBS_CORRELATE_BUSINESS: trace.py reads the env flag and passes
2+
it into the sgp_obs Correlator, version-resiliently.
3+
4+
The gate BEHAVIOR lives in sgp_obs (Correlator + bridge); here we only prove the
5+
SDK's construction pass-through: the env is parsed correctly and _build_correlator
6+
never crashes even when the installed sgp_obs predates the parameter."""
7+
8+
import inspect
9+
10+
from agentex.lib.core.tracing.trace import _build_correlator, _correlate_business
11+
from sgp_obs.traces.correlator import Correlator
12+
13+
14+
def test_correlate_business_env_parsing(monkeypatch):
15+
monkeypatch.delenv("SGP_OBS_CORRELATE_BUSINESS", raising=False)
16+
assert _correlate_business() is True # default on
17+
for falsey in ("false", "0", "no", "FALSE", " no "):
18+
monkeypatch.setenv("SGP_OBS_CORRELATE_BUSINESS", falsey)
19+
assert _correlate_business() is False
20+
for truthy in ("true", "1", "yes", "", "anything"):
21+
monkeypatch.setenv("SGP_OBS_CORRELATE_BUSINESS", truthy)
22+
assert _correlate_business() is True
23+
24+
25+
def test_build_correlator_never_crashes():
26+
# Works whether or not the installed sgp_obs accepts the kwarg (version skew):
27+
# with the param -> honored; without -> TypeError fallback to no-arg form.
28+
assert isinstance(_build_correlator(), Correlator)
29+
30+
31+
def test_build_correlator_passes_flag_when_supported(monkeypatch):
32+
supported = "correlate_business" in inspect.signature(Correlator.__init__).parameters
33+
if not supported:
34+
# Pinned sgp_obs predates the flag; nothing to assert beyond no-crash.
35+
assert isinstance(_build_correlator(), Correlator)
36+
return
37+
monkeypatch.setenv("SGP_OBS_CORRELATE_BUSINESS", "false")
38+
corr = _build_correlator()
39+
# the flag reached the Correlator instance
40+
assert getattr(corr, "_correlate_business") is False

0 commit comments

Comments
 (0)