1 | use std::sync::{Arc, Mutex}; |
2 | use tracing::subscriber::with_default; |
3 | use tracing_core::span::{Attributes, Record}; |
4 | use tracing_core::{span, Event, Level, LevelFilter, Metadata, Subscriber}; |
5 | use tracing_log::{LogTracer, NormalizeEvent}; |
6 | |
7 | struct State { |
8 | last_normalized_metadata: Mutex<(bool, Option<OwnedMetadata>)>, |
9 | } |
10 | |
11 | #[derive(PartialEq, Debug)] |
12 | struct 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 | |
21 | struct TestSubscriber(Arc<State>); |
22 | |
23 | impl 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] |
62 | fn 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 | |
117 | fn 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 | |