Repository navigation
Use Litestar's OpenTelemetryPlugin in the Litestar bootstrapper - #154
personage-hub wants to merge 2 commits into
Conversation
5e8d302 to
80a9b11
Compare
|
Two things from running this branch (80a9b11):
|
|
#157 landed on
While rebasing, could this PR also cover #159? The plugin's |
Litestar ships its own OpenTelemetry plugin since the custom middleware was written, so the bootstrapper now registers OpenTelemetryPlugin instead of building an ASGI middleware around OpenTelemetryMiddleware by hand (which also re-created the OTel middleware on every request). opentelemetry_exclude_urls map to the plugin's exclude, OTEL_PYTHON_LITESTAR_EXCLUDED_URLS keeps working through the plugin's exclude_urls_env_key. Litestar applies the plugin middleware outside the router, before path_template is known, so a small LitestarOpentelemetryRouteMiddleware inside the handler stack renames the server span by the route template and sets http.route, keeping the span names unchanged. Requires litestar>=2.22.0, where litestar.plugins.opentelemetry appeared. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Litestar searches the plugin's exclude patterns unanchored in scope["path"], so the derived paths (prometheus_metrics_path, and health_checks_path when health spans are off) are now anchored as ^<path>(?:/|$) by define_excluded_path_patterns(), the path-based counterpart of define_excluded_url_patterns(); user-supplied regexes stay verbatim. /health and /health/ are both excluded, /api/metrics-report and /api/health/details keep their spans. The plugin opens the span before routing, so the extractor no longer falls back to the raw path: an unmatched request gets a span named by the method alone and no http.route, keeping cardinality bounded under a 404 scan. Matched routes are still renamed by LitestarOpentelemetryRouteMiddleware. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
80a9b11 to
d851cc7
Compare
|
Rebased on #157, both points addressed.
One caveat: the HTTP server metrics of |
Summary
Litestar ships its own
OpenTelemetryPluginnow, so the Litestar bootstrapper registers it instead of hand-building an ASGI middleware aroundOpenTelemetryMiddleware(the oldLitestarOpenTelemetryInstrumentationMiddleware, which also re-created the OTel middleware on every request inhandle).opentelemetry_exclude_urls(plus the health check path whenopentelemetry_generate_health_check_spansis off) map to the plugin'sexclude;OTEL_PYTHON_LITESTAR_EXCLUDED_URLSkeeps working through the plugin'sexclude_urls_env_key, soCombinedExcludeListis no longer needed for Litestar.User-supplied
pluginsare preserved, the lists are merged like any other container config.Requires
litestar>=2.22.0, wherelitestar.plugins.opentelemetryappeared (2.21 only has the deprecatedlitestar.contrib.opentelemetrypath).Fixes Anchor derived trace exclusions for Litestar #159: the derived exclusions (
prometheus_metrics_path, and the health path when health spans are off) are anchored as^<path>(?:/|$)bydefine_excluded_path_patterns(), the path-based counterpart ofdefine_excluded_url_patterns()from Anchor derived trace exclusions for FastAPI and FastMCP #157, so/api/metrics-reportand/api/health/detailskeep their spans while/healthand/health/are both excluded.Requests that match no route produce a span named by the method only, without
http.route, so a 404 scan does not explode span cardinality.Why there is still a middleware
Litestar applies the plugin's middleware outside the router (
Litestar.__init__wrapsasgi_handlerwith it), i.e. beforepath_templateis known. That is also why Litestar's defaultscope_span_details_extractorreportsGET /users/123. To keep the span names andhttp.routeas they are today (GET /users/{user_id}), a tinyLitestarOpentelemetryRouteMiddlewareinside the route handler stack renames the current server span by the route template. It does nothing for excluded urls (the span is non-recording there). The HTTP server metrics ofopentelemetry-instrumentation-asgitake their attributes at span start, so they are not renamed; no MeterProvider is configured here, and litestar-org/litestar#5120 is the proper fix, after which both the extractor and the middleware can be removed.Tests
test_litestar_opentelemetry_server_spans_use_path_templateasserts real exported spans:GET /users/{user_id}withhttp.route, andGETwithouthttp.routefor a 404.test_litestar_opentelemetry_exclusions_do_not_silence_lookalike_routesmirrors the FastAPI test from Anchor derived trace exclusions for FastAPI and FastMCP #157, plus/healthwithout the slash;..._custom_metrics_path_is_excludedchecks a customprometheus_metrics_path.OTEL_PYTHON_LITESTAR_EXCLUDED_URLSare now integration tests over exported spans.just test: 348 passed.Note:
uv run mypy .reports two pre-existing errors inmicrobootstrap/helpers.py:29with the locked mypy on Python 3.14; untouched here.🤖 Generated with Claude Code