tracing_stackdriver/
layer.rs

1use crate::event_formatter::EventFormatter;
2use std::{fmt, io, ops::Deref};
3use tracing_core::{Event, Subscriber};
4use tracing_subscriber::{
5    fmt::{format::JsonFields, MakeWriter},
6    registry::LookupSpan,
7};
8
9#[derive(Debug, thiserror::Error)]
10enum Error {
11    #[error(transparent)]
12    Formatting(#[from] fmt::Error),
13    #[error("JSON serialization error: {0}")]
14    Serialization(#[from] serde_json::Error),
15    #[error(transparent)]
16    Io(#[from] std::io::Error),
17    #[error("Time formatting error: {0}")]
18    Time(#[from] time::error::Format),
19}
20
21impl From<Error> for fmt::Error {
22    fn from(_: Error) -> Self {
23        Self
24    }
25}
26
27/// Create a configurable stackdriver-specific Layer and event formatter
28pub fn layer<S>() -> Layer<S>
29where
30    S: Subscriber + for<'span> LookupSpan<'span>,
31{
32    Layer(
33        tracing_subscriber::fmt::layer()
34            .json()
35            .event_format(EventFormatter::default()),
36    )
37}
38
39/// A tracing-compatible Layer implementation for Stackdriver
40pub struct Layer<S, W = fn() -> io::Stdout>(
41    tracing_subscriber::fmt::Layer<S, JsonFields, EventFormatter, W>,
42)
43where
44    S: Subscriber + for<'span> LookupSpan<'span>;
45
46impl<S, W> Layer<S, W>
47where
48    S: Subscriber + for<'span> LookupSpan<'span>,
49    W: for<'writer> MakeWriter<'writer> + 'static,
50{
51    /// Sets the MakeWriter that the Layer being built will use to write events.
52    pub fn with_writer<M>(self, make_writer: M) -> Layer<S, M>
53    where
54        M: for<'writer> MakeWriter<'writer> + 'static,
55    {
56        Layer(self.0.with_writer(make_writer))
57    }
58
59    /// Configures whether or not Events will include source locations in a special LogEntry field
60    pub fn with_source_location(self, include_source_location: bool) -> Self {
61        Self(self.0.map_event_format(|mut event_formatter| {
62            event_formatter.include_source_location = include_source_location;
63            event_formatter
64        }))
65    }
66
67    /// Configures the Cloud Trace integration with OpenTelemetry through special LogEntry fields
68    #[cfg_attr(docsrs, doc(cfg(feature = "opentelemetry")))]
69    #[cfg(any(docsrs, feature = "opentelemetry"))]
70    pub fn with_cloud_trace(self, configuration: crate::CloudTraceConfiguration) -> Self {
71        Self(self.0.map_event_format(|mut event_formatter| {
72            event_formatter.cloud_trace_configuration = Some(configuration);
73            event_formatter
74        }))
75    }
76}
77
78/// Layer trait implementation that delegates to the inner Layer methods
79impl<S, W> tracing_subscriber::layer::Layer<S> for Layer<S, W>
80where
81    S: Subscriber + for<'span> LookupSpan<'span>,
82    W: for<'writer> MakeWriter<'writer> + 'static,
83{
84    fn on_new_span(
85        &self,
86        attrs: &tracing_core::span::Attributes<'_>,
87        id: &tracing_core::span::Id,
88        context: tracing_subscriber::layer::Context<'_, S>,
89    ) {
90        self.0.on_new_span(attrs, id, context)
91    }
92
93    fn on_record(
94        &self,
95        span: &tracing_core::span::Id,
96        values: &tracing_core::span::Record<'_>,
97        context: tracing_subscriber::layer::Context<'_, S>,
98    ) {
99        self.0.on_record(span, values, context)
100    }
101
102    fn on_enter(
103        &self,
104        id: &tracing_core::span::Id,
105        context: tracing_subscriber::layer::Context<'_, S>,
106    ) {
107        self.0.on_enter(id, context)
108    }
109
110    fn on_exit(
111        &self,
112        id: &tracing_core::span::Id,
113        context: tracing_subscriber::layer::Context<'_, S>,
114    ) {
115        self.0.on_exit(id, context)
116    }
117
118    fn on_close(
119        &self,
120        id: tracing_core::span::Id,
121        context: tracing_subscriber::layer::Context<'_, S>,
122    ) {
123        self.0.on_close(id, context)
124    }
125
126    fn on_event(&self, event: &Event<'_>, context: tracing_subscriber::layer::Context<'_, S>) {
127        self.0.on_event(event, context)
128    }
129
130    unsafe fn downcast_raw(&self, id: std::any::TypeId) -> Option<*const ()> {
131        self.0.downcast_raw(id)
132    }
133}
134
135impl<S, W> Deref for Layer<S, W>
136where
137    S: Subscriber + for<'span> LookupSpan<'span>,
138{
139    type Target = tracing_subscriber::fmt::Layer<S, JsonFields, EventFormatter, W>;
140
141    fn deref(&self) -> &Self::Target {
142        &self.0
143    }
144}