-
-
Notifications
You must be signed in to change notification settings - Fork 490
feat(otel): instrument Litestar specific components #4483
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: feat/otel-contrib-deprecate
Are you sure you want to change the base?
Conversation
Properly wrap guards, CLI, and events with OTEL spans
Properly wrap guards, CLI, and events with OTEL spans
…into feat/otel-updates
provinzkraut
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally a good idea, but I don't think this is the right approach.
Specifically, we shouldn't resort to patching, as it is extremely brittle. The only reason naive instrumentations do this is because frameworks do not provide the necessary hooks. Since we're doing a first party integration though, we can use all the hooks and, if needed, add additional ones.
| _OTEL_AVAILABLE: bool | None = None | ||
| try: # pragma: no cover - optional dependency | ||
| from opentelemetry.trace import TracerProvider as _RuntimeTracerProvider | ||
| except ImportError: # pragma: no cover | ||
| _RuntimeTracerProvider = object # type: ignore[misc,assignment] | ||
|
|
||
| _CUSTOM_TRACER_PROVIDER: _RuntimeTracerProvider | None = None # pyright: ignore | ||
|
|
||
|
|
||
| def _get_tracer(name: str) -> Any: | ||
| from opentelemetry import trace | ||
|
|
||
| tracer_provider = _CUSTOM_TRACER_PROVIDER or trace.get_tracer_provider() | ||
| return tracer_provider.get_tracer(name) | ||
|
|
||
|
|
||
| def _is_otel_available() -> bool: | ||
| """Check if OpenTelemetry is installed and available.""" | ||
| global _OTEL_AVAILABLE | ||
| if _OTEL_AVAILABLE is not None: | ||
| return _OTEL_AVAILABLE | ||
|
|
||
| try: | ||
| import opentelemetry # noqa: F401 | ||
|
|
||
| _OTEL_AVAILABLE = True | ||
| except ImportError: | ||
| _OTEL_AVAILABLE = False | ||
|
|
||
| return _OTEL_AVAILABLE |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand this part. Importing the otel module doesn't make any sense if otel isn't available
|
|
||
|
|
||
| @asynccontextmanager | ||
| async def create_span_async(name: str, attributes: dict[str, Any] | None = None) -> AsyncGenerator[Any, None]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the purpose of this? It doesn't do anything async as far as I can tell?
| yield None | ||
| return | ||
|
|
||
| from opentelemetry.trace import Status, StatusCode |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There really shouldn't be an import in a hot path
|
|
||
| try: | ||
| yield span | ||
| except Exception as exc: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this necessary? I was under the impression that the active span already records exceptions
| result = provider_func(*args, **kwargs) | ||
| if inspect.isawaitable(result): | ||
| result = await result | ||
|
|
||
| # Add result type as attribute | ||
| if span and span.is_recording(): | ||
| span.set_attribute("litestar.dependency.result_type", type(result).__name__) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this might break for generator dependencies
Since we rely on the upstream ASGI open telemetry integration, some of the Litestar specific concepts did not always get wrapped inside the correct span.
This change allows the Open Telemetry plugin to instrument guards, events, and the CLI commands in Litestar.