From 7d490dc3bd0e1a06019f6a6ba8328fa3723dca9b Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Fri, 6 Dec 2024 16:27:05 -0800 Subject: [PATCH] feat: integrate dioxus-logger inline (#3302) * feat: integrate dioxus-logger inline * remove log/simple logger references * fix: add dioxus-data-id-0 to root elements to not emit errors internally * drop config.toml and use cargo.toml profiles instead * make clippy happy with the unit value lint * feat: better presentation for logging --- .cargo/config.toml | 14 --- Cargo.lock | 64 ++-------- Cargo.toml | 22 +++- example-projects/file-explorer/Cargo.toml | 4 - .../fullstack-hackernews/Cargo.toml | 3 - .../fullstack-hackernews/src/main.rs | 6 - examples/fullstack-auth/Cargo.toml | 3 +- examples/fullstack-auth/src/main.rs | 4 +- examples/fullstack-hello-world/Cargo.toml | 4 - examples/fullstack-hello-world/src/main.rs | 6 - examples/fullstack-streaming/Cargo.toml | 10 +- examples/fullstack-streaming/src/main.rs | 1 + examples/logging.rs | 43 +++++++ examples/pwa/Cargo.toml | 6 - examples/pwa/src/main.rs | 8 +- examples/tailwind/Cargo.toml | 10 +- examples/tailwind/src/main.rs | 19 +-- packages/cli/Cargo.toml | 2 +- packages/config-macro/src/lib.rs | 2 +- packages/core/Cargo.toml | 2 +- packages/desktop/src/webview.rs | 1 - packages/dioxus/Cargo.toml | 4 +- packages/dioxus/src/launch.rs | 3 + packages/dioxus/src/lib.rs | 4 + packages/fullstack/Cargo.toml | 3 +- packages/interpreter/src/js/core.js | 2 +- packages/interpreter/src/js/hash.txt | 2 +- packages/interpreter/src/ts/core.ts | 5 +- packages/logger/Cargo.toml | 25 ++++ packages/logger/src/lib.rs | 110 ++++++++++++++++++ packages/signals/Cargo.toml | 7 +- packages/signals/tests/memo.rs | 4 +- packages/signals/tests/subscribe.rs | 2 +- packages/web/Cargo.toml | 4 +- packages/web/src/cfg.rs | 10 -- packages/web/src/lib.rs | 5 - 36 files changed, 255 insertions(+), 169 deletions(-) delete mode 100644 .cargo/config.toml create mode 100644 examples/logging.rs create mode 100644 packages/logger/Cargo.toml create mode 100644 packages/logger/src/lib.rs diff --git a/.cargo/config.toml b/.cargo/config.toml deleted file mode 100644 index a61121287e..0000000000 --- a/.cargo/config.toml +++ /dev/null @@ -1,14 +0,0 @@ -[profile] - -[profile.dioxus-wasm] -inherits = "dev" -opt-level = 2 - -[profile.dioxus-server] -inherits = "dev" -opt-level = 2 - -[profile.dioxus-android] -inherits = "dev" -opt-level = 1 -debug = 0 diff --git a/Cargo.lock b/Cargo.lock index bc103f85fd..e479924662 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2413,16 +2413,6 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" -[[package]] -name = "colored" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" -dependencies = [ - "lazy_static", - "windows-sys 0.48.0", -] - [[package]] name = "com" version = "0.6.0" @@ -3400,6 +3390,7 @@ dependencies = [ "dioxus-hooks", "dioxus-html", "dioxus-liveview", + "dioxus-logger", "dioxus-mobile", "dioxus-router", "dioxus-signals", @@ -4005,12 +3996,13 @@ dependencies = [ [[package]] name = "dioxus-logger" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d7cbab0b5519060fe9e14b3c21e3f2329b8386cd905618f78c7b929cd00cf54" +version = "0.6.0-rc.0" dependencies = [ - "log", - "web-sys", + "console_error_panic_hook", + "dioxus-cli-config", + "tracing", + "tracing-subscriber", + "tracing-wasm", ] [[package]] @@ -4057,10 +4049,7 @@ dependencies = [ name = "dioxus-pwa-example" version = "0.1.0" dependencies = [ - "console_error_panic_hook", "dioxus", - "log", - "wasm-logger", ] [[package]] @@ -4154,7 +4143,6 @@ dependencies = [ "reqwest 0.12.9", "rustc-hash 1.1.0", "serde", - "simple_logger", "tokio", "tracing", "tracing-subscriber", @@ -4186,7 +4174,6 @@ version = "0.6.0-rc.0" dependencies = [ "async-trait", "ciborium", - "console_error_panic_hook", "dioxus", "dioxus-cli-config", "dioxus-core", @@ -4845,8 +4832,6 @@ name = "file-explorer" version = "0.1.0" dependencies = [ "dioxus", - "dioxus-logger", - "log", "open", ] @@ -5035,7 +5020,6 @@ dependencies = [ "execute", "http 1.1.0", "serde", - "simple_logger", "sqlx", "tokio", "tower 0.4.13", @@ -5058,9 +5042,6 @@ dependencies = [ "dioxus", "reqwest 0.12.9", "serde", - "tracing", - "tracing-subscriber", - "tracing-wasm", ] [[package]] @@ -5070,10 +5051,6 @@ dependencies = [ "dioxus", "reqwest 0.12.9", "serde", - "simple_logger", - "tracing", - "tracing-subscriber", - "tracing-wasm", ] [[package]] @@ -5095,11 +5072,7 @@ dependencies = [ "futures-util", "once_cell", "serde", - "simple_logger", "tokio", - "tracing", - "tracing-subscriber", - "tracing-wasm", ] [[package]] @@ -11346,18 +11319,6 @@ dependencies = [ "time", ] -[[package]] -name = "simple_logger" -version = "4.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e7e46c8c90251d47d08b28b8a419ffb4aede0f87c2eea95e17d1d5bacbf3ef1" -dependencies = [ - "colored", - "log", - "time", - "windows-sys 0.48.0", -] - [[package]] name = "siphasher" version = "0.3.11" @@ -15106,17 +15067,6 @@ dependencies = [ "leb128", ] -[[package]] -name = "wasm-logger" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "074649a66bb306c8f2068c9016395fa65d8e08d2affcbf95acf3c24c3ab19718" -dependencies = [ - "log", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "wasm-opt" version = "0.116.1" diff --git a/Cargo.toml b/Cargo.toml index 5ad86f2087..b137e2a20e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,6 +64,7 @@ members = [ "packages/const-serialize", "packages/const-serialize-macro", "packages/dx-wire-format", + "packages/logger", # Playwright tests "packages/playwright-tests/liveview", @@ -138,7 +139,7 @@ dioxus-devtools-types = { path = "packages/devtools-types", version = "0.6.0-rc. dioxus-fullstack = { path = "packages/fullstack", version = "0.6.0-rc.0" } dioxus_server_macro = { path = "packages/server-macro", version = "0.6.0-rc.0", default-features = false } dioxus-dx-wire-format = { path = "packages/dx-wire-format", version = "0.6.0-rc.0" } - +dioxus-logger = { path = "packages/logger", version = "0.6.0-rc.0" } const-serialize = { path = "packages/const-serialize", version = "0.6.0-rc.0" } const-serialize-macro = { path = "packages/const-serialize-macro", version = "0.6.0-rc.0" } generational-box = { path = "packages/generational-box", version = "0.6.0-rc.0" } @@ -157,10 +158,12 @@ clap = { version = "4.5.7" } askama_escape = "0.10.3" tracing = "0.1.37" tracing-futures = "0.2.5" +tracing-subscriber = { version = "0.3.18", default-features = false } toml = "0.8" tokio = "1.40" slab = "0.4.2" slotmap = { version = "1.0.7", features = ["serde"] } +futures = "0.3.30" futures-channel = "0.3.21" futures-util = { version = "0.3", default-features = false } rustc-hash = "1.1.0" @@ -207,7 +210,6 @@ fluent-uri = { version = "0.2.0", features = ["serde"] } internment = { version = "0.7.0" } proc-macro2-diagnostics = { version = "0.10", default-features = false } env_logger = "0.11.0" -tracing-subscriber = "0.3.17" chrono = { version = "0.4.34" } gloo = { version = "0.8.0" } gloo-utils = { version = "0.1.6" } @@ -222,6 +224,8 @@ cargo-config2 = "0.1.26" criterion = { version = "0.5" } walrus = "0.23.2" cargo_metadata = "0.18.1" +tracing-wasm = "0.2.1" +console_error_panic_hook = "0.1.7" # desktop wry = { version = "0.45.0", default-features = false } @@ -260,6 +264,16 @@ inherits = "dev" debug-assertions = false incremental = true +[profile.wasm-dev] +inherits = "dev" +opt-level = 1 + +[profile.server-dev] +inherits = "dev" + +[profile.android-dev] +inherits = "dev" + # This is a "virtual package" # It is not meant to be published, but is used so "cargo run --example XYZ" works properly [package] @@ -473,3 +487,7 @@ doc-scrape-examples = true [[example]] name = "eval" doc-scrape-examples = true + +[[example]] +name = "logging" +doc-scrape-examples = true diff --git a/example-projects/file-explorer/Cargo.toml b/example-projects/file-explorer/Cargo.toml index bd38076a3b..2d0e48f005 100644 --- a/example-projects/file-explorer/Cargo.toml +++ b/example-projects/file-explorer/Cargo.toml @@ -8,8 +8,4 @@ publish = false [dependencies] dioxus = { workspace = true, features = ["desktop"] } - -# Debug -log = "0.4.19" -dioxus-logger = "0.4.1" open = "5.1.2" diff --git a/example-projects/fullstack-hackernews/Cargo.toml b/example-projects/fullstack-hackernews/Cargo.toml index b44ad35462..c1ebc10f6e 100644 --- a/example-projects/fullstack-hackernews/Cargo.toml +++ b/example-projects/fullstack-hackernews/Cargo.toml @@ -12,9 +12,6 @@ dioxus = { workspace = true, features = ["fullstack", "router"] } chrono = { version = "0.4.38", features = ["serde"] } reqwest = { workspace= true, features = ["json"] } serde = { workspace = true, features = ["derive"] } -tracing-wasm = "0.2.1" -tracing = { workspace = true } -tracing-subscriber = "0.3.17" [features] default = [] diff --git a/example-projects/fullstack-hackernews/src/main.rs b/example-projects/fullstack-hackernews/src/main.rs index a645b0c608..9aabfc103a 100644 --- a/example-projects/fullstack-hackernews/src/main.rs +++ b/example-projects/fullstack-hackernews/src/main.rs @@ -11,12 +11,6 @@ use std::{ use svg_attributes::to; fn main() { - #[cfg(feature = "web")] - tracing_wasm::set_as_global_default(); - - #[cfg(feature = "server")] - tracing_subscriber::fmt::init(); - LaunchBuilder::new() .with_cfg(server_only! { dioxus::fullstack::ServeConfig::builder().enable_out_of_order_streaming() diff --git a/examples/fullstack-auth/Cargo.toml b/examples/fullstack-auth/Cargo.toml index cee550e5d2..561edd19b6 100644 --- a/examples/fullstack-auth/Cargo.toml +++ b/examples/fullstack-auth/Cargo.toml @@ -14,7 +14,6 @@ dioxus-fullstack = { workspace = true } axum = { workspace = true, optional = true } tokio = { workspace = true, features = ["full"], optional = true } tower-http = { workspace = true, features = ["auth"], optional = true } -simple_logger = { version = "4.2.0", optional = true } async-trait = { version = "0.1.71", optional = true } sqlx = { version = "0.7.0", features = [ "macros", @@ -44,5 +43,5 @@ optional = true [features] default = [] -server = ["axum", "tokio", "dioxus-fullstack/axum", "tower-http", "simple_logger", "async-trait", "sqlx", "axum_session", "axum_session_auth", "http", "tower"] +server = ["axum", "tokio", "dioxus-fullstack/axum", "tower-http", "async-trait", "sqlx", "axum_session", "axum_session_auth", "http", "tower"] web = ["dioxus-web"] diff --git a/examples/fullstack-auth/src/main.rs b/examples/fullstack-auth/src/main.rs index ec8097997b..799e97a454 100644 --- a/examples/fullstack-auth/src/main.rs +++ b/examples/fullstack-auth/src/main.rs @@ -15,6 +15,9 @@ use dioxus_fullstack::prelude::*; use serde::{Deserialize, Serialize}; fn main() { + // Set the logger ahead of time since we don't use `dioxus::launch` on the server + dioxus::logger::initialize_default(); + #[cfg(feature = "web")] // Hydrate the application on the client dioxus_web::launch::launch_cfg(app, dioxus_web::Config::new().hydrate(true)); @@ -27,7 +30,6 @@ fn main() { use axum_session::SessionStore; use axum_session_auth::AuthConfig; use axum_session_auth::SessionSqlitePool; - simple_logger::SimpleLogger::new().init().unwrap(); tokio::runtime::Runtime::new() .unwrap() .block_on(async move { diff --git a/examples/fullstack-hello-world/Cargo.toml b/examples/fullstack-hello-world/Cargo.toml index da75ac94b1..bee8fc71bb 100644 --- a/examples/fullstack-hello-world/Cargo.toml +++ b/examples/fullstack-hello-world/Cargo.toml @@ -9,10 +9,6 @@ publish = false [dependencies] dioxus = { workspace = true, features = ["fullstack"]} serde = "1.0.159" -simple_logger = "4.2.0" -tracing-wasm = "0.2.1" -tracing = { workspace = true } -tracing-subscriber = "0.3.17" reqwest = { workspace = true } [features] diff --git a/examples/fullstack-hello-world/src/main.rs b/examples/fullstack-hello-world/src/main.rs index 2a1217c408..1eaeb0563e 100644 --- a/examples/fullstack-hello-world/src/main.rs +++ b/examples/fullstack-hello-world/src/main.rs @@ -45,11 +45,5 @@ async fn get_server_data() -> Result { } fn main() { - #[cfg(feature = "web")] - tracing_wasm::set_as_global_default(); - - #[cfg(feature = "server")] - tracing_subscriber::fmt::init(); - dioxus::launch(app); } diff --git a/examples/fullstack-streaming/Cargo.toml b/examples/fullstack-streaming/Cargo.toml index 963e532714..1df8508651 100644 --- a/examples/fullstack-streaming/Cargo.toml +++ b/examples/fullstack-streaming/Cargo.toml @@ -8,15 +8,11 @@ publish = false [dependencies] dioxus = { workspace = true, features = ["fullstack"] } -serde = "1.0.159" -simple_logger = "4.2.0" -tracing-wasm = "0.2.1" -tracing.workspace = true -tracing-subscriber = "0.3.17" -futures = "0.3.30" +serde = { workspace = true } +futures = { workspace = true } tokio = { workspace = true, optional = true } futures-util.workspace = true -once_cell = "1.19.0" +once_cell = { workspace = true } [features] default = [] diff --git a/examples/fullstack-streaming/src/main.rs b/examples/fullstack-streaming/src/main.rs index f090a847a2..ac3bb7e9a7 100644 --- a/examples/fullstack-streaming/src/main.rs +++ b/examples/fullstack-streaming/src/main.rs @@ -29,6 +29,7 @@ pub async fn test_stream() -> Result { tokio::spawn(async move { loop { tokio::time::sleep(tokio::time::Duration::from_millis(500)).await; + dioxus::logger::tracing::info!("Sending new chunk!"); let _ = tx.unbounded_send(Ok("Hello, world!".to_string())); } }); diff --git a/examples/logging.rs b/examples/logging.rs new file mode 100644 index 0000000000..d6a4e3575d --- /dev/null +++ b/examples/logging.rs @@ -0,0 +1,43 @@ +//! Dioxus ships out-of-the-box with tracing hooks that integrate with the Dioxus-CLI. +//! +//! The built-in tracing-subscriber automatically sets up a wasm panic hook and wires up output +//! to be consumed in a machine-readable format when running under `dx`. +//! +//! You can disable the built-in tracing-subscriber or customize the log level yourself. +//! +//! By default: +//! - in `dev` mode, the default log output is `debug` +//! - in `release` mode, the default log output is `info` +//! +//! To use the dioxus logger in your app, simply call any of the tracing functions (info!(), warn!(), error!()) + +use dioxus::logger::tracing::{debug, error, info, warn}; +use dioxus::prelude::*; + +fn main() { + dioxus::launch(app); +} + +fn app() -> Element { + rsx! { + div { + h1 { "Logger demo" } + button { + onclick: move |_| warn!("Here's a warning!"), + "Warn!" + } + button { + onclick: move |_| error!("Here's an error!"), + "Error!" + } + button { + onclick: move |_| debug!("Here's a debug"), + "Debug!" + } + button { + onclick: move |_| info!("Here's an info!"), + "Info!" + } + } + } +} diff --git a/examples/pwa/Cargo.toml b/examples/pwa/Cargo.toml index bee204f20a..ccfd87cec1 100644 --- a/examples/pwa/Cargo.toml +++ b/examples/pwa/Cargo.toml @@ -9,9 +9,3 @@ publish = false [dependencies] dioxus = { workspace = true, features = ["web"] } - -log = "0.4.6" - -# WebAssembly Debug -wasm-logger = "0.2.0" -console_error_panic_hook = "0.1.7" diff --git a/examples/pwa/src/main.rs b/examples/pwa/src/main.rs index 581395e3d2..badc27f7af 100644 --- a/examples/pwa/src/main.rs +++ b/examples/pwa/src/main.rs @@ -1,10 +1,6 @@ use dioxus::prelude::*; fn main() { - // init debug tool for WebAssembly - wasm_logger::init(wasm_logger::Config::default()); - console_error_panic_hook::set_once(); - dioxus::launch(app); } @@ -13,9 +9,7 @@ fn app() -> Element { div { style: "text-align: center;", h1 { "🌗 Dioxus 🚀" } h3 { "Frontend that scales." } - p { - "Dioxus is a portable, performant, and ergonomic framework for building cross-platform user interfaces in Rust." - } + p { "Build web, desktop, and mobile apps with Dioxus" } } ) } diff --git a/examples/tailwind/Cargo.toml b/examples/tailwind/Cargo.toml index 6660b87397..783209f224 100644 --- a/examples/tailwind/Cargo.toml +++ b/examples/tailwind/Cargo.toml @@ -12,9 +12,9 @@ publish = false [dependencies] manganis = { workspace = true } +dioxus = { workspace = true } -[target.'cfg(not(target_arch = "wasm32"))'.dependencies] -dioxus = { path = "../../packages/dioxus", features = ["desktop"] } - -[target.'cfg(target_arch = "wasm32")'.dependencies] -dioxus = { path = "../../packages/dioxus", features = ["web"] } +[features] +default = ["desktop"] +web = ["dioxus/web"] +desktop = ["dioxus/desktop"] diff --git a/examples/tailwind/src/main.rs b/examples/tailwind/src/main.rs index d871acdd1d..b254268faf 100644 --- a/examples/tailwind/src/main.rs +++ b/examples/tailwind/src/main.rs @@ -1,14 +1,13 @@ -#![allow(non_snake_case)] - use dioxus::prelude::*; fn main() { dioxus::launch(app); } -pub fn app() -> Element { +fn app() -> Element { let grey_background = true; - rsx! ( + + rsx! { document::Link { rel: "stylesheet", href: asset!("/public/tailwind.css") } div { header { @@ -66,11 +65,12 @@ pub fn app() -> Element { } } } - ) + } } +#[component] pub fn StacksIcon() -> Element { - rsx!( + rsx! { svg { fill: "none", stroke: "currentColor", @@ -81,11 +81,12 @@ pub fn StacksIcon() -> Element { view_box: "0 0 24 24", path { d: "M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5" } } - ) + } } +#[component] pub fn RightArrowIcon() -> Element { - rsx!( + rsx! { svg { fill: "none", stroke: "currentColor", @@ -96,5 +97,5 @@ pub fn RightArrowIcon() -> Element { view_box: "0 0 24 24", path { d: "M5 12h14M12 5l7 7-7 7" } } - ) + } } diff --git a/packages/cli/Cargo.toml b/packages/cli/Cargo.toml index 5ca2d357d7..d8ad421ed7 100644 --- a/packages/cli/Cargo.toml +++ b/packages/cli/Cargo.toml @@ -91,7 +91,7 @@ ignore = "0.4.22" env_logger = { workspace = true } const-serialize = { workspace = true, features = ["serde"] } -tracing-subscriber = { version = "0.3.18", features = ["std", "env-filter", "json"] } +tracing-subscriber = { version = "0.3.18", features = ["std", "env-filter", "json", "registry", "fmt"] } console-subscriber = { version = "0.3.0", optional = true } tracing = { workspace = true } wasm-opt = { version = "0.116.1", optional = true } diff --git a/packages/config-macro/src/lib.rs b/packages/config-macro/src/lib.rs index 399e891d9c..d54cb84b6b 100644 --- a/packages/config-macro/src/lib.rs +++ b/packages/config-macro/src/lib.rs @@ -19,7 +19,7 @@ macro_rules! define_config_macro { } } else { quote! { - {} + () } } .into() diff --git a/packages/core/Cargo.toml b/packages/core/Cargo.toml index 9ba11ad466..9f282af5dc 100644 --- a/packages/core/Cargo.toml +++ b/packages/core/Cargo.toml @@ -31,7 +31,7 @@ dioxus-html = { workspace = true, features = ["serialize"] } tokio = { workspace = true, features = ["full"] } rand = { workspace = true } reqwest = { workspace = true } -tracing-subscriber = { workspace = true } +tracing-subscriber = { workspace = true, default-features = true } tracing-fluent-assertions = "0.3.0" pretty_assertions = "1.3.0" diff --git a/packages/desktop/src/webview.rs b/packages/desktop/src/webview.rs index 5d0ae71a78..f155bb9021 100644 --- a/packages/desktop/src/webview.rs +++ b/packages/desktop/src/webview.rs @@ -69,7 +69,6 @@ impl WebviewEdits { self.handle_html_event(event) } Err(err) => { - tracing::error!("cannot decippher format of user event"); tracing::error!( "Error parsing user_event: {:?}.Contents: {:?}, raw: {:#?}", err, diff --git a/packages/dioxus/Cargo.toml b/packages/dioxus/Cargo.toml index a55da263fa..6ae139e08f 100644 --- a/packages/dioxus/Cargo.toml +++ b/packages/dioxus/Cargo.toml @@ -27,6 +27,7 @@ dioxus-fullstack = { workspace = true, default-features = true, optional = true dioxus-liveview = { workspace = true, optional = true } dioxus-ssr = { workspace = true, optional = true } manganis = { workspace = true, features = ["dioxus"], optional = true } +dioxus-logger = { workspace = true, optional = true } serde = { version = "1.0.136", optional = true } dioxus-cli-config = { workspace = true, optional = true } @@ -35,7 +36,7 @@ dioxus-cli-config = { workspace = true, optional = true } dioxus-devtools = { workspace = true, optional = true } [features] -default = ["macro", "html", "devtools", "signals", "hooks", "launch", "mounted", "file_engine", "document", "asset"] +default = ["macro", "html", "signals", "hooks", "launch", "mounted", "file_engine", "document", "asset", "devtools", "logger"] minimal = ["macro", "html", "signals", "hooks", "launch"] signals = ["dep:dioxus-signals"] macro = ["dep:dioxus-core-macro"] @@ -46,6 +47,7 @@ mounted = ["dioxus-web?/mounted", "dioxus-html?/mounted"] file_engine = ["dioxus-web?/file_engine"] asset = ["dep:manganis"] document = ["dioxus-web?/document", "dep:dioxus-document", "dep:dioxus-history"] +logger = ["dep:dioxus-logger"] launch = ["dep:dioxus-config-macro"] router = ["dep:dioxus-router"] diff --git a/packages/dioxus/src/launch.rs b/packages/dioxus/src/launch.rs index aa22d3a0d8..7dd6acf7e0 100644 --- a/packages/dioxus/src/launch.rs +++ b/packages/dioxus/src/launch.rs @@ -155,6 +155,9 @@ impl LaunchBuilder { } fn launch_inner(self, app: fn() -> Element) { + #[cfg(feature = "logger")] + dioxus_logger::initialize_default(); + #[cfg(all(feature = "fullstack", any(feature = "desktop", feature = "mobile")))] { use dioxus_fullstack::prelude::server_fn::client::{get_server_url, set_server_url}; diff --git a/packages/dioxus/src/lib.rs b/packages/dioxus/src/lib.rs index 9c60ac6276..7481e7d308 100644 --- a/packages/dioxus/src/lib.rs +++ b/packages/dioxus/src/lib.rs @@ -65,6 +65,10 @@ pub use dioxus_html as html; #[cfg_attr(docsrs, doc(cfg(feature = "macro")))] pub use dioxus_core_macro as core_macro; +#[cfg(feature = "logger")] +#[cfg_attr(docsrs, doc(cfg(feature = "logger")))] +pub use dioxus_logger as logger; + pub mod prelude { #[cfg(feature = "document")] #[cfg_attr(docsrs, doc(cfg(feature = "document")))] diff --git a/packages/fullstack/Cargo.toml b/packages/fullstack/Cargo.toml index 212cb84c70..df3e4e2a3d 100644 --- a/packages/fullstack/Cargo.toml +++ b/packages/fullstack/Cargo.toml @@ -77,8 +77,7 @@ tokio = { workspace = true, features = ["rt", "sync", "rt-multi-thread"], option dioxus = { workspace = true, features = ["fullstack"] } [features] -default = ["devtools", "panic_hook", "document", "file_engine", "mounted"] -panic_hook = ["dioxus-web?/panic_hook"] +default = ["devtools", "document", "file_engine", "mounted"] devtools = ["dioxus-web?/devtools", "dep:dioxus-devtools"] mounted = ["dioxus-web?/mounted"] file_engine = ["dioxus-web?/file_engine"] diff --git a/packages/interpreter/src/js/core.js b/packages/interpreter/src/js/core.js index 518d94cedd..82a3e2be04 100644 --- a/packages/interpreter/src/js/core.js +++ b/packages/interpreter/src/js/core.js @@ -1 +1 @@ -function setAttributeInner(node,field,value,ns){if(ns==="style"){node.style.setProperty(field,value);return}if(ns){node.setAttributeNS(ns,field,value);return}switch(field){case"value":if(node.value!==value)node.value=value;break;case"initial_value":node.defaultValue=value;break;case"checked":node.checked=truthy(value);break;case"initial_checked":node.defaultChecked=truthy(value);break;case"selected":node.selected=truthy(value);break;case"initial_selected":node.defaultSelected=truthy(value);break;case"dangerous_inner_html":node.innerHTML=value;break;default:if(!truthy(value)&&isBoolAttr(field))node.removeAttribute(field);else node.setAttribute(field,value)}}var truthy=function(val){return val==="true"||val===!0},isBoolAttr=function(field){switch(field){case"allowfullscreen":case"allowpaymentrequest":case"async":case"autofocus":case"autoplay":case"checked":case"controls":case"default":case"defer":case"disabled":case"formnovalidate":case"hidden":case"ismap":case"itemscope":case"loop":case"multiple":case"muted":case"nomodule":case"novalidate":case"open":case"playsinline":case"readonly":case"required":case"reversed":case"selected":case"truespeed":case"webkitdirectory":return!0;default:return!1}};class BaseInterpreter{global;local;root;handler;resizeObserver;intersectionObserver;nodes;stack;templates;m;constructor(){}initialize(root,handler=null){this.global={},this.local={},this.root=root,this.nodes=[root],this.stack=[root],this.templates={},this.handler=handler}handleResizeEvent(entry){const target=entry.target;let event=new CustomEvent("resize",{bubbles:!1,detail:entry});target.dispatchEvent(event)}createResizeObserver(element){if(!this.resizeObserver)this.resizeObserver=new ResizeObserver((entries)=>{for(let entry of entries)this.handleResizeEvent(entry)});this.resizeObserver.observe(element)}removeResizeObserver(element){if(this.resizeObserver)this.resizeObserver.unobserve(element)}handleIntersectionEvent(entry){const target=entry.target;let event=new CustomEvent("visible",{bubbles:!1,detail:entry});target.dispatchEvent(event)}createIntersectionObserver(element){if(!this.intersectionObserver)this.intersectionObserver=new IntersectionObserver((entries)=>{for(let entry of entries)this.handleIntersectionEvent(entry)});this.intersectionObserver.observe(element)}removeIntersectionObserver(element){if(this.intersectionObserver)this.intersectionObserver.unobserve(element)}createListener(event_name,element,bubbles){if(event_name=="resize")this.createResizeObserver(element);else if(event_name=="visible")this.createIntersectionObserver(element);if(bubbles)if(this.global[event_name]===void 0)this.global[event_name]={active:1,callback:this.handler},this.root.addEventListener(event_name,this.handler);else this.global[event_name].active++;else{const id=element.getAttribute("data-dioxus-id");if(!this.local[id])this.local[id]={};element.addEventListener(event_name,this.handler)}}removeListener(element,event_name,bubbles){if(event_name=="resize")this.removeResizeObserver(element);else if(event_name=="visible")this.removeIntersectionObserver(element);else if(bubbles)this.removeBubblingListener(event_name);else this.removeNonBubblingListener(element,event_name)}removeBubblingListener(event_name){if(this.global[event_name].active--,this.global[event_name].active===0)this.root.removeEventListener(event_name,this.global[event_name].callback),delete this.global[event_name]}removeNonBubblingListener(element,event_name){const id=element.getAttribute("data-dioxus-id");if(delete this.local[id][event_name],Object.keys(this.local[id]).length===0)delete this.local[id];element.removeEventListener(event_name,this.handler)}removeAllNonBubblingListeners(element){const id=element.getAttribute("data-dioxus-id");delete this.local[id]}getNode(id){return this.nodes[id]}pushRoot(node){this.stack.push(node)}appendChildren(id,many){const root=this.nodes[id],els=this.stack.splice(this.stack.length-many);for(let k=0;k0;end--)node=node.nextSibling}return node}saveTemplate(nodes,tmpl_id){this.templates[tmpl_id]=nodes}hydrate_node(hydrateNode,ids){const split=hydrateNode.getAttribute("data-node-hydration").split(","),id=ids[parseInt(split[0])];if(this.nodes[id]=hydrateNode,split.length>1){hydrateNode.listening=split.length-1,hydrateNode.setAttribute("data-dioxus-id",id.toString());for(let j=1;j1){if(this.nodes[ids[parseInt(placeholderSplit[1])]]=currentNode,!treeWalker.nextNode())break;continue}const textNodeSplit=id.split("node-id");if(textNodeSplit.length>1){let next=currentNode.nextSibling;currentNode.remove();let commentAfterText,textNode;if(next.nodeType===Node.COMMENT_NODE){const newText=next.parentElement.insertBefore(document.createTextNode(""),next);commentAfterText=next,textNode=newText}else textNode=next,commentAfterText=textNode.nextSibling;treeWalker.currentNode=commentAfterText,this.nodes[ids[parseInt(textNodeSplit[1])]]=textNode;let exit=!treeWalker.nextNode();if(commentAfterText.remove(),exit)break;continue}}if(!treeWalker.nextNode())break}}}setAttributeInner(node,field,value,ns){setAttributeInner(node,field,value,ns)}}export{BaseInterpreter}; +function setAttributeInner(node,field,value,ns){if(ns==="style"){node.style.setProperty(field,value);return}if(ns){node.setAttributeNS(ns,field,value);return}switch(field){case"value":if(node.value!==value)node.value=value;break;case"initial_value":node.defaultValue=value;break;case"checked":node.checked=truthy(value);break;case"initial_checked":node.defaultChecked=truthy(value);break;case"selected":node.selected=truthy(value);break;case"initial_selected":node.defaultSelected=truthy(value);break;case"dangerous_inner_html":node.innerHTML=value;break;default:if(!truthy(value)&&isBoolAttr(field))node.removeAttribute(field);else node.setAttribute(field,value)}}var truthy=function(val){return val==="true"||val===!0},isBoolAttr=function(field){switch(field){case"allowfullscreen":case"allowpaymentrequest":case"async":case"autofocus":case"autoplay":case"checked":case"controls":case"default":case"defer":case"disabled":case"formnovalidate":case"hidden":case"ismap":case"itemscope":case"loop":case"multiple":case"muted":case"nomodule":case"novalidate":case"open":case"playsinline":case"readonly":case"required":case"reversed":case"selected":case"truespeed":case"webkitdirectory":return!0;default:return!1}};class BaseInterpreter{global;local;root;handler;resizeObserver;intersectionObserver;nodes;stack;templates;m;constructor(){}initialize(root,handler=null){this.global={},this.local={},this.root=root,this.nodes=[root],this.stack=[root],this.templates={},this.handler=handler,root.setAttribute("data-dioxus-id","0")}handleResizeEvent(entry){const target=entry.target;let event=new CustomEvent("resize",{bubbles:!1,detail:entry});target.dispatchEvent(event)}createResizeObserver(element){if(!this.resizeObserver)this.resizeObserver=new ResizeObserver((entries)=>{for(let entry of entries)this.handleResizeEvent(entry)});this.resizeObserver.observe(element)}removeResizeObserver(element){if(this.resizeObserver)this.resizeObserver.unobserve(element)}handleIntersectionEvent(entry){const target=entry.target;let event=new CustomEvent("visible",{bubbles:!1,detail:entry});target.dispatchEvent(event)}createIntersectionObserver(element){if(!this.intersectionObserver)this.intersectionObserver=new IntersectionObserver((entries)=>{for(let entry of entries)this.handleIntersectionEvent(entry)});this.intersectionObserver.observe(element)}removeIntersectionObserver(element){if(this.intersectionObserver)this.intersectionObserver.unobserve(element)}createListener(event_name,element,bubbles){if(event_name=="resize")this.createResizeObserver(element);else if(event_name=="visible")this.createIntersectionObserver(element);if(bubbles)if(this.global[event_name]===void 0)this.global[event_name]={active:1,callback:this.handler},this.root.addEventListener(event_name,this.handler);else this.global[event_name].active++;else{const id=element.getAttribute("data-dioxus-id");if(!this.local[id])this.local[id]={};element.addEventListener(event_name,this.handler)}}removeListener(element,event_name,bubbles){if(event_name=="resize")this.removeResizeObserver(element);else if(event_name=="visible")this.removeIntersectionObserver(element);else if(bubbles)this.removeBubblingListener(event_name);else this.removeNonBubblingListener(element,event_name)}removeBubblingListener(event_name){if(this.global[event_name].active--,this.global[event_name].active===0)this.root.removeEventListener(event_name,this.global[event_name].callback),delete this.global[event_name]}removeNonBubblingListener(element,event_name){const id=element.getAttribute("data-dioxus-id");if(delete this.local[id][event_name],Object.keys(this.local[id]).length===0)delete this.local[id];element.removeEventListener(event_name,this.handler)}removeAllNonBubblingListeners(element){const id=element.getAttribute("data-dioxus-id");delete this.local[id]}getNode(id){return this.nodes[id]}pushRoot(node){this.stack.push(node)}appendChildren(id,many){const root=this.nodes[id],els=this.stack.splice(this.stack.length-many);for(let k=0;k0;end--)node=node.nextSibling}return node}saveTemplate(nodes,tmpl_id){this.templates[tmpl_id]=nodes}hydrate_node(hydrateNode,ids){const split=hydrateNode.getAttribute("data-node-hydration").split(","),id=ids[parseInt(split[0])];if(this.nodes[id]=hydrateNode,split.length>1){hydrateNode.listening=split.length-1,hydrateNode.setAttribute("data-dioxus-id",id.toString());for(let j=1;j1){if(this.nodes[ids[parseInt(placeholderSplit[1])]]=currentNode,!treeWalker.nextNode())break;continue}const textNodeSplit=id.split("node-id");if(textNodeSplit.length>1){let next=currentNode.nextSibling;currentNode.remove();let commentAfterText,textNode;if(next.nodeType===Node.COMMENT_NODE){const newText=next.parentElement.insertBefore(document.createTextNode(""),next);commentAfterText=next,textNode=newText}else textNode=next,commentAfterText=textNode.nextSibling;treeWalker.currentNode=commentAfterText,this.nodes[ids[parseInt(textNodeSplit[1])]]=textNode;let exit=!treeWalker.nextNode();if(commentAfterText.remove(),exit)break;continue}}if(!treeWalker.nextNode())break}}}setAttributeInner(node,field,value,ns){setAttributeInner(node,field,value,ns)}}export{BaseInterpreter}; diff --git a/packages/interpreter/src/js/hash.txt b/packages/interpreter/src/js/hash.txt index 231738eb9c..e103a97f2f 100644 --- a/packages/interpreter/src/js/hash.txt +++ b/packages/interpreter/src/js/hash.txt @@ -1 +1 @@ -[6449103750905854967, 5429983586723452597, 13069001215487072322, 8716623267269178440, 5336385715226370016, 14456089431355876478, 7422899642446454418, 5052021921702764563, 12925655762638175824, 5638004933879392817] \ No newline at end of file +[6449103750905854967, 3846442265490457921, 13069001215487072322, 8716623267269178440, 5336385715226370016, 14456089431355876478, 7422899642446454418, 5052021921702764563, 12925655762638175824, 5638004933879392817] \ No newline at end of file diff --git a/packages/interpreter/src/ts/core.ts b/packages/interpreter/src/ts/core.ts index 98e424969d..d7609a9967 100644 --- a/packages/interpreter/src/ts/core.ts +++ b/packages/interpreter/src/ts/core.ts @@ -31,7 +31,7 @@ export class BaseInterpreter { // sledgehammer is generating this... m: any; - constructor() {} + constructor() { } initialize(root: HTMLElement, handler: EventListener | null = null) { this.global = {}; @@ -43,6 +43,9 @@ export class BaseInterpreter { this.templates = {}; this.handler = handler; + + // make sure to set the root element's ID so it still registers events + root.setAttribute('data-dioxus-id', "0"); } handleResizeEvent(entry: ResizeObserverEntry) { diff --git a/packages/logger/Cargo.toml b/packages/logger/Cargo.toml new file mode 100644 index 0000000000..b7e278d180 --- /dev/null +++ b/packages/logger/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "dioxus-logger" +version = { workspace = true } +edition = "2021" +description = "A logging utility to provide a standard interface whether you're targetting web desktop, fullstack, and more." +authors = ["DogeDark", "Jonathan Kelley"] +repository = "https://github.com/dioxuslabs/dioxus" +homepage = "https://github.com/dioxuslabs/dioxus" +readme = "README.md" +license = "MIT" +keywords = ["dioxus", "log", "logging"] +categories = ["development-tools::debugging"] + + +[dependencies] +dioxus-cli-config = { workspace = true } +tracing = { workspace = true } +tracing-subscriber = { workspace = true, features = ["registry", "std"] } + +[target.'cfg(target_arch = "wasm32")'.dependencies] +tracing-wasm = { workspace = true } +console_error_panic_hook = { workspace = true } + +[target.'cfg(not(target_arch = "wasm32"))'.dependencies] +tracing-subscriber = { workspace = true, features = [ "fmt" ] } diff --git a/packages/logger/src/lib.rs b/packages/logger/src/lib.rs new file mode 100644 index 0000000000..df78c8b567 --- /dev/null +++ b/packages/logger/src/lib.rs @@ -0,0 +1,110 @@ +use tracing::{ + subscriber::{set_global_default, SetGlobalDefaultError}, + Level, +}; + +pub use tracing; + +/// Attempt to initialize the subscriber if it doesn't already exist, with default settings. +/// +/// See [`crate::init`] for more info. +/// +/// If you're doing setup before your `dioxus::launch` function that requires lots of logging, then +/// it might be worth calling this earlier than launch. +/// +/// `dioxus::launch` calls this for you automatically and won't replace any facade you've already set. +/// +/// # Example +/// +/// ```rust,no_run +/// use dioxus::prelude::*; +/// use tracing::info; +/// +/// fn main() { +/// dioxus::logger::initialize_default(); +/// +/// info!("Doing some work before launching..."); +/// +/// dioxus::launch(App); +/// } +/// +/// #[component] +/// fn App() -> Element { +/// info!("App rendered"); +/// rsx! { +/// p { "hi" } +/// } +/// } +/// ``` +pub fn initialize_default() { + if tracing::dispatcher::has_been_set() { + return; + } + + if cfg!(debug_assertions) { + _ = init(Level::DEBUG); + } else { + _ = init(Level::INFO); + } +} + +/// Initialize `dioxus-logger` with a specified max filter. +/// +/// Generally it is best to initialize the logger before launching your Dioxus app. +/// Works on Web, Desktop, Fullstack, and Liveview. +/// +/// # Example +/// +/// ```rust,no_run +/// use dioxus::prelude::*; +/// use dioxus::logger::tracing::{Level, info}; +/// +/// fn main() { +/// dioxus::logger::init(Level::INFO).expect("logger failed to init"); +/// dioxus::launch(App); +/// } +/// +/// #[component] +/// fn App() -> Element { +/// info!("App rendered"); +/// rsx! { +/// p { "hi" } +/// } +/// } +/// ``` +pub fn init(level: Level) -> Result<(), SetGlobalDefaultError> { + /* + The default logger is currently set to log in fmt mode (meaning print directly to stdout) + + Eventually we want to change the output mode to be `json` when running under `dx`. This would let + use re-format the tracing spans to be better integrated with `dx` + */ + + #[cfg(target_arch = "wasm32")] + { + use tracing_subscriber::layer::SubscriberExt; + use tracing_subscriber::Registry; + + let layer_config = tracing_wasm::WASMLayerConfigBuilder::new() + .set_max_level(level) + .build(); + let layer = tracing_wasm::WASMLayer::new(layer_config); + let reg = Registry::default().with(layer); + + console_error_panic_hook::set_once(); + set_global_default(reg) + } + + #[cfg(not(target_arch = "wasm32"))] + { + let sub = tracing_subscriber::FmtSubscriber::builder().with_max_level(level); + + if !dioxus_cli_config::is_cli_enabled() { + return set_global_default(sub.finish()); + } + + // todo(jon): this is a small hack to clean up logging when running under the CLI + // eventually we want to emit everything as json and let the CLI manage the parsing + display + set_global_default(sub.without_time().with_target(false).finish()) + } +} diff --git a/packages/signals/Cargo.toml b/packages/signals/Cargo.toml index 1d952b71d4..b214e69e3a 100644 --- a/packages/signals/Cargo.toml +++ b/packages/signals/Cargo.toml @@ -16,9 +16,9 @@ rust-version = "1.79.0" dioxus-core = { workspace = true } generational-box = { workspace = true } tracing = { workspace = true } -serde = { version = "1", features = ["derive"], optional = true } +serde = { workspace = true, features = ["derive"], optional = true } parking_lot = "0.12.1" -once_cell = "1.18.0" +once_cell = { workspace = true } rustc-hash = { workspace = true } futures-channel = { workspace = true } futures-util = { workspace = true } @@ -27,8 +27,7 @@ warnings = { workspace = true } [dev-dependencies] dioxus = { workspace = true } tokio = { workspace = true, features = ["full"] } -tracing-subscriber = "0.3.17" -simple_logger = "4.2.0" +tracing-subscriber = { workspace = true, default-features = true } reqwest = { workspace = true } rand = { workspace = true } diff --git a/packages/signals/tests/memo.rs b/packages/signals/tests/memo.rs index 0aa065d227..04b4560850 100644 --- a/packages/signals/tests/memo.rs +++ b/packages/signals/tests/memo.rs @@ -11,7 +11,7 @@ use std::sync::atomic::{AtomicBool, Ordering}; #[test] fn memos_rerun() { - let _ = simple_logger::SimpleLogger::new().init(); + tracing_subscriber::fmt::init(); #[derive(Default)] struct RunCounter { @@ -53,8 +53,6 @@ fn memos_rerun() { #[test] fn memos_prevents_component_rerun() { - let _ = simple_logger::SimpleLogger::new().init(); - #[derive(Default)] struct RunCounter { component: usize, diff --git a/packages/signals/tests/subscribe.rs b/packages/signals/tests/subscribe.rs index 6e26b7188e..9066935571 100644 --- a/packages/signals/tests/subscribe.rs +++ b/packages/signals/tests/subscribe.rs @@ -11,7 +11,7 @@ use std::cell::RefCell; #[test] fn reading_subscribes() { - simple_logger::SimpleLogger::new().init().unwrap(); + tracing_subscriber::fmt::init(); #[derive(Default)] struct RunCounter { diff --git a/packages/web/Cargo.toml b/packages/web/Cargo.toml index 0a907c3d9d..c481b20e60 100644 --- a/packages/web/Cargo.toml +++ b/packages/web/Cargo.toml @@ -29,7 +29,6 @@ wasm-bindgen = { workspace = true } wasm-bindgen-futures = "0.4.29" tracing = { workspace = true } rustc-hash = { workspace = true } -console_error_panic_hook = { version = "0.1.7", optional = true } futures-util = { workspace = true, features = [ "std", "async-await", @@ -85,8 +84,7 @@ features = [ lazy-js-bundle = { workspace = true } [features] -default = ["panic_hook", "mounted", "file_engine", "devtools", "document"] -panic_hook = ["dep:console_error_panic_hook"] +default = ["mounted", "file_engine", "devtools", "document"] hydrate = ["web-sys/Comment", "ciborium", "dep:serde"] mounted = [ "web-sys/Element", diff --git a/packages/web/src/cfg.rs b/packages/web/src/cfg.rs index a7ed6f223a..c46ea36e11 100644 --- a/packages/web/src/cfg.rs +++ b/packages/web/src/cfg.rs @@ -13,7 +13,6 @@ use wasm_bindgen::JsCast as _; pub struct Config { pub(crate) hydrate: bool, pub(crate) root: ConfigRoot, - pub(crate) default_panic_hook: bool, } impl LaunchConfig for Config {} @@ -68,14 +67,6 @@ impl Config { self.root = ConfigRoot::RootNode(node); self } - - /// Set whether or not Dioxus should use the built-in panic hook or defer to your own. - /// - /// The panic hook is set to true normally so even the simplest apps have helpful error messages. - pub fn with_default_panic_hook(mut self, f: bool) -> Self { - self.default_panic_hook = f; - self - } } impl Default for Config { @@ -83,7 +74,6 @@ impl Default for Config { Self { hydrate: false, root: ConfigRoot::RootName("main".to_string()), - default_panic_hook: true, } } } diff --git a/packages/web/src/lib.rs b/packages/web/src/lib.rs index 991c7661cd..11071d8910 100644 --- a/packages/web/src/lib.rs +++ b/packages/web/src/lib.rs @@ -66,11 +66,6 @@ pub async fn run(mut virtual_dom: VirtualDom, web_config: Config) -> ! { #[cfg(feature = "document")] virtual_dom.in_runtime(document::init_document); - #[cfg(feature = "panic_hook")] - if web_config.default_panic_hook { - console_error_panic_hook::set_once(); - } - #[cfg(all(feature = "devtools", debug_assertions))] let mut hotreload_rx = devtools::init();