chore: refactor according to semantic conventions#224
Conversation
Add a LoongSuiteResourceDetector that contributes two resource attributes to the agent: * host.ip: the local host IP combined with the process id, formatted as <ip>-<pid> (e.g. 127.0.0.1-1). * gen_ai.instrumentation.sdk.name: set to "loongsuite-genai-utils". The detector is wired into LoongSuiteConfigurator so the attributes are always present on the SDK resource. Includes unit tests for the detector (ip-pid format, fixed sdk name, fallback on socket error) and the configurator wiring. Change-Id: I7fdfd07ffa8e2021e82c1d85d7d6b527c2cf8170 Co-developed-by: Claude <noreply@anthropic.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add missing GenAI semantic convention attributes across instrumentation plugins: - execute_tool spans: add tool_type="function" (Recommended) - invoke_agent spans: add agent_id (Conditionally Required) - inference spans: add server_address/server_port (Conditionally Required) - inference spans: add response_id extraction (Recommended) Plugins modified: - hermes-agent: agent_id, server_address/port from base_url, tool_type - vita: agent_id, tool_type, response_id, server_address inference - langchain: agent_id, tool_type - dashscope: server_address/port - widesearch: agent_id - agentscope: tool_type - qwen-agent: agent_id, tool_type - minisweagent: agent_id - google-adk: agent_id, tool_type - claude-agent-sdk: tool_type Change-Id: I21fc87489630d2ac6a0d9df22ef70dde60c57fff Co-developed-by: Qoder <noreply@qoder.com>
There was a problem hiding this comment.
Pull request overview
Adds/aligns GenAI semantic-convention fields across LoongSuite distro + multiple LoongSuite instrumentations, including new resource attributes and additional invocation metadata.
Changes:
- Introduces
LoongSuiteResourceDetectorand wires it intoLoongSuiteConfiguratorto inject LoongSuite resource attributes. - Adds/propagates GenAI semconv fields (
agent_id,tool_type,response_id, and someserver_address/server_port) across several instrumentations. - Adds initial unit tests for the new LoongSuite distro resource/configurator behavior.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| loongsuite-distro/src/loongsuite/distro/resource.py | Adds a resource detector that provides host.ip and gen_ai.instrumentation.sdk.name. |
| loongsuite-distro/src/loongsuite/distro/init.py | Updates configurator to inject LoongSuite resource attributes during SDK configuration. |
| loongsuite-distro/tests/test_resource.py | Adds unit tests for the resource detector and host IP detection helpers. |
| loongsuite-distro/tests/test_configurator.py | Adds unit tests asserting injected resource attributes are forwarded into SDK initialization. |
| loongsuite-distro/tests/init.py | Adds package marker for distro tests. |
| instrumentation-loongsuite/loongsuite-instrumentation-widesearch/src/opentelemetry/instrumentation/widesearch/utils.py | Populates agent_id for agent invocations. |
| instrumentation-loongsuite/loongsuite-instrumentation-vita/src/opentelemetry/instrumentation/vita/utils.py | Adds server address inference helper (currently unused). |
| instrumentation-loongsuite/loongsuite-instrumentation-vita/src/opentelemetry/instrumentation/vita/patch.py | Adds agent_id, response_id, and tool_type for Vita spans/invocations. |
| instrumentation-loongsuite/loongsuite-instrumentation-qwen-agent/src/opentelemetry/instrumentation/qwen_agent/utils.py | Populates agent_id and tool_type in invocations. |
| instrumentation-loongsuite/loongsuite-instrumentation-minisweagent/src/opentelemetry/instrumentation/minisweagent/internal/agent_wrappers.py | Populates agent_id for agent invocations. |
| instrumentation-loongsuite/loongsuite-instrumentation-langchain/src/opentelemetry/instrumentation/langchain/internal/_tracer.py | Adds agent_id and tool_type for LangChain invocations. |
| instrumentation-loongsuite/loongsuite-instrumentation-hermes-agent/src/opentelemetry/instrumentation/hermes_agent/helpers.py | Adds agent_id, infers server info from base_url, and sets tool_type. |
| instrumentation-loongsuite/loongsuite-instrumentation-google-adk/src/opentelemetry/instrumentation/google_adk/internal/_plugin.py | Adds agent_id and tool_type for Google ADK invocations. |
| instrumentation-loongsuite/loongsuite-instrumentation-dashscope/src/opentelemetry/instrumentation/dashscope/utils/generation.py | Sets server_address/server_port on DashScope LLM invocations. |
| instrumentation-loongsuite/loongsuite-instrumentation-claude-agent-sdk/src/opentelemetry/instrumentation/claude_agent_sdk/patch.py | Populates tool_type for tool spans. |
| instrumentation-loongsuite/loongsuite-instrumentation-agentscope/tests/test_skill_detection.py | Updates tests to include tool_type. |
| instrumentation-loongsuite/loongsuite-instrumentation-agentscope/src/opentelemetry/instrumentation/agentscope/patch.py | Populates tool_type for tool invocations. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
ralf0131
left a comment
There was a problem hiding this comment.
Summary
PR #224 propagates GenAI semantic-convention fields (tool_type, agent_id, server_address/server_port, response_id) across multiple LoongSuite instrumentations and introduces a LoongSuiteResourceDetector that injects host.ip and gen_ai.instrumentation.sdk.name resource attributes. Overall direction is good — aligning with OTel GenAI semconv is the right move. The review below focuses on additional findings beyond what Copilot already flagged (host.ip format, unused _infer_server_address, schemeless-URL handling in _extract_server_info).
CLA is signed ✅.
Findings
- [Warning]
__init__.py:40— resource detector silently overrides user-providedhost.ip/gen_ai.instrumentation.sdk.nameviadict.update(); considersetdefaultso caller values win. - [Warning]
hermes_agent/helpers.py:574—agent_id="hermes-agent"is hardcoded for all instances; inconsistent with other instrumentations and defeats the uniqueness purpose ofagent.id. - [Info]
dashscope/utils/generation.py:471—server_address/server_porthardcoded; inconsistent with the dynamic extraction added for hermes-agent in this same PR. - [Info]
agentscope/patch.py:406—tool_typehardcoded to"function"across all instrumentations; consider deriving from framework metadata where available.
Additional Notes
agent_idalways mirrorsagent_name: across every instrumentation in this PR,agent_idis set toagent_name(or a derivative), so both attributes always carry the same value. The GenAI semconv distinguishesagent.id(unique instance identifier) fromagent.name(display name). If no truly unique per-instance ID is available right now, that's acceptable, but worth a follow-up to see whether session IDs or similar can provide real uniqueness.- PR description: The description body is still the unfilled GitHub template (no summary, no test instructions, checklist items unchecked). No changelog files appear to have been modified. Please fill in the description and update changelogs per the project's contributing guidelines.
Automated review by github-manager-bot
- dashscope: add _extract_cache_tokens() for cache_creation/cache_read tokens - dashscope: set server_address/port on embedding invocations - dashscope: update test to use text-embedding-v4 model - hermes-agent: extract cache tokens from usage.prompt_tokens_details - vita: extract cache tokens from OpenAI-compatible usage format These changes enable gen_ai.usage.cache_creation.input_tokens and gen_ai.usage.cache_read.input_tokens attributes for LLM plugins that interact with providers supporting prompt caching (e.g. Anthropic, OpenAI with cached prompts, DashScope with context caching). Change-Id: I6f0c4035561b43eb5e8ed132257a6438b2a323f1 Co-developed-by: Qoder <noreply@qoder.com>
ralf0131
left a comment
There was a problem hiding this comment.
Summary
Re-review after commit 4064298 (cache token extraction + dashscope embedding improvements). The new _extract_cache_tokens helper and its propagation across dashscope / hermes-agent / vita look correct — the or-chain fallback across cache_creation_input_tokens / cache_creation_tokens / prompt_cache_hit_tokens / prompt_tokens_details.cached_tokens is a sensible way to handle provider field variation. CLA is signed ✅.
Findings
- [Info]
dashscope/utils/generation.py—from ..utils.common import _extract_cache_tokensis a function-local import. It works, but a top-level import is preferable unless there's a circular-import concern; if there is, a short comment explaining it would help future readers. - [Info]
hermes-agent/helpers.py&vita/patch.py— the cache-token extraction logic is duplicated inline rather than reusing the dashscope helper. Acceptable since these are separate instrumentation packages, but if they share a common response shape it's a candidate for a shared utility later. - [Note] Prior findings from my last review remain open (not addressed by this commit): resource detector
dict.update()override (__init__.py:40) and hardcodedagent_id="hermes-agent"(helpers.py:574). Not blocking, but worth tracking.
Additional Notes
- Embedding now hardcodes
server_address="dashscope.aliyuncs.com"/port=443, making it consistent withgeneration.py. Still a fixed value — fine for a single-provider SDK, just flagging the pattern.
Automated review by github-manager-bot
Add _infer_provider_name() helper to resolve provider name from the provider instance. This fixes a P0 compliance gap where the Required attribute gen_ai.provider.name was missing on invoke_agent_internal spans in the CLAW-eval instrumentation. Change-Id: Iad6b28ea1c9f09b4fae4aef03c625b35fcdff3d0 Co-developed-by: Qoder <noreply@qoder.com>
ralf0131
left a comment
There was a problem hiding this comment.
Summary
Re-review after commit d99dd0026b — adds gen_ai.provider.name (a required GenAI semconv attribute) to the invoke_agent span via a new _infer_provider_name() helper. The attribute addition is correct and improves semconv compliance; the provider-inference logic (provider_name attr → class-name matching → model-id prefix matching) is pragmatic and sound. CLA signed ✅.
Findings
- [Warning]
wrappers.py:88— default fallback returns hardcoded"openai"when provider is unidentifiable; risks misattributing unknown providers to OpenAI in telemetry. - [Info]
wrappers.py:547—if _provider_name:guard is always true (function never returns empty); dead code. - [Info]
wrappers.py:84— model-id inference only covers OpenAI/Anthropic/DashScope; other providers fall through to"openai".
Suggestions
- Change the default fallback from
"openai"to"unknown"so consumers can distinguish unidentified providers. If you prefer to keep a value, consider matching theprovider is Nonebranch which returns"claw-eval". - Add unit tests for
_infer_provider_name()intest_wrappers.py— the branching logic (attr lookup, class-name matching, model-id prefix matching) is straightforward to test with mock provider objects.
Note
Prior findings from earlier reviews remain open (not addressed by this commit): resource detector dict.update() override and hardcoded agent_id="hermes-agent". Not blocking.
Automated review by github-manager-bot
- Add # noqa: PLC0415 for intentional in-function imports in dashscope and hermes-agent - Fix unsorted imports (I001) in loongsuite-distro - Remove unnecessary # type: ignore comments in vertexai/patch.py - Apply ruff format to all affected files - Add CHANGELOG-loongsuite.md entry for semconv changes Change-Id: Ibb440bd9e057fa82a91710db85380311d11a8c86 Co-developed-by: Qoder <noreply@qoder.com>
ralf0131
left a comment
There was a problem hiding this comment.
Summary
Re-review after commit 8906ae65 — CI-fix commit addressing lint, format, typecheck, and changelog. All changes are non-functional: # noqa: PLC0415 added for intentional lazy imports (dashscope, hermes-agent), # type: ignore comments removed from vertexai, multi-line lambda/call reformatting (ruff format), import reordering (first-party before third-party in loongsuite-distro), and a CHANGELOG entry for semconv adoption. No functional logic changes, no new issues introduced. CLA signed ✅.
Findings
No new findings in this commit — all changes are mechanical formatting/lint fixes that look correct.
Open Items (from prior reviews, not addressed by this commit, not blocking)
- [Warning]
claw-eval/wrappers.py:88—_infer_provider_name()default fallback returns hardcoded"openai"; risks misattributing unknown providers to OpenAI in telemetry. Suggested: return"unknown"instead. - [Info]
claw-eval/wrappers.py:547—if _provider_name:guard is always true (function never returns empty); dead code. - [Info]
claw-eval/wrappers.py:84— model-id inference only covers OpenAI/Anthropic/DashScope; other providers fall through to"openai". - [Prior] resource detector
dict.update()override pattern and hardcodedagent_id="hermes-agent"remain open.
Suggestions
- Consider addressing the
"openai"fallback in a follow-up commit so telemetry consumers can distinguish unidentified providers. - Add unit tests for
_infer_provider_name()branching logic.
Automated review by github-manager-bot
- resource.py: Use raw IP for host.ip, add service.instance.id for <ip>-<pid> - distro/__init__.py: Use setdefault so user-provided values take precedence - hermes_agent/helpers.py: Handle schemeless URLs in _extract_server_info, return (None, None) when hostname is falsy; use agent_name for agent_id - vita/utils.py: Remove unused _infer_server_address function - claw-eval/wrappers.py: Change default fallback from 'openai' to 'unknown', add Google/Gemini provider detection, remove dead if-guard - agentscope/patch.py: Add comment explaining tool_type='function' assumption - dashscope/generation.py: Add comment about hardcoded server_address - tox-loongsuite.ini: Add loongsuite-distro test environment - test_resource.py/test_configurator.py: Update tests for new behavior Change-Id: I9128e7bb1db9bd10b1529a40c5f450e61dcc2aa8 Co-developed-by: Qoder <noreply@qoder.com>
| py3{10,11,12,13}-test-loongsuite-instrumentation-wildtool | ||
| lint-loongsuite-instrumentation-wildtool | ||
|
|
||
| ; loongsuite-distro | ||
| py3{9,10,11,12,13}-test-loongsuite-distro | ||
|
|
| loongsuite-distro: {[testenv]test_deps} | ||
| loongsuite-distro: {toxinidir}/loongsuite-distro |
| LoongSuite configurator, inherits from OpenTelemetry SDK configurator. | ||
|
|
||
| Augments the resource with LoongSuite specific attributes (``host.ip`` and | ||
| ``gen_ai.instrumentation.sdk.name``) before delegating to the OpenTelemetry | ||
| SDK configurator. |
| Opens a UDP socket towards a public address to discover which local | ||
| interface would be used for outbound traffic. No packet is actually sent. | ||
| Falls back to ``127.0.0.1`` when detection fails. |
| sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) | ||
| sock.connect(("8.8.8.8", 80)) | ||
| return sock.getsockname()[0] |
| # Handle schemeless URLs by prepending "//" for urlparse. | ||
| if "://" not in base_url_str: | ||
| base_url_str = "//" + base_url_str |
| parsed = urlparse(base_url_str) | ||
| address = parsed.hostname | ||
| if not address: | ||
| return None, None | ||
| port = parsed.port | ||
| if port is None: | ||
| port = 443 if parsed.scheme == "https" else 80 | ||
| return address, port |
| invocation.provider = "dashscope" | ||
| # DashScope SDK always targets dashscope.aliyuncs.com; if custom endpoint | ||
| # support is added in the future, extract from instance/env instead. | ||
| invocation.server_address = "dashscope.aliyuncs.com" | ||
| invocation.server_port = 443 |
| @mock.patch("opentelemetry.sdk._configuration._initialize_components") | ||
| def test_configure_injects_loongsuite_attributes(self, mock_init): | ||
| LoongSuiteConfigurator().configure() | ||
|
|
||
| mock_init.assert_called_once() | ||
| resource_attributes = mock_init.call_args.kwargs["resource_attributes"] |
| ## Unreleased | ||
|
|
||
| ### Changed | ||
|
|
||
| - Adopt upstream semantic conventions for LoongSuite instrumentation packages. |
Description
Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.
Fixes # (issue)
Type of change
Please delete options that are not relevant.
How Has This Been Tested?
Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration
Does This PR Require a Core Repo Change?
Checklist:
See contributing.md for styleguide, changelog guidelines, and more.