tracing_logstash/
format.rs

1use crate::fields::TryForEachField;
2use crate::span_recorder::{DefaultSpanRecorder, SpanRecorder};
3use crate::DisplayLevelFilter;
4use serde::ser::{SerializeMap, SerializeSeq};
5use serde::{Serialize, Serializer};
6use std::collections::HashSet;
7use tracing_core::{Event, Subscriber};
8use tracing_subscriber::layer::Context;
9use tracing_subscriber::registry::{LookupSpan, SpanRef};
10
11pub trait FormatSpan {
12    fn format_span<S, Span>(&self, serializer: S, span: &SpanRef<Span>) -> Result<S::Ok, S::Error>
13    where
14        S: Serializer,
15        Span: Subscriber + for<'lookup> LookupSpan<'lookup>;
16}
17
18pub trait FormatEvent {
19    type R: SpanRecorder + Send + Sync;
20    fn span_recorder(&self) -> Self::R;
21    fn format_event<S: Serializer, SS: Subscriber + for<'a> LookupSpan<'a>>(
22        &self,
23        serializer: S,
24        event: &Event<'_>,
25        ctx: Context<'_, SS>,
26    ) -> Result<S::Ok, S::Error>;
27}
28
29#[derive(Default)]
30pub struct DefaultSpanFormat {
31    display_location: bool,
32    display_fields: bool,
33}
34
35impl DefaultSpanFormat {
36    pub fn with_location(self, display_location: bool) -> Self {
37        Self {
38            display_location,
39            ..self
40        }
41    }
42    pub fn with_fields(self, display_fields: bool) -> Self {
43        Self {
44            display_fields,
45            ..self
46        }
47    }
48}
49
50const RESERVED_SPAN_FIELDS: [&str; 5] = ["name", "target", "level", "file", "line"];
51
52impl FormatSpan for DefaultSpanFormat {
53    fn format_span<S, Span>(&self, serializer: S, span: &SpanRef<Span>) -> Result<S::Ok, S::Error>
54    where
55        S: Serializer,
56        Span: Subscriber + for<'lookup> LookupSpan<'lookup>,
57    {
58        let mut s = serializer.serialize_map(None)?;
59        let metadata = span.metadata();
60        s.serialize_entry("name", span.name())?;
61        s.serialize_entry("target", metadata.target())?;
62        s.serialize_entry("level", metadata.level().as_str())?;
63        if self.display_location {
64            if let Some(file) = metadata.file() {
65                s.serialize_entry("file", file)?;
66            }
67            if let Some(line) = metadata.line() {
68                s.serialize_entry("line", &line)?;
69            }
70        }
71        if self.display_fields {
72            if let Some(fields) = span.extensions().get::<DefaultSpanRecorder>() {
73                write_extension_fields(&mut HashSet::from(RESERVED_SPAN_FIELDS), &mut s, fields)?;
74            }
75        }
76        s.end()
77    }
78}
79
80pub(crate) fn write_extension_fields<S: SerializeMap, R: TryForEachField>(
81    seen: &mut HashSet<&str>,
82    serialize_map: &mut S,
83    recorded: &R,
84) -> Result<(), S::Error> {
85    recorded.try_for_each(|name, value| {
86        if !value.is_unset() && seen.insert(name) {
87            serialize_map.serialize_entry(name, value)?;
88        }
89        Ok(())
90    })?;
91    Ok(())
92}
93
94pub(crate) struct SerializableSpan<'fmt_span, 'span, FmtSpan, Span>(
95    pub &'fmt_span FmtSpan,
96    pub &'span SpanRef<'fmt_span, Span>,
97)
98where
99    Span: for<'lookup> LookupSpan<'lookup>;
100
101impl<'a, 'b, FmtSpan, Span> Serialize for SerializableSpan<'a, 'b, FmtSpan, Span>
102where
103    FmtSpan: FormatSpan,
104    Span: Subscriber + for<'lookup> LookupSpan<'lookup>,
105{
106    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
107    where
108        S: Serializer,
109    {
110        self.0.format_span(serializer, self.1)
111    }
112}
113
114pub(crate) struct SerializableSpanList<'a, FS, Span>(
115    pub(crate) &'a FS,
116    pub(crate) &'a Event<'a>,
117    pub(crate) &'a Context<'a, Span>,
118    pub(crate) DisplayLevelFilter,
119)
120where
121    Span: for<'lookup> LookupSpan<'lookup>;
122
123impl<'a, FS, SS> Serialize for SerializableSpanList<'a, FS, SS>
124where
125    FS: FormatSpan,
126    SS: Subscriber + for<'lookup> LookupSpan<'lookup>,
127{
128    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
129    where
130        S: Serializer,
131    {
132        let mut s = serializer.serialize_seq(None)?;
133        if let Some(scope) = self.2.event_scope(self.1) {
134            for span in scope {
135                if self.3.is_enabled(self.1, span.metadata().level()) {
136                    s.serialize_element(&SerializableSpan(self.0, &span))?;
137                }
138            }
139        }
140        s.end()
141    }
142}