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 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.len() > 0 {
85 writers.push(file_writer);
86 }
87
88 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 .with_max_level(options.level)
97 .with_target(false)
101 .with_thread_ids(include_thread_ids)
103 .with_thread_names(include_thread_names)
104 .with_writer(make_composite_writer)
106 .with_env_filter(filter)
107 .finish();
108
109 return Box::new(collector);
110}
111
112