veadk-python 0.2.27__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- veadk/__init__.py +37 -0
- veadk/a2a/__init__.py +13 -0
- veadk/a2a/agent_card.py +45 -0
- veadk/a2a/remote_ve_agent.py +390 -0
- veadk/a2a/utils/__init__.py +13 -0
- veadk/a2a/utils/agent_to_a2a.py +170 -0
- veadk/a2a/ve_a2a_server.py +93 -0
- veadk/a2a/ve_agent_executor.py +78 -0
- veadk/a2a/ve_middlewares.py +313 -0
- veadk/a2a/ve_task_store.py +37 -0
- veadk/agent.py +402 -0
- veadk/agent_builder.py +93 -0
- veadk/agents/loop_agent.py +68 -0
- veadk/agents/parallel_agent.py +72 -0
- veadk/agents/sequential_agent.py +64 -0
- veadk/auth/__init__.py +13 -0
- veadk/auth/base_auth.py +22 -0
- veadk/auth/ve_credential_service.py +203 -0
- veadk/auth/veauth/__init__.py +13 -0
- veadk/auth/veauth/apmplus_veauth.py +58 -0
- veadk/auth/veauth/ark_veauth.py +75 -0
- veadk/auth/veauth/base_veauth.py +50 -0
- veadk/auth/veauth/cozeloop_veauth.py +13 -0
- veadk/auth/veauth/opensearch_veauth.py +75 -0
- veadk/auth/veauth/postgresql_veauth.py +75 -0
- veadk/auth/veauth/prompt_pilot_veauth.py +60 -0
- veadk/auth/veauth/speech_veauth.py +54 -0
- veadk/auth/veauth/utils.py +69 -0
- veadk/auth/veauth/vesearch_veauth.py +62 -0
- veadk/auth/veauth/viking_mem0_veauth.py +91 -0
- veadk/cli/__init__.py +13 -0
- veadk/cli/cli.py +58 -0
- veadk/cli/cli_clean.py +87 -0
- veadk/cli/cli_create.py +163 -0
- veadk/cli/cli_deploy.py +233 -0
- veadk/cli/cli_eval.py +215 -0
- veadk/cli/cli_init.py +214 -0
- veadk/cli/cli_kb.py +110 -0
- veadk/cli/cli_pipeline.py +285 -0
- veadk/cli/cli_prompt.py +86 -0
- veadk/cli/cli_update.py +106 -0
- veadk/cli/cli_uploadevalset.py +139 -0
- veadk/cli/cli_web.py +143 -0
- veadk/cloud/__init__.py +13 -0
- veadk/cloud/cloud_agent_engine.py +485 -0
- veadk/cloud/cloud_app.py +475 -0
- veadk/config.py +115 -0
- veadk/configs/__init__.py +13 -0
- veadk/configs/auth_configs.py +133 -0
- veadk/configs/database_configs.py +132 -0
- veadk/configs/model_configs.py +78 -0
- veadk/configs/tool_configs.py +54 -0
- veadk/configs/tracing_configs.py +110 -0
- veadk/consts.py +74 -0
- veadk/evaluation/__init__.py +17 -0
- veadk/evaluation/adk_evaluator/__init__.py +17 -0
- veadk/evaluation/adk_evaluator/adk_evaluator.py +302 -0
- veadk/evaluation/base_evaluator.py +642 -0
- veadk/evaluation/deepeval_evaluator/__init__.py +17 -0
- veadk/evaluation/deepeval_evaluator/deepeval_evaluator.py +339 -0
- veadk/evaluation/eval_set_file_loader.py +48 -0
- veadk/evaluation/eval_set_recorder.py +146 -0
- veadk/evaluation/types.py +65 -0
- veadk/evaluation/utils/prometheus.py +196 -0
- veadk/integrations/__init__.py +13 -0
- veadk/integrations/ve_apig/__init__.py +13 -0
- veadk/integrations/ve_apig/ve_apig.py +349 -0
- veadk/integrations/ve_apig/ve_apig_utils.py +332 -0
- veadk/integrations/ve_code_pipeline/__init__.py +13 -0
- veadk/integrations/ve_code_pipeline/ve_code_pipeline.py +431 -0
- veadk/integrations/ve_cozeloop/__init__.py +13 -0
- veadk/integrations/ve_cozeloop/ve_cozeloop.py +96 -0
- veadk/integrations/ve_cr/__init__.py +13 -0
- veadk/integrations/ve_cr/ve_cr.py +220 -0
- veadk/integrations/ve_faas/__init__.py +13 -0
- veadk/integrations/ve_faas/template/cookiecutter.json +15 -0
- veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/__init__.py +13 -0
- veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/clean.py +23 -0
- veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/config.yaml.example +6 -0
- veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/deploy.py +106 -0
- veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/__init__.py +13 -0
- veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/agent.py +25 -0
- veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/app.py +202 -0
- veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/requirements.txt +3 -0
- veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/run.sh +49 -0
- veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/{{ cookiecutter.app_name }}/__init__.py +14 -0
- veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/{{ cookiecutter.app_name }}/agent.py +27 -0
- veadk/integrations/ve_faas/ve_faas.py +754 -0
- veadk/integrations/ve_faas/ve_faas_utils.py +408 -0
- veadk/integrations/ve_faas/web_template/cookiecutter.json +20 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/__init__.py +13 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/clean.py +23 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/config.yaml.example +2 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/deploy.py +44 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/Dockerfile +23 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/app.py +123 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/init_db.py +46 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/models.py +36 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/requirements.txt +4 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/run.sh +21 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/static/css/style.css +368 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/static/js/admin.js +0 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/dashboard.html +21 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/edit_post.html +24 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/login.html +21 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/posts.html +53 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/base.html +45 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/index.html +29 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/post.html +14 -0
- veadk/integrations/ve_identity/__init__.py +110 -0
- veadk/integrations/ve_identity/auth_config.py +261 -0
- veadk/integrations/ve_identity/auth_mixins.py +650 -0
- veadk/integrations/ve_identity/auth_processor.py +385 -0
- veadk/integrations/ve_identity/function_tool.py +158 -0
- veadk/integrations/ve_identity/identity_client.py +864 -0
- veadk/integrations/ve_identity/mcp_tool.py +181 -0
- veadk/integrations/ve_identity/mcp_toolset.py +431 -0
- veadk/integrations/ve_identity/models.py +228 -0
- veadk/integrations/ve_identity/token_manager.py +188 -0
- veadk/integrations/ve_identity/utils.py +151 -0
- veadk/integrations/ve_prompt_pilot/__init__.py +13 -0
- veadk/integrations/ve_prompt_pilot/ve_prompt_pilot.py +85 -0
- veadk/integrations/ve_tls/__init__.py +13 -0
- veadk/integrations/ve_tls/utils.py +116 -0
- veadk/integrations/ve_tls/ve_tls.py +212 -0
- veadk/integrations/ve_tos/ve_tos.py +710 -0
- veadk/integrations/ve_viking_db_memory/__init__.py +13 -0
- veadk/integrations/ve_viking_db_memory/ve_viking_db_memory.py +308 -0
- veadk/knowledgebase/__init__.py +17 -0
- veadk/knowledgebase/backends/__init__.py +13 -0
- veadk/knowledgebase/backends/base_backend.py +72 -0
- veadk/knowledgebase/backends/in_memory_backend.py +91 -0
- veadk/knowledgebase/backends/opensearch_backend.py +162 -0
- veadk/knowledgebase/backends/redis_backend.py +172 -0
- veadk/knowledgebase/backends/utils.py +92 -0
- veadk/knowledgebase/backends/vikingdb_knowledge_backend.py +608 -0
- veadk/knowledgebase/entry.py +25 -0
- veadk/knowledgebase/knowledgebase.py +307 -0
- veadk/memory/__init__.py +35 -0
- veadk/memory/long_term_memory.py +365 -0
- veadk/memory/long_term_memory_backends/__init__.py +13 -0
- veadk/memory/long_term_memory_backends/base_backend.py +35 -0
- veadk/memory/long_term_memory_backends/in_memory_backend.py +67 -0
- veadk/memory/long_term_memory_backends/mem0_backend.py +155 -0
- veadk/memory/long_term_memory_backends/opensearch_backend.py +124 -0
- veadk/memory/long_term_memory_backends/redis_backend.py +140 -0
- veadk/memory/long_term_memory_backends/vikingdb_memory_backend.py +189 -0
- veadk/memory/short_term_memory.py +252 -0
- veadk/memory/short_term_memory_backends/__init__.py +13 -0
- veadk/memory/short_term_memory_backends/base_backend.py +31 -0
- veadk/memory/short_term_memory_backends/mysql_backend.py +49 -0
- veadk/memory/short_term_memory_backends/postgresql_backend.py +49 -0
- veadk/memory/short_term_memory_backends/sqlite_backend.py +55 -0
- veadk/memory/short_term_memory_processor.py +100 -0
- veadk/processors/__init__.py +26 -0
- veadk/processors/base_run_processor.py +120 -0
- veadk/prompts/__init__.py +13 -0
- veadk/prompts/agent_default_prompt.py +30 -0
- veadk/prompts/prompt_evaluator.py +20 -0
- veadk/prompts/prompt_memory_processor.py +55 -0
- veadk/prompts/prompt_optimization.py +150 -0
- veadk/runner.py +732 -0
- veadk/tools/__init__.py +13 -0
- veadk/tools/builtin_tools/__init__.py +13 -0
- veadk/tools/builtin_tools/agent_authorization.py +94 -0
- veadk/tools/builtin_tools/generate_image.py +23 -0
- veadk/tools/builtin_tools/image_edit.py +300 -0
- veadk/tools/builtin_tools/image_generate.py +446 -0
- veadk/tools/builtin_tools/lark.py +67 -0
- veadk/tools/builtin_tools/las.py +24 -0
- veadk/tools/builtin_tools/link_reader.py +66 -0
- veadk/tools/builtin_tools/llm_shield.py +381 -0
- veadk/tools/builtin_tools/load_knowledgebase.py +97 -0
- veadk/tools/builtin_tools/mcp_router.py +29 -0
- veadk/tools/builtin_tools/run_code.py +113 -0
- veadk/tools/builtin_tools/tts.py +253 -0
- veadk/tools/builtin_tools/vesearch.py +49 -0
- veadk/tools/builtin_tools/video_generate.py +363 -0
- veadk/tools/builtin_tools/web_scraper.py +76 -0
- veadk/tools/builtin_tools/web_search.py +83 -0
- veadk/tools/demo_tools.py +58 -0
- veadk/tools/load_knowledgebase_tool.py +149 -0
- veadk/tools/sandbox/__init__.py +13 -0
- veadk/tools/sandbox/browser_sandbox.py +37 -0
- veadk/tools/sandbox/code_sandbox.py +40 -0
- veadk/tools/sandbox/computer_sandbox.py +34 -0
- veadk/tracing/__init__.py +13 -0
- veadk/tracing/base_tracer.py +58 -0
- veadk/tracing/telemetry/__init__.py +13 -0
- veadk/tracing/telemetry/attributes/attributes.py +29 -0
- veadk/tracing/telemetry/attributes/extractors/common_attributes_extractors.py +180 -0
- veadk/tracing/telemetry/attributes/extractors/llm_attributes_extractors.py +858 -0
- veadk/tracing/telemetry/attributes/extractors/tool_attributes_extractors.py +152 -0
- veadk/tracing/telemetry/attributes/extractors/types.py +164 -0
- veadk/tracing/telemetry/exporters/__init__.py +13 -0
- veadk/tracing/telemetry/exporters/apmplus_exporter.py +558 -0
- veadk/tracing/telemetry/exporters/base_exporter.py +39 -0
- veadk/tracing/telemetry/exporters/cozeloop_exporter.py +129 -0
- veadk/tracing/telemetry/exporters/inmemory_exporter.py +248 -0
- veadk/tracing/telemetry/exporters/tls_exporter.py +139 -0
- veadk/tracing/telemetry/opentelemetry_tracer.py +320 -0
- veadk/tracing/telemetry/telemetry.py +411 -0
- veadk/types.py +47 -0
- veadk/utils/__init__.py +13 -0
- veadk/utils/audio_manager.py +95 -0
- veadk/utils/auth.py +294 -0
- veadk/utils/logger.py +59 -0
- veadk/utils/mcp_utils.py +44 -0
- veadk/utils/misc.py +184 -0
- veadk/utils/patches.py +101 -0
- veadk/utils/volcengine_sign.py +205 -0
- veadk/version.py +15 -0
- veadk_python-0.2.27.dist-info/METADATA +373 -0
- veadk_python-0.2.27.dist-info/RECORD +218 -0
- veadk_python-0.2.27.dist-info/WHEEL +5 -0
- veadk_python-0.2.27.dist-info/entry_points.txt +2 -0
- veadk_python-0.2.27.dist-info/licenses/LICENSE +201 -0
- veadk_python-0.2.27.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from typing import Any
|
|
16
|
+
|
|
17
|
+
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
|
|
18
|
+
from opentelemetry.sdk.trace.export import BatchSpanProcessor
|
|
19
|
+
from pydantic import BaseModel, Field
|
|
20
|
+
from typing_extensions import override
|
|
21
|
+
|
|
22
|
+
from veadk.config import settings
|
|
23
|
+
from veadk.tracing.telemetry.exporters.base_exporter import BaseExporter
|
|
24
|
+
from veadk.utils.logger import get_logger
|
|
25
|
+
|
|
26
|
+
logger = get_logger(__name__)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class CozeloopExporterConfig(BaseModel):
|
|
30
|
+
"""Configuration model for CozeLoop exporter settings.
|
|
31
|
+
|
|
32
|
+
Manages connection parameters and authentication details for
|
|
33
|
+
integrating with CozeLoop observability and evaluation platform.
|
|
34
|
+
|
|
35
|
+
Attributes:
|
|
36
|
+
endpoint: OTLP HTTP endpoint URL for CozeLoop data ingestion
|
|
37
|
+
space_id: Workspace identifier for organizing data in CozeLoop
|
|
38
|
+
token: Authentication token for CozeLoop API access
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
endpoint: str = Field(
|
|
42
|
+
default_factory=lambda: settings.cozeloop_config.otel_exporter_endpoint,
|
|
43
|
+
)
|
|
44
|
+
space_id: str = Field(
|
|
45
|
+
default_factory=lambda: settings.cozeloop_config.otel_exporter_space_id,
|
|
46
|
+
)
|
|
47
|
+
token: str = Field(
|
|
48
|
+
default_factory=lambda: settings.cozeloop_config.otel_exporter_api_key,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class CozeloopExporter(BaseExporter):
|
|
53
|
+
"""OpenTelemetry exporter for CozeLoop evaluation and observability platform.
|
|
54
|
+
|
|
55
|
+
CozeloopExporter provides integration with CozeLoop platform for agent
|
|
56
|
+
evaluation, monitoring, and analysis. It uses HTTP-based OTLP export
|
|
57
|
+
to send trace data to CozeLoop's evaluation infrastructure for detailed
|
|
58
|
+
performance analysis and evaluation workflows.
|
|
59
|
+
|
|
60
|
+
Integration:
|
|
61
|
+
CozeLoop specializes in AI agent evaluation and provides advanced
|
|
62
|
+
analytics for conversation quality, tool usage effectiveness, and
|
|
63
|
+
overall agent performance metrics. The exporter enables seamless
|
|
64
|
+
integration with CozeLoop's evaluation workflows.
|
|
65
|
+
|
|
66
|
+
Examples:
|
|
67
|
+
Basic usage with default settings:
|
|
68
|
+
```python
|
|
69
|
+
exporter = CozeloopExporter()
|
|
70
|
+
tracer = OpentelemetryTracer(exporters=[exporter])
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Note:
|
|
74
|
+
- Requires valid CozeLoop workspace ID and authentication token
|
|
75
|
+
- Data is organized by workspace for multi-tenant isolation
|
|
76
|
+
- Suitable for both development and production evaluation workflows
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
config: CozeloopExporterConfig = Field(default_factory=CozeloopExporterConfig)
|
|
80
|
+
|
|
81
|
+
def model_post_init(self, context: Any) -> None:
|
|
82
|
+
"""Initialize CozeLoop exporter components after model construction.
|
|
83
|
+
|
|
84
|
+
Sets up HTTP-based OTLP span exporter and batch processor with
|
|
85
|
+
proper authentication headers and workspace identification for
|
|
86
|
+
CozeLoop platform integration.
|
|
87
|
+
|
|
88
|
+
Components Initialized:
|
|
89
|
+
- HTTP OTLP span exporter with CozeLoop endpoint
|
|
90
|
+
- Batch span processor for efficient data transmission
|
|
91
|
+
- Authentication headers with workspace ID and bearer token
|
|
92
|
+
- Timeout configuration for reliable network operations
|
|
93
|
+
"""
|
|
94
|
+
logger.info(f"CozeloopExporter space ID: {self.config.space_id}")
|
|
95
|
+
|
|
96
|
+
headers = {
|
|
97
|
+
"cozeloop-workspace-id": self.config.space_id,
|
|
98
|
+
"authorization": f"Bearer {self.config.token}",
|
|
99
|
+
}
|
|
100
|
+
self.headers |= headers
|
|
101
|
+
|
|
102
|
+
self._exporter = OTLPSpanExporter(
|
|
103
|
+
endpoint=self.config.endpoint,
|
|
104
|
+
headers=self.headers,
|
|
105
|
+
timeout=10,
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
self.processor = BatchSpanProcessor(self._exporter)
|
|
109
|
+
|
|
110
|
+
@override
|
|
111
|
+
def export(self) -> None:
|
|
112
|
+
"""Force immediate export of pending telemetry data to CozeLoop.
|
|
113
|
+
|
|
114
|
+
Triggers force flush on the HTTP OTLP span exporter to ensure all
|
|
115
|
+
buffered span data is immediately transmitted to CozeLoop for
|
|
116
|
+
real-time evaluation and analysis.
|
|
117
|
+
|
|
118
|
+
Operations:
|
|
119
|
+
- Forces flush of span exporter if initialized
|
|
120
|
+
- Logs export status with endpoint and workspace details
|
|
121
|
+
- Handles cases where exporter is not properly initialized
|
|
122
|
+
"""
|
|
123
|
+
if self._exporter:
|
|
124
|
+
self._exporter.force_flush()
|
|
125
|
+
logger.info(
|
|
126
|
+
f"CozeloopExporter exports data to {self.config.endpoint}, space id: {self.config.space_id}"
|
|
127
|
+
)
|
|
128
|
+
else:
|
|
129
|
+
logger.warning("CozeloopExporter internal exporter is not initialized.")
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from typing import Sequence
|
|
16
|
+
|
|
17
|
+
from opentelemetry.context import (
|
|
18
|
+
_SUPPRESS_INSTRUMENTATION_KEY,
|
|
19
|
+
attach,
|
|
20
|
+
detach,
|
|
21
|
+
set_value,
|
|
22
|
+
)
|
|
23
|
+
from opentelemetry.sdk.trace import ReadableSpan, export
|
|
24
|
+
from typing_extensions import override
|
|
25
|
+
|
|
26
|
+
from veadk.tracing.telemetry.exporters.base_exporter import BaseExporter
|
|
27
|
+
from veadk.utils.logger import get_logger
|
|
28
|
+
|
|
29
|
+
logger = get_logger(__name__)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
# ======== Adapted from Google ADK ========
|
|
33
|
+
class _InMemoryExporter(export.SpanExporter):
|
|
34
|
+
"""Internal span exporter that stores spans in memory for local analysis and debugging.
|
|
35
|
+
|
|
36
|
+
This exporter collects and stores OpenTelemetry spans in memory rather than
|
|
37
|
+
sending them to external services. It's particularly useful for development,
|
|
38
|
+
testing, and local trace analysis scenarios where immediate access to span
|
|
39
|
+
data is needed.
|
|
40
|
+
|
|
41
|
+
Key Features:
|
|
42
|
+
- In-memory span storage with session-based organization
|
|
43
|
+
- Trace ID tracking for span correlation
|
|
44
|
+
- Session-to-trace mapping for efficient filtering
|
|
45
|
+
- Support for span retrieval by session ID
|
|
46
|
+
|
|
47
|
+
Attributes:
|
|
48
|
+
_spans: List of all collected ReadableSpan objects
|
|
49
|
+
trace_id: Current trace identifier from the most recent span
|
|
50
|
+
session_trace_dict: Mapping of session IDs to their associated trace IDs
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
def __init__(self) -> None:
|
|
54
|
+
"""Initialize the in-memory exporter with empty storage containers."""
|
|
55
|
+
super().__init__()
|
|
56
|
+
self._spans = []
|
|
57
|
+
self.trace_id = ""
|
|
58
|
+
self.session_trace_dict = {}
|
|
59
|
+
|
|
60
|
+
@override
|
|
61
|
+
def export(self, spans: Sequence[ReadableSpan]) -> export.SpanExportResult:
|
|
62
|
+
"""Export spans to in-memory storage with session tracking.
|
|
63
|
+
|
|
64
|
+
Processes and stores spans while maintaining session-to-trace mapping
|
|
65
|
+
for efficient retrieval. Extracts session information from LLM call spans
|
|
66
|
+
to enable session-based filtering.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
spans: Sequence of ReadableSpan objects to store
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
SpanExportResult.SUCCESS: Always returns success for in-memory storage
|
|
73
|
+
"""
|
|
74
|
+
for span in spans:
|
|
75
|
+
if span.context:
|
|
76
|
+
self.trace_id = span.context.trace_id
|
|
77
|
+
else:
|
|
78
|
+
logger.warning(
|
|
79
|
+
f"Span context is missing, failed to get `trace_id`. span: {span}"
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
if span.name == "call_llm":
|
|
83
|
+
attributes = dict(span.attributes or {})
|
|
84
|
+
session_id = attributes.get("gen_ai.session.id", None)
|
|
85
|
+
if session_id:
|
|
86
|
+
if session_id not in self.session_trace_dict:
|
|
87
|
+
self.session_trace_dict[session_id] = [self.trace_id]
|
|
88
|
+
else:
|
|
89
|
+
self.session_trace_dict[session_id] += [self.trace_id]
|
|
90
|
+
self._spans.extend(spans)
|
|
91
|
+
return export.SpanExportResult.SUCCESS
|
|
92
|
+
|
|
93
|
+
@override
|
|
94
|
+
def force_flush(self, timeout_millis: int = 30000) -> bool:
|
|
95
|
+
"""Force flush operation for in-memory exporter.
|
|
96
|
+
|
|
97
|
+
Since spans are immediately stored in memory, this operation
|
|
98
|
+
always succeeds without performing any actual flushing.
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
bool: Always True indicating successful flush
|
|
102
|
+
"""
|
|
103
|
+
return True
|
|
104
|
+
|
|
105
|
+
def get_finished_spans(self, session_id: str):
|
|
106
|
+
"""Retrieve all spans associated with a specific session ID.
|
|
107
|
+
|
|
108
|
+
Filters stored spans to return only those belonging to the specified
|
|
109
|
+
session, enabling session-scoped trace analysis and debugging.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
session_id: Session identifier to filter spans by
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
list[ReadableSpan]: List of spans associated with the session,
|
|
116
|
+
empty list if session not found or no spans available
|
|
117
|
+
"""
|
|
118
|
+
trace_ids = self.session_trace_dict.get(session_id, None)
|
|
119
|
+
if trace_ids is None or not trace_ids:
|
|
120
|
+
return []
|
|
121
|
+
return [x for x in self._spans if x.context.trace_id in trace_ids]
|
|
122
|
+
|
|
123
|
+
def clear(self):
|
|
124
|
+
"""Clear all stored spans and session mappings.
|
|
125
|
+
|
|
126
|
+
Removes all collected span data from memory, useful for cleanup
|
|
127
|
+
between test runs or to free memory in long-running processes.
|
|
128
|
+
"""
|
|
129
|
+
self._spans.clear()
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
class _InMemorySpanProcessor(export.SimpleSpanProcessor):
|
|
133
|
+
"""Custom span processor for in-memory export with enhanced span annotation.
|
|
134
|
+
|
|
135
|
+
Extends SimpleSpanProcessor to add VeADK-specific span attributes and
|
|
136
|
+
context management. Handles span lifecycle events to set appropriate
|
|
137
|
+
attributes and manage OpenTelemetry context for nested span hierarchies.
|
|
138
|
+
"""
|
|
139
|
+
|
|
140
|
+
def __init__(self, exporter: _InMemoryExporter) -> None:
|
|
141
|
+
"""Initialize the span processor with the given in-memory exporter.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
exporter: _InMemoryExporter instance for storing processed spans
|
|
145
|
+
"""
|
|
146
|
+
super().__init__(exporter)
|
|
147
|
+
|
|
148
|
+
def on_start(self, span, parent_context) -> None:
|
|
149
|
+
"""Handle span start events with type-specific attribute setting.
|
|
150
|
+
|
|
151
|
+
Automatically detects span types based on name patterns and applies
|
|
152
|
+
appropriate attributes. Sets up OpenTelemetry context for hierarchical
|
|
153
|
+
span management and instrumentation suppression.
|
|
154
|
+
|
|
155
|
+
Args:
|
|
156
|
+
span: The span being started
|
|
157
|
+
parent_context: Parent OpenTelemetry context
|
|
158
|
+
"""
|
|
159
|
+
if span.name.startswith("invocation"):
|
|
160
|
+
span.set_attribute("gen_ai.operation.name", "chain")
|
|
161
|
+
span.set_attribute("gen_ai.span.kind", "workflow")
|
|
162
|
+
span.set_attribute("gen_ai.usage.total_tokens", 0)
|
|
163
|
+
ctx = set_value("invocation_span_instance", span, context=parent_context)
|
|
164
|
+
# suppress instrumentation for llm to avoid auto instrument from apmplus, such as openai
|
|
165
|
+
ctx = set_value(
|
|
166
|
+
"suppress_language_model_instrumentation", True, context=ctx
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
token = attach(ctx) # mount context on `invocation` root span in Google ADK
|
|
170
|
+
setattr(span, "_invocation_token", token) # for later detach
|
|
171
|
+
|
|
172
|
+
if span.name.startswith("agent_run") or span.name.startswith("invoke_agent"):
|
|
173
|
+
span.set_attribute("gen_ai.operation.name", "agent")
|
|
174
|
+
span.set_attribute("gen_ai.span.kind", "agent")
|
|
175
|
+
|
|
176
|
+
ctx = set_value("agent_run_span_instance", span, context=parent_context)
|
|
177
|
+
token = attach(ctx)
|
|
178
|
+
setattr(span, "_agent_run_token", token) # for later detach
|
|
179
|
+
|
|
180
|
+
def on_end(self, span: ReadableSpan) -> None:
|
|
181
|
+
"""Handle span end events with proper context cleanup.
|
|
182
|
+
|
|
183
|
+
Exports the finished span to the in-memory storage while managing
|
|
184
|
+
OpenTelemetry context and cleaning up attached tokens to prevent
|
|
185
|
+
memory leaks.
|
|
186
|
+
|
|
187
|
+
Args:
|
|
188
|
+
span: The span that has finished execution
|
|
189
|
+
"""
|
|
190
|
+
if span.context:
|
|
191
|
+
if not span.context.trace_flags.sampled:
|
|
192
|
+
return
|
|
193
|
+
token = attach(set_value(_SUPPRESS_INSTRUMENTATION_KEY, True))
|
|
194
|
+
try:
|
|
195
|
+
self.span_exporter.export((span,))
|
|
196
|
+
# pylint: disable=broad-exception-caught
|
|
197
|
+
except Exception:
|
|
198
|
+
logger.exception("Exception while exporting Span.")
|
|
199
|
+
detach(token)
|
|
200
|
+
|
|
201
|
+
token = getattr(span, "_invocation_token", None)
|
|
202
|
+
if token:
|
|
203
|
+
detach(token)
|
|
204
|
+
|
|
205
|
+
token = getattr(span, "_agent_run_token", None)
|
|
206
|
+
if token:
|
|
207
|
+
detach(token)
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
class InMemoryExporter(BaseExporter):
|
|
211
|
+
"""In-memory span exporter for local debugging and observability analysis.
|
|
212
|
+
|
|
213
|
+
InMemoryExporter provides a complete in-memory tracing solution that stores
|
|
214
|
+
spans locally for immediate analysis, debugging, and testing. It's ideal for
|
|
215
|
+
development environments where external observability platforms are not
|
|
216
|
+
available or not desired.
|
|
217
|
+
|
|
218
|
+
Use Cases:
|
|
219
|
+
- Development and debugging of agent workflows
|
|
220
|
+
- Unit and integration testing with trace verification
|
|
221
|
+
- Local trace analysis and performance profiling
|
|
222
|
+
- Offline environments without external connectivity
|
|
223
|
+
- Trace data export for post-processing and analysis
|
|
224
|
+
|
|
225
|
+
Integration:
|
|
226
|
+
The exporter is automatically added to OpentelemetryTracer instances
|
|
227
|
+
and cannot be manually configured to avoid conflicts. It provides the
|
|
228
|
+
foundation for local trace file generation and analysis.
|
|
229
|
+
|
|
230
|
+
Note:
|
|
231
|
+
- Cannot be added to exporter lists (validation prevents this)
|
|
232
|
+
- Automatically managed by OpentelemetryTracer
|
|
233
|
+
- Memory usage grows with span count - consider periodic clearing
|
|
234
|
+
- Session tracking requires properly configured session IDs
|
|
235
|
+
"""
|
|
236
|
+
|
|
237
|
+
def __init__(self, name: str = "inmemory_exporter") -> None:
|
|
238
|
+
"""Initialize the in-memory exporter with internal components.
|
|
239
|
+
|
|
240
|
+
Args:
|
|
241
|
+
name: Identifier for this exporter instance.
|
|
242
|
+
"""
|
|
243
|
+
super().__init__()
|
|
244
|
+
|
|
245
|
+
self.name = name
|
|
246
|
+
|
|
247
|
+
self._exporter = _InMemoryExporter()
|
|
248
|
+
self.processor = _InMemorySpanProcessor(self._exporter)
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from typing import Any
|
|
16
|
+
|
|
17
|
+
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
|
|
18
|
+
from opentelemetry.sdk.trace.export import BatchSpanProcessor
|
|
19
|
+
from pydantic import BaseModel, Field
|
|
20
|
+
from typing_extensions import override
|
|
21
|
+
|
|
22
|
+
from veadk.config import getenv, settings
|
|
23
|
+
from veadk.tracing.telemetry.exporters.base_exporter import BaseExporter
|
|
24
|
+
from veadk.utils.logger import get_logger
|
|
25
|
+
|
|
26
|
+
logger = get_logger(__name__)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class TLSExporterConfig(BaseModel):
|
|
30
|
+
"""Configuration model for Volcengine TLS exporter settings.
|
|
31
|
+
|
|
32
|
+
Manages connection parameters and authentication details for
|
|
33
|
+
integrating with Volcengine's TLS logging and observability platform.
|
|
34
|
+
|
|
35
|
+
Attributes:
|
|
36
|
+
endpoint: OTLP HTTP endpoint URL for TLS data ingestion
|
|
37
|
+
region: Volcengine region where the TLS service is deployed
|
|
38
|
+
topic_id: TLS topic identifier for organizing log data
|
|
39
|
+
access_key: Volcengine access key for API authentication
|
|
40
|
+
secret_key: Volcengine secret key for API authentication
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
endpoint: str = Field(
|
|
44
|
+
default_factory=lambda: settings.tls_config.otel_exporter_endpoint,
|
|
45
|
+
)
|
|
46
|
+
region: str = Field(
|
|
47
|
+
default_factory=lambda: settings.tls_config.otel_exporter_region,
|
|
48
|
+
)
|
|
49
|
+
topic_id: str = Field(
|
|
50
|
+
default_factory=lambda: settings.tls_config.otel_exporter_topic_id,
|
|
51
|
+
)
|
|
52
|
+
access_key: str = Field(default_factory=lambda: getenv("VOLCENGINE_ACCESS_KEY"))
|
|
53
|
+
secret_key: str = Field(default_factory=lambda: getenv("VOLCENGINE_SECRET_KEY"))
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class TLSExporter(BaseExporter):
|
|
57
|
+
"""OpenTelemetry exporter for Volcengine TLS platform.
|
|
58
|
+
|
|
59
|
+
TLSExporter provides integration with Volcengine's TLS platform for
|
|
60
|
+
centralized logging and trace data management. It uses HTTP-based OTLP
|
|
61
|
+
export to send trace data to TLS topics for storage, analysis, and
|
|
62
|
+
long-term retention.
|
|
63
|
+
|
|
64
|
+
Use Cases:
|
|
65
|
+
- Centralized trace data storage and archival
|
|
66
|
+
- Long-term performance trend analysis
|
|
67
|
+
- Compliance and audit trail requirements
|
|
68
|
+
- Cross-service trace correlation and analysis
|
|
69
|
+
- Integration with existing TLS logging infrastructure
|
|
70
|
+
|
|
71
|
+
Examples:
|
|
72
|
+
Basic usage with default settings:
|
|
73
|
+
```python
|
|
74
|
+
exporter = TLSExporter()
|
|
75
|
+
tracer = OpentelemetryTracer(exporters=[exporter])
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Note:
|
|
79
|
+
- Requires valid Volcengine credentials and TLS topic ID
|
|
80
|
+
- Data is organized by topics for efficient management
|
|
81
|
+
- Supports regional deployments for data locality compliance
|
|
82
|
+
- Integrates with TLS alerting and analysis features
|
|
83
|
+
- Suitable for production environments requiring data retention
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
config: TLSExporterConfig = Field(default_factory=TLSExporterConfig)
|
|
87
|
+
|
|
88
|
+
def model_post_init(self, context: Any) -> None:
|
|
89
|
+
"""Initialize TLS exporter components after model construction.
|
|
90
|
+
|
|
91
|
+
Sets up HTTP-based OTLP span exporter and batch processor with
|
|
92
|
+
Volcengine authentication headers and TLS topic configuration for
|
|
93
|
+
centralized trace data management.
|
|
94
|
+
|
|
95
|
+
Components Initialized:
|
|
96
|
+
- HTTP OTLP span exporter with TLS endpoint
|
|
97
|
+
- Batch span processor for efficient data transmission
|
|
98
|
+
- Authentication headers with Volcengine credentials
|
|
99
|
+
- Topic and region configuration for data routing
|
|
100
|
+
- Timeout configuration for reliable network operations
|
|
101
|
+
"""
|
|
102
|
+
logger.info(f"TLSExporter topic ID: {self.config.topic_id}")
|
|
103
|
+
|
|
104
|
+
headers = {
|
|
105
|
+
"x-tls-otel-tracetopic": self.config.topic_id,
|
|
106
|
+
"x-tls-otel-ak": self.config.access_key,
|
|
107
|
+
"x-tls-otel-sk": self.config.secret_key,
|
|
108
|
+
"x-tls-otel-region": self.config.region,
|
|
109
|
+
}
|
|
110
|
+
self.headers |= headers
|
|
111
|
+
|
|
112
|
+
self._exporter = OTLPSpanExporter(
|
|
113
|
+
endpoint=self.config.endpoint,
|
|
114
|
+
headers=headers,
|
|
115
|
+
timeout=10,
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
self.processor = BatchSpanProcessor(self._exporter)
|
|
119
|
+
|
|
120
|
+
@override
|
|
121
|
+
def export(self) -> None:
|
|
122
|
+
"""Force immediate export of pending telemetry data to TLS.
|
|
123
|
+
|
|
124
|
+
Triggers force flush on the HTTP OTLP span exporter to ensure all
|
|
125
|
+
buffered span data is immediately transmitted to TLS for centralized
|
|
126
|
+
logging and analysis.
|
|
127
|
+
|
|
128
|
+
Operations:
|
|
129
|
+
- Forces flush of span exporter if initialized
|
|
130
|
+
- Logs export status with endpoint and topic details
|
|
131
|
+
- Handles cases where exporter is not properly initialized
|
|
132
|
+
"""
|
|
133
|
+
if self._exporter:
|
|
134
|
+
self._exporter.force_flush()
|
|
135
|
+
logger.info(
|
|
136
|
+
f"TLSExporter exports data to {self.config.endpoint}, topic id: {self.config.topic_id}"
|
|
137
|
+
)
|
|
138
|
+
else:
|
|
139
|
+
logger.warning("TLSExporter internal exporter is not initialized.")
|