use reqwest::{Request, Response}; use reqwest_middleware::{Middleware, Next, Result}; use task_local_extensions::Extensions; use tracing::Instrument; use crate::{DefaultSpanBackend, ReqwestOtelSpanBackend}; /// Middleware for tracing requests using the current Opentelemetry Context. pub struct TracingMiddleware { span_backend: std::marker::PhantomData, } impl TracingMiddleware { pub fn new() -> TracingMiddleware { TracingMiddleware { span_backend: Default::default(), } } } impl Default for TracingMiddleware { fn default() -> Self { TracingMiddleware::new() } } impl Clone for TracingMiddleware { fn clone(&self) -> Self { Self::new() } } #[async_trait::async_trait] impl Middleware for TracingMiddleware where ReqwestOtelSpan: ReqwestOtelSpanBackend + Sync + Send + 'static, { async fn handle( &self, req: Request, extensions: &mut Extensions, next: Next<'_>, ) -> Result { let request_span = ReqwestOtelSpan::on_request_start(&req, extensions); let outcome_future = async { // Adds tracing headers to the given request to propagate the OpenTelemetry context to downstream revivers of the request. // Spans added by downstream consumers will be part of the same trace. #[cfg(any( feature = "opentelemetry_0_13", feature = "opentelemetry_0_14", feature = "opentelemetry_0_15", feature = "opentelemetry_0_16", feature = "opentelemetry_0_17", ))] let req = crate::otel::inject_opentelemetry_context_into_request(req); // Run the request let outcome = next.run(req, extensions).await; ReqwestOtelSpan::on_request_end(&request_span, &outcome, extensions); outcome }; outcome_future.instrument(request_span.clone()).await } }