1use std::sync::{Arc, Mutex};
2use tracing::subscriber::with_default;
3use tracing_core::span::{Attributes, Record};
4use tracing_core::{span, Event, Level, LevelFilter, Metadata, Subscriber};
5use tracing_log::{LogTracer, NormalizeEvent};
6
7struct State {
8 last_normalized_metadata: Mutex<(bool, Option<OwnedMetadata>)>,
9}
10
11#[derive(PartialEq, Debug)]
12struct OwnedMetadata {
13 name: String,
14 target: String,
15 level: Level,
16 module_path: Option<String>,
17 file: Option<String>,
18 line: Option<u32>,
19}
20
21struct TestSubscriber(Arc<State>);
22
23impl Subscriber for TestSubscriber {
24 fn enabled(&self, meta: &Metadata<'_>) -> bool {
25 dbg!(meta);
26 true
27 }
28
29 fn max_level_hint(&self) -> Option<LevelFilter> {
30 Some(LevelFilter::from_level(Level::INFO))
31 }
32
33 fn new_span(&self, _span: &Attributes<'_>) -> span::Id {
34 span::Id::from_u64(42)
35 }
36
37 fn record(&self, _span: &span::Id, _values: &Record<'_>) {}
38
39 fn record_follows_from(&self, _span: &span::Id, _follows: &span::Id) {}
40
41 fn event(&self, event: &Event<'_>) {
42 dbg!(event);
43 *self.0.last_normalized_metadata.lock().unwrap() = (
44 event.is_log(),
45 event.normalized_metadata().map(|normalized| OwnedMetadata {
46 name: normalized.name().to_string(),
47 target: normalized.target().to_string(),
48 level: *normalized.level(),
49 module_path: normalized.module_path().map(String::from),
50 file: normalized.file().map(String::from),
51 line: normalized.line(),
52 }),
53 )
54 }
55
56 fn enter(&self, _span: &span::Id) {}
57
58 fn exit(&self, _span: &span::Id) {}
59}
60
61#[test]
62fn normalized_metadata() {
63 LogTracer::init().unwrap();
64 let me = Arc::new(State {
65 last_normalized_metadata: Mutex::new((false, None)),
66 });
67 let state = me.clone();
68
69 with_default(TestSubscriber(me), || {
70 log::info!("expected info log");
71 log::debug!("unexpected debug log");
72 let log = log::Record::builder()
73 .args(format_args!("Error!"))
74 .level(log::Level::Info)
75 .build();
76 log::logger().log(&log);
77 last(
78 &state,
79 true,
80 Some(OwnedMetadata {
81 name: "log event".to_string(),
82 target: "".to_string(),
83 level: Level::INFO,
84 module_path: None,
85 file: None,
86 line: None,
87 }),
88 );
89
90 let log = log::Record::builder()
91 .args(format_args!("Error!"))
92 .level(log::Level::Info)
93 .target("log_tracer_target")
94 .file(Some("server.rs"))
95 .line(Some(144))
96 .module_path(Some("log_tracer"))
97 .build();
98 log::logger().log(&log);
99 last(
100 &state,
101 true,
102 Some(OwnedMetadata {
103 name: "log event".to_string(),
104 target: "log_tracer_target".to_string(),
105 level: Level::INFO,
106 module_path: Some("log_tracer".to_string()),
107 file: Some("server.rs".to_string()),
108 line: Some(144),
109 }),
110 );
111
112 tracing::info!("test with a tracing info");
113 last(&state, false, None);
114 })
115}
116
117fn last(state: &State, should_be_log: bool, expected: Option<OwnedMetadata>) {
118 let lock = state.last_normalized_metadata.lock().unwrap();
119 let (is_log, metadata) = &*lock;
120 dbg!(&metadata);
121 assert_eq!(dbg!(*is_log), should_be_log);
122 assert_eq!(metadata.as_ref(), expected.as_ref());
123}
124