Skip to content

Commit 7567eac

Browse files
authored
fix: isolate maf and autogen span processors (#236)
2 parents c7618d2 + 2717324 commit 7567eac

20 files changed

Lines changed: 1542 additions & 125 deletions

File tree

.github/workflows/loongsuite_lint_0.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ jobs:
8484
shell: bash
8585
env:
8686
LOONGSUITE_ALL_JOBS: >-
87-
[{"name": "lint-loongsuite-instrumentation-agentscope", "package": "loongsuite-instrumentation-agentscope", "tox_env": "lint-loongsuite-instrumentation-agentscope", "ui_name": "loongsuite-instrumentation-agentscope"}, {"name": "lint-loongsuite-instrumentation-dashscope", "package": "loongsuite-instrumentation-dashscope", "tox_env": "lint-loongsuite-instrumentation-dashscope", "ui_name": "loongsuite-instrumentation-dashscope"}, {"name": "lint-loongsuite-instrumentation-claude-agent-sdk", "package": "loongsuite-instrumentation-claude-agent-sdk", "tox_env": "lint-loongsuite-instrumentation-claude-agent-sdk", "ui_name": "loongsuite-instrumentation-claude-agent-sdk"}, {"name": "lint-loongsuite-instrumentation-google-adk", "package": "loongsuite-instrumentation-google-adk", "tox_env": "lint-loongsuite-instrumentation-google-adk", "ui_name": "loongsuite-instrumentation-google-adk"}, {"name": "lint-loongsuite-instrumentation-agno", "package": "loongsuite-instrumentation-agno", "tox_env": "lint-loongsuite-instrumentation-agno", "ui_name": "loongsuite-instrumentation-agno"}, {"name": "lint-loongsuite-instrumentation-langchain", "package": "loongsuite-instrumentation-langchain", "tox_env": "lint-loongsuite-instrumentation-langchain", "ui_name": "loongsuite-instrumentation-langchain"}, {"name": "lint-loongsuite-instrumentation-langgraph", "package": "loongsuite-instrumentation-langgraph", "tox_env": "lint-loongsuite-instrumentation-langgraph", "ui_name": "loongsuite-instrumentation-langgraph"}, {"name": "lint-loongsuite-instrumentation-deepagents", "package": "loongsuite-instrumentation-deepagents", "tox_env": "lint-loongsuite-instrumentation-deepagents", "ui_name": "loongsuite-instrumentation-deepagents"}, {"name": "lint-loongsuite-instrumentation-microsoft-agent-framework", "package": "loongsuite-instrumentation-microsoft-agent-framework", "tox_env": "lint-loongsuite-instrumentation-microsoft-agent-framework", "ui_name": "loongsuite-instrumentation-microsoft-agent-framework"}, {"name": "lint-loongsuite-instrumentation-qwen-agent", "package": "loongsuite-instrumentation-qwen-agent", "tox_env": "lint-loongsuite-instrumentation-qwen-agent", "ui_name": "loongsuite-instrumentation-qwen-agent"}, {"name": "lint-loongsuite-instrumentation-hermes-agent", "package": "loongsuite-instrumentation-hermes-agent", "tox_env": "lint-loongsuite-instrumentation-hermes-agent", "ui_name": "loongsuite-instrumentation-hermes-agent"}, {"name": "lint-loongsuite-instrumentation-mem0", "package": "loongsuite-instrumentation-mem0", "tox_env": "lint-loongsuite-instrumentation-mem0", "ui_name": "loongsuite-instrumentation-mem0"}, {"name": "lint-util-genai", "package": "util-genai", "tox_env": "lint-util-genai", "ui_name": "util-genai"}, {"name": "lint-loongsuite-instrumentation-litellm", "package": "loongsuite-instrumentation-litellm", "tox_env": "lint-loongsuite-instrumentation-litellm", "ui_name": "loongsuite-instrumentation-litellm"}, {"name": "lint-loongsuite-instrumentation-crewai", "package": "loongsuite-instrumentation-crewai", "tox_env": "lint-loongsuite-instrumentation-crewai", "ui_name": "loongsuite-instrumentation-crewai"}, {"name": "lint-loongsuite-instrumentation-qwenpaw", "package": "loongsuite-instrumentation-qwenpaw", "tox_env": "lint-loongsuite-instrumentation-qwenpaw", "ui_name": "loongsuite-instrumentation-qwenpaw"}, {"name": "lint-loongsuite-instrumentation-algotune", "package": "loongsuite-instrumentation-algotune", "tox_env": "lint-loongsuite-instrumentation-algotune", "ui_name": "loongsuite-instrumentation-algotune"}, {"name": "lint-loongsuite-instrumentation-bfclv4", "package": "loongsuite-instrumentation-bfclv4", "tox_env": "lint-loongsuite-instrumentation-bfclv4", "ui_name": "loongsuite-instrumentation-bfclv4"}, {"name": "lint-loongsuite-instrumentation-claw-eval", "package": "loongsuite-instrumentation-claw-eval", "tox_env": "lint-loongsuite-instrumentation-claw-eval", "ui_name": "loongsuite-instrumentation-claw-eval"}, {"name": "lint-loongsuite-instrumentation-minisweagent", "package": "loongsuite-instrumentation-minisweagent", "tox_env": "lint-loongsuite-instrumentation-minisweagent", "ui_name": "loongsuite-instrumentation-minisweagent"}, {"name": "lint-loongsuite-instrumentation-openhands", "package": "loongsuite-instrumentation-openhands", "tox_env": "lint-loongsuite-instrumentation-openhands", "ui_name": "loongsuite-instrumentation-openhands"}, {"name": "lint-loongsuite-instrumentation-slop-code", "package": "loongsuite-instrumentation-slop-code", "tox_env": "lint-loongsuite-instrumentation-slop-code", "ui_name": "loongsuite-instrumentation-slop-code"}, {"name": "lint-loongsuite-instrumentation-terminus2", "package": "loongsuite-instrumentation-terminus2", "tox_env": "lint-loongsuite-instrumentation-terminus2", "ui_name": "loongsuite-instrumentation-terminus2"}, {"name": "lint-loongsuite-instrumentation-vita", "package": "loongsuite-instrumentation-vita", "tox_env": "lint-loongsuite-instrumentation-vita", "ui_name": "loongsuite-instrumentation-vita"}, {"name": "lint-loongsuite-instrumentation-webarena", "package": "loongsuite-instrumentation-webarena", "tox_env": "lint-loongsuite-instrumentation-webarena", "ui_name": "loongsuite-instrumentation-webarena"}, {"name": "lint-loongsuite-instrumentation-widesearch", "package": "loongsuite-instrumentation-widesearch", "tox_env": "lint-loongsuite-instrumentation-widesearch", "ui_name": "loongsuite-instrumentation-widesearch"}, {"name": "lint-loongsuite-instrumentation-wildtool", "package": "loongsuite-instrumentation-wildtool", "tox_env": "lint-loongsuite-instrumentation-wildtool", "ui_name": "loongsuite-instrumentation-wildtool"}]
87+
[{"name": "lint-loongsuite-instrumentation-agentscope", "package": "loongsuite-instrumentation-agentscope", "tox_env": "lint-loongsuite-instrumentation-agentscope", "ui_name": "loongsuite-instrumentation-agentscope"}, {"name": "lint-loongsuite-instrumentation-dashscope", "package": "loongsuite-instrumentation-dashscope", "tox_env": "lint-loongsuite-instrumentation-dashscope", "ui_name": "loongsuite-instrumentation-dashscope"}, {"name": "lint-loongsuite-instrumentation-claude-agent-sdk", "package": "loongsuite-instrumentation-claude-agent-sdk", "tox_env": "lint-loongsuite-instrumentation-claude-agent-sdk", "ui_name": "loongsuite-instrumentation-claude-agent-sdk"}, {"name": "lint-loongsuite-instrumentation-google-adk", "package": "loongsuite-instrumentation-google-adk", "tox_env": "lint-loongsuite-instrumentation-google-adk", "ui_name": "loongsuite-instrumentation-google-adk"}, {"name": "lint-loongsuite-instrumentation-agno", "package": "loongsuite-instrumentation-agno", "tox_env": "lint-loongsuite-instrumentation-agno", "ui_name": "loongsuite-instrumentation-agno"}, {"name": "lint-loongsuite-instrumentation-langchain", "package": "loongsuite-instrumentation-langchain", "tox_env": "lint-loongsuite-instrumentation-langchain", "ui_name": "loongsuite-instrumentation-langchain"}, {"name": "lint-loongsuite-instrumentation-langgraph", "package": "loongsuite-instrumentation-langgraph", "tox_env": "lint-loongsuite-instrumentation-langgraph", "ui_name": "loongsuite-instrumentation-langgraph"}, {"name": "lint-loongsuite-instrumentation-autogen", "package": "loongsuite-instrumentation-autogen", "tox_env": "lint-loongsuite-instrumentation-autogen", "ui_name": "loongsuite-instrumentation-autogen"}, {"name": "lint-loongsuite-instrumentation-deepagents", "package": "loongsuite-instrumentation-deepagents", "tox_env": "lint-loongsuite-instrumentation-deepagents", "ui_name": "loongsuite-instrumentation-deepagents"}, {"name": "lint-loongsuite-instrumentation-microsoft-agent-framework", "package": "loongsuite-instrumentation-microsoft-agent-framework", "tox_env": "lint-loongsuite-instrumentation-microsoft-agent-framework", "ui_name": "loongsuite-instrumentation-microsoft-agent-framework"}, {"name": "lint-loongsuite-instrumentation-qwen-agent", "package": "loongsuite-instrumentation-qwen-agent", "tox_env": "lint-loongsuite-instrumentation-qwen-agent", "ui_name": "loongsuite-instrumentation-qwen-agent"}, {"name": "lint-loongsuite-instrumentation-hermes-agent", "package": "loongsuite-instrumentation-hermes-agent", "tox_env": "lint-loongsuite-instrumentation-hermes-agent", "ui_name": "loongsuite-instrumentation-hermes-agent"}, {"name": "lint-loongsuite-instrumentation-mem0", "package": "loongsuite-instrumentation-mem0", "tox_env": "lint-loongsuite-instrumentation-mem0", "ui_name": "loongsuite-instrumentation-mem0"}, {"name": "lint-util-genai", "package": "util-genai", "tox_env": "lint-util-genai", "ui_name": "util-genai"}, {"name": "lint-loongsuite-instrumentation-litellm", "package": "loongsuite-instrumentation-litellm", "tox_env": "lint-loongsuite-instrumentation-litellm", "ui_name": "loongsuite-instrumentation-litellm"}, {"name": "lint-loongsuite-instrumentation-crewai", "package": "loongsuite-instrumentation-crewai", "tox_env": "lint-loongsuite-instrumentation-crewai", "ui_name": "loongsuite-instrumentation-crewai"}, {"name": "lint-loongsuite-instrumentation-qwenpaw", "package": "loongsuite-instrumentation-qwenpaw", "tox_env": "lint-loongsuite-instrumentation-qwenpaw", "ui_name": "loongsuite-instrumentation-qwenpaw"}, {"name": "lint-loongsuite-instrumentation-algotune", "package": "loongsuite-instrumentation-algotune", "tox_env": "lint-loongsuite-instrumentation-algotune", "ui_name": "loongsuite-instrumentation-algotune"}, {"name": "lint-loongsuite-instrumentation-bfclv4", "package": "loongsuite-instrumentation-bfclv4", "tox_env": "lint-loongsuite-instrumentation-bfclv4", "ui_name": "loongsuite-instrumentation-bfclv4"}, {"name": "lint-loongsuite-instrumentation-claw-eval", "package": "loongsuite-instrumentation-claw-eval", "tox_env": "lint-loongsuite-instrumentation-claw-eval", "ui_name": "loongsuite-instrumentation-claw-eval"}, {"name": "lint-loongsuite-instrumentation-minisweagent", "package": "loongsuite-instrumentation-minisweagent", "tox_env": "lint-loongsuite-instrumentation-minisweagent", "ui_name": "loongsuite-instrumentation-minisweagent"}, {"name": "lint-loongsuite-instrumentation-openhands", "package": "loongsuite-instrumentation-openhands", "tox_env": "lint-loongsuite-instrumentation-openhands", "ui_name": "loongsuite-instrumentation-openhands"}, {"name": "lint-loongsuite-instrumentation-slop-code", "package": "loongsuite-instrumentation-slop-code", "tox_env": "lint-loongsuite-instrumentation-slop-code", "ui_name": "loongsuite-instrumentation-slop-code"}, {"name": "lint-loongsuite-instrumentation-terminus2", "package": "loongsuite-instrumentation-terminus2", "tox_env": "lint-loongsuite-instrumentation-terminus2", "ui_name": "loongsuite-instrumentation-terminus2"}, {"name": "lint-loongsuite-instrumentation-vita", "package": "loongsuite-instrumentation-vita", "tox_env": "lint-loongsuite-instrumentation-vita", "ui_name": "loongsuite-instrumentation-vita"}, {"name": "lint-loongsuite-instrumentation-webarena", "package": "loongsuite-instrumentation-webarena", "tox_env": "lint-loongsuite-instrumentation-webarena", "ui_name": "loongsuite-instrumentation-webarena"}, {"name": "lint-loongsuite-instrumentation-widesearch", "package": "loongsuite-instrumentation-widesearch", "tox_env": "lint-loongsuite-instrumentation-widesearch", "ui_name": "loongsuite-instrumentation-widesearch"}, {"name": "lint-loongsuite-instrumentation-wildtool", "package": "loongsuite-instrumentation-wildtool", "tox_env": "lint-loongsuite-instrumentation-wildtool", "ui_name": "loongsuite-instrumentation-wildtool"}]
8888
LOONGSUITE_FULL: ${{ steps.detect.outputs.full }}
8989
LOONGSUITE_PACKAGES: ${{ steps.detect.outputs.packages }}
9090
run: |

.github/workflows/loongsuite_test_0.yml

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

instrumentation-loongsuite/loongsuite-instrumentation-autogen/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## Unreleased
99

10+
### Fixed
11+
12+
- Avoid enriching non-AutoGen spans that use overlapping GenAI operation names.
13+
1014
## Version 0.7.0 (2026-07-03)
1115

1216
### Added

instrumentation-loongsuite/loongsuite-instrumentation-autogen/src/opentelemetry/instrumentation/autogen/patch.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333

3434
from .config import is_agent_span_enabled, is_llm_span_enabled
3535
from .semantic_conventions import (
36+
AUTOGEN_LIVE_SPAN_MARKER,
3637
AUTOGEN_PROVIDER_NAME,
3738
GEN_AI_OPERATION_NAME,
3839
GEN_AI_PROVIDER_NAME,
@@ -239,6 +240,16 @@ def _apply_invoke_agent_attrs(
239240
logger.debug("AutoGen invoke_agent span enrichment failed: %s", exc)
240241

241242

243+
def _mark_autogen_live_span(invocation: Any) -> None:
244+
span = getattr(invocation, "span", None)
245+
if span is None:
246+
return
247+
try:
248+
setattr(span, AUTOGEN_LIVE_SPAN_MARKER, AUTOGEN_PROVIDER_NAME)
249+
except Exception:
250+
pass
251+
252+
242253
def _model_client_arg(
243254
args: tuple[Any, ...], kwargs: dict[str, Any], name: str
244255
) -> Any:
@@ -433,6 +444,7 @@ async def _direct_model_create_wrapper(wrapped, instance, args, kwargs): # type
433444
handler = _get_handler()
434445
invocation = _make_direct_model_invocation(instance, args, kwargs)
435446
handler.start_llm(invocation)
447+
_mark_autogen_live_span(invocation)
436448
try:
437449
result = await wrapped(*args, **kwargs)
438450
apply_create_result(invocation, result)
@@ -453,6 +465,7 @@ async def _generator(): # type: ignore[no-untyped-def]
453465
handler = _get_handler()
454466
invocation = _make_direct_model_invocation(instance, args, kwargs)
455467
handler.start_llm(invocation)
468+
_mark_autogen_live_span(invocation)
456469
try:
457470
async for item in wrapped(*args, **kwargs):
458471
if (
@@ -511,6 +524,7 @@ async def _generator(): # type: ignore[no-untyped-def]
511524
output_type=output_type,
512525
)
513526
handler.start_llm(invocation)
527+
_mark_autogen_live_span(invocation)
514528
try:
515529
async for item in _contextual_async_iter(
516530
wrapped(*args, **kwargs),

instrumentation-loongsuite/loongsuite-instrumentation-autogen/src/opentelemetry/instrumentation/autogen/semantic_conventions.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class GenAIOperation:
3535

3636

3737
AUTOGEN_PROVIDER_NAME: Final = "autogen"
38+
AUTOGEN_LIVE_SPAN_MARKER: Final = "_loongsuite_autogen_framework"
3839

3940
GEN_AI_AGENT_DESCRIPTION: Final = "gen_ai.agent.description"
4041
GEN_AI_AGENT_ID: Final = "gen_ai.agent.id"

instrumentation-loongsuite/loongsuite-instrumentation-autogen/src/opentelemetry/instrumentation/autogen/span_processor.py

Lines changed: 88 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,19 @@
1818

1919
import logging
2020
import threading
21-
from typing import Any, Optional
21+
from typing import Any, Mapping, Optional
2222

2323
from opentelemetry.context import Context
2424
from opentelemetry.sdk.trace import SpanProcessor
2525
from opentelemetry.trace import Span as OtelSpan
2626
from opentelemetry.trace import SpanKind
2727

2828
from .semantic_conventions import (
29+
AUTOGEN_LIVE_SPAN_MARKER,
2930
AUTOGEN_PROVIDER_NAME,
31+
GEN_AI_AGENT_DESCRIPTION,
32+
GEN_AI_AGENT_ID,
33+
GEN_AI_AGENT_NAME,
3034
GEN_AI_OPERATION_NAME,
3135
GEN_AI_PROVIDER_NAME,
3236
GEN_AI_SPAN_KIND,
@@ -42,9 +46,39 @@
4246
f"{GenAIOperation.EXECUTE_TOOL} ",
4347
f"{GenAIOperation.INVOKE_AGENT} ",
4448
)
49+
_AUTOGEN_PRIVATE_ATTRS = frozenset(
50+
{
51+
"autogen.code.block_count",
52+
"autogen.code.exit_code",
53+
"autogen.code.retry_attempt",
54+
"autogen.handoff.context_count",
55+
"autogen.handoff.source",
56+
"autogen.handoff.target",
57+
"autogen.memory.result_count",
58+
"autogen.team.message_count",
59+
"autogen.team.participants",
60+
"autogen.team.stop_reason",
61+
"autogen.team.type",
62+
"autogen.user_input.request_id",
63+
}
64+
)
65+
_CREATE_AGENT_LIFECYCLE_ATTRS = (
66+
GEN_AI_AGENT_DESCRIPTION,
67+
GEN_AI_AGENT_ID,
68+
GEN_AI_AGENT_NAME,
69+
GEN_AI_OPERATION_NAME,
70+
GEN_AI_PROVIDER_NAME,
71+
GEN_AI_SPAN_KIND,
72+
GEN_AI_SYSTEM,
73+
"gen_ai.agent.version",
74+
"gen_ai.system_instructions",
75+
"gen_ai.tool.definitions",
76+
)
4577

4678

4779
def _attr_value(span: Any, key: str) -> Any:
80+
if isinstance(span, Mapping):
81+
return span.get(key)
4882
attrs = getattr(span, "_attributes", None)
4983
if attrs is not None:
5084
try:
@@ -57,6 +91,46 @@ def _attr_value(span: Any, key: str) -> Any:
5791
return None
5892

5993

94+
def _attr_values(value: Any) -> tuple[str, ...]:
95+
if value is None:
96+
return ()
97+
if isinstance(value, (list, tuple)):
98+
values = value
99+
else:
100+
values = (value,)
101+
return tuple(str(item).lower() for item in values if item is not None)
102+
103+
104+
def _span_attrs(span: Any) -> Mapping[Any, Any]:
105+
if isinstance(span, Mapping):
106+
return span
107+
attrs = getattr(span, "_attributes", None)
108+
if attrs is not None:
109+
return attrs
110+
attrs = getattr(span, "attributes", None)
111+
if attrs is not None:
112+
return attrs
113+
return {}
114+
115+
116+
def _has_live_autogen_marker(live: Any | None) -> bool:
117+
if live is None:
118+
return False
119+
return (
120+
getattr(live, AUTOGEN_LIVE_SPAN_MARKER, None) == AUTOGEN_PROVIDER_NAME
121+
)
122+
123+
124+
def _has_autogen_marker(readable: Any, live: Any | None = None) -> bool:
125+
if _has_live_autogen_marker(live):
126+
return True
127+
for key in (GEN_AI_SYSTEM, GEN_AI_PROVIDER_NAME):
128+
if AUTOGEN_PROVIDER_NAME in _attr_values(_attr_value(readable, key)):
129+
return True
130+
attrs = _span_attrs(readable)
131+
return any(str(key) in _AUTOGEN_PRIVATE_ATTRS for key in attrs)
132+
133+
60134
def _set_attr(live_span: OtelSpan, key: str, value: Any) -> None:
61135
if value is None:
62136
return
@@ -138,19 +212,9 @@ def _set_otel_span_kind(
138212

139213

140214
def _is_autogen_span(
141-
name: str, operation: Optional[str], readable: Any
215+
_name: str, _operation: Optional[str], readable: Any, live: Any | None
142216
) -> bool:
143-
if _attr_value(readable, GEN_AI_SYSTEM) == AUTOGEN_PROVIDER_NAME:
144-
return True
145-
if _attr_value(readable, GEN_AI_PROVIDER_NAME) == AUTOGEN_PROVIDER_NAME:
146-
return True
147-
if operation in {
148-
GenAIOperation.CREATE_AGENT,
149-
GenAIOperation.EXECUTE_TOOL,
150-
GenAIOperation.INVOKE_AGENT,
151-
}:
152-
return True
153-
return name.startswith(_AUTOGEN_NAME_PREFIXES)
217+
return _has_autogen_marker(readable, live)
154218

155219

156220
def _classify_span(
@@ -208,10 +272,15 @@ def on_end(self, span: Any) -> None:
208272
name = span.name or ""
209273
existing_op = _attr_value(span, GEN_AI_OPERATION_NAME)
210274
operation = existing_op if isinstance(existing_op, str) else None
211-
if not _is_autogen_span(name, operation, span):
275+
if not _is_autogen_span(name, operation, span, live):
212276
return
213277

214278
span_kind, op_name = _classify_span(name, operation)
279+
if op_name == GenAIOperation.CREATE_AGENT:
280+
for attr_name in _CREATE_AGENT_LIFECYCLE_ATTRS:
281+
_delete_attr_on_both(live, span, attr_name)
282+
return
283+
215284
if span_kind and not _attr_value(span, GEN_AI_SPAN_KIND):
216285
_set_attr_on_both(live, span, GEN_AI_SPAN_KIND, span_kind)
217286
if not operation:
@@ -235,7 +304,11 @@ def on_end(self, span: Any) -> None:
235304

236305
if span_kind == GenAISpanKind.LLM:
237306
_set_otel_span_kind(live, span, SpanKind.CLIENT)
238-
elif span_kind in {GenAISpanKind.AGENT, GenAISpanKind.TOOL}:
307+
elif span_kind == GenAISpanKind.AGENT and op_name == (
308+
GenAIOperation.INVOKE_AGENT
309+
):
310+
_set_otel_span_kind(live, span, SpanKind.INTERNAL)
311+
elif span_kind == GenAISpanKind.TOOL:
239312
_set_otel_span_kind(live, span, SpanKind.INTERNAL)
240313
except Exception as exc: # pragma: no cover - defensive
241314
logger.warning("AutoGenSemanticProcessor.on_end failed: %s", exc)

0 commit comments

Comments
 (0)