tracing_logstash/
lib.rs

1mod event_recorder;
2mod fields;
3pub mod format;
4pub mod logstash;
5mod span_recorder;
6
7use crate::logstash::LogstashFormat;
8use span_recorder::SpanRecorder;
9use std::io::Write;
10use std::marker::PhantomData;
11use tracing_core::span::{Attributes, Id, Record};
12use tracing_core::{Event, Level, Subscriber};
13use tracing_subscriber::fmt::MakeWriter;
14use tracing_subscriber::layer::Context;
15use tracing_subscriber::registry::LookupSpan;
16
17pub struct Layer<S, E = LogstashFormat, W = fn() -> std::io::StdoutLock<'static>> {
18    record_separator: Vec<u8>,
19    make_writer: W,
20    event_format: E,
21    _inner: PhantomData<S>,
22}
23
24impl<S> Default for Layer<S> {
25    fn default() -> Self {
26        Self {
27            record_separator: vec![b'\n'],
28            make_writer: || std::io::stdout().lock(),
29            event_format: Default::default(),
30            _inner: Default::default(),
31        }
32    }
33}
34
35impl<S, E, W> Layer<S, E, W>
36where
37    E: format::FormatEvent + 'static,
38    S: Subscriber + for<'a> LookupSpan<'a>,
39    W: for<'writer> MakeWriter<'writer> + 'static,
40{
41    pub fn record_separator(self, separator: impl Into<Vec<u8>>) -> Layer<S, E, W> {
42        Layer {
43            record_separator: separator.into(),
44            ..self
45        }
46    }
47
48    pub fn event_format<E2>(self, event_format: E2) -> Layer<S, E2, W>
49    where
50        E2: format::FormatEvent + 'static,
51    {
52        Layer {
53            event_format,
54            record_separator: self.record_separator,
55            make_writer: self.make_writer,
56            _inner: self._inner,
57        }
58    }
59
60    pub fn with_writer<W2>(self, make_writer: W2) -> Layer<S, E, W2>
61    where
62        W2: for<'writer> MakeWriter<'writer> + 'static,
63    {
64        Layer {
65            make_writer,
66            event_format: self.event_format,
67            record_separator: self.record_separator,
68            _inner: self._inner,
69        }
70    }
71
72    fn write_event(&self, event: &Event<'_>, ctx: Context<'_, S>) {
73        let mut serializer = serde_json::Serializer::new(self.make_writer.make_writer());
74        self.event_format
75            .format_event(&mut serializer, event, ctx)
76            .unwrap();
77        let mut inner = serializer.into_inner();
78        inner.write_all(&self.record_separator).unwrap();
79    }
80}
81
82impl<S, E, W> tracing_subscriber::Layer<S> for Layer<S, E, W>
83where
84    S: Subscriber + for<'a> LookupSpan<'a>,
85    E: format::FormatEvent + 'static,
86    W: for<'writer> MakeWriter<'writer> + 'static,
87{
88    fn on_new_span(&self, attrs: &Attributes<'_>, id: &Id, ctx: Context<'_, S>) {
89        let span = ctx.span(id).expect("Span not found, this is a bug");
90
91        let mut extensions = span.extensions_mut();
92
93        if extensions.get_mut::<E::R>().is_none() {
94            let mut recorder = self.event_format.span_recorder();
95            recorder.record_span(attrs);
96
97            extensions.insert(recorder);
98        }
99    }
100
101    fn on_record(&self, id: &Id, record: &Record<'_>, ctx: Context<'_, S>) {
102        let span = ctx.span(id).expect("Span not found, this is a bug");
103        let mut extensions = span.extensions_mut();
104
105        if let Some(fields) = extensions.get_mut::<E::R>() {
106            fields.merge(record);
107        }
108    }
109
110    fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) {
111        self.write_event(event, ctx);
112    }
113}
114
115#[derive(Copy, Clone)]
116pub enum LoggerName {
117    Event,
118    Span,
119}
120
121#[derive(Copy, Clone)]
122pub enum DisplayLevelFilter {
123    Off,
124    All,
125    Level(Level),
126    Event,
127}
128
129impl DisplayLevelFilter {
130    pub const ERROR: DisplayLevelFilter = Self::from_level(Level::ERROR);
131    pub const WARN: DisplayLevelFilter = Self::from_level(Level::WARN);
132    pub const INFO: DisplayLevelFilter = Self::from_level(Level::INFO);
133    pub const DEBUG: DisplayLevelFilter = Self::from_level(Level::DEBUG);
134    pub const TRACE: DisplayLevelFilter = Self::from_level(Level::TRACE);
135
136    #[inline]
137    const fn from_level(level: Level) -> DisplayLevelFilter {
138        DisplayLevelFilter::Level(level)
139    }
140
141    #[inline]
142    pub fn is_enabled(&self, event: &Event, span_level: &Level) -> bool {
143        let filter_level = match self {
144            DisplayLevelFilter::Level(level) => level,
145            DisplayLevelFilter::Event => event.metadata().level(),
146            DisplayLevelFilter::All => return true,
147            DisplayLevelFilter::Off => return false,
148        };
149        filter_level >= span_level
150    }
151}