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(
211 &mut self,
212 level: Option<log::Level>,
213 message_prefix: impl Into<String>,
214 ) {
215 self.prepare_failed_level = level;
216 self.prepare_failed_message = message_prefix.into();
217 }
218
219 /// Disables logging for prepare-action failures.
220 #[inline]
221 pub fn disable_prepare_failure(&mut self) {
222 self.prepare_failed_level = None;
223 }
224
225 /// Updates logging for a failed prepare commit action (after a successful task
226 /// when prepare had completed).
227 ///
228 /// When [`Self::prepare_commit_failed_level`] is [`None`],
229 /// [`Self::log_prepare_commit_failed`] becomes a no-op.
230 ///
231 /// # Parameters
232 ///
233 /// * `level` - Optional severity for the diagnostic line, or [`None`] to disable.
234 /// * `message_prefix` - Text placed before the error; the emitted line has the
235 /// form `"{prefix}: {error}"`.
236 #[inline]
237 pub fn set_prepare_commit_failure(
238 &mut self,
239 level: Option<log::Level>,
240 message_prefix: impl Into<String>,
241 ) {
242 self.prepare_commit_failed_level = level;
243 self.prepare_commit_failed_message = message_prefix.into();
244 }
245
246 /// Disables logging for prepare-commit failures.
247 #[inline]
248 pub fn disable_prepare_commit_failure(&mut self) {
249 self.prepare_commit_failed_level = None;
250 }
251
252 /// Updates logging for a failed prepare rollback action (after a failed second
253 /// check or task when prepare had completed).
254 ///
255 /// When [`Self::prepare_rollback_failed_level`] is [`None`],
256 /// [`Self::log_prepare_rollback_failed`] becomes a no-op.
257 ///
258 /// # Parameters
259 ///
260 /// * `level` - Optional severity for the diagnostic line, or [`None`] to disable.
261 /// * `message_prefix` - Text placed before the error; the emitted line has the
262 /// form `"{prefix}: {error}"`.
263 #[inline]
264 pub fn set_prepare_rollback_failure(
265 &mut self,
266 level: Option<log::Level>,
267 message_prefix: impl Into<String>,
268 ) {
269 self.prepare_rollback_failed_level = level;
270 self.prepare_rollback_failed_message = message_prefix.into();
271 }
272
273 /// Disables logging for prepare-rollback failures.
274 #[inline]
275 pub fn disable_prepare_rollback_failure(&mut self) {
276 self.prepare_rollback_failed_level = None;
277 }
278
279 /// Emits the condition-unmet log line if enabled.
280 ///
281 /// Does nothing when [`Self::unmet_condition_level`] is [`None`]. Otherwise
282 /// writes [`Self::unmet_condition_message`] through the `log` facade at the
283 /// configured level, subject to the crate-wide maximum log level (for example
284 /// set via [`log::set_max_level`] or compile-time filters).
285 #[inline]
286 pub fn log_unmet_condition(&self) {
287 let Some(level) = self.unmet_condition_level else {
288 return;
289 };
290 log::log!(level, "{}", self.unmet_condition_message);
291 }
292
293 /// Emits a diagnostic line when the prepare action fails.
294 ///
295 /// Does nothing when [`Self::prepare_failed_level`] is [`None`]. Otherwise
296 /// logs `"{prefix}: {err}"` at the configured level via the `log` facade,
297 /// where `prefix` is [`Self::prepare_failed_message`], subject to the
298 /// crate-wide maximum log level.
299 ///
300 /// # Type Parameters
301 ///
302 /// * `E` - Displayable error or message value appended after the prefix.
303 ///
304 /// # Parameters
305 ///
306 /// * `err` - Failure to record next to the configured prefix.
307 #[inline]
308 pub fn log_prepare_failed<E: fmt::Display>(&self, err: E) {
309 let Some(level) = self.prepare_failed_level else {
310 return;
311 };
312 log::log!(level, "{}: {}", self.prepare_failed_message, err);
313 }
314
315 /// Emits a diagnostic line when the prepare commit action fails.
316 ///
317 /// Does nothing when [`Self::prepare_commit_failed_level`] is [`None`].
318 /// Otherwise logs `"{prefix}: {err}"` at the configured level, where `prefix`
319 /// is [`Self::prepare_commit_failed_message`], subject to the crate-wide
320 /// maximum log level.
321 ///
322 /// # Type Parameters
323 ///
324 /// * `E` - Displayable error or message value appended after the prefix.
325 ///
326 /// # Parameters
327 ///
328 /// * `err` - Commit failure to record next to the configured prefix.
329 #[inline]
330 pub fn log_prepare_commit_failed<E: fmt::Display>(&self, err: E) {
331 let Some(level) = self.prepare_commit_failed_level else {
332 return;
333 };
334 log::log!(level, "{}: {}", self.prepare_commit_failed_message, err);
335 }
336
337 /// Emits a diagnostic line when the prepare rollback action fails.
338 ///
339 /// Does nothing when [`Self::prepare_rollback_failed_level`] is [`None`].
340 /// Otherwise logs `"{prefix}: {err}"` at the configured level, where `prefix`
341 /// is [`Self::prepare_rollback_failed_message`], subject to the crate-wide
342 /// maximum log level.
343 ///
344 /// # Type Parameters
345 ///
346 /// * `E` - Displayable error or message value appended after the prefix.
347 ///
348 /// # Parameters
349 ///
350 /// * `err` - Rollback failure to record next to the configured prefix.
351 #[inline]
352 pub fn log_prepare_rollback_failed<E: fmt::Display>(&self, err: E) {
353 let Some(level) = self.prepare_rollback_failed_level else {
354 return;
355 };
356 log::log!(level, "{}: {}", self.prepare_rollback_failed_message, err);
357 }
358}