tracing_actix_web/
root_span.rs

1use actix_web::{dev::Payload, HttpMessage};
2use actix_web::{FromRequest, HttpRequest, ResponseError};
3use std::future::{ready, Ready};
4use tracing::Span;
5
6#[derive(Clone)]
7/// The root span associated to the in-flight current request.
8///
9/// It can be used to populate additional properties using values computed or retrieved in the request
10/// handler - see the crate-level documentation for more details.
11///
12/// Extracting a `RootSpan` when the `TracingLogger` middleware is not registered will result in
13/// an internal server error.
14///
15/// # Usage
16/// ```rust
17/// use actix_web::get;
18/// use tracing_actix_web::RootSpan;
19/// use uuid::Uuid;
20///
21/// #[get("/")]
22/// async fn index(root_span: RootSpan) -> String {
23///     root_span.record("route", &"/");
24///     # "Hello".to_string()
25/// }
26/// ```
27pub struct RootSpan(Span);
28
29impl RootSpan {
30    pub(crate) fn new(span: Span) -> Self {
31        Self(span)
32    }
33}
34
35impl std::ops::Deref for RootSpan {
36    type Target = Span;
37
38    fn deref(&self) -> &Self::Target {
39        &self.0
40    }
41}
42
43impl From<RootSpan> for Span {
44    fn from(r: RootSpan) -> Self {
45        r.0
46    }
47}
48
49impl FromRequest for RootSpan {
50    type Error = RootSpanExtractionError;
51    type Future = Ready<Result<Self, Self::Error>>;
52
53    fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
54        ready(
55            req.extensions()
56                .get::<RootSpan>()
57                .cloned()
58                .ok_or(RootSpanExtractionError { _priv: () }),
59        )
60    }
61}
62
63#[derive(Debug)]
64/// Error returned by the [`RootSpan`] extractor when it fails to retrieve
65/// the root span from request-local storage.
66///
67/// It only happens if you try to extract the root span without having
68/// registered [`TracingLogger`] as a middleware for your application.
69///
70/// [`TracingLogger`]: crate::TracingLogger
71pub struct RootSpanExtractionError {
72    // It turns out that a unit struct has a public constructor!
73    // Therefore adding fields to it (either public or private) later on
74    // is an API breaking change.
75    // Therefore we are adding a dummy private field that the compiler is going
76    // to optimise away to make sure users cannot construct this error
77    // manually in their own code.
78    _priv: (),
79}
80
81impl ResponseError for RootSpanExtractionError {}
82
83impl std::fmt::Display for RootSpanExtractionError {
84    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
85        write!(
86            f,
87            "Failed to retrieve the root span from request-local storage."
88        )
89    }
90}
91
92impl std::error::Error for RootSpanExtractionError {}