Creates a scope-based OpenTelemetry span, representing a node invocation. Implements emitting of the following spans: - `invoke_agent {agent.name}` - `invoke_workflow {workflow.name}` - `invoke_node {node.name}` invoke_agent spans align with OpenTelemetry Semantic Conventions (semconv) v
(
context: Context, node: BaseNode
)
| 57 | |
| 58 | @asynccontextmanager |
| 59 | async def start_as_current_node_span( |
| 60 | context: Context, node: BaseNode |
| 61 | ) -> AsyncIterator[TelemetryContext]: |
| 62 | """Creates a scope-based OpenTelemetry span, representing a node invocation. |
| 63 | |
| 64 | Implements emitting of the following spans: |
| 65 | - `invoke_agent {agent.name}` |
| 66 | - `invoke_workflow {workflow.name}` |
| 67 | - `invoke_node {node.name}` |
| 68 | |
| 69 | invoke_agent spans align with OpenTelemetry Semantic Conventions (semconv) version 1.36 spans for backwards compatibility. |
| 70 | https://github.com/open-telemetry/semantic-conventions/blob/v1.36.0/docs/gen-ai/README.md |
| 71 | |
| 72 | invoke_workflow spans align with semconv version 1.41, because these were not included in any prior releases. |
| 73 | https://github.com/open-telemetry/semantic-conventions/blob/main/docs/gen-ai/README.md |
| 74 | |
| 75 | invoke_node spans are not present in any semconv release. |
| 76 | We will create a proposal to standardize them. |
| 77 | |
| 78 | Args: |
| 79 | context: Context in which the span is created. |
| 80 | node: The node to be invoked inside the created span. |
| 81 | |
| 82 | Yields: |
| 83 | Context with the started span. |
| 84 | """ |
| 85 | |
| 86 | span_metadata = _span_metadata(context, node) |
| 87 | if span_metadata is None: |
| 88 | token = context_api.attach(context.telemetry_context.otel_context) |
| 89 | try: |
| 90 | yield TelemetryContext( |
| 91 | otel_context=context.telemetry_context.otel_context |
| 92 | ) |
| 93 | finally: |
| 94 | context_api.detach(token) |
| 95 | return |
| 96 | |
| 97 | with tracer.start_as_current_span( |
| 98 | span_metadata.name, |
| 99 | attributes=span_metadata.attributes, |
| 100 | context=context.telemetry_context.otel_context, |
| 101 | ) as span: |
| 102 | telemetry_context = TelemetryContext(otel_context=context_api.get_current()) |
| 103 | yield telemetry_context |
| 104 | |
| 105 | if span.is_recording() and len(telemetry_context._associated_event_ids) > 0: |
| 106 | span.set_attribute( |
| 107 | "gcp.vertex.agent.associated_event_ids", |
| 108 | telemetry_context._associated_event_ids, |
| 109 | ) |
| 110 | |
| 111 | |
| 112 | def _span_metadata(context: Context, node: BaseNode) -> _SpanMetadata | None: |
nothing calls this directly
no test coverage detected