oauth2_broker/obs/
tracing.rs1use crate::{_prelude::*, obs::FlowKind};
3
4#[cfg(feature = "tracing")]
6pub type InstrumentedFlow<F> = tracing::instrument::Instrumented<F>;
7#[cfg(not(feature = "tracing"))]
9pub type InstrumentedFlow<F> = F;
10
11#[derive(Clone, Debug)]
13pub struct FlowSpan {
14 #[cfg(feature = "tracing")]
15 span: tracing::Span,
16}
17impl FlowSpan {
18 pub fn new(kind: FlowKind, stage: &'static str) -> Self {
20 #[cfg(feature = "tracing")]
21 {
22 let span = tracing::info_span!("oauth2_broker.flow", flow = kind.as_str(), stage);
23
24 Self { span }
25 }
26 #[cfg(not(feature = "tracing"))]
27 {
28 let _ = (kind, stage);
29
30 Self {}
31 }
32 }
33
34 pub fn entered(self) -> FlowSpanGuard {
36 #[cfg(feature = "tracing")]
37 {
38 FlowSpanGuard { guard: self.span.entered() }
39 }
40 #[cfg(not(feature = "tracing"))]
41 {
42 let _ = self;
43
44 FlowSpanGuard {}
45 }
46 }
47
48 pub fn instrument<Fut>(&self, fut: Fut) -> InstrumentedFlow<Fut>
50 where
51 Fut: Future,
52 {
53 #[cfg(feature = "tracing")]
54 {
55 use tracing::Instrument;
56
57 fut.instrument(self.span.clone())
58 }
59 #[cfg(not(feature = "tracing"))]
60 {
61 fut
62 }
63 }
64}
65
66pub struct FlowSpanGuard {
68 #[cfg(feature = "tracing")]
69 #[allow(dead_code)]
70 guard: tracing::span::EnteredSpan,
71}
72impl Debug for FlowSpanGuard {
73 fn fmt(&self, f: &mut Formatter) -> FmtResult {
74 f.write_str("FlowSpanGuard(..)")
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
82
83 #[test]
84 fn flow_span_noop_without_tracing() {
85 let _guard = FlowSpan::new(FlowKind::ClientCredentials, "test").entered();
86 }
88
89 #[cfg(feature = "tracing")]
90 #[tokio::test]
91 async fn instrument_wraps_future() {
92 let span = FlowSpan::new(FlowKind::Refresh, "instrument_wraps_future");
93 let value = span.instrument(async { 42 }).await;
94
95 assert_eq!(value, 42);
96 }
97}