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