1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
//! # `wasm-bindgen` console logger
//!
//! This small utility crate integrates the [`log`](https://crates.io/crates/log)
//! crate with the JavaScript console logging functions with the help of
//! [`wasm-bindgen`](https://crates.io/crates/wasm-bindgen).

//! ## Example
//!
//! ```
//! use log::{error, info, warn};
//! use wasm_bindgen::prelude::*;
//! use wasm_bindgen_console_logger::DEFAULT_LOGGER;
//!
//! #[wasm_bindgen]
//! pub fn start() {
//!     log::set_logger(&DEFAULT_LOGGER).unwrap();
//!     log::set_max_level(log::LevelFilter::Info);
//!
//!     error!("Error message");
//!     warn!("Warning message");
//!     info!("Informational message");
//! }
//! ```

use log::{Level, Log, Metadata, Record};
use wasm_bindgen::prelude::*;

pub const DEFAULT_LOGGER: ConsoleLogger = ConsoleLogger {
    formatter: &format_message,
    log_level: Level::Trace,
};

fn format_message(record: &Record) -> String {
    if record.level() >= Level::Debug {
        format!("{}: {}", record.level(), record.args())
    } else {
        format!("{}", record.args())
    }
}

/// Formats a `log::Record` as a `String`
pub type RecordFormatter = Fn(&Record) -> String + Send + Sync;

/// Logs messages to the Web browser's console
///
/// Error and warning messages will be logged with `console.error()` and `console.warn()`, respectively.
/// All other messages will be logged with `console.log()`.
pub struct ConsoleLogger {
    formatter: &'static RecordFormatter,
    log_level: Level,
}

impl ConsoleLogger {
    /// Constructs a new `ConsoleLogger`
    ///
    /// The given function will be used to format the logged messages.
    pub fn new(formatter: &'static RecordFormatter, log_level: Level) -> Self {
        ConsoleLogger { formatter, log_level }
    }

    /// Constructs a `ConsoleLogger` with the given maximum log level
    /// 
    /// A default log formatter will be used.
    pub fn with_level(level: Level) -> Self {
        ConsoleLogger::new(&format_message, level)
    }
}

impl Default for ConsoleLogger {
    fn default() -> Self {
        DEFAULT_LOGGER
    }
}

impl Log for ConsoleLogger {
    fn enabled(&self, metadata: &Metadata) -> bool {
        metadata.level() <= self.log_level
    }

    fn log(&self, record: &Record) {
        if self.enabled(record.metadata()) {
            let msg = (self.formatter)(record);
            match record.level() {
                Level::Error => error(&msg),
                Level::Warn => warn(&msg),
                _ => log(&msg),
            }
        }
    }

    fn flush(&self) {}
}

// Bindings to console functions
#[wasm_bindgen]
extern "C" {
    #[wasm_bindgen(js_namespace=console)]
    fn log(text: &str);

    #[wasm_bindgen(js_namespace=console)]
    fn warn(text: &str);

    #[wasm_bindgen(js_namespace=console)]
    fn error(text: &str);
}