tracing_stackdriver/
event_formatter.rs1use crate::{
2 google::LogSeverity,
3 serializers::{SerializableContext, SerializableSpan, SourceLocation},
4 visitor::Visitor,
5 writer::WriteAdaptor,
6};
7use serde::ser::{SerializeMap, Serializer as _};
8use std::fmt;
9use time::{format_description::well_known::Rfc3339, OffsetDateTime};
10use tracing_core::{Event, Subscriber};
11use tracing_subscriber::{
12 field::VisitOutput,
13 fmt::{
14 format::{self, JsonFields},
15 FmtContext, FormatEvent,
16 },
17 registry::LookupSpan,
18};
19
20#[derive(Debug, thiserror::Error)]
21enum Error {
22 #[error(transparent)]
23 Formatting(#[from] fmt::Error),
24 #[error("JSON serialization error: {0}")]
25 Serialization(#[from] serde_json::Error),
26 #[error(transparent)]
27 Io(#[from] std::io::Error),
28 #[error("Time formatting error: {0}")]
29 Time(#[from] time::error::Format),
30}
31
32impl From<Error> for fmt::Error {
33 fn from(_: Error) -> Self {
34 Self
35 }
36}
37
38pub struct EventFormatter {
40 pub(crate) include_source_location: bool,
41 #[cfg(feature = "opentelemetry")]
42 pub(crate) cloud_trace_configuration: Option<crate::CloudTraceConfiguration>,
43}
44
45impl EventFormatter {
46 fn format_event<S>(
48 &self,
49 context: &FmtContext<S, JsonFields>,
50 mut serializer: serde_json::Serializer<WriteAdaptor>,
51 event: &Event,
52 ) -> Result<(), Error>
53 where
54 S: Subscriber + for<'span> LookupSpan<'span>,
55 {
56 let time = OffsetDateTime::now_utc().format(&Rfc3339)?;
57 let meta = event.metadata();
58 let severity = LogSeverity::from(meta.level());
59
60 let span = event
61 .parent()
62 .and_then(|id| context.span(id))
63 .or_else(|| context.lookup_current());
64
65 let mut map = serializer.serialize_map(None)?;
67
68 map.serialize_entry("time", &time)?;
70 map.serialize_entry("target", &meta.target())?;
71
72 if self.include_source_location {
73 if let Some(file) = meta.file() {
74 map.serialize_entry(
75 "logging.googleapis.com/sourceLocation",
76 &SourceLocation {
77 file,
78 line: meta.line(),
79 },
80 )?;
81 }
82 }
83
84 if let Some(span) = span {
86 map.serialize_entry("span", &SerializableSpan::new(&span))?;
87 map.serialize_entry("spans", &SerializableContext::new(context))?;
88
89 #[cfg(feature = "opentelemetry")]
90 if let (Some(crate::CloudTraceConfiguration { project_id }), Some(otel_data)) = (
91 self.cloud_trace_configuration.as_ref(),
92 span.extensions().get::<tracing_opentelemetry::OtelData>(),
93 ) {
94 use opentelemetry::trace::TraceContextExt;
95
96 let builder = &otel_data.builder;
97
98 if let Some(span_id) = builder.span_id {
99 map.serialize_entry("logging.googleapis.com/spanId", &span_id.to_string())?;
100 }
101
102 let (trace_id, trace_sampled) = if otel_data.parent_cx.has_active_span() {
103 let span_ref = otel_data.parent_cx.span();
104 let span_context = span_ref.span_context();
105
106 (Some(span_context.trace_id()), span_context.is_sampled())
107 } else {
108 (builder.trace_id, false)
109 };
110
111 if let Some(trace_id) = trace_id {
112 map.serialize_entry(
113 "logging.googleapis.com/trace",
114 &format!("projects/{project_id}/traces/{trace_id}",),
115 )?;
116 }
117
118 if trace_sampled {
119 map.serialize_entry("logging.googleapis.com/trace_sampled", &true)?;
120 }
121 }
122 }
123
124 let mut visitor = Visitor::new(severity, map);
126 event.record(&mut visitor);
127 visitor.finish().map_err(Error::from)?;
128 Ok(())
129 }
130}
131
132impl<S> FormatEvent<S, JsonFields> for EventFormatter
133where
134 S: Subscriber + for<'span> LookupSpan<'span>,
135{
136 fn format_event(
137 &self,
138 context: &FmtContext<S, JsonFields>,
139 mut writer: format::Writer,
140 event: &Event,
141 ) -> fmt::Result
142 where
143 S: Subscriber + for<'span> LookupSpan<'span>,
144 {
145 let serializer = serde_json::Serializer::new(WriteAdaptor::new(&mut writer));
146 self.format_event(context, serializer, event)?;
147 writeln!(writer)
148 }
149}
150
151impl Default for EventFormatter {
152 fn default() -> Self {
153 Self {
154 include_source_location: true,
155 #[cfg(feature = "opentelemetry")]
156 cloud_trace_configuration: None,
157 }
158 }
159}