cs_trace/
utils.rs

1use tracing::{Level, Subscriber};
2use std::{io::{stdout, Write}};
3use tracing_subscriber::{self, EnvFilter};
4
5use crate::writers::{FileWriter, MakeCompositeWriter};
6
7pub struct TraceListenerOptions {
8    level: Level,
9    is_stdout: bool,
10    cleanup_file: bool,
11    include_thread_ids: bool,
12    include_thread_names: bool,
13    file_path: String,
14    filter: EnvFilter,
15}
16
17impl Default for TraceListenerOptions {
18    fn default() -> Self {
19        return TraceListenerOptions {
20            level: Level::TRACE,
21            is_stdout: true,
22            cleanup_file: false,
23            include_thread_ids: false,
24            include_thread_names: false,
25            file_path: String::new(),
26            filter: EnvFilter::default(),
27        };
28    }
29}
30
31impl TraceListenerOptions {
32    pub fn new() -> Self {
33        return TraceListenerOptions::default();
34    }
35
36    pub fn with_stdout(self, is_stdout: bool) -> Self {
37        return TraceListenerOptions { is_stdout, ..self };
38    }
39
40    pub fn with_level(self, level: Level) -> Self {
41        return TraceListenerOptions { level, ..self };
42    }
43
44    pub fn with_file_path<S: AsRef<str> + ToString>(self, file_path: S, cleanup_file: bool) -> Self {
45        let file_path = file_path.to_string();
46
47        return TraceListenerOptions { file_path, cleanup_file: cleanup_file, ..self };
48    }
49
50    pub fn with_thread_names(self, include_thread_names: bool) -> Self {
51        return TraceListenerOptions { include_thread_names, ..self };
52    }
53
54    pub fn with_thread_ids(self, include_thread_ids: bool) -> Self {
55        return TraceListenerOptions { include_thread_ids, ..self };
56    }
57
58    pub fn with_env_filter(self, filter: impl Into<EnvFilter>) -> Self {
59        let filter = filter.into();
60
61        return TraceListenerOptions { filter, ..self };
62    }
63}
64
65pub fn create_trace_listener(
66    options: TraceListenerOptions,
67) -> Box<dyn Subscriber + Send + Sync> {
68    // get the file path and stdout options
69    let TraceListenerOptions {
70        file_path,
71        is_stdout,
72        cleanup_file,
73        include_thread_names,
74        include_thread_ids,
75        filter,
76        ..
77    } = options;
78
79    let file_writer = FileWriter::new(&file_path, cleanup_file);
80    let stdout_writer: Box<dyn Write + Send + Sync> = Box::new(stdout());
81    let mut writers: Vec<Box<dyn Write + Send + Sync>> = vec![];
82
83    // if file path is set, use the file writer
84    if file_path.len() > 0 {
85        writers.push(file_writer);
86    }
87
88    // is stdout set, write to console
89    if is_stdout {
90        writers.push(stdout_writer);
91    }
92
93    let make_composite_writer = MakeCompositeWriter::new(writers);
94    let collector = tracing_subscriber::fmt()
95        // make sure the tracing level filtering is respected
96        .with_max_level(options.level)
97        // otherwise the log line will always contain trace::trace
98        // since we wrap the tracing functionality and the macros
99        // are called from within the trace create
100        .with_target(false)
101        // include thread name
102        .with_thread_ids(include_thread_ids)
103        .with_thread_names(include_thread_names)
104        // setup writers based on options
105        .with_writer(make_composite_writer)
106        .with_env_filter(filter)
107        .finish();
108
109    return Box::new(collector);
110}
111
112// pub use spin;
113
114// static START: spin::Once<()> = spin::Once::new();
115
116// START.call_once(|| {
117//     // run initialization here
118// });