tracing_formatters/
log_layer.rs

1use crate::formatter::LogFormatter;
2use crate::get_exec_name;
3use crate::log_value::LogValue;
4use crate::storage::Storage;
5use actix_web::cookie::time::format_description::well_known::Rfc3339;
6use chrono::Utc;
7use core::fmt;
8use std::collections::HashMap;
9use std::io::Write;
10use std::marker::PhantomData;
11use tracing::span::Attributes;
12use tracing::{Event, Id, Subscriber};
13use tracing_subscriber::fmt::MakeWriter;
14use tracing_subscriber::layer::Context;
15use tracing_subscriber::Layer;
16
17const TRACING_COMMON: &'static str = "tracing-log.";
18const TRACING_OVERWRITES: &'static str = "tracing-log.overwrites.";
19
20pub struct LogLayer<W: for<'a> MakeWriter<'a> + 'static, F: LogFormatter + Default> {
21    make_writer: W,
22    version: Option<i32>,
23    hostname: Option<String>,
24    application: Option<String>,
25    proc_id: Option<u32>,
26    phantom: PhantomData<F>,
27}
28
29impl<W: for<'a> MakeWriter<'a> + 'static, F: LogFormatter + Default> LogLayer<W, F> {
30    pub fn new(name: Option<String>, make_writer: W, _: F) -> Self {
31        Self::with_default_fields(name, make_writer, HashMap::new())
32    }
33
34    pub fn with_default_fields(
35        name: Option<String>,
36        make_writer: W,
37        default_fields: HashMap<String, LogValue>,
38    ) -> Self {
39        println!("PROCESS ID: {}", std::process::id());
40        Self {
41            make_writer,
42            version: Option::from(1),
43            proc_id: Option::from(std::process::id()),
44            hostname: Option::from(gethostname::gethostname().to_string_lossy().into_owned()),
45            application: name.or_else(|| get_exec_name()),
46            phantom: Default::default(),
47        }
48    }
49
50    pub fn emit(&self, mut buffer: Vec<u8>) -> Result<(), std::io::Error> {
51        buffer.write_all(b"\n")?;
52        self.make_writer.make_writer().write_all(&buffer)
53    }
54
55    pub fn version(&self) -> &Option<i32> {
56        &self.version
57    }
58
59    pub fn proc_id(&self) -> &Option<u32> {
60        &self.proc_id
61    }
62
63    pub fn hostname(&self) -> &Option<String> {
64        &self.hostname
65    }
66
67    pub fn application(&self) -> &Option<String> {
68        &self.application
69    }
70}
71
72impl<S, W, F> Layer<S> for LogLayer<W, F>
73where
74    S: Subscriber + for<'a> tracing_subscriber::registry::LookupSpan<'a>,
75    W: for<'a> MakeWriter<'a> + 'static,
76    F: LogFormatter + Default + 'static,
77{
78    fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) {
79        // Creating the SPAN from context.
80        let current_span = ctx.lookup_current();
81
82        // Event Visitor and storage initialization.
83        let mut event_visitor = Storage::default();
84        event.record(&mut event_visitor);
85
86        let mut entry = F::from_log_layer(self);
87
88        let _ = self.emit(
89            entry
90                .format_event(&current_span, event, &event_visitor)
91                .into_bytes(),
92        );
93    }
94
95    fn on_new_span(&self, _attrs: &Attributes, id: &Id, ctx: Context<'_, S>) {
96        let span = ctx.span(id).expect("Span not found, this is a bug");
97        let mut entry = F::from_log_layer(self);
98        let _ = self.emit(entry.format_span(&span, Type::EnterSpan).into_bytes());
99    }
100
101    fn on_close(&self, id: Id, ctx: Context<'_, S>) {
102        let span = ctx.span(&id).expect("Span not found, this is a bug");
103        let mut entry = F::from_log_layer(self);
104        let _ = self.emit(entry.format_span(&span, Type::ExitSpan).into_bytes());
105    }
106}
107
108/// The type of record we are dealing with: entering a span, exiting a span, an event.
109#[derive(Clone, Debug)]
110pub enum Type {
111    EnterSpan,
112    ExitSpan,
113    Event,
114}
115
116impl fmt::Display for Type {
117    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118        let repr = match self {
119            Type::EnterSpan => "START",
120            Type::ExitSpan => "ENDED",
121            Type::Event => "EVENT",
122        };
123        write!(f, "{}", repr)
124    }
125}