qubit_dcl/double_checked/execution_logger.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025 - 2026 Haixing Hu.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10//! # Execution Logger
11//!
12//! Logging configuration and helpers for the double-checked lock executor.
13//!
14
15use std::fmt;
16
17/// Logger for double-checked execution (condition unmet, prepare failures,
18/// prepare commit failures, and prepare rollback failures).
19///
20/// Each event has its own optional [`log::Level`] and message. `None` means
21/// that event does not emit logs. For prepare-style events the message is a
22/// prefix formatted as `"{prefix}: {error}"`.
23///
24/// [`ExecutionLogger::default`] matches the previous `Option` logger unset
25/// behavior: condition-unmet is silent (`None`); prepare lifecycle lines use
26/// [`log::Level::Error`] with English default prefixes.
27///
28#[derive(Debug, Clone)]
29pub struct ExecutionLogger {
30 /// Log level for the condition-unmet message; `None` skips it.
31 unmet_condition_level: Option<log::Level>,
32
33 /// Message logged when the execution condition is not met.
34 unmet_condition_message: String,
35
36 /// Log level for prepare-action failure lines; `None` skips them.
37 prepare_failed_level: Option<log::Level>,
38
39 /// Prefix for prepare-failure lines, formatted as `"{prefix}: {error}"`.
40 prepare_failed_message: String,
41
42 /// Log level for prepare-commit failure lines; `None` skips them.
43 prepare_commit_failed_level: Option<log::Level>,
44
45 /// Prefix for prepare-commit failure lines, formatted as `"{prefix}: {error}"`.
46 prepare_commit_failed_message: String,
47
48 /// Log level for prepare-rollback failure lines; `None` skips them.
49 prepare_rollback_failed_level: Option<log::Level>,
50
51 /// Prefix for prepare-rollback failure lines, formatted as
52 /// `"{prefix}: {error}"`.
53 prepare_rollback_failed_message: String,
54}
55
56impl Default for ExecutionLogger {
57 /// Returns the logger configuration used when the executor builder does not
58 /// apply any logging overrides.
59 ///
60 /// Condition-unmet logging is disabled ([`ExecutionLogger::unmet_condition_level`]
61 /// is [`None`]). Prepare lifecycle failures log at [`log::Level::Error`] with
62 /// short English default prefixes (see the field defaults on [`ExecutionLogger`]).
63 ///
64 /// # Returns
65 ///
66 /// A new [`ExecutionLogger`] with the values described above.
67 #[inline]
68 fn default() -> Self {
69 Self {
70 unmet_condition_level: None,
71 unmet_condition_message: String::new(),
72 prepare_failed_level: Some(log::Level::Error),
73 prepare_failed_message: "Prepare action failed".to_string(),
74 prepare_commit_failed_level: Some(log::Level::Error),
75 prepare_commit_failed_message: "Prepare commit action failed".to_string(),
76 prepare_rollback_failed_level: Some(log::Level::Error),
77 prepare_rollback_failed_message: "Prepare rollback action failed".to_string(),
78 }
79 }
80}
81
82impl ExecutionLogger {
83 /// Returns the configured level for unmet-condition logging.
84 ///
85 /// [`None`] means the event does not emit a log line.
86 ///
87 /// # Returns
88 ///
89 /// The optional log level for unmet-condition events.
90 #[inline]
91 pub fn unmet_condition_level(&self) -> Option<log::Level> {
92 self.unmet_condition_level
93 }
94
95 /// Returns the message used for unmet-condition logging.
96 ///
97 /// # Returns
98 ///
99 /// The stored unmet-condition log message.
100 #[inline]
101 pub fn unmet_condition_message(&self) -> &str {
102 &self.unmet_condition_message
103 }
104
105 /// Returns the configured level for prepare-action failures.
106 ///
107 /// [`None`] means the event does not emit a log line.
108 ///
109 /// # Returns
110 ///
111 /// The optional log level for prepare-action failure events.
112 #[inline]
113 pub fn prepare_failed_level(&self) -> Option<log::Level> {
114 self.prepare_failed_level
115 }
116
117 /// Returns the message prefix used for prepare-action failures.
118 ///
119 /// # Returns
120 ///
121 /// The prefix placed before prepare-action failure text.
122 #[inline]
123 pub fn prepare_failed_message(&self) -> &str {
124 &self.prepare_failed_message
125 }
126
127 /// Returns the configured level for prepare-commit failures.
128 ///
129 /// [`None`] means the event does not emit a log line.
130 ///
131 /// # Returns
132 ///
133 /// The optional log level for prepare-commit failure events.
134 #[inline]
135 pub fn prepare_commit_failed_level(&self) -> Option<log::Level> {
136 self.prepare_commit_failed_level
137 }
138
139 /// Returns the message prefix used for prepare-commit failures.
140 ///
141 /// # Returns
142 ///
143 /// The prefix placed before prepare-commit failure text.
144 #[inline]
145 pub fn prepare_commit_failed_message(&self) -> &str {
146 &self.prepare_commit_failed_message
147 }
148
149 /// Returns the configured level for prepare-rollback failures.
150 ///
151 /// [`None`] means the event does not emit a log line.
152 ///
153 /// # Returns
154 ///
155 /// The optional log level for prepare-rollback failure events.
156 #[inline]
157 pub fn prepare_rollback_failed_level(&self) -> Option<log::Level> {
158 self.prepare_rollback_failed_level
159 }
160
161 /// Returns the message prefix used for prepare-rollback failures.
162 ///
163 /// # Returns
164 ///
165 /// The prefix placed before prepare-rollback failure text.
166 #[inline]
167 pub fn prepare_rollback_failed_message(&self) -> &str {
168 &self.prepare_rollback_failed_message
169 }
170
171 /// Updates logging for the case where the double-checked condition is not met
172 /// (the tester returns `false` before or after taking the lock).
173 ///
174 /// When [`Self::unmet_condition_level`] is [`None`], [`Self::log_unmet_condition`]
175 /// becomes a no-op. The `message` is still stored and used if the level is set
176 /// to [`Some`] later.
177 ///
178 /// # Parameters
179 ///
180 /// * `level` - Optional severity for the line written through the `log` crate,
181 /// or [`None`] to disable this event.
182 /// * `message` - Full line text (not a prefix); passed to [`log::log!`] as the
183 /// format argument when logging runs.
184 #[inline]
185 pub fn set_unmet_condition(&mut self, level: Option<log::Level>, message: impl Into<String>) {
186 self.unmet_condition_level = level;
187 self.unmet_condition_message = message.into();
188 }
189
190 /// Disables logging for unmet double-checked conditions.
191 ///
192 /// This keeps the stored message unchanged so a later call to
193 /// [`Self::set_unmet_condition`] can re-enable the event with a new message.
194 #[inline]
195 pub fn disable_unmet_condition(&mut self) {
196 self.unmet_condition_level = None;
197 }
198
199 /// Updates logging for a failed optional prepare action (before the lock is taken).
200 ///
201 /// When [`Self::prepare_failed_level`] is [`None`], [`Self::log_prepare_failed`]
202 /// becomes a no-op.
203 ///
204 /// # Parameters
205 ///
206 /// * `level` - Optional severity for the diagnostic line, or [`None`] to disable.
207 /// * `message_prefix` - Text placed before the error; the emitted line has the
208 /// form `"{prefix}: {error}"`.
209 #[inline]
210 pub fn set_prepare_failure(&mut self, level: Option<log::Level>, message_prefix: impl Into<String>) {
211 self.prepare_failed_level = level;
212 self.prepare_failed_message = message_prefix.into();
213 }
214
215 /// Disables logging for prepare-action failures.
216 #[inline]
217 pub fn disable_prepare_failure(&mut self) {
218 self.prepare_failed_level = None;
219 }
220
221 /// Updates logging for a failed prepare commit action (after a successful task
222 /// when prepare had completed).
223 ///
224 /// When [`Self::prepare_commit_failed_level`] is [`None`],
225 /// [`Self::log_prepare_commit_failed`] becomes a no-op.
226 ///
227 /// # Parameters
228 ///
229 /// * `level` - Optional severity for the diagnostic line, or [`None`] to disable.
230 /// * `message_prefix` - Text placed before the error; the emitted line has the
231 /// form `"{prefix}: {error}"`.
232 #[inline]
233 pub fn set_prepare_commit_failure(&mut self, level: Option<log::Level>, message_prefix: impl Into<String>) {
234 self.prepare_commit_failed_level = level;
235 self.prepare_commit_failed_message = message_prefix.into();
236 }
237
238 /// Disables logging for prepare-commit failures.
239 #[inline]
240 pub fn disable_prepare_commit_failure(&mut self) {
241 self.prepare_commit_failed_level = None;
242 }
243
244 /// Updates logging for a failed prepare rollback action (after a failed second
245 /// check or task when prepare had completed).
246 ///
247 /// When [`Self::prepare_rollback_failed_level`] is [`None`],
248 /// [`Self::log_prepare_rollback_failed`] becomes a no-op.
249 ///
250 /// # Parameters
251 ///
252 /// * `level` - Optional severity for the diagnostic line, or [`None`] to disable.
253 /// * `message_prefix` - Text placed before the error; the emitted line has the
254 /// form `"{prefix}: {error}"`.
255 #[inline]
256 pub fn set_prepare_rollback_failure(&mut self, level: Option<log::Level>, message_prefix: impl Into<String>) {
257 self.prepare_rollback_failed_level = level;
258 self.prepare_rollback_failed_message = message_prefix.into();
259 }
260
261 /// Disables logging for prepare-rollback failures.
262 #[inline]
263 pub fn disable_prepare_rollback_failure(&mut self) {
264 self.prepare_rollback_failed_level = None;
265 }
266
267 /// Emits the condition-unmet log line if enabled.
268 ///
269 /// Does nothing when [`Self::unmet_condition_level`] is [`None`]. Otherwise
270 /// writes [`Self::unmet_condition_message`] through the `log` facade at the
271 /// configured level, subject to the crate-wide maximum log level (for example
272 /// set via [`log::set_max_level`] or compile-time filters).
273 #[inline]
274 pub fn log_unmet_condition(&self) {
275 let Some(level) = self.unmet_condition_level else {
276 return;
277 };
278 log::log!(level, "{}", self.unmet_condition_message);
279 }
280
281 /// Emits a diagnostic line when the prepare action fails.
282 ///
283 /// Does nothing when [`Self::prepare_failed_level`] is [`None`]. Otherwise
284 /// logs `"{prefix}: {err}"` at the configured level via the `log` facade,
285 /// where `prefix` is [`Self::prepare_failed_message`], subject to the
286 /// crate-wide maximum log level.
287 ///
288 /// # Type Parameters
289 ///
290 /// * `E` - Displayable error or message value appended after the prefix.
291 ///
292 /// # Parameters
293 ///
294 /// * `err` - Failure to record next to the configured prefix.
295 #[inline]
296 pub fn log_prepare_failed<E: fmt::Display>(&self, err: E) {
297 let Some(level) = self.prepare_failed_level else {
298 return;
299 };
300 log::log!(level, "{}: {}", self.prepare_failed_message, err);
301 }
302
303 /// Emits a diagnostic line when the prepare commit action fails.
304 ///
305 /// Does nothing when [`Self::prepare_commit_failed_level`] is [`None`].
306 /// Otherwise logs `"{prefix}: {err}"` at the configured level, where `prefix`
307 /// is [`Self::prepare_commit_failed_message`], subject to the crate-wide
308 /// maximum log level.
309 ///
310 /// # Type Parameters
311 ///
312 /// * `E` - Displayable error or message value appended after the prefix.
313 ///
314 /// # Parameters
315 ///
316 /// * `err` - Commit failure to record next to the configured prefix.
317 #[inline]
318 pub fn log_prepare_commit_failed<E: fmt::Display>(&self, err: E) {
319 let Some(level) = self.prepare_commit_failed_level else {
320 return;
321 };
322 log::log!(level, "{}: {}", self.prepare_commit_failed_message, err);
323 }
324
325 /// Emits a diagnostic line when the prepare rollback action fails.
326 ///
327 /// Does nothing when [`Self::prepare_rollback_failed_level`] is [`None`].
328 /// Otherwise logs `"{prefix}: {err}"` at the configured level, where `prefix`
329 /// is [`Self::prepare_rollback_failed_message`], subject to the crate-wide
330 /// maximum log level.
331 ///
332 /// # Type Parameters
333 ///
334 /// * `E` - Displayable error or message value appended after the prefix.
335 ///
336 /// # Parameters
337 ///
338 /// * `err` - Rollback failure to record next to the configured prefix.
339 #[inline]
340 pub fn log_prepare_rollback_failed<E: fmt::Display>(&self, err: E) {
341 let Some(level) = self.prepare_rollback_failed_level else {
342 return;
343 };
344 log::log!(level, "{}: {}", self.prepare_rollback_failed_message, err);
345 }
346}