Skip to content

Commit 6894084

Browse files
authored
Merge pull request #49 from context-labs/integrate-session-id-in-tracing
integrate session id in tracing
2 parents b953538 + e6a18c5 commit 6894084

7 files changed

Lines changed: 80 additions & 28 deletions

File tree

engine/main.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,9 @@ async def stream_engine_async(
5959
telemetry_handle = setup_telemetry(enable=telemetry, run_id=run_id)
6060
try:
6161
# Root + subagent share ``agent_id="halo"`` so Catalyst's Agents
62-
# view collapses every HALO run into one identity row; the
63-
# span-level ``agent.name`` ("halo-root" vs "halo-sub") still
64-
# distinguishes the two for span-tree rendering.
65-
with halo_agent_span(name="halo-root", agent_id="halo", system="openai"):
62+
# view collapses every HALO run into one identity row; the span
63+
# name still distinguishes root vs subagent work in the trace tree.
64+
with halo_agent_span(span_name="halo-root.run", agent_id="halo", system="openai"):
6665
configure_default_sdk_client(engine_config.model_provider)
6766
sandbox = Sandbox.get()
6867

engine/telemetry/tracing.py

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,36 +22,48 @@
2222

2323
from __future__ import annotations
2424

25+
import os
2526
from collections.abc import Iterator
2627
from contextlib import contextmanager
2728

2829
from inference_catalyst_tracing import AgentSpanHandle, agent_span
2930
from opentelemetry import trace
3031

3132
_TRACER_NAME = "halo-engine"
33+
_SESSION_ID_ENV = "CATALYST_TRACING_CONVERSATION_ID"
34+
35+
36+
def _session_id_from_env() -> str | None:
37+
value = os.environ.get(_SESSION_ID_ENV, "").strip()
38+
if not value:
39+
return None
40+
return value
3241

3342

3443
@contextmanager
3544
def halo_agent_span(
3645
*,
37-
name: str,
46+
span_name: str,
3847
system: str = "openai",
3948
agent_id: str | None = None,
4049
) -> Iterator[AgentSpanHandle]:
4150
"""Open an OpenInference AGENT span around a chunk of HALO agent work.
4251
43-
``name`` becomes the span's ``agent.name`` and the prefix of its
44-
span name (``f"{name}.run"``). ``agent_id`` becomes the span's
45-
``agent.id`` — Catalyst groups the Agents view on that field with
46-
``agent.name`` as a fallback, so passing a stable ``agent_id`` (e.g.
47-
``"halo"`` for both root + subagent) collapses every HALO run under
48-
a single Agents-tab row regardless of which name the span carries.
49-
``system`` becomes ``gen_ai.system``.
52+
``span_name`` is the OTel operation name. ``agent_id`` is the
53+
stable agent identity Catalyst groups by, so passing ``"halo"``
54+
for both root and subagent spans collapses every HALO run under a
55+
single Agents-tab row. ``system`` becomes ``gen_ai.system``.
5056
5157
Yields the ``AgentSpanHandle`` from catalyst-tracing. When telemetry
5258
is off or the local backend is active, the handle wraps a
5359
no-op ``NonRecordingSpan`` and all attribute setters silently no-op.
5460
"""
5561
tracer = trace.get_tracer(_TRACER_NAME)
56-
with agent_span(tracer, name=name, system=system, agent_id=agent_id) as span:
62+
with agent_span(
63+
tracer,
64+
span_name=span_name,
65+
system=system,
66+
agent_id=agent_id,
67+
session_id=_session_id_from_env(),
68+
) as span:
5769
yield span

engine/tools/subagent_tool_factory.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -272,12 +272,10 @@ async def _run_streamed(*, agent, input, context):
272272

273273
# ``agent_id="halo"`` matches the root span (see
274274
# ``engine/main.py``) so Catalyst groups root + every
275-
# subagent invocation under one Agents-tab identity. The
276-
# span ``agent.name`` is fixed at ``"halo-sub"`` for
277-
# display; ``engine_config.subagent.name`` ("sub") still
278-
# drives the HALO run page UI via
279-
# ``child_execution.agent_name``.
280-
with halo_agent_span(name="halo-sub", agent_id="halo", system="openai"):
275+
# subagent invocation under one Agents-tab identity.
276+
# ``engine_config.subagent.name`` ("sub") still drives the
277+
# HALO run page UI via ``child_execution.agent_name``.
278+
with halo_agent_span(span_name="halo-sub.run", agent_id="halo", system="openai"):
281279
try:
282280
await runner.run(
283281
sdk_agent=child_agent,

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ dependencies = [
2323
# by ``CATALYST_OTLP_TOKEN``. When the token is unset and the local
2424
# JSONL backend is in use, OTel's proxy tracer makes the wrapper a
2525
# no-op without any extra branching in engine code.
26-
"inference-catalyst-tracing[openai-agents]==0.0.13",
26+
"inference-catalyst-tracing[openai-agents]==0.0.19",
2727
]
2828

2929
[project.scripts]

pyrightconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"pythonVersion": "3.10",
1313
"venvPath": ".",
1414
"venv": ".venv",
15-
"typeCheckingMode": "basic",
15+
"typeCheckingMode": "standard",
1616
"reportMissingTypeStubs": false,
1717
"executionEnvironments": [
1818
{

tests/unit/test_telemetry.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
import logging
66
import os
7+
from collections.abc import Iterator
8+
from contextlib import contextmanager
79

810
import pytest
911

@@ -42,6 +44,46 @@ def test_setup_returns_none_when_disabled(monkeypatch) -> None:
4244
assert cleared == [[]]
4345

4446

47+
def test_halo_agent_span_passes_conversation_id_as_session_id(monkeypatch) -> None:
48+
from engine.telemetry import tracing
49+
50+
captured: dict[str, object] = {}
51+
52+
class _FakeSpan:
53+
pass
54+
55+
@contextmanager
56+
def _fake_agent_span(
57+
tracer: object,
58+
*,
59+
span_name: str,
60+
system: str,
61+
agent_id: str | None,
62+
session_id: str | None,
63+
) -> Iterator[_FakeSpan]:
64+
captured["tracer"] = tracer
65+
captured["span_name"] = span_name
66+
captured["system"] = system
67+
captured["agent_id"] = agent_id
68+
captured["session_id"] = session_id
69+
yield _FakeSpan()
70+
71+
monkeypatch.setenv("CATALYST_TRACING_CONVERSATION_ID", " conv-123 ")
72+
monkeypatch.setattr(tracing.trace, "get_tracer", lambda name: f"tracer:{name}")
73+
monkeypatch.setattr(tracing, "agent_span", _fake_agent_span)
74+
75+
with tracing.halo_agent_span(span_name="halo-root.run", agent_id="halo"):
76+
pass
77+
78+
assert captured == {
79+
"tracer": "tracer:halo-engine",
80+
"span_name": "halo-root.run",
81+
"system": "openai",
82+
"agent_id": "halo",
83+
"session_id": "conv-123",
84+
}
85+
86+
4587
def test_setup_attaches_local_processor(monkeypatch, tmp_path) -> None:
4688
"""setup_telemetry attaches the InferenceOtlpFileProcessor to the
4789
openai-agents SDK at the path indicated by HALO_TELEMETRY_PATH."""

uv.lock

Lines changed: 8 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)