1 #![warn(
2     missing_debug_implementations,
3     // missing_docs, // TODO: add documentation!
4     rust_2018_idioms,
5     unreachable_pub,
6     bad_style,
7     const_err,
8     dead_code,
9     improper_ctypes,
10     legacy_directory_ownership,
11     non_shorthand_field_patterns,
12     no_mangle_generic_items,
13     overflowing_literals,
14     path_statements,
15     patterns_in_fns_without_body,
16     plugin_as_library,
17     private_in_public,
18     safe_extern_statics,
19     unconditional_recursion,
20 
21     unused,
22     unused_allocation,
23     unused_comparisons,
24     unused_parens,
25     while_true
26 )]
27 
28 use std::fmt;
29 use tower_service::Service;
30 use tracing::Level;
31 
32 pub mod request_span;
33 pub mod service_span;
34 
35 #[cfg(feature = "http")]
36 pub mod http;
37 
38 pub type InstrumentedService<S, R> = service_span::Service<request_span::Service<S, R>>;
39 
40 pub trait InstrumentableService<Request>
41 where
42     Self: Service<Request> + Sized,
43 {
instrument<G>(self, svc_span: G) -> InstrumentedService<Self, Request> where G: GetSpan<Self>, Request: fmt::Debug,44     fn instrument<G>(self, svc_span: G) -> InstrumentedService<Self, Request>
45     where
46         G: GetSpan<Self>,
47         Request: fmt::Debug,
48     {
49         let req_span: fn(&Request) -> tracing::Span =
50             |request| tracing::span!(Level::TRACE, "request", ?request);
51         let svc_span = svc_span.span_for(&self);
52         self.trace_requests(req_span).trace_service(svc_span)
53     }
54 
trace_requests<G>(self, get_span: G) -> request_span::Service<Self, Request, G> where G: GetSpan<Request> + Clone,55     fn trace_requests<G>(self, get_span: G) -> request_span::Service<Self, Request, G>
56     where
57         G: GetSpan<Request> + Clone,
58     {
59         request_span::Service::new(self, get_span)
60     }
61 
trace_service<G>(self, get_span: G) -> service_span::Service<Self> where G: GetSpan<Self>,62     fn trace_service<G>(self, get_span: G) -> service_span::Service<Self>
63     where
64         G: GetSpan<Self>,
65     {
66         let span = get_span.span_for(&self);
67         service_span::Service::new(self, span)
68     }
69 }
70 
71 #[cfg(feature = "tower-util")]
72 pub trait InstrumentMake<T, R>
73 where
74     Self: tower_util::MakeService<T, R> + Sized,
75 {
with_traced_service<G>(self, get_span: G) -> service_span::MakeService<Self, T, R, G> where G: GetSpan<T>,76     fn with_traced_service<G>(self, get_span: G) -> service_span::MakeService<Self, T, R, G>
77     where
78         G: GetSpan<T>,
79     {
80         service_span::MakeService::new(self, get_span)
81     }
82 
with_traced_requests<G>(self, get_span: G) -> request_span::MakeService<Self, R, G> where G: GetSpan<R> + Clone,83     fn with_traced_requests<G>(self, get_span: G) -> request_span::MakeService<Self, R, G>
84     where
85         G: GetSpan<R> + Clone,
86     {
87         request_span::MakeService::new(self, get_span)
88     }
89 }
90 
91 impl<S, R> InstrumentableService<R> for S where S: Service<R> + Sized {}
92 
93 #[cfg(feature = "tower-util")]
94 impl<M, T, R> InstrumentMake<T, R> for M where M: tower_util::MakeService<T, R> {}
95 
96 pub trait GetSpan<T>: crate::sealed::Sealed<T> {
span_for(&self, target: &T) -> tracing::Span97     fn span_for(&self, target: &T) -> tracing::Span;
98 }
99 
100 impl<T, F> crate::sealed::Sealed<T> for F where F: Fn(&T) -> tracing::Span {}
101 
102 impl<T, F> GetSpan<T> for F
103 where
104     F: Fn(&T) -> tracing::Span,
105 {
106     #[inline]
span_for(&self, target: &T) -> tracing::Span107     fn span_for(&self, target: &T) -> tracing::Span {
108         (self)(target)
109     }
110 }
111 
112 impl<T> crate::sealed::Sealed<T> for tracing::Span {}
113 
114 impl<T> GetSpan<T> for tracing::Span {
115     #[inline]
span_for(&self, _: &T) -> tracing::Span116     fn span_for(&self, _: &T) -> tracing::Span {
117         self.clone()
118     }
119 }
120 
121 mod sealed {
122     pub trait Sealed<T = ()> {}
123 }
124