Skip to main content

bitwarden_wasm_internal/
init.rs

1use std::num::NonZeroUsize;
2
3use bitwarden_logging::{FlightRecorderConfig, init_flight_recorder};
4use tracing::Level;
5use tracing_subscriber::{EnvFilter, layer::SubscriberExt as _, util::SubscriberInitExt as _};
6use tracing_web::MakeWebConsoleWriter;
7
8#[bitwarden_ffi::wasm_object]
9pub enum LogLevel {
10    Trace,
11    Debug,
12    Info,
13    Warn,
14    Error,
15}
16
17pub(crate) fn convert_level(level: LogLevel) -> Level {
18    match level {
19        LogLevel::Trace => Level::TRACE,
20        LogLevel::Debug => Level::DEBUG,
21        LogLevel::Info => Level::INFO,
22        LogLevel::Warn => Level::WARN,
23        LogLevel::Error => Level::ERROR,
24    }
25}
26
27/// Initialize the SDK. Must be called before using any other API.
28/// Only the first invocation has effect; subsequent calls are ignored.
29///
30/// - `log_level`: Minimum level for console output. Defaults to `Info`.
31/// - `flight_recorder_level`: Minimum level for the flight recorder. Defaults to `Info`.
32/// - `flight_recorder_buffer_size`: Ring-buffer capacity for the flight recorder. Defaults to 1000.
33///   Pass `0` to disable the flight recorder entirely.
34#[bitwarden_ffi::wasm_export]
35pub fn init_sdk(
36    log_level: Option<LogLevel>,
37    flight_recorder_level: Option<LogLevel>,
38    flight_recorder_buffer_size: Option<usize>,
39) {
40    console_error_panic_hook::set_once();
41
42    let log_level = convert_level(log_level.unwrap_or(LogLevel::Info));
43    let flight_recorder_level = convert_level(flight_recorder_level.unwrap_or(LogLevel::Info));
44    let flight_recorder_buffer_size =
45        NonZeroUsize::new(flight_recorder_buffer_size.unwrap_or(1000));
46
47    // If the flight recorder buffer size we get is zero, we disable the flight recorder entirely.
48    let flight_recorder_layer = flight_recorder_buffer_size.map(|size| {
49        let config = FlightRecorderConfig::new(size, flight_recorder_level);
50        init_flight_recorder(config)
51    });
52
53    let fmt = tracing_subscriber::fmt::layer()
54        .with_ansi(false) // only partially supported across browsers
55        .without_time() // time is not supported in wasm
56        .with_writer(MakeWebConsoleWriter::new()); // write events to the console
57
58    let filter = EnvFilter::builder()
59        .with_default_directive(log_level.into())
60        .from_env_lossy();
61
62    let perf_layer = cfg!(feature = "performance-tracing").then(|| {
63        tracing_web::performance_layer()
64            .with_details_from_fields(tracing_subscriber::fmt::format::Pretty::default())
65    });
66
67    let _ = tracing_subscriber::registry()
68        .with(flight_recorder_layer)
69        .with(fmt)
70        .with(filter)
71        .with(perf_layer)
72        .try_init();
73
74    #[cfg(feature = "dangerous-crypto-debug")]
75    tracing::warn!(
76        "Dangerous crypto debug features are enabled. THIS MUST NOT BE USED IN PRODUCTION BUILDS!!"
77    );
78}