A span processor that prints information about spans. This processor is particularly useful for debugging and monitoring as it prints information about spans as they are created and ended. For session spans, it prints a URL to the AgentOps dashboard. Note about span kinds:
| 13 | |
| 14 | |
| 15 | class InternalSpanProcessor(SpanProcessor): |
| 16 | """ |
| 17 | A span processor that prints information about spans. |
| 18 | |
| 19 | This processor is particularly useful for debugging and monitoring |
| 20 | as it prints information about spans as they are created and ended. |
| 21 | For session spans, it prints a URL to the AgentOps dashboard. |
| 22 | |
| 23 | Note about span kinds: |
| 24 | - OpenTelemetry spans have a native 'kind' property (INTERNAL, CLIENT, CONSUMER, etc.) |
| 25 | - AgentOps also uses a semantic convention attribute AGENTOPS_SPAN_KIND for domain-specific kinds |
| 26 | - This processor tries to use the native kind first, then falls back to the attribute |
| 27 | """ |
| 28 | |
| 29 | _root_span_id: Optional[int] = None |
| 30 | |
| 31 | def on_start(self, span: Span, parent_context: Optional[Context] = None) -> None: |
| 32 | """ |
| 33 | Called when a span is started. |
| 34 | |
| 35 | Args: |
| 36 | span: The span that was started. |
| 37 | parent_context: The parent context, if any. |
| 38 | """ |
| 39 | # Skip if span is not sampled |
| 40 | if not span.context or not span.context.trace_flags.sampled: |
| 41 | return |
| 42 | |
| 43 | if not self._root_span_id: |
| 44 | self._root_span_id = span.context.span_id |
| 45 | logger.debug(f"[agentops.InternalSpanProcessor] Found root span: {span.name}") |
| 46 | |
| 47 | def on_end(self, span: ReadableSpan) -> None: |
| 48 | """ |
| 49 | Called when a span is ended. |
| 50 | |
| 51 | Args: |
| 52 | span: The span that was ended. |
| 53 | """ |
| 54 | # Skip if span is not sampled |
| 55 | if not span.context or not span.context.trace_flags.sampled: |
| 56 | return |
| 57 | |
| 58 | if self._root_span_id and (span.context.span_id is self._root_span_id): |
| 59 | logger.debug(f"[agentops.InternalSpanProcessor] Ending root span: {span.name}") |
| 60 | try: |
| 61 | upload_logfile(span.context.trace_id) |
| 62 | except Exception as e: |
| 63 | logger.error(f"[agentops.InternalSpanProcessor] Error uploading logfile: {e}") |
| 64 | |
| 65 | def shutdown(self) -> None: |
| 66 | """Shutdown the processor.""" |
| 67 | self._root_span_id = None |
| 68 | |
| 69 | def force_flush(self, timeout_millis: int = 30000) -> bool: |
| 70 | """Force flush the processor.""" |
| 71 | return True |
no outgoing calls
searching dependent graphs…