1 // Copyright 2022, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 //! Logger for vmbase.
16 //!
17 //! Internally uses the println! vmbase macro, which prints to crosvm's UART.
18 //! Note: may not work if the VM is in an inconsistent state. Exception handlers
19 //! should avoid using this logger and instead print with eprintln!.
20
21 use crate::console::println;
22 use core::sync::atomic::{AtomicBool, Ordering};
23 use log::{Log, Metadata, Record, SetLoggerError};
24
25 struct Logger {
26 is_enabled: AtomicBool,
27 }
28
29 static LOGGER: Logger = Logger::new();
30
31 impl Logger {
new() -> Self32 const fn new() -> Self {
33 Self { is_enabled: AtomicBool::new(true) }
34 }
35
swap_enabled(&self, enabled: bool) -> bool36 fn swap_enabled(&self, enabled: bool) -> bool {
37 self.is_enabled.swap(enabled, Ordering::Relaxed)
38 }
39 }
40
41 impl Log for Logger {
enabled(&self, _metadata: &Metadata) -> bool42 fn enabled(&self, _metadata: &Metadata) -> bool {
43 self.is_enabled.load(Ordering::Relaxed)
44 }
45
log(&self, record: &Record)46 fn log(&self, record: &Record) {
47 if self.enabled(record.metadata()) {
48 println!("[{}] {}", record.level(), record.args());
49 }
50 }
51
flush(&self)52 fn flush(&self) {}
53 }
54
55 /// An RAII implementation of a log suppressor. When the instance is dropped, logging is re-enabled.
56 pub struct SuppressGuard {
57 old_enabled: bool,
58 }
59
60 impl SuppressGuard {
new() -> Self61 fn new() -> Self {
62 Self { old_enabled: LOGGER.swap_enabled(false) }
63 }
64 }
65
66 impl Drop for SuppressGuard {
drop(&mut self)67 fn drop(&mut self) {
68 LOGGER.swap_enabled(self.old_enabled);
69 }
70 }
71
72 /// Initialize vmbase logger with a given max logging level.
init() -> Result<(), SetLoggerError>73 pub(crate) fn init() -> Result<(), SetLoggerError> {
74 log::set_logger(&LOGGER)?;
75 Ok(())
76 }
77
78 /// Suppress logging until the return value goes out of scope.
suppress() -> SuppressGuard79 pub fn suppress() -> SuppressGuard {
80 SuppressGuard::new()
81 }
82