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