-
Notifications
You must be signed in to change notification settings - Fork 77
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Disable ASGI send/receive spans by default (#371)
- Loading branch information
1 parent
ffe0c25
commit b7afdd5
Showing
14 changed files
with
515 additions
and
38 deletions.
There are no files selected for viewing
2 changes: 1 addition & 1 deletion
2
logfire-api/logfire_api/_internal/exporters/processor_wrapper.pyi
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
from dataclasses import dataclass | ||
from logfire import Logfire as Logfire | ||
from logfire._internal.utils import is_asgi_send_receive_span_name as is_asgi_send_receive_span_name | ||
from opentelemetry.context import Context | ||
from opentelemetry.trace import Span, Tracer, TracerProvider | ||
from typing import Any | ||
|
||
def tweak_asgi_spans_tracer_provider(logfire_instance: Logfire, record_send_receive: bool) -> TracerProvider: | ||
"""If record_send_receive is False, return a TracerProvider that skips spans for ASGI send and receive events.""" | ||
|
||
@dataclass | ||
class TweakAsgiTracerProvider(TracerProvider): | ||
tracer_provider: TracerProvider | ||
def get_tracer(self, *args: Any, **kwargs: Any) -> Tracer: ... | ||
|
||
@dataclass | ||
class TweakAsgiSpansTracer(Tracer): | ||
tracer: Tracer | ||
def start_span(self, name: str, context: Context | None = None, *args: Any, **kwargs: Any) -> Span: ... | ||
start_as_current_span = ... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 5 additions & 13 deletions
18
logfire-api/logfire_api/_internal/integrations/starlette.pyi
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
from __future__ import annotations | ||
|
||
from dataclasses import dataclass | ||
from typing import TYPE_CHECKING, Any | ||
|
||
from opentelemetry.context import Context | ||
from opentelemetry.sdk.trace import Tracer as SDKTracer | ||
from opentelemetry.trace import NonRecordingSpan, Span, Tracer, TracerProvider | ||
from opentelemetry.trace.propagation import get_current_span | ||
|
||
from logfire._internal.utils import is_asgi_send_receive_span_name | ||
|
||
if TYPE_CHECKING: | ||
from logfire import Logfire | ||
|
||
|
||
def tweak_asgi_spans_tracer_provider(logfire_instance: Logfire, record_send_receive: bool) -> TracerProvider: | ||
"""If record_send_receive is False, return a TracerProvider that skips spans for ASGI send and receive events.""" | ||
tracer_provider = logfire_instance.config.get_tracer_provider() | ||
if record_send_receive: | ||
return tracer_provider | ||
else: | ||
return TweakAsgiTracerProvider(tracer_provider) | ||
|
||
|
||
@dataclass | ||
class TweakAsgiTracerProvider(TracerProvider): | ||
tracer_provider: TracerProvider | ||
|
||
def get_tracer(self, *args: Any, **kwargs: Any) -> Tracer: | ||
return TweakAsgiSpansTracer(self.tracer_provider.get_tracer(*args, **kwargs)) | ||
|
||
|
||
@dataclass | ||
class TweakAsgiSpansTracer(Tracer): | ||
tracer: Tracer | ||
|
||
def start_span(self, name: str, context: Context | None = None, *args: Any, **kwargs: Any) -> Span: | ||
if is_asgi_send_receive_span_name(name): | ||
# These are the noisy spans we want to skip. | ||
# Create a no-op span with the same SpanContext as the current span. | ||
# This means that any spans created within will have the current span as their parent, | ||
# as if this span didn't exist at all. | ||
return NonRecordingSpan(get_current_span(context).get_span_context()) | ||
|
||
return self.tracer.start_span(name, context, *args, **kwargs) | ||
|
||
# This means that `with start_as_current_span(...):` | ||
# is roughly equivalent to `with use_span(start_span(...)):` | ||
start_as_current_span = SDKTracer.start_as_current_span |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,39 @@ | ||
from __future__ import annotations | ||
|
||
from typing import TYPE_CHECKING, Any | ||
from typing import TYPE_CHECKING | ||
|
||
from opentelemetry.instrumentation.starlette import StarletteInstrumentor | ||
from starlette.applications import Starlette | ||
|
||
from logfire import Logfire | ||
from logfire._internal.integrations.asgi import tweak_asgi_spans_tracer_provider | ||
from logfire._internal.utils import maybe_capture_server_headers | ||
|
||
if TYPE_CHECKING: | ||
from opentelemetry.trace import Span | ||
from typing_extensions import Protocol, TypedDict, Unpack | ||
|
||
class ServerRequestHook(Protocol): | ||
def __call__(self, span: Span, scope: dict[str, Any]): ... | ||
|
||
class ClientRequestHook(Protocol): | ||
def __call__(self, span: Span, scope: dict[str, Any]): ... | ||
|
||
class ClientResponseHook(Protocol): | ||
def __call__(self, span: Span, message: dict[str, Any]): ... | ||
from opentelemetry.instrumentation.asgi.types import ClientRequestHook, ClientResponseHook, ServerRequestHook | ||
from typing_extensions import TypedDict, Unpack | ||
|
||
class StarletteInstrumentKwargs(TypedDict, total=False): | ||
server_request_hook: ServerRequestHook | None | ||
client_request_hook: ClientRequestHook | None | ||
client_response_hook: ClientResponseHook | None | ||
|
||
|
||
def instrument_starlette(app: Starlette, *, capture_headers: bool = False, **kwargs: Unpack[StarletteInstrumentKwargs]): | ||
def instrument_starlette( | ||
logfire_instance: Logfire, | ||
app: Starlette, | ||
*, | ||
record_send_receive: bool = False, | ||
capture_headers: bool = False, | ||
**kwargs: Unpack[StarletteInstrumentKwargs], | ||
): | ||
"""Instrument `app` so that spans are automatically created for each request. | ||
See the `Logfire.instrument_starlette` method for details. | ||
""" | ||
maybe_capture_server_headers(capture_headers) | ||
StarletteInstrumentor().instrument_app(app, **kwargs) # type: ignore[reportUnknownMemberType] | ||
StarletteInstrumentor().instrument_app( # type: ignore[reportUnknownMemberType] | ||
app, | ||
tracer_provider=tweak_asgi_spans_tracer_provider(logfire_instance, record_send_receive), | ||
**kwargs, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.