diff --git a/Cargo.lock b/Cargo.lock index d36fda4dc..0e553853b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -724,6 +724,19 @@ dependencies = [ "wasm-bindgen-futures", ] +[[package]] +name = "bitwarden-logging" +version = "1.0.0" +dependencies = [ + "js-sys", + "once_cell", + "tokio", + "tracing", + "tracing_dynamic", + "tsify", + "wasm-bindgen", +] + [[package]] name = "bitwarden-pm" version = "1.0.0" @@ -953,15 +966,17 @@ dependencies = [ "bitwarden-crypto", "bitwarden-error", "bitwarden-ipc", + "bitwarden-logging", "bitwarden-pm", "bitwarden-ssh", "bitwarden-state", "bitwarden-threading", "bitwarden-vault", "console_error_panic_hook", - "console_log", - "log", "serde", + "tracing", + "tracing-subscriber", + "tracing-web", "tsify", "wasm-bindgen", "wasm-bindgen-futures", @@ -1371,17 +1386,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "console_log" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be8aed40e4edbf4d3b4431ab260b63fdc40f5780a4766824329ea0f1eefe3c0f" -dependencies = [ - "log", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "const-oid" version = "0.9.6" @@ -3020,6 +3024,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + [[package]] name = "memchr" version = "2.7.5" @@ -5090,9 +5103,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tracing-core" version = "0.1.34" @@ -5113,14 +5138,55 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + [[package]] name = "tracing-subscriber" -version = "0.3.19" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex-automata", "sharded-slab", + "smallvec", "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "tracing-web" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e6a141feebd51f8d91ebfd785af50fca223c570b86852166caa3b141defe7c" +dependencies = [ + "js-sys", + "tracing-core", + "tracing-subscriber", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "tracing_dynamic" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "636b306d6eee126f663f6e39d049378976d6cdcc63ea99253648385ee7247ac2" +dependencies = [ + "tracing", "tracing-core", ] diff --git a/Cargo.toml b/Cargo.toml index 83a055ea6..61ce09661 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,6 +35,7 @@ bitwarden-exporters = { path = "crates/bitwarden-exporters", version = "=1.0.0" bitwarden-fido = { path = "crates/bitwarden-fido", version = "=1.0.0" } bitwarden-generators = { path = "crates/bitwarden-generators", version = "=1.0.0" } bitwarden-ipc = { path = "crates/bitwarden-ipc", version = "=1.0.0" } +bitwarden-logging = { path = "crates/bitwarden-logging", version = "=1.0.0" } bitwarden-pm = { path = "crates/bitwarden-pm", version = "=1.0.0" } bitwarden-send = { path = "crates/bitwarden-send", version = "=1.0.0" } bitwarden-sm = { path = "bitwarden_license/bitwarden-sm", version = "=1.0.0" } @@ -76,6 +77,12 @@ serde-wasm-bindgen = ">=0.6.0, <0.7" syn = ">=2.0.87, <3" thiserror = ">=1.0.40, <3" tokio = { version = "1.36.0", features = ["macros"] } +tracing = { version = "0.1.41" } +tracing-subscriber = { version = "0.3.20", features = [ + "fmt", + "env-filter", + "tracing-log", +] } tsify = { version = ">=0.5.5, <0.6", features = [ "js", ], default-features = false } diff --git a/crates/bitwarden-logging/Cargo.toml b/crates/bitwarden-logging/Cargo.toml new file mode 100644 index 000000000..b4cab3a05 --- /dev/null +++ b/crates/bitwarden-logging/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "bitwarden-logging" +description = """ +Internal crate for the bitwarden crate. Do not use. +""" + +version.workspace = true +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +readme.workspace = true +homepage.workspace = true +repository.workspace = true +license-file.workspace = true +keywords.workspace = true + +[features] +wasm = ["dep:js-sys", "dep:tsify", "dep:wasm-bindgen"] + +[dependencies] +js-sys = { workspace = true, optional = true } +tokio = { workspace = true } +tracing = { workspace = true } +tracing_dynamic = "0.3.1" +once_cell = "1.21.3" +tsify = { workspace = true, optional = true } +wasm-bindgen = { workspace = true, optional = true } + +[lints] +workspace = true diff --git a/crates/bitwarden-logging/README.md b/crates/bitwarden-logging/README.md new file mode 100644 index 000000000..94c5f361f --- /dev/null +++ b/crates/bitwarden-logging/README.md @@ -0,0 +1 @@ +# Bitwarden Logging diff --git a/crates/bitwarden-logging/src/lib.rs b/crates/bitwarden-logging/src/lib.rs new file mode 100644 index 000000000..8449dd181 --- /dev/null +++ b/crates/bitwarden-logging/src/lib.rs @@ -0,0 +1,5 @@ +#![doc = include_str!("../README.md")] + +#[cfg(feature = "wasm")] +#[allow(missing_docs)] +pub mod wasm; diff --git a/crates/bitwarden-logging/src/wasm/event.rs b/crates/bitwarden-logging/src/wasm/event.rs new file mode 100644 index 000000000..676e23c9b --- /dev/null +++ b/crates/bitwarden-logging/src/wasm/event.rs @@ -0,0 +1,33 @@ +use tracing_dynamic::EventFactory; +use wasm_bindgen::prelude::*; + +use crate::wasm::level::TracingLevel; + +#[wasm_bindgen] +pub struct EventDefinition { + factory: EventFactory<'static>, +} + +#[wasm_bindgen] +impl EventDefinition { + #[wasm_bindgen(constructor)] + pub fn new(name: String, target: String, level: TracingLevel, fields: Vec) -> Self { + let fields_slice: &[&str] = &fields.iter().map(String::as_str).collect::>(); + Self { + factory: EventFactory::new( + &name, + &target, + level.into(), + None, + None, + None, + fields_slice, + ), + } + } + + // TODO: Add fields + pub fn record(&self) { + self.factory.create().build(); + } +} diff --git a/crates/bitwarden-logging/src/wasm/level.rs b/crates/bitwarden-logging/src/wasm/level.rs new file mode 100644 index 000000000..338aa5a92 --- /dev/null +++ b/crates/bitwarden-logging/src/wasm/level.rs @@ -0,0 +1,38 @@ +use tracing::Level; +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +pub enum TracingLevel { + /// The "trace" level. + /// + /// Designates very low priority, often extremely verbose, information. + Trace, + /// The "debug" level. + /// + /// Designates lower priority information. + Debug, + /// The "info" level. + /// + /// Designates useful information. + Info, + /// The "warn" level. + /// + /// Designates hazardous situations. + Warn, + /// The "error" level. + /// + /// Designates very serious errors. + Error, +} + +impl From for Level { + fn from(level: TracingLevel) -> Self { + match level { + TracingLevel::Trace => Level::TRACE, + TracingLevel::Debug => Level::DEBUG, + TracingLevel::Info => Level::INFO, + TracingLevel::Warn => Level::WARN, + TracingLevel::Error => Level::ERROR, + } + } +} diff --git a/crates/bitwarden-logging/src/wasm/mod.rs b/crates/bitwarden-logging/src/wasm/mod.rs new file mode 100644 index 000000000..edc6c2834 --- /dev/null +++ b/crates/bitwarden-logging/src/wasm/mod.rs @@ -0,0 +1,7 @@ +mod event; +mod level; +mod span; + +pub use event::*; +pub use level::*; +pub use span::*; diff --git a/crates/bitwarden-logging/src/wasm/span.rs b/crates/bitwarden-logging/src/wasm/span.rs new file mode 100644 index 000000000..13e9af4d6 --- /dev/null +++ b/crates/bitwarden-logging/src/wasm/span.rs @@ -0,0 +1,40 @@ +use tracing; +use tracing_dynamic::SpanFactory; +use wasm_bindgen::prelude::*; + +use crate::wasm::level::TracingLevel; + +#[wasm_bindgen] +pub struct SpanDefinition { + factory: SpanFactory<'static>, +} + +#[wasm_bindgen] +impl SpanDefinition { + #[wasm_bindgen(constructor)] + pub fn new(name: String, target: String, level: TracingLevel, fields: Vec) -> Self { + let fields_slice: &[&str] = &fields.iter().map(String::as_str).collect::>(); + Self { + factory: SpanFactory::new(&name, &target, level.into(), None, None, None, fields_slice), + } + } + + // TODO: Add fields + pub fn enter(&self) -> Span { + let span = self.factory.create().build(); + Span::new(span) + } +} + +#[wasm_bindgen] +pub struct Span { + _span: tracing::span::EnteredSpan, +} + +impl Span { + fn new(span: tracing::Span) -> Self { + Self { + _span: span.entered(), + } + } +} diff --git a/crates/bitwarden-wasm-internal/Cargo.toml b/crates/bitwarden-wasm-internal/Cargo.toml index ed5576fe8..84053366e 100644 --- a/crates/bitwarden-wasm-internal/Cargo.toml +++ b/crates/bitwarden-wasm-internal/Cargo.toml @@ -13,7 +13,10 @@ license-file.workspace = true keywords.workspace = true [features] -bitwarden-license = ["bitwarden-pm/bitwarden-license", "dep:bitwarden-commercial-vault"] +bitwarden-license = [ + "bitwarden-pm/bitwarden-license", + "dep:bitwarden-commercial-vault", +] [lib] crate-type = ["cdylib"] @@ -27,15 +30,17 @@ bitwarden-core = { workspace = true, features = ["wasm", "internal"] } bitwarden-crypto = { workspace = true, features = ["wasm"] } bitwarden-error = { workspace = true } bitwarden-ipc = { workspace = true, features = ["wasm"] } +bitwarden-logging = { workspace = true, features = ["wasm"] } bitwarden-pm = { workspace = true, features = ["wasm"] } bitwarden-ssh = { workspace = true, features = ["wasm"] } bitwarden-state = { workspace = true, features = ["wasm"] } bitwarden-threading = { workspace = true } bitwarden-vault = { workspace = true, features = ["wasm"] } console_error_panic_hook = "0.1.7" -console_log = { version = "1.0.0", features = ["color"] } -log = "0.4.20" serde = { workspace = true } +tracing = { workspace = true } +tracing-subscriber = { workspace = true } +tracing-web = { version = "0.1.3" } tsify = { workspace = true } # When upgrading wasm-bindgen, make sure to update the version in the workflows! wasm-bindgen = { version = "=0.2.105", features = ["serde-serialize"] } diff --git a/crates/bitwarden-wasm-internal/src/init.rs b/crates/bitwarden-wasm-internal/src/init.rs index 0fd20f069..283e68856 100644 --- a/crates/bitwarden-wasm-internal/src/init.rs +++ b/crates/bitwarden-wasm-internal/src/init.rs @@ -1,4 +1,8 @@ -use log::{Level, set_max_level}; +use tracing::Level; +use tracing_subscriber::{ + EnvFilter, fmt::format::Pretty, layer::SubscriberExt as _, util::SubscriberInitExt as _, +}; +use tracing_web::{MakeWebConsoleWriter, performance_layer}; use wasm_bindgen::prelude::*; #[wasm_bindgen] @@ -12,26 +16,35 @@ pub enum LogLevel { fn convert_level(level: LogLevel) -> Level { match level { - LogLevel::Trace => Level::Trace, - LogLevel::Debug => Level::Debug, - LogLevel::Info => Level::Info, - LogLevel::Warn => Level::Warn, - LogLevel::Error => Level::Error, + LogLevel::Trace => Level::TRACE, + LogLevel::Debug => Level::DEBUG, + LogLevel::Info => Level::INFO, + LogLevel::Warn => Level::WARN, + LogLevel::Error => Level::ERROR, } } -#[wasm_bindgen] -pub fn set_log_level(level: LogLevel) { - let log_level = convert_level(level); - set_max_level(log_level.to_level_filter()); -} - #[allow(missing_docs)] #[wasm_bindgen] pub fn init_sdk(log_level: Option) { console_error_panic_hook::set_once(); + let log_level = convert_level(log_level.unwrap_or(LogLevel::Info)); - if let Err(_e) = console_log::init_with_level(log_level) { - set_max_level(log_level.to_level_filter()) - } + + let filter = EnvFilter::builder() + .with_default_directive(log_level.into()) + .from_env_lossy(); + + let fmt = tracing_subscriber::fmt::layer() + .with_ansi(false) // only partially supported across browsers + .without_time() // time is not supported in wasm + .with_writer(MakeWebConsoleWriter::new()); // write events to the console + + let perf_layer = performance_layer().with_details_from_fields(Pretty::default()); + + tracing_subscriber::registry() + .with(perf_layer) + .with(filter) + .with(fmt) + .init(); } diff --git a/crates/bitwarden-wasm-internal/src/lib.rs b/crates/bitwarden-wasm-internal/src/lib.rs index 253ec8ffd..16e56e351 100644 --- a/crates/bitwarden-wasm-internal/src/lib.rs +++ b/crates/bitwarden-wasm-internal/src/lib.rs @@ -8,5 +8,6 @@ mod pure_crypto; mod ssh; pub use bitwarden_ipc::wasm::*; +pub use bitwarden_logging::wasm::*; pub use client::BitwardenClient; pub use init::init_sdk;