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.
Files changed (218) hide show
  1. veadk/__init__.py +37 -0
  2. veadk/a2a/__init__.py +13 -0
  3. veadk/a2a/agent_card.py +45 -0
  4. veadk/a2a/remote_ve_agent.py +390 -0
  5. veadk/a2a/utils/__init__.py +13 -0
  6. veadk/a2a/utils/agent_to_a2a.py +170 -0
  7. veadk/a2a/ve_a2a_server.py +93 -0
  8. veadk/a2a/ve_agent_executor.py +78 -0
  9. veadk/a2a/ve_middlewares.py +313 -0
  10. veadk/a2a/ve_task_store.py +37 -0
  11. veadk/agent.py +402 -0
  12. veadk/agent_builder.py +93 -0
  13. veadk/agents/loop_agent.py +68 -0
  14. veadk/agents/parallel_agent.py +72 -0
  15. veadk/agents/sequential_agent.py +64 -0
  16. veadk/auth/__init__.py +13 -0
  17. veadk/auth/base_auth.py +22 -0
  18. veadk/auth/ve_credential_service.py +203 -0
  19. veadk/auth/veauth/__init__.py +13 -0
  20. veadk/auth/veauth/apmplus_veauth.py +58 -0
  21. veadk/auth/veauth/ark_veauth.py +75 -0
  22. veadk/auth/veauth/base_veauth.py +50 -0
  23. veadk/auth/veauth/cozeloop_veauth.py +13 -0
  24. veadk/auth/veauth/opensearch_veauth.py +75 -0
  25. veadk/auth/veauth/postgresql_veauth.py +75 -0
  26. veadk/auth/veauth/prompt_pilot_veauth.py +60 -0
  27. veadk/auth/veauth/speech_veauth.py +54 -0
  28. veadk/auth/veauth/utils.py +69 -0
  29. veadk/auth/veauth/vesearch_veauth.py +62 -0
  30. veadk/auth/veauth/viking_mem0_veauth.py +91 -0
  31. veadk/cli/__init__.py +13 -0
  32. veadk/cli/cli.py +58 -0
  33. veadk/cli/cli_clean.py +87 -0
  34. veadk/cli/cli_create.py +163 -0
  35. veadk/cli/cli_deploy.py +233 -0
  36. veadk/cli/cli_eval.py +215 -0
  37. veadk/cli/cli_init.py +214 -0
  38. veadk/cli/cli_kb.py +110 -0
  39. veadk/cli/cli_pipeline.py +285 -0
  40. veadk/cli/cli_prompt.py +86 -0
  41. veadk/cli/cli_update.py +106 -0
  42. veadk/cli/cli_uploadevalset.py +139 -0
  43. veadk/cli/cli_web.py +143 -0
  44. veadk/cloud/__init__.py +13 -0
  45. veadk/cloud/cloud_agent_engine.py +485 -0
  46. veadk/cloud/cloud_app.py +475 -0
  47. veadk/config.py +115 -0
  48. veadk/configs/__init__.py +13 -0
  49. veadk/configs/auth_configs.py +133 -0
  50. veadk/configs/database_configs.py +132 -0
  51. veadk/configs/model_configs.py +78 -0
  52. veadk/configs/tool_configs.py +54 -0
  53. veadk/configs/tracing_configs.py +110 -0
  54. veadk/consts.py +74 -0
  55. veadk/evaluation/__init__.py +17 -0
  56. veadk/evaluation/adk_evaluator/__init__.py +17 -0
  57. veadk/evaluation/adk_evaluator/adk_evaluator.py +302 -0
  58. veadk/evaluation/base_evaluator.py +642 -0
  59. veadk/evaluation/deepeval_evaluator/__init__.py +17 -0
  60. veadk/evaluation/deepeval_evaluator/deepeval_evaluator.py +339 -0
  61. veadk/evaluation/eval_set_file_loader.py +48 -0
  62. veadk/evaluation/eval_set_recorder.py +146 -0
  63. veadk/evaluation/types.py +65 -0
  64. veadk/evaluation/utils/prometheus.py +196 -0
  65. veadk/integrations/__init__.py +13 -0
  66. veadk/integrations/ve_apig/__init__.py +13 -0
  67. veadk/integrations/ve_apig/ve_apig.py +349 -0
  68. veadk/integrations/ve_apig/ve_apig_utils.py +332 -0
  69. veadk/integrations/ve_code_pipeline/__init__.py +13 -0
  70. veadk/integrations/ve_code_pipeline/ve_code_pipeline.py +431 -0
  71. veadk/integrations/ve_cozeloop/__init__.py +13 -0
  72. veadk/integrations/ve_cozeloop/ve_cozeloop.py +96 -0
  73. veadk/integrations/ve_cr/__init__.py +13 -0
  74. veadk/integrations/ve_cr/ve_cr.py +220 -0
  75. veadk/integrations/ve_faas/__init__.py +13 -0
  76. veadk/integrations/ve_faas/template/cookiecutter.json +15 -0
  77. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/__init__.py +13 -0
  78. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/clean.py +23 -0
  79. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/config.yaml.example +6 -0
  80. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/deploy.py +106 -0
  81. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/__init__.py +13 -0
  82. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/agent.py +25 -0
  83. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/app.py +202 -0
  84. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/requirements.txt +3 -0
  85. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/run.sh +49 -0
  86. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/{{ cookiecutter.app_name }}/__init__.py +14 -0
  87. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/{{ cookiecutter.app_name }}/agent.py +27 -0
  88. veadk/integrations/ve_faas/ve_faas.py +754 -0
  89. veadk/integrations/ve_faas/ve_faas_utils.py +408 -0
  90. veadk/integrations/ve_faas/web_template/cookiecutter.json +20 -0
  91. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/__init__.py +13 -0
  92. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/clean.py +23 -0
  93. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/config.yaml.example +2 -0
  94. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/deploy.py +44 -0
  95. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/Dockerfile +23 -0
  96. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/app.py +123 -0
  97. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/init_db.py +46 -0
  98. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/models.py +36 -0
  99. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/requirements.txt +4 -0
  100. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/run.sh +21 -0
  101. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/static/css/style.css +368 -0
  102. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/static/js/admin.js +0 -0
  103. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/dashboard.html +21 -0
  104. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/edit_post.html +24 -0
  105. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/login.html +21 -0
  106. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/posts.html +53 -0
  107. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/base.html +45 -0
  108. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/index.html +29 -0
  109. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/post.html +14 -0
  110. veadk/integrations/ve_identity/__init__.py +110 -0
  111. veadk/integrations/ve_identity/auth_config.py +261 -0
  112. veadk/integrations/ve_identity/auth_mixins.py +650 -0
  113. veadk/integrations/ve_identity/auth_processor.py +385 -0
  114. veadk/integrations/ve_identity/function_tool.py +158 -0
  115. veadk/integrations/ve_identity/identity_client.py +864 -0
  116. veadk/integrations/ve_identity/mcp_tool.py +181 -0
  117. veadk/integrations/ve_identity/mcp_toolset.py +431 -0
  118. veadk/integrations/ve_identity/models.py +228 -0
  119. veadk/integrations/ve_identity/token_manager.py +188 -0
  120. veadk/integrations/ve_identity/utils.py +151 -0
  121. veadk/integrations/ve_prompt_pilot/__init__.py +13 -0
  122. veadk/integrations/ve_prompt_pilot/ve_prompt_pilot.py +85 -0
  123. veadk/integrations/ve_tls/__init__.py +13 -0
  124. veadk/integrations/ve_tls/utils.py +116 -0
  125. veadk/integrations/ve_tls/ve_tls.py +212 -0
  126. veadk/integrations/ve_tos/ve_tos.py +710 -0
  127. veadk/integrations/ve_viking_db_memory/__init__.py +13 -0
  128. veadk/integrations/ve_viking_db_memory/ve_viking_db_memory.py +308 -0
  129. veadk/knowledgebase/__init__.py +17 -0
  130. veadk/knowledgebase/backends/__init__.py +13 -0
  131. veadk/knowledgebase/backends/base_backend.py +72 -0
  132. veadk/knowledgebase/backends/in_memory_backend.py +91 -0
  133. veadk/knowledgebase/backends/opensearch_backend.py +162 -0
  134. veadk/knowledgebase/backends/redis_backend.py +172 -0
  135. veadk/knowledgebase/backends/utils.py +92 -0
  136. veadk/knowledgebase/backends/vikingdb_knowledge_backend.py +608 -0
  137. veadk/knowledgebase/entry.py +25 -0
  138. veadk/knowledgebase/knowledgebase.py +307 -0
  139. veadk/memory/__init__.py +35 -0
  140. veadk/memory/long_term_memory.py +365 -0
  141. veadk/memory/long_term_memory_backends/__init__.py +13 -0
  142. veadk/memory/long_term_memory_backends/base_backend.py +35 -0
  143. veadk/memory/long_term_memory_backends/in_memory_backend.py +67 -0
  144. veadk/memory/long_term_memory_backends/mem0_backend.py +155 -0
  145. veadk/memory/long_term_memory_backends/opensearch_backend.py +124 -0
  146. veadk/memory/long_term_memory_backends/redis_backend.py +140 -0
  147. veadk/memory/long_term_memory_backends/vikingdb_memory_backend.py +189 -0
  148. veadk/memory/short_term_memory.py +252 -0
  149. veadk/memory/short_term_memory_backends/__init__.py +13 -0
  150. veadk/memory/short_term_memory_backends/base_backend.py +31 -0
  151. veadk/memory/short_term_memory_backends/mysql_backend.py +49 -0
  152. veadk/memory/short_term_memory_backends/postgresql_backend.py +49 -0
  153. veadk/memory/short_term_memory_backends/sqlite_backend.py +55 -0
  154. veadk/memory/short_term_memory_processor.py +100 -0
  155. veadk/processors/__init__.py +26 -0
  156. veadk/processors/base_run_processor.py +120 -0
  157. veadk/prompts/__init__.py +13 -0
  158. veadk/prompts/agent_default_prompt.py +30 -0
  159. veadk/prompts/prompt_evaluator.py +20 -0
  160. veadk/prompts/prompt_memory_processor.py +55 -0
  161. veadk/prompts/prompt_optimization.py +150 -0
  162. veadk/runner.py +732 -0
  163. veadk/tools/__init__.py +13 -0
  164. veadk/tools/builtin_tools/__init__.py +13 -0
  165. veadk/tools/builtin_tools/agent_authorization.py +94 -0
  166. veadk/tools/builtin_tools/generate_image.py +23 -0
  167. veadk/tools/builtin_tools/image_edit.py +300 -0
  168. veadk/tools/builtin_tools/image_generate.py +446 -0
  169. veadk/tools/builtin_tools/lark.py +67 -0
  170. veadk/tools/builtin_tools/las.py +24 -0
  171. veadk/tools/builtin_tools/link_reader.py +66 -0
  172. veadk/tools/builtin_tools/llm_shield.py +381 -0
  173. veadk/tools/builtin_tools/load_knowledgebase.py +97 -0
  174. veadk/tools/builtin_tools/mcp_router.py +29 -0
  175. veadk/tools/builtin_tools/run_code.py +113 -0
  176. veadk/tools/builtin_tools/tts.py +253 -0
  177. veadk/tools/builtin_tools/vesearch.py +49 -0
  178. veadk/tools/builtin_tools/video_generate.py +363 -0
  179. veadk/tools/builtin_tools/web_scraper.py +76 -0
  180. veadk/tools/builtin_tools/web_search.py +83 -0
  181. veadk/tools/demo_tools.py +58 -0
  182. veadk/tools/load_knowledgebase_tool.py +149 -0
  183. veadk/tools/sandbox/__init__.py +13 -0
  184. veadk/tools/sandbox/browser_sandbox.py +37 -0
  185. veadk/tools/sandbox/code_sandbox.py +40 -0
  186. veadk/tools/sandbox/computer_sandbox.py +34 -0
  187. veadk/tracing/__init__.py +13 -0
  188. veadk/tracing/base_tracer.py +58 -0
  189. veadk/tracing/telemetry/__init__.py +13 -0
  190. veadk/tracing/telemetry/attributes/attributes.py +29 -0
  191. veadk/tracing/telemetry/attributes/extractors/common_attributes_extractors.py +180 -0
  192. veadk/tracing/telemetry/attributes/extractors/llm_attributes_extractors.py +858 -0
  193. veadk/tracing/telemetry/attributes/extractors/tool_attributes_extractors.py +152 -0
  194. veadk/tracing/telemetry/attributes/extractors/types.py +164 -0
  195. veadk/tracing/telemetry/exporters/__init__.py +13 -0
  196. veadk/tracing/telemetry/exporters/apmplus_exporter.py +558 -0
  197. veadk/tracing/telemetry/exporters/base_exporter.py +39 -0
  198. veadk/tracing/telemetry/exporters/cozeloop_exporter.py +129 -0
  199. veadk/tracing/telemetry/exporters/inmemory_exporter.py +248 -0
  200. veadk/tracing/telemetry/exporters/tls_exporter.py +139 -0
  201. veadk/tracing/telemetry/opentelemetry_tracer.py +320 -0
  202. veadk/tracing/telemetry/telemetry.py +411 -0
  203. veadk/types.py +47 -0
  204. veadk/utils/__init__.py +13 -0
  205. veadk/utils/audio_manager.py +95 -0
  206. veadk/utils/auth.py +294 -0
  207. veadk/utils/logger.py +59 -0
  208. veadk/utils/mcp_utils.py +44 -0
  209. veadk/utils/misc.py +184 -0
  210. veadk/utils/patches.py +101 -0
  211. veadk/utils/volcengine_sign.py +205 -0
  212. veadk/version.py +15 -0
  213. veadk_python-0.2.27.dist-info/METADATA +373 -0
  214. veadk_python-0.2.27.dist-info/RECORD +218 -0
  215. veadk_python-0.2.27.dist-info/WHEEL +5 -0
  216. veadk_python-0.2.27.dist-info/entry_points.txt +2 -0
  217. veadk_python-0.2.27.dist-info/licenses/LICENSE +201 -0
  218. 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.")