zebra_chain/
diagnostic.rs
1pub mod task;
7
8use std::time::{Duration, Instant};
15
16use crate::fmt::duration_short;
17
18pub const DEFAULT_MIN_INFO_TIME: Duration = Duration::from_secs(5 * 60);
22
23pub const DEFAULT_MIN_WARN_TIME: Duration = Duration::from_secs(9 * 60);
27
28#[derive(Debug)]
30pub struct CodeTimer {
31 start: Instant,
33
34 min_info_time: Duration,
36
37 min_warn_time: Duration,
39
40 has_finished: bool,
42}
43
44impl CodeTimer {
45 #[track_caller]
50 pub fn start() -> Self {
51 let start = Instant::now();
52 trace!(
53 target: "run time",
54 ?start,
55 "started code timer",
56 );
57
58 Self {
59 start,
60 min_info_time: DEFAULT_MIN_INFO_TIME,
61 min_warn_time: DEFAULT_MIN_WARN_TIME,
62 has_finished: false,
63 }
64 }
65
66 pub fn finish<S>(
68 mut self,
69 module_path: &'static str,
70 line: u32,
71 description: impl Into<Option<S>>,
72 ) where
73 S: ToString,
74 {
75 self.finish_inner(Some(module_path), Some(line), description);
76 }
77
78 pub fn ignore(mut self) {
80 self.has_finished = true;
81 }
82
83 fn finish_inner<S>(
87 &mut self,
88 module_path: impl Into<Option<&'static str>>,
89 line: impl Into<Option<u32>>,
90 description: impl Into<Option<S>>,
91 ) where
92 S: ToString,
93 {
94 if self.has_finished {
95 return;
96 }
97
98 self.has_finished = true;
99
100 let execution = self.start.elapsed();
101 let time = duration_short(execution);
102 let time = time.as_str();
103
104 let module = module_path.into().unwrap_or_default();
105
106 let line = line.into().map(|line| line.to_string()).unwrap_or_default();
107 let line = line.as_str();
108
109 let description = description
110 .into()
111 .map(|desc| desc.to_string())
112 .unwrap_or_default();
113
114 if execution >= self.min_warn_time {
115 warn!(
116 target: "run time",
117 %time,
118 %module,
119 %line,
120 "very long {description}",
121 );
122 } else if execution >= self.min_info_time {
123 info!(
124 target: "run time",
125 %time,
126 %module,
127 %line,
128 "long {description}",
129 );
130 } else {
131 trace!(
132 target: "run time",
133 %time,
134 %module,
135 %line,
136 "finished {description} code timer",
137 );
138 }
139 }
140}
141
142impl Drop for CodeTimer {
143 fn drop(&mut self) {
144 self.finish_inner(None, None, "(dropped, cancelled, or aborted)")
145 }
146}