|
19 | 19 |
|
20 | 20 | from google.adk.tools import BaseTool, ToolContext |
21 | 21 | from google.genai import types |
| 22 | +from opentelemetry import trace |
| 23 | +from opentelemetry.sdk.trace import _Span |
| 24 | +from opentelemetry.trace.status import Status, StatusCode |
22 | 25 |
|
23 | 26 | from veadk.skills.skill import Skill |
24 | 27 | from veadk.tools.skills_tools.session_path import get_session_path |
| 28 | +from veadk.tracing.telemetry.telemetry import set_common_attributes_on_tool_span |
25 | 29 | from veadk.utils.logger import get_logger |
26 | 30 |
|
| 31 | +tracer = trace.get_tracer("veadk.skills_tool") |
| 32 | + |
27 | 33 | logger = get_logger(__name__) |
28 | 34 |
|
29 | 35 |
|
@@ -94,7 +100,11 @@ async def run_async( |
94 | 100 | if not skill_name: |
95 | 101 | return "Error: No skill name provided" |
96 | 102 |
|
97 | | - return self._invoke_skill(skill_name, tool_context) |
| 103 | + with tracer.start_as_current_span(f"execute_skill {skill_name}") as span: |
| 104 | + result = self._invoke_skill(skill_name, tool_context) |
| 105 | + self._add_skill_span_attributes(span, skill_name, result) |
| 106 | + self._upload_skill_metrics(span, skill_name, result) |
| 107 | + return result |
98 | 108 |
|
99 | 109 | def _invoke_skill(self, skill_name: str, tool_context: ToolContext) -> str: |
100 | 110 | """Load and return the full content of a skill.""" |
@@ -345,3 +355,75 @@ def _format_skill_content(self, skill_name: str, content: str, skill_dir) -> str |
345 | 355 | "The skill has been loaded. Follow the instructions above and use the bash tool to execute commands." |
346 | 356 | ) |
347 | 357 | return header + content + footer |
| 358 | + |
| 359 | + def _add_skill_span_attributes( |
| 360 | + self, |
| 361 | + span: _Span, |
| 362 | + skill_name: str, |
| 363 | + result: str, |
| 364 | + ) -> None: |
| 365 | + """Add attributes to the skill execution span.""" |
| 366 | + try: |
| 367 | + set_common_attributes_on_tool_span(current_span=span) |
| 368 | + |
| 369 | + if result: |
| 370 | + if result.startswith("Error:"): |
| 371 | + span.set_status(Status(StatusCode.ERROR, result)) |
| 372 | + |
| 373 | + span.set_attribute("skill.name", skill_name) |
| 374 | + span.set_attribute("tool.name", self.name) |
| 375 | + span.set_attribute("gen_ai.operation.name", "execute_skill") |
| 376 | + span.set_attribute("gen_ai.span.kind", "tool") |
| 377 | + if skill_name in self.skills: |
| 378 | + skill = self.skills[skill_name] |
| 379 | + if hasattr(skill, "skill_space_id") and skill.skill_space_id: |
| 380 | + span.set_attribute("skill.space_id", skill.skill_space_id) |
| 381 | + if hasattr(skill, "bucket_name") and skill.bucket_name: |
| 382 | + span.set_attribute("skill.bucket_name", skill.bucket_name) |
| 383 | + if hasattr(skill, "path") and skill.path: |
| 384 | + span.set_attribute("skill.path", skill.path) |
| 385 | + if hasattr(skill, "id") and skill.id: |
| 386 | + span.set_attribute("skill.id", skill.id) |
| 387 | + logger.debug(f"Added skill span attributes for {skill_name}") |
| 388 | + except Exception as e: |
| 389 | + logger.warning(f"Failed to add skill span attributes: {e}") |
| 390 | + |
| 391 | + def _upload_skill_metrics(self, span: _Span, skill_name: str, result: str) -> None: |
| 392 | + """Upload skill metrics to the telemetry system.""" |
| 393 | + try: |
| 394 | + import time |
| 395 | + from veadk.tracing.telemetry.telemetry import meter_uploader |
| 396 | + |
| 397 | + if meter_uploader: |
| 398 | + # 初始化属性,包含技能相关信息 |
| 399 | + skill = self.skills.get(skill_name) |
| 400 | + attributes = { |
| 401 | + "skill_name": skill_name, |
| 402 | + "tool_name": self.name, |
| 403 | + "skill_space_id": ( |
| 404 | + skill.skill_space_id if skill and skill.skill_space_id else "" |
| 405 | + ), |
| 406 | + "skill_id": skill.id if skill and skill.id else "", |
| 407 | + "gen_ai.operation.name": "execute_skill", |
| 408 | + "error_type": ( |
| 409 | + "skill_execution_error" if result.startswith("Error:") else "" |
| 410 | + ), |
| 411 | + } |
| 412 | + |
| 413 | + # 计算 span 执行耗时(秒) |
| 414 | + latency_seconds = 0 |
| 415 | + if hasattr(span, "start_time"): |
| 416 | + # 计算耗时(秒) |
| 417 | + latency_seconds = (time.time_ns() - span.start_time) / 1e9 # type: ignore |
| 418 | + |
| 419 | + # 记录技能执行延迟 |
| 420 | + if hasattr(meter_uploader, "skill_invoke_latency"): |
| 421 | + # 使用 skill_invoke_latency 记录技能执行延迟(秒) |
| 422 | + meter_uploader.skill_invoke_latency.record( |
| 423 | + latency_seconds, attributes |
| 424 | + ) |
| 425 | + logger.debug( |
| 426 | + f"Uploaded skill metrics for {skill_name} with latency {latency_seconds:.4f}s and attributes {attributes}" |
| 427 | + ) |
| 428 | + except Exception as e: |
| 429 | + logger.warning(f"Failed to upload skill metrics: {e}") |
0 commit comments