|
6 | 6 | from opentelemetry.context import Context |
7 | 7 | from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware |
8 | 8 | from opentelemetry.sdk.trace import Tracer as SDKTracer |
9 | | -from opentelemetry.trace import NonRecordingSpan, Span, Tracer, TracerProvider |
| 9 | +from opentelemetry.trace import NonRecordingSpan, SpanKind, Tracer, TracerProvider |
10 | 10 | from opentelemetry.trace.propagation import get_current_span |
| 11 | +from opentelemetry.util import types as otel_types |
11 | 12 |
|
| 13 | +from logfire._internal.constants import log_level_attributes |
12 | 14 | from logfire._internal.utils import is_asgi_send_receive_span_name, maybe_capture_server_headers |
13 | 15 |
|
14 | 16 | if TYPE_CHECKING: |
@@ -41,35 +43,51 @@ class ASGIInstrumentKwargs(TypedDict, total=False): |
41 | 43 |
|
42 | 44 |
|
43 | 45 | def tweak_asgi_spans_tracer_provider(logfire_instance: Logfire, record_send_receive: bool) -> TracerProvider: |
44 | | - """If record_send_receive is False, return a TracerProvider that skips spans for ASGI send and receive events.""" |
| 46 | + """Return a TracerProvider that customizes ASGI send/receive spans. |
| 47 | +
|
| 48 | + If record_send_receive is False, spans are filtered out. |
| 49 | + If record_send_receive is True, spans are created with debug log level. |
| 50 | + """ |
45 | 51 | tracer_provider = logfire_instance.config.get_tracer_provider() |
46 | | - if record_send_receive: |
47 | | - return tracer_provider |
48 | | - else: |
49 | | - return TweakAsgiTracerProvider(tracer_provider) |
| 52 | + return TweakAsgiTracerProvider(tracer_provider, record_send_receive) |
50 | 53 |
|
51 | 54 |
|
52 | 55 | @dataclass |
53 | 56 | class TweakAsgiTracerProvider(TracerProvider): |
54 | 57 | tracer_provider: TracerProvider |
| 58 | + record_send_receive: bool |
55 | 59 |
|
56 | 60 | def get_tracer(self, *args: Any, **kwargs: Any) -> Tracer: |
57 | | - return TweakAsgiSpansTracer(self.tracer_provider.get_tracer(*args, **kwargs)) |
| 61 | + return TweakAsgiSpansTracer(self.tracer_provider.get_tracer(*args, **kwargs), self.record_send_receive) |
58 | 62 |
|
59 | 63 |
|
60 | 64 | @dataclass |
61 | 65 | class TweakAsgiSpansTracer(Tracer): |
62 | 66 | tracer: Tracer |
63 | | - |
64 | | - def start_span(self, name: str, context: Context | None = None, *args: Any, **kwargs: Any) -> Span: |
| 67 | + record_send_receive: bool |
| 68 | + |
| 69 | + def start_span( |
| 70 | + self, |
| 71 | + name: str, |
| 72 | + context: Context | None = None, |
| 73 | + kind: SpanKind = SpanKind.INTERNAL, |
| 74 | + attributes: otel_types.Attributes = None, |
| 75 | + *args: Any, |
| 76 | + **kwargs: Any, |
| 77 | + ) -> Span: |
65 | 78 | if is_asgi_send_receive_span_name(name): |
66 | | - # These are the noisy spans we want to skip. |
67 | | - # Create a no-op span with the same SpanContext as the current span. |
68 | | - # This means that any spans created within will have the current span as their parent, |
69 | | - # as if this span didn't exist at all. |
70 | | - return NonRecordingSpan(get_current_span(context).get_span_context()) |
71 | | - |
72 | | - return self.tracer.start_span(name, context, *args, **kwargs) |
| 79 | + if not self.record_send_receive: |
| 80 | + # These are the noisy spans we want to skip. |
| 81 | + # Create a no-op span with the same SpanContext as the current span. |
| 82 | + # This means that any spans created within will have the current span as their parent, |
| 83 | + # as if this span didn't exist at all. |
| 84 | + return NonRecordingSpan(get_current_span(context).get_span_context()) |
| 85 | + |
| 86 | + # If we're recording send/receive spans, set the log level to debug |
| 87 | + attributes = {**(attributes or {}), **log_level_attributes('debug')} |
| 88 | + return self.tracer.start_span(name, context, kind, attributes, *args, **kwargs) |
| 89 | + |
| 90 | + return self.tracer.start_span(name, context, kind, attributes, *args, **kwargs) |
73 | 91 |
|
74 | 92 | # This means that `with start_as_current_span(...):` |
75 | 93 | # is roughly equivalent to `with use_span(start_span(...)):` |
|
0 commit comments