zebra_chain/
diagnostic.rs1pub 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 description: &'static str,
42
43 has_finished: bool,
45}
46
47impl CodeTimer {
48 #[track_caller]
52 pub fn start() -> Self {
53 Self::start_desc("")
54 }
55
56 #[track_caller]
61 pub fn start_desc(description: &'static str) -> Self {
62 let start = Instant::now();
63 trace!(
64 target: "run time",
65 ?start,
66 "started code timer",
67 );
68
69 Self {
70 start,
71 description,
72 min_info_time: DEFAULT_MIN_INFO_TIME,
73 min_warn_time: DEFAULT_MIN_WARN_TIME,
74 has_finished: false,
75 }
76 }
77
78 #[track_caller]
80 pub fn finish_desc(mut self, description: &'static str) {
81 let location = std::panic::Location::caller();
82 self.finish_inner(Some(location.file()), Some(location.line()), description);
83 }
84
85 pub fn ignore(mut self) {
87 self.has_finished = true;
88 }
89
90 pub fn finish_inner(
92 &mut self,
93 file: impl Into<Option<&'static str>>,
94 line: impl Into<Option<u32>>,
95 description: &'static str,
96 ) {
97 if self.has_finished {
98 return;
99 }
100
101 let description = if description.is_empty() {
102 self.description
103 } else {
104 description
105 };
106
107 self.has_finished = true;
108
109 let execution = self.start.elapsed();
110 let time = duration_short(execution);
111 let time = time.as_str();
112
113 let file = file.into().unwrap_or_default();
114
115 let line = line.into().map(|line| line.to_string()).unwrap_or_default();
116 let line = line.as_str();
117
118 if execution >= self.min_warn_time {
119 warn!(
120 target: "run time",
121 %time,
122 %file,
123 %line,
124 "very long {description}",
125 );
126 } else if execution >= self.min_info_time {
127 info!(
128 target: "run time",
129 %time,
130 %file,
131 %line,
132 "long {description}",
133 );
134 } else {
135 trace!(
136 target: "run time",
137 %time,
138 %file,
139 %line,
140 "finished {description} code timer",
141 );
142 }
143 }
144}
145
146impl Drop for CodeTimer {
147 fn drop(&mut self) {
148 self.finish_inner(None, None, "(dropped, cancelled, or aborted)")
149 }
150}