proxy_wasm_experimental/
logger.rs

1// Copyright 2020 Google LLC
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
15use crate::hostcalls;
16use crate::types::LogLevel;
17use std::panic;
18use std::sync::atomic::{AtomicBool, Ordering};
19
20struct Logger;
21
22static LOGGER: Logger = Logger;
23static INITIALIZED: AtomicBool = AtomicBool::new(false);
24
25pub(crate) fn set_log_level(level: LogLevel) {
26    if !INITIALIZED.load(Ordering::Relaxed) {
27        log::set_logger(&LOGGER).unwrap();
28        panic::set_hook(Box::new(|panic_info| {
29            hostcalls::log(LogLevel::Critical, &panic_info.to_string()).unwrap_or(());
30        }));
31        INITIALIZED.store(true, Ordering::Relaxed);
32    }
33    LOGGER.set_log_level(level);
34}
35
36impl Logger {
37    pub fn set_log_level(&self, level: LogLevel) {
38        let filter = match level {
39            LogLevel::Trace => log::LevelFilter::Trace,
40            LogLevel::Debug => log::LevelFilter::Debug,
41            LogLevel::Info => log::LevelFilter::Info,
42            LogLevel::Warn => log::LevelFilter::Warn,
43            LogLevel::Error => log::LevelFilter::Error,
44            LogLevel::Critical => log::LevelFilter::Off,
45        };
46        log::set_max_level(filter);
47    }
48}
49
50impl log::Log for Logger {
51    fn enabled(&self, metadata: &log::Metadata) -> bool {
52        metadata.level() <= log::max_level()
53    }
54
55    fn log(&self, record: &log::Record) {
56        if !self.enabled(record.metadata()) {
57            return;
58        }
59        let level = match record.level() {
60            log::Level::Trace => LogLevel::Trace,
61            log::Level::Debug => LogLevel::Debug,
62            log::Level::Info => LogLevel::Info,
63            log::Level::Warn => LogLevel::Warn,
64            log::Level::Error => LogLevel::Error,
65        };
66        let message = record.args().to_string();
67        hostcalls::log(level, &message).unwrap_or(());
68    }
69
70    fn flush(&self) {}
71}