//! Middleware which instruments each request passing through a service with a new span. use super::GetSpan; use futures::future::Future; use std::marker::PhantomData; use std::pin::Pin; use std::task::{Context, Poll}; use tracing::Instrument; #[derive(Debug)] pub struct Service tracing::Span> where S: tower_service::Service, G: GetSpan, { get_span: G, inner: S, _p: PhantomData, } #[cfg(feature = "tower-layer")] #[cfg_attr(docsrs, doc(cfg(feature = "tower-layer")))] pub use self::layer::*; #[cfg(feature = "tower-layer")] #[cfg_attr(docsrs, doc(cfg(feature = "tower-layer")))] mod layer { use super::*; #[derive(Debug)] pub struct Layer tracing::Span> where G: GetSpan + Clone, { get_span: G, _p: PhantomData, } pub fn layer(get_span: G) -> Layer where G: GetSpan + Clone, { Layer { get_span, _p: PhantomData, } } // === impl Layer === impl tower_layer::Layer for Layer where S: tower_service::Service, G: GetSpan + Clone, { type Service = Service; fn layer(&self, service: S) -> Self::Service { Service::new(service, self.get_span.clone()) } } impl Clone for Layer where G: GetSpan + Clone, { fn clone(&self) -> Self { Self { get_span: self.get_span.clone(), _p: PhantomData, } } } } #[cfg(feature = "tower-make")] #[cfg_attr(docsrs, doc(cfg(feature = "tower-make")))] pub use self::make::MakeService; #[cfg(feature = "tower-make")] #[cfg_attr(docsrs, doc(cfg(feature = "tower-make")))] pub mod make { use super::*; use pin_project_lite::pin_project; #[derive(Debug)] pub struct MakeService tracing::Span> { get_span: G, inner: S, _p: PhantomData, } #[cfg(feature = "tower-layer")] #[cfg_attr(docsrs, doc(cfg(feature = "tower-layer")))] #[derive(Debug)] pub struct MakeLayer tracing::Span> where G: GetSpan + Clone, { get_span: G, _p: PhantomData, } pin_project! { #[derive(Debug)] pub struct MakeFuture tracing::Span> { get_span: Option, #[pin] inner: F, _p: PhantomData, } } #[cfg(feature = "tower-layer")] #[cfg_attr(docsrs, doc(cfg(feature = "tower-layer")))] pub fn layer(get_span: G) -> MakeLayer where G: GetSpan + Clone, { MakeLayer { get_span, _p: PhantomData, } } // === impl MakeLayer === #[cfg(feature = "tower-layer")] #[cfg_attr(docsrs, doc(cfg(feature = "tower-layer")))] impl tower_layer::Layer for MakeLayer where S: tower_make::MakeService, G: GetSpan + Clone, { type Service = MakeService; fn layer(&self, inner: S) -> Self::Service { MakeService::new(inner, self.get_span.clone()) } } #[cfg(feature = "tower-layer")] #[cfg_attr(docsrs, doc(cfg(feature = "tower-layer")))] impl Clone for MakeLayer where G: GetSpan + Clone, { fn clone(&self) -> Self { Self { get_span: self.get_span.clone(), _p: PhantomData, } } } // === impl MakeService === impl tower_service::Service for MakeService where S: tower_make::MakeService, G: GetSpan + Clone, { type Response = Service; type Error = S::MakeError; type Future = MakeFuture; fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { self.inner.poll_ready(cx) } fn call(&mut self, target: T) -> Self::Future { let inner = self.inner.make_service(target); let get_span = Some(self.get_span.clone()); MakeFuture { get_span, inner, _p: PhantomData, } } } impl MakeService where G: GetSpan + Clone, { pub fn new(inner: S, get_span: G) -> Self where S: tower_make::MakeService, { Self { get_span, inner, _p: PhantomData, } } } impl Clone for MakeService where G: GetSpan + Clone, S: Clone, { fn clone(&self) -> Self { Self { get_span: self.get_span.clone(), inner: self.inner.clone(), _p: PhantomData, } } } impl Future for MakeFuture where F: Future>, S: tower_service::Service, G: GetSpan + Clone, { type Output = Result, E>; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = self.project(); let inner = futures::ready!(this.inner.poll(cx)); let get_span = this.get_span.take().expect("polled after ready"); Poll::Ready(inner.map(|inner| Service { inner, get_span, _p: PhantomData, })) } } } // === impl Service === impl tower_service::Service for Service where S: tower_service::Service, G: GetSpan + Clone, { type Response = S::Response; type Error = S::Error; type Future = tracing::instrument::Instrumented; fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { self.inner.poll_ready(cx) } fn call(&mut self, request: R) -> Self::Future { let span = self.get_span.span_for(&request); let _enter = span.enter(); self.inner.call(request).instrument(span.clone()) } } impl Clone for Service where S: tower_service::Service + Clone, G: GetSpan + Clone, { fn clone(&self) -> Self { Service { get_span: self.get_span.clone(), inner: self.inner.clone(), _p: PhantomData, } } } impl Service where S: tower_service::Service, G: GetSpan + Clone, { pub fn new(inner: S, get_span: G) -> Self { Service { get_span, inner, _p: PhantomData, } } }