Litestar OpenTelemetry 集成指南:使用 OpenTelemetryConfig 与 OpenTelemetryPlugin 实现可观测性
Litestar OpenTelemetry 集成指南使用 OpenTelemetryConfig 与 OpenTelemetryPlugin 实现可观测性【免费下载链接】litestarLight, flexible and extensible ASGI framework | Built to scale项目地址: https://gitcode.com/GitHub_Trending/li/litestarLitestar 内置了可选的 OpenTelemetry 插桩能力由litestar.plugins.opentelemetry包导出可对 HTTP 与 WebSocket 请求自动生成 Trace追踪Span 与 Metrics指标无缝接入 Jaeger、Prometheus、OTLP Collector 等后端。本文以 OpenTelemetry 参考文档 为骨架结合 opentelemetry 模块源码 与 单元测试完整讲解从安装、配置到深度定制的全部环节——读完你既能 5 分钟接入默认埋点也能掌握 Span 命名、请求/响应钩子、敏感头脱敏、异常钩子等进阶玩法。安装依赖OpenTelemetry 插桩并非 Litestar 的默认依赖使用前需显式安装。推荐直接安装 Litestar 的opentelemetryextra它会一并带入 ASGI 插桩库与 SDK# 作为独立的包安装 pip install opentelemetry-instrumentation-asgi # 或者作为 Litestar 的 extra 安装 pip install litestar[opentelemetry]在 pyproject.toml 中该 extra 的定义为[opentelemetry-instrumentation-asgi, opentelemetry-sdk]即包含 ASGI 插桩和标准 SDK 两部分。若缺少opentelemetry基础包模块会在导入时直接抛出MissingDependencyException见 config.py提示你先补齐依赖。快速开始三步接入自动埋点安装完成后只需三个步骤即可让应用开始产出 Trace 与 Metricsfrom litestar import Litestar from litestar.plugins.opentelemetry import OpenTelemetryConfig, OpenTelemetryPlugin open_telemetry_config OpenTelemetryConfig() app Litestar(plugins[OpenTelemetryPlugin(open_telemetry_config)])工作流程如下创建OpenTelemetryConfig实例——这是一个 dataclass集中管理中间件的全部行为参数将其传入OpenTelemetryPlugin——该插件实现了 InitPlugin 协议在应用初始化阶段自动把中间件注册进应用把插件加入Litestar(plugins[...])即可。上述代码在“开箱即用”模式下即可工作前提是你已经配置了全局的tracer_provider和/或meter_provider并设置了对应的 exporter如 OTLP、Jaeger、Prometheus 等。如果尚未配置全局 Provider也可以直接在OpenTelemetryConfig中传入自定义 Provider详见下文。两种等效的接入方式从 测试代码 可以看到中间件与插件两种接入方式是等效的# 方式一手动把 config.middleware 加入中间件列表 app_config AppConfig(middleware[OpenTelemetryConfig().middleware]) # 方式二通过插件自动注册推荐 app_config AppConfig(plugins[OpenTelemetryPlugin(OpenTelemetryConfig())])推荐使用插件方式原因有二其一插件在on_app_init阶段会调用_pop_otel_middleware见 plugin.py自动从现有中间件列表中识别并去重已注册的 OpenTelemetry 中间件避免重复包裹其二若配置了after_exception_hook_handler插件还会自动将其追加到应用的after_exception异常钩子链上。OpenTelemetryConfig 配置项全解析OpenTelemetryConfig的全部字段定义在 config.py底层直接透传给opentelemetry.instrumentation.asgi.OpenTelemetryMiddleware见 middleware.py。下表逐项说明配置项类型默认值作用scope_span_details_extractorCallable[[Scope], tuple[str, dict]]get_route_details_from_scope根据 ASGI scope 生成默认 Span 名称与附加属性server_request_hook_handlerServerRequestHookHandlerNone每个请求到达时以「服务端 Span ASGI scope」调用client_request_hook_handlerClientRequestHookHandlerNone调用receive读取请求体时以「内部 Span scope ASGI message」调用client_response_hook_handlerClientResponseHookHandlerNone调用send发送响应时以「内部 Span scope ASGI message」调用after_exception_hook_handlerAfterExceptionHookHandlerNone每次异常抛出时以「异常 scope」调用经插件注册为应用级异常钩子meter_providerMeterProviderNone指标 Provider缺省使用全局配置tracer_providerTracerProviderNone追踪 Provider缺省使用全局配置tracerTracerNone预构建的 Tracer 实例缺省由 Provider 创建meterMeterNone预构建的 Meter 实例缺省取自 Provider 或全局excludestr \| list[str]None需要跳过的路径模式列表继承自中间件基类exclude_opt_keystrNone路由级开关标识在某路由上设置该键即可跳过该路由的插桩exclude_urls_env_keystrLITESTAR配合环境变量{key}_EXCLUDED_URLS排除 URL默认即LITESTAR_EXCLUDED_URLSexclude_spanslist[Literal[receive, send]]None从 Trace 中排除 HTTP 的 receive/send 内部 SpanscopesScopesNone中间件处理的 ASGI scope 类型缺省同时处理http与websockethttp_capture_headers_server_requestlist[str]None捕获为 Span 属性的服务端请求头列表http_capture_headers_server_responselist[str]None捕获为 Span 属性的服务端响应头列表http_capture_headers_sanitize_fieldslist[str]None值将被替换为[REDACTED]的敏感头列表middleware_classtype[OpenTelemetryInstrumentationMiddleware]内置中间件类可替换为自定义中间件子类config.middleware属性会据此构建并返回一个 DefineMiddleware 实例config.py这也是手动方式接入时直接使用的对象。自定义 Provider 与预构建实例如果你的应用使用 OTLP、Jaeger 等后端且不想依赖全局 Provider可以直接注入from opentelemetry.sdk.resources import SERVICE_NAME, Resource from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import SimpleSpanProcessor from opentelemetry.sdk.trace.export.in_memory_span_exporter import InMemorySpanExporter from opentelemetry.sdk.metrics._internal import MeterProvider from opentelemetry.sdk.metrics._internal.export import InMemoryMetricReader resource Resource(attributes{SERVICE_NAME: my-litestar-app}) tracer_provider TracerProvider(resourceresource) tracer_provider.add_span_processor(SimpleSpanProcessor(InMemorySpanExporter())) meter_provider MeterProvider( resourceresource, metric_readers[InMemoryMetricReader()], ) config OpenTelemetryConfig( tracer_providertracer_provider, meter_providermeter_provider, ) app Litestar(plugins[OpenTelemetryPlugin(config)])该用法与 测试夹具 的构造方式一致tracer_provider、meter_provider与meter缺省时都会回退到全局配置显式传入则可做到完全隔离。测试还验证了tracer参数可直接传入预构建实例OpenTelemetryConfig(tracertracer)。排除规则与路由级开关全局排除通过exclude路径模式或环境变量LITESTAR_EXCLUDED_URLS排除不需要插桩的 URL环境变量键名由exclude_urls_env_key控制最终交给opentelemetry.util.http.get_excluded_urls解析见 middleware.py。路由级排除设置exclude_opt_key如skip_otel后可在单个路由上通过该键跳过插桩。需要注意OpenTelemetry 中间件运行在路由解析之前scope 中尚未填充route_handler回归测试 专门验证了设置exclude_opt_key时不会因缺少route_handler而抛出 KeyError。敏感请求头脱敏http_capture_headers_sanitize_fields用于保护Authorization、Cookie等敏感头命中后其值在 Span 属性中统一替换为[REDACTED]http_capture_headers_server_request/http_capture_headers_server_response则白名单式指定要捕获的请求/响应头见 测试用例。深入源码Span 如何生成、命名与修饰默认 Span 命名规则默认的scope_span_details_extractor为 get_route_details_from_scope其逻辑为HTTP 请求Span 名为{METHOD} {path}如GET /并写入属性http.route GET /WebSocketSpan 名为路径本身scope 中无method并写入http.route path。该行为与 测试断言 中http.route: GET /完全吻合。需要自定义命名例如去掉查询参数、归一化 RESTful 路由时可传入自己的提取器from litestar.types import Scope def my_extractor(scope: Scope) - tuple[str, dict]: route scope.get(path, ) return flitestar:{route}, {http.route: route} config OpenTelemetryConfig(scope_span_details_extractormy_extractor)三大 Hook 的触发时机与签名server_request_hook_handler每个请求到达时触发签名(span, scope)只调用一次见 测试client_request_hook_handler当receive被调用即读取请求体时触发签名(span, scope, message)三个参数缺一不可测试client_response_hook_handler当send被调用即发送响应时触发签名(span, scope, message)测试。注意 client 系列 Hook 为三参数签名与 server 系列的两参数签名不同这是 上游 OpenTelemetry ASGI 插桩 的定义测试中亦有专门回归。典型用法在 server_request_hook 中为 Span 追加业务属性如用户 ID、租户或在 client_response_hook 中记录响应体大小def add_user_id(span, scope) - None: span.set_attribute(app.user_id, scope.get(user_id, anonymous)) config OpenTelemetryConfig(server_request_hook_handleradd_user_id)异常钩子after_exception_hook_handler该回调在每次异常抛出时以(exception, scope)调用且由插件自动注册到应用级after_exception钩子见 plugin.py。测试 验证了异常发生时钩子恰好调用一次且能拿到原始异常对象与 scopescope[type] http、scope[path]、scope[method]请求成功时钩子不会被调用。def on_exception(exc: Exception, scope: dict) - None: print(fexception {exc!r} on {scope.get(path)}) config OpenTelemetryConfig(after_exception_hook_handleron_exception)底层实现中间件如何工作OpenTelemetryInstrumentationMiddlewaremiddleware.py继承自 Litestar 的AbstractMiddleware构造时将OpenTelemetryConfig的每一项参数逐一映射给上游OpenTelemetryMiddleware随后在__call__中把 ASGI 三元组(scope, receive, send)原样委托给上游实现。这意味着Span 的创建、属性填充、上下文传播完全由 OpenTelemetry 官方 ASGI 插桩负责Litestar 侧只做参数适配中间件默认同时覆盖http与websocket两种 scope也可通过scopes收窄范围。从 HTTP 测试断言 可以看到一次 GET 请求实际产出的 Span 形态一个服务端 Span 携带http.scheme、http.host、http.method、http.target、http.url、http.route、http.status_code等语义化属性外加http.response.start与http.response.body两个内部事件 SpanWebSocket 场景测试则产生websocket.connect、websocket.accept、websocket.send、websocket.close等事件 Span。对于 404测试、405测试乃至中间件自身抛出的 401测试错误状态码同样会被记录到 Span 属性中——这得益于中间件位于中间件链的最外层能够捕获路由解析与内部中间件产生的错误。生产实践建议优先使用插件接入OpenTelemetryPlugin自带中间件去重与异常钩子注册避免手动管理DefineMiddleware带来的重复与遗漏。显式注入 Provider在应用中显式构造TracerProvider/MeterProvider并配置 exporter避免依赖隐式全局状态便于多应用隔离与测试。合理使用排除机制对健康检查、指标抓取等高频且无观测价值的端点用exclude或LITESTAR_EXCLUDED_URLS排除降低采样开销。务必脱敏敏感头通过http_capture_headers_sanitize_fields保护authorization、cookie等字段防止凭据流入 Trace 后端。按需裁剪内部 Spanexclude_spans[receive, send]可减少单请求产生的 Span 数量适合高吞吐场景。更完整的配置项语义可查阅 OpenTelemetryConfig 参考文档 与 OpenTelemetry 用法指南若需在应用其他部分接入指标采集可参考 metrics 使用文档。【免费下载链接】litestarLight, flexible and extensible ASGI framework | Built to scale项目地址: https://gitcode.com/GitHub_Trending/li/litestar创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考