diff --git a/any_spawner/Cargo.toml b/any_spawner/Cargo.toml index 081f2073b..b18e25d09 100644 --- a/any_spawner/Cargo.toml +++ b/any_spawner/Cargo.toml @@ -28,3 +28,6 @@ futures-executor = ["futures/thread-pool", "futures/executor"] [package.metadata.docs.rs] all-features = true rustdoc-args = ["--cfg", "docsrs"] + +[package.metadata.cargo-all-features] +denylist = ["tracing"] diff --git a/integrations/actix/Cargo.toml b/integrations/actix/Cargo.toml index 2bf71728a..824e73d87 100644 --- a/integrations/actix/Cargo.toml +++ b/integrations/actix/Cargo.toml @@ -22,7 +22,7 @@ leptos_router = { workspace = true, features = ["ssr"] } server_fn = { workspace = true, features = ["actix"] } serde_json = "1.0" parking_lot = "0.12.3" -tracing = "0.1.40" +tracing = { version = "0.1", optional = true } tokio = { version = "1.39", features = ["rt", "fs"] } send_wrapper = "0.6.0" @@ -31,3 +31,7 @@ rustdoc-args = ["--generate-link-to-definition"] [features] islands-router = [] +tracing = ["dep:tracing"] + +[package.metadata.cargo-all-features] +denylist = ["tracing"] diff --git a/integrations/actix/src/lib.rs b/integrations/actix/src/lib.rs index ae481796a..f30687af4 100644 --- a/integrations/actix/src/lib.rs +++ b/integrations/actix/src/lib.rs @@ -207,7 +207,10 @@ impl ExtendResponse for ActixResponse { /// without actually setting the status code. This means that the client will not follow the /// redirect, and can therefore return the value of the server function and then handle /// the redirect with client-side routing. -#[tracing::instrument(level = "trace", fields(error), skip_all)] +#[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) +)] pub fn redirect(path: &str) { if let (Some(req), Some(res)) = (use_context::(), use_context::()) @@ -239,10 +242,14 @@ pub fn redirect(path: &str) { ); } } else { - tracing::warn!( - "Couldn't retrieve either Parts or ResponseOptions while trying \ - to redirect()." - ); + let msg = "Couldn't retrieve either Parts or ResponseOptions while \ + trying to redirect()."; + + #[cfg(feature = "tracing")] + tracing::warn!("{}", &msg); + + #[cfg(not(feature = "tracing"))] + eprintln!("{}", &msg); } } @@ -282,7 +289,10 @@ pub fn redirect(path: &str) { /// This function always provides context values including the following types: /// - [ResponseOptions] /// - [HttpRequest](actix_web::HttpRequest) -#[tracing::instrument(level = "trace", fields(error), skip_all)] +#[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) +)] pub fn handle_server_fns() -> Route { handle_server_fns_with_context(|| {}) } @@ -306,7 +316,10 @@ pub fn handle_server_fns() -> Route { /// This function always provides context values including the following types: /// - [ResponseOptions] /// - [HttpRequest](actix_web::HttpRequest) -#[tracing::instrument(level = "trace", fields(error), skip_all)] +#[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) +)] pub fn handle_server_fns_with_context( additional_context: impl Fn() + 'static + Clone + Send, ) -> Route { @@ -438,7 +451,10 @@ pub fn handle_server_fns_with_context( /// - [HttpRequest](actix_web::HttpRequest) /// - [MetaContext](leptos_meta::MetaContext) /// - [RouterIntegrationContext](leptos_router::RouterIntegrationContext) -#[tracing::instrument(level = "trace", fields(error), skip_all)] +#[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) +)] pub fn render_app_to_stream( app_fn: impl Fn() -> IV + Clone + Send + 'static, method: Method, @@ -505,7 +521,10 @@ where /// - [HttpRequest](actix_web::HttpRequest) /// - [MetaContext](leptos_meta::MetaContext) /// - [RouterIntegrationContext](leptos_router::RouterIntegrationContext) -#[tracing::instrument(level = "trace", fields(error), skip_all)] +#[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) +)] pub fn render_app_to_stream_in_order( app_fn: impl Fn() -> IV + Clone + Send + 'static, method: Method, @@ -567,7 +586,10 @@ where /// - [HttpRequest](actix_web::HttpRequest) /// - [MetaContext](leptos_meta::MetaContext) /// - [RouterIntegrationContext](leptos_router::RouterIntegrationContext) -#[tracing::instrument(level = "trace", fields(error), skip_all)] +#[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) +)] pub fn render_app_async( app_fn: impl Fn() -> IV + Clone + Send + 'static, method: Method, @@ -590,7 +612,10 @@ where /// - [HttpRequest](actix_web::HttpRequest) /// - [MetaContext](leptos_meta::MetaContext) /// - [RouterIntegrationContext](leptos_router::RouterIntegrationContext) -#[tracing::instrument(level = "trace", fields(error), skip_all)] +#[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) +)] pub fn render_app_to_stream_with_context( additional_context: impl Fn() + 'static + Clone + Send, app_fn: impl Fn() -> IV + Clone + Send + 'static, @@ -624,7 +649,10 @@ where /// - [HttpRequest](actix_web::HttpRequest) /// - [MetaContext](leptos_meta::MetaContext) /// - [RouterIntegrationContext](leptos_router::RouterIntegrationContext) -#[tracing::instrument(level = "trace", fields(error), skip_all)] +#[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) +)] pub fn render_app_to_stream_with_context_and_replace_blocks( additional_context: impl Fn() + 'static + Clone + Send, app_fn: impl Fn() -> IV + Clone + Send + 'static, @@ -655,7 +683,10 @@ where /// - [HttpRequest](actix_web::HttpRequest) /// - [MetaContext](leptos_meta::MetaContext) /// - [RouterIntegrationContext](leptos_router::RouterIntegrationContext) -#[tracing::instrument(level = "trace", fields(error), skip_all)] +#[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) +)] pub fn render_app_to_stream_in_order_with_context( additional_context: impl Fn() + 'static + Clone + Send, app_fn: impl Fn() -> IV + Clone + Send + 'static, @@ -685,7 +716,10 @@ where /// - [HttpRequest](actix_web::HttpRequest) /// - [MetaContext](leptos_meta::MetaContext) /// - [RouterIntegrationContext](leptos_router::RouterIntegrationContext) -#[tracing::instrument(level = "trace", fields(error), skip_all)] +#[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) +)] pub fn render_app_async_with_context( additional_context: impl Fn() + 'static + Clone + Send, app_fn: impl Fn() -> IV + Clone + Send + 'static, @@ -704,7 +738,10 @@ where }) } -#[tracing::instrument(level = "trace", fields(error), skip_all)] +#[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) +)] fn provide_contexts( req: Request, meta_context: &ServerMetaContext, @@ -1205,7 +1242,10 @@ where InitError = (), >, { - #[tracing::instrument(level = "trace", fields(error), skip_all)] + #[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) + )] fn leptos_routes( self, paths: Vec, @@ -1217,7 +1257,10 @@ where self.leptos_routes_with_context(paths, || {}, app_fn) } - #[tracing::instrument(level = "trace", fields(error), skip_all)] + #[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) + )] fn leptos_routes_with_context( self, paths: Vec, @@ -1304,7 +1347,10 @@ where /// The default implementation of `LeptosRoutes` which takes in a list of paths, and dispatches GET requests /// to those paths to Leptos's renderer. impl LeptosRoutes for &mut ServiceConfig { - #[tracing::instrument(level = "trace", fields(error), skip_all)] + #[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) + )] fn leptos_routes( self, paths: Vec, @@ -1316,7 +1362,10 @@ impl LeptosRoutes for &mut ServiceConfig { self.leptos_routes_with_context(paths, || {}, app_fn) } - #[tracing::instrument(level = "trace", fields(error), skip_all)] + #[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) + )] fn leptos_routes_with_context( self, paths: Vec, diff --git a/integrations/axum/Cargo.toml b/integrations/axum/Cargo.toml index f57a02ba0..90bce7b6e 100644 --- a/integrations/axum/Cargo.toml +++ b/integrations/axum/Cargo.toml @@ -28,7 +28,7 @@ serde_json = "1.0" tokio = { version = "1.39", default-features = false } tower = "0.4.13" tower-http = "0.5.2" -tracing = "0.1.40" +tracing = { version = "0.1.40", optional = true } [dev-dependencies] axum = "0.7.5" @@ -38,6 +38,10 @@ tokio = { version = "1.39", features = ["net", "rt-multi-thread"] } wasm = [] default = ["tokio/fs", "tokio/sync", "tower-http/fs"] islands-router = [] +tracing = ["dep:tracing"] [package.metadata.docs.rs] rustdoc-args = ["--generate-link-to-definition"] + +[package.metadata.cargo-all-features] +denylist = ["tracing"] diff --git a/integrations/axum/src/lib.rs b/integrations/axum/src/lib.rs index 55bfff3f4..b530d0f4c 100644 --- a/integrations/axum/src/lib.rs +++ b/integrations/axum/src/lib.rs @@ -236,10 +236,14 @@ pub fn redirect(path: &str) { ); } } else { - tracing::warn!( - "Couldn't retrieve either Parts or ResponseOptions while trying \ - to redirect()." - ); + let msg = "Couldn't retrieve either Parts or ResponseOptions while \ + trying to redirect()."; + + #[cfg(feature = "tracing")] + tracing::warn!("{}", &msg); + + #[cfg(not(feature = "tracing"))] + eprintln!("{}", &msg); } } @@ -289,7 +293,10 @@ pub fn generate_request_and_parts( /// This function always provides context values including the following types: /// - [`Parts`] /// - [`ResponseOptions`] -#[tracing::instrument(level = "trace", fields(error), skip_all)] +#[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) +)] pub async fn handle_server_fns(req: Request) -> impl IntoResponse { handle_server_fns_inner(|| {}, req).await } @@ -331,7 +338,10 @@ fn init_executor() { /// This function always provides context values including the following types: /// - [`Parts`] /// - [`ResponseOptions`] -#[tracing::instrument(level = "trace", fields(error), skip_all)] +#[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) +)] pub async fn handle_server_fns_with_context( additional_context: impl Fn() + 'static + Clone + Send, req: Request, @@ -460,7 +470,10 @@ pub type PinnedHtmlStream = /// - [`ResponseOptions`] /// - [`ServerMetaContext`](leptos_meta::ServerMetaContext) /// - [`RouterIntegrationContext`](leptos_router::RouterIntegrationContext) -#[tracing::instrument(level = "trace", fields(error), skip_all)] +#[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) +)] pub fn render_app_to_stream( app_fn: impl Fn() -> IV + Clone + Send + 'static, ) -> impl Fn( @@ -480,7 +493,10 @@ where /// The difference between calling this and `render_app_to_stream_with_context()` is that this /// one respects the `SsrMode` on each Route and thus requires `Vec` for route checking. /// This is useful if you are using `.leptos_routes_with_handler()` -#[tracing::instrument(level = "trace", fields(error), skip_all)] +#[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) +)] pub fn render_route( paths: Vec, app_fn: impl Fn() -> IV + Clone + Send + 'static, @@ -546,7 +562,10 @@ where /// - [`ResponseOptions`] /// - [`ServerMetaContext`](leptos_meta::ServerMetaContext) /// - [`RouterIntegrationContext`](leptos_router::RouterIntegrationContext) -#[tracing::instrument(level = "trace", fields(error), skip_all)] +#[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) +)] pub fn render_app_to_stream_in_order( app_fn: impl Fn() -> IV + Clone + Send + 'static, ) -> impl Fn( @@ -597,7 +616,10 @@ where /// - [`ResponseOptions`] /// - [`ServerMetaContext`](leptos_meta::ServerMetaContext) /// - [`RouterIntegrationContext`](leptos_router::RouterIntegrationContext) -#[tracing::instrument(level = "trace", fields(error), skip_all)] +#[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) +)] pub fn render_app_to_stream_with_context( additional_context: impl Fn() + 'static + Clone + Send, app_fn: impl Fn() -> IV + Clone + Send + 'static, @@ -622,7 +644,10 @@ where /// The difference between calling this and `render_app_to_stream_with_context()` is that this /// one respects the `SsrMode` on each Route, and thus requires `Vec` for route checking. /// This is useful if you are using `.leptos_routes_with_handler()`. -#[tracing::instrument(level = "trace", fields(error), skip_all)] +#[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) +)] pub fn render_route_with_context( paths: Vec, additional_context: impl Fn() + 'static + Clone + Send, @@ -701,7 +726,10 @@ where /// - [`ResponseOptions`] /// - [`ServerMetaContext`](leptos_meta::ServerMetaContext) /// - [`RouterIntegrationContext`](leptos_router::RouterIntegrationContext) -#[tracing::instrument(level = "trace", fields(error), skip_all)] +#[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) +)] pub fn render_app_to_stream_with_context_and_replace_blocks( additional_context: impl Fn() + 'static + Clone + Send, app_fn: impl Fn() -> IV + Clone + Send + 'static, @@ -766,7 +794,10 @@ where /// - [`ResponseOptions`] /// - [`ServerMetaContext`](leptos_meta::ServerMetaContext) /// - [`RouterIntegrationContext`](leptos_router::RouterIntegrationContext) -#[tracing::instrument(level = "trace", fields(error), skip_all)] +#[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) +)] pub fn render_app_to_stream_in_order_with_context( additional_context: impl Fn() + 'static + Clone + Send, app_fn: impl Fn() -> IV + Clone + Send + 'static, @@ -859,7 +890,10 @@ where }) } -#[tracing::instrument(level = "trace", fields(error), skip_all)] +#[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) +)] fn provide_contexts( path: &str, meta_context: &ServerMetaContext, @@ -924,7 +958,10 @@ fn provide_contexts( /// - [`ResponseOptions`] /// - [`ServerMetaContext`](leptos_meta::ServerMetaContext) /// - [`RouterIntegrationContext`](leptos_router::RouterIntegrationContext) -#[tracing::instrument(level = "trace", fields(error), skip_all)] +#[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) +)] pub fn render_app_async( app_fn: impl Fn() -> IV + Clone + Send + 'static, ) -> impl Fn( @@ -976,7 +1013,10 @@ where /// - [`ResponseOptions`] /// - [`ServerMetaContext`](leptos_meta::ServerMetaContext) /// - [`RouterIntegrationContext`](leptos_router::RouterIntegrationContext) -#[tracing::instrument(level = "trace", fields(error), skip_all)] +#[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) +)] pub fn render_app_async_stream_with_context( additional_context: impl Fn() + 'static + Clone + Send, app_fn: impl Fn() -> IV + Clone + Send + 'static, @@ -1041,7 +1081,10 @@ where /// - [`ResponseOptions`] /// - [`ServerMetaContext`](leptos_meta::ServerMetaContext) /// - [`RouterIntegrationContext`](leptos_router::RouterIntegrationContext) -#[tracing::instrument(level = "trace", fields(error), skip_all)] +#[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) +)] pub fn render_app_async_with_context( additional_context: impl Fn() + 'static + Clone + Send, app_fn: impl Fn() -> IV + Clone + Send + 'static, @@ -1072,7 +1115,10 @@ where /// Generates a list of all routes defined in Leptos's Router in your app. We can then use this to automatically /// create routes in Axum's Router without having to use wildcard matching or fallbacks. Takes in your root app Element /// as an argument so it can walk you app tree. This version is tailored to generate Axum compatible paths. -#[tracing::instrument(level = "trace", fields(error), skip_all)] +#[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) +)] pub fn generate_route_list( app_fn: impl Fn() -> IV + 'static + Clone, ) -> Vec @@ -1085,7 +1131,10 @@ where /// Generates a list of all routes defined in Leptos's Router in your app. We can then use this to automatically /// create routes in Axum's Router without having to use wildcard matching or fallbacks. Takes in your root app Element /// as an argument so it can walk you app tree. This version is tailored to generate Axum compatible paths. -#[tracing::instrument(level = "trace", fields(error), skip_all)] +#[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) +)] pub fn generate_route_list_with_ssg( app_fn: impl Fn() -> IV + 'static + Clone, ) -> (Vec, StaticDataMap) @@ -1099,7 +1148,10 @@ where /// create routes in Axum's Router without having to use wildcard matching or fallbacks. Takes in your root app Element /// as an argument so it can walk you app tree. This version is tailored to generate Axum compatible paths. Adding excluded_routes /// to this function will stop `.leptos_routes()` from generating a route for it, allowing a custom handler. These need to be in Axum path format -#[tracing::instrument(level = "trace", fields(error), skip_all)] +#[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) +)] pub fn generate_route_list_with_exclusions( app_fn: impl Fn() -> IV + 'static + Clone, excluded_routes: Option>, @@ -1140,7 +1192,10 @@ pub async fn build_static_routes( /// create routes in Axum's Router without having to use wildcard matching or fallbacks. Takes in your root app Element /// as an argument so it can walk you app tree. This version is tailored to generate Axum compatible paths. Adding excluded_routes /// to this function will stop `.leptos_routes()` from generating a route for it, allowing a custom handler. These need to be in Axum path format -#[tracing::instrument(level = "trace", fields(error), skip_all)] +#[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) +)] pub fn generate_route_list_with_exclusions_and_ssg( app_fn: impl Fn() -> IV + 'static + Clone, excluded_routes: Option>, @@ -1227,7 +1282,10 @@ impl AxumRouteListing { /// as an argument so it can walk you app tree. This version is tailored to generate Axum compatible paths. Adding excluded_routes /// to this function will stop `.leptos_routes()` from generating a route for it, allowing a custom handler. These need to be in Axum path format /// Additional context will be provided to the app Element. -#[tracing::instrument(level = "trace", fields(error), skip_all)] +#[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) +)] pub fn generate_route_list_with_exclusions_and_ssg_and_context( app_fn: impl Fn() -> IV + 'static + Clone, excluded_routes: Option>, @@ -1554,7 +1612,10 @@ impl LeptosRoutes for axum::Router where S: Clone + Send + Sync + 'static, { - #[tracing::instrument(level = "trace", fields(error), skip_all)] + #[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) + )] fn leptos_routes( self, state: &S, @@ -1567,7 +1628,10 @@ where self.leptos_routes_with_context(state, paths, || {}, app_fn) } - #[tracing::instrument(level = "trace", fields(error), skip_all)] + #[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) + )] fn leptos_routes_with_context( self, state: &S, @@ -1710,7 +1774,10 @@ where router } - #[tracing::instrument(level = "trace", fields(error), skip_all)] + #[cfg_attr( + feature = "tracing", + tracing::instrument(level = "trace", fields(error), skip_all) + )] fn leptos_routes_with_handler( self, paths: Vec, diff --git a/integrations/utils/Cargo.toml b/integrations/utils/Cargo.toml index 46cddac42..57bb89c02 100644 --- a/integrations/utils/Cargo.toml +++ b/integrations/utils/Cargo.toml @@ -16,7 +16,6 @@ leptos_meta = { workspace = true, features = ["ssr"] } leptos_router = { workspace = true, features = ["ssr"] } leptos_config = { workspace = true } reactive_graph = { workspace = true, features = ["sandboxed-arenas"] } -tracing = "0.1.40" [package.metadata.docs.rs] rustdoc-args = ["--generate-link-to-definition"] diff --git a/leptos/Cargo.toml b/leptos/Cargo.toml index e96a49124..d9b462814 100644 --- a/leptos/Cargo.toml +++ b/leptos/Cargo.toml @@ -30,7 +30,7 @@ reactive_graph = { workspace = true, features = ["serde"] } rustc-hash = "2.0" tachys = { workspace = true, features = ["reactive_graph", "oco"] } thiserror = "1.0" -tracing = "0.1.40" +tracing = { version = "0.1.40", optional = true } typed-builder = "0.19.1" typed-builder-macro = "0.19.1" serde = "1.0" @@ -76,13 +76,20 @@ ssr = [ nightly = ["leptos_macro/nightly", "reactive_graph/nightly", "tachys/nightly"] rkyv = ["server_fn/rkyv"] tracing = [ + "dep:tracing", "reactive_graph/tracing", "tachys/tracing", -] #, "leptos_macro/tracing", "leptos_dom/tracing"] + "leptos_macro/tracing", + "leptos_dom/tracing", + "leptos_server/tracing", +] nonce = ["base64", "rand"] spin = ["leptos-spin-macro"] experimental-islands = ["leptos_macro/experimental-islands", "dep:serde_json"] -trace-component-props = ["leptos_macro/trace-component-props"] +trace-component-props = [ + "leptos_macro/trace-component-props", + "leptos_dom/trace-component-props" +] delegation = ["tachys/delegation"] [package.metadata.cargo-all-features] @@ -93,52 +100,22 @@ denylist = [ "rustls", "default-tls", "wasm-bindgen", - "rkyv", # was causing clippy issues on nightly + "rkyv", # was causing clippy issues on nightly "trace-component-props", "spin", "experimental-islands", ] skip_feature_sets = [ - [ - "csr", - "ssr", - ], - [ - "csr", - "hydrate", - ], - [ - "ssr", - "hydrate", - ], - [ - "serde", - "serde-lite", - ], - [ - "serde-lite", - "miniserde", - ], - [ - "serde", - "miniserde", - ], - [ - "serde", - "rkyv", - ], - [ - "miniserde", - "rkyv", - ], - [ - "serde-lite", - "rkyv", - ], - [ - "default-tls", - "rustls", - ], + ["csr", "ssr"], + ["csr", "hydrate"], + ["ssr", "hydrate"], + ["serde", "serde-lite"], + ["serde-lite", "miniserde"], + ["serde", "miniserde"], + ["serde", "rkyv"], + ["miniserde", "rkyv"], + ["serde-lite", "rkyv"], + ["default-tls", "rustls"], ] [package.metadata.docs.rs] diff --git a/leptos/src/animated_show.rs b/leptos/src/animated_show.rs index 8a4db98c8..6e6c95521 100644 --- a/leptos/src/animated_show.rs +++ b/leptos/src/animated_show.rs @@ -43,10 +43,7 @@ use leptos_reactive::{ /// } /// # } /// ``` -#[cfg_attr( - any(debug_assertions, feature = "ssr"), - tracing::instrument(level = "trace", skip_all) -)] +#[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))] #[component] pub fn AnimatedShow( /// The components Show wraps diff --git a/leptos/src/form.rs b/leptos/src/form.rs index 59f6f1349..29aa87bf5 100644 --- a/leptos/src/form.rs +++ b/leptos/src/form.rs @@ -69,10 +69,7 @@ use web_sys::{ /// Ok(()) /// } /// ``` -#[cfg_attr( - any(debug_assertions, feature = "ssr"), - tracing::instrument(level = "trace", skip_all,) -)] +#[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))] #[component] pub fn ActionForm( /// The action from which to build the form. This should include a URL, which can be generated diff --git a/leptos/src/lib.rs b/leptos/src/lib.rs index d58bc8878..d8de83550 100644 --- a/leptos/src/lib.rs +++ b/leptos/src/lib.rs @@ -302,6 +302,9 @@ pub use serde; #[cfg(feature = "experimental-islands")] #[doc(hidden)] pub use serde_json; +#[cfg(feature = "tracing")] +#[doc(hidden)] +pub use tracing; #[doc(hidden)] pub use wasm_bindgen; #[doc(hidden)] @@ -376,7 +379,7 @@ pub use show::*; //pub use suspense_component::*; mod suspense_component; //mod transition; -#[cfg(any(debug_assertions, feature = "ssr"))] +#[cfg(feature = "tracing")] #[doc(hidden)] pub use tracing; pub use transition::*; diff --git a/leptos/src/portal.rs b/leptos/src/portal.rs index 2768e9504..dfc4364f9 100644 --- a/leptos/src/portal.rs +++ b/leptos/src/portal.rs @@ -10,10 +10,7 @@ use std::sync::Arc; /// If no mount point is given, the portal is inserted in `document.body`; /// it is wrapped in a `
` unless `is_svg` is `true` in which case it's wrappend in a ``. /// Setting `use_shadow` to `true` places the element in a shadow root to isolate styles. -#[cfg_attr( - any(debug_assertions, feature = "ssr"), - tracing::instrument(level = "trace", skip_all) -)] +#[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))] #[component] pub fn Portal( /// Target element where the children will be appended diff --git a/leptos_dom/Cargo.toml b/leptos_dom/Cargo.toml index 840a964bb..4b862b8dd 100644 --- a/leptos_dom/Cargo.toml +++ b/leptos_dom/Cargo.toml @@ -14,8 +14,10 @@ reactive_graph = { workspace = true } or_poisoned = { workspace = true } js-sys = "0.3.69" send_wrapper = "0.6.0" -tracing = "0.1.40" +tracing = { version = "0.1.40", optional = true } wasm-bindgen = "0.2.93" +serde_json = { version = "1.0", optional = true } +serde = { version = "1.0", optional = true } [dev-dependencies] leptos = { path = "../leptos" } @@ -26,7 +28,11 @@ features = ["Location"] [features] default = [] -tracing = [] +tracing = ["dep:tracing"] +trace-component-props = ["dep:serde", "dep:serde_json"] [package.metadata.docs.rs] rustdoc-args = ["--generate-link-to-definition"] + +[package.metadata.cargo-all-features] +denylist = ["tracing"] diff --git a/leptos_dom/src/lib.rs b/leptos_dom/src/lib.rs index ce3f8c8a5..925cba8b9 100644 --- a/leptos_dom/src/lib.rs +++ b/leptos_dom/src/lib.rs @@ -4,6 +4,8 @@ //! DOM helpers for Leptos. pub mod helpers; +#[doc(hidden)] +pub mod macro_helpers; /// Utilities for simple isomorphic logging to the console or terminal. #[macro_use] diff --git a/leptos_dom/src/macro_helpers/mod.rs b/leptos_dom/src/macro_helpers/mod.rs new file mode 100644 index 000000000..6762d0489 --- /dev/null +++ b/leptos_dom/src/macro_helpers/mod.rs @@ -0,0 +1,3 @@ +#[cfg(feature = "trace-component-props")] +#[doc(hidden)] +pub mod tracing_property; diff --git a/leptos_dom/src/macro_helpers/tracing_property.rs b/leptos_dom/src/macro_helpers/tracing_property.rs new file mode 100644 index 000000000..488ee807f --- /dev/null +++ b/leptos_dom/src/macro_helpers/tracing_property.rs @@ -0,0 +1,170 @@ +use wasm_bindgen::UnwrapThrowExt; + +#[macro_export] +/// Use for tracing property +macro_rules! tracing_props { + () => { + ::leptos::tracing::span!( + ::leptos::tracing::Level::TRACE, + "leptos_dom::tracing_props", + props = String::from("[]") + ); + }; + ($($prop:tt),+ $(,)?) => { + { + use ::leptos::leptos_dom::macro_helpers::tracing_property::{Match, SerializeMatch, DefaultMatch}; + let mut props = String::from('['); + $( + let prop = (&&Match { + name: stringify!{$prop}, + value: std::cell::Cell::new(Some(&$prop)) + }).spez(); + props.push_str(&format!("{prop},")); + )* + props.pop(); + props.push(']'); + ::leptos::tracing::span!( + ::leptos::tracing::Level::TRACE, + "leptos_dom::tracing_props", + props + ); + } + }; +} + +// Implementation based on spez +// see https://github.com/m-ou-se/spez + +pub struct Match { + pub name: &'static str, + pub value: std::cell::Cell>, +} + +pub trait SerializeMatch { + type Return; + fn spez(&self) -> Self::Return; +} +impl SerializeMatch for &Match<&T> { + type Return = String; + fn spez(&self) -> Self::Return { + let name = self.name; + + // suppresses warnings when serializing signals into props + #[cfg(debug_assertions)] + let _z = reactive_graph::diagnostics::SpecialNonReactiveZone::enter(); + + serde_json::to_string(self.value.get().unwrap_throw()).map_or_else( + |err| format!(r#"{{"name": "{name}", "error": "{err}"}}"#), + |value| format!(r#"{{"name": "{name}", "value": {value}}}"#), + ) + } +} + +pub trait DefaultMatch { + type Return; + fn spez(&self) -> Self::Return; +} +impl DefaultMatch for Match<&T> { + type Return = String; + fn spez(&self) -> Self::Return { + let name = self.name; + format!(r#"{{"name": "{name}", "value": "[unserializable value]"}}"#) + } +} + +#[test] +fn match_primitive() { + // String + let test = String::from("string"); + let prop = (&&Match { + name: stringify! {test}, + value: std::cell::Cell::new(Some(&test)), + }) + .spez(); + assert_eq!(prop, r#"{"name": "test", "value": "string"}"#); + + // &str + let test = "string"; + let prop = (&&Match { + name: stringify! {test}, + value: std::cell::Cell::new(Some(&test)), + }) + .spez(); + assert_eq!(prop, r#"{"name": "test", "value": "string"}"#); + + // u128 + let test: u128 = 1; + let prop = (&&Match { + name: stringify! {test}, + value: std::cell::Cell::new(Some(&test)), + }) + .spez(); + assert_eq!(prop, r#"{"name": "test", "value": 1}"#); + + // i128 + let test: i128 = -1; + let prop = (&&Match { + name: stringify! {test}, + value: std::cell::Cell::new(Some(&test)), + }) + .spez(); + assert_eq!(prop, r#"{"name": "test", "value": -1}"#); + + // f64 + let test = 3.25; + let prop = (&&Match { + name: stringify! {test}, + value: std::cell::Cell::new(Some(&test)), + }) + .spez(); + assert_eq!(prop, r#"{"name": "test", "value": 3.25}"#); + + // bool + let test = true; + let prop = (&&Match { + name: stringify! {test}, + value: std::cell::Cell::new(Some(&test)), + }) + .spez(); + assert_eq!(prop, r#"{"name": "test", "value": true}"#); +} + +#[test] +fn match_serialize() { + use serde::Serialize; + #[derive(Serialize)] + struct CustomStruct { + field: &'static str, + } + + let test = CustomStruct { field: "field" }; + let prop = (&&Match { + name: stringify! {test}, + value: std::cell::Cell::new(Some(&test)), + }) + .spez(); + assert_eq!(prop, r#"{"name": "test", "value": {"field":"field"}}"#); + // Verification of ownership + assert_eq!(test.field, "field"); +} + +#[test] +#[allow(clippy::needless_borrow)] +fn match_no_serialize() { + struct CustomStruct { + field: &'static str, + } + + let test = CustomStruct { field: "field" }; + let prop = (&&Match { + name: stringify! {test}, + value: std::cell::Cell::new(Some(&test)), + }) + .spez(); + assert_eq!( + prop, + r#"{"name": "test", "value": "[unserializable value]"}"# + ); + // Verification of ownership + assert_eq!(test.field, "field"); +} diff --git a/leptos_macro/Cargo.toml b/leptos_macro/Cargo.toml index bf3c5d9d5..c96ecc3d8 100644 --- a/leptos_macro/Cargo.toml +++ b/leptos_macro/Cargo.toml @@ -27,7 +27,7 @@ leptos_hot_reload = { workspace = true } server_fn_macro = { workspace = true } convert_case = "0.6.0" uuid = { version = "1.10", features = ["v4"] } -tracing = "0.1.40" +tracing = { version = "0.1.40", optional = true } [dev-dependencies] log = "0.4.22" @@ -43,7 +43,7 @@ csr = [] hydrate = [] ssr = ["server_fn_macro/ssr", "leptos/ssr"] nightly = ["server_fn_macro/nightly"] -tracing = [] +tracing = ["dep:tracing"] experimental-islands = [] trace-component-props = [] actix = ["server_fn_macro/actix"] diff --git a/leptos_macro/src/component.rs b/leptos_macro/src/component.rs index 7abfe9653..79771bd7c 100644 --- a/leptos_macro/src/component.rs +++ b/leptos_macro/src/component.rs @@ -142,6 +142,7 @@ impl ToTokens for Model { let props_name = format_ident!("{name}Props"); let props_builder_name = format_ident!("{name}PropsBuilder"); let props_serialized_name = format_ident!("{name}PropsSerialized"); + #[cfg(feature = "tracing")] let trace_name = format!("<{name} />"); let is_island_with_children = *is_island @@ -190,32 +191,38 @@ impl ToTokens for Model { tracing_span_expr, tracing_guard_expr, tracing_props_expr, - ) = if cfg!(feature = "tracing") { - ( - quote! { - #[allow(clippy::let_with_type_underscore)] - #[cfg_attr( - any(debug_assertions, feature="ssr"), - ::leptos::tracing::instrument(level = "info", name = #trace_name, skip_all) - )] - }, - quote! { - let span = ::leptos::tracing::Span::current(); - }, - quote! { - #[cfg(debug_assertions)] - let _guard = span.entered(); - }, - if no_props { - quote! {} - } else { + ) = { + #[cfg(feature = "tracing")] + { + ( quote! { - ::leptos::tracing_props![#prop_names]; - } - }, - ) - } else { - (quote! {}, quote! {}, quote! {}, quote! {}) + #[allow(clippy::let_with_type_underscore)] + #[cfg_attr( + feature = "tracing", + ::leptos::tracing::instrument(level = "info", name = #trace_name, skip_all) + )] + }, + quote! { + let span = ::leptos::tracing::Span::current(); + }, + quote! { + #[cfg(debug_assertions)] + let _guard = span.entered(); + }, + if no_props || !cfg!(feature = "trace-component-props") { + quote!() + } else { + quote! { + ::leptos::leptos_dom::tracing_props![#prop_names]; + } + }, + ) + } + + #[cfg(not(feature = "tracing"))] + { + (quote!(), quote!(), quote!(), quote!()) + } }; let component_id = name.to_string(); diff --git a/leptos_macro/src/lib.rs b/leptos_macro/src/lib.rs index c5dfd8e04..c0f7b4b44 100644 --- a/leptos_macro/src/lib.rs +++ b/leptos_macro/src/lib.rs @@ -261,10 +261,7 @@ mod slot; /// ``` #[proc_macro_error::proc_macro_error] #[proc_macro] -#[cfg_attr( - any(debug_assertions, feature = "ssr"), - tracing::instrument(level = "trace", skip_all,) -)] +#[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))] pub fn view(tokens: TokenStream) -> TokenStream { let tokens: proc_macro2::TokenStream = tokens.into(); let mut tokens = tokens.into_iter(); diff --git a/leptos_server/Cargo.toml b/leptos_server/Cargo.toml index 024262485..06e5541cb 100644 --- a/leptos_server/Cargo.toml +++ b/leptos_server/Cargo.toml @@ -38,7 +38,7 @@ tachys = ["dep:tachys"] tracing = ["dep:tracing"] [package.metadata.cargo-all-features] -denylist = ["nightly"] +denylist = ["tracing"] [package.metadata.docs.rs] rustdoc-args = ["--generate-link-to-definition"] diff --git a/leptos_server/src/multi_action_old.rs b/leptos_server/src/multi_action_old.rs index b9e45ffe8..f08767ef4 100644 --- a/leptos_server/src/multi_action_old.rs +++ b/leptos_server/src/multi_action_old.rs @@ -95,8 +95,8 @@ where { /// Calls the `async` function with a reference to the input type as its argument. #[cfg_attr( - any(debug_assertions, feature = "ssr"), - tracing::instrument(level = "trace", skip_all,) + feature = "tracing", + tracing::instrument(level = "trace", skip_all) )] pub fn dispatch(&self, input: I) { self.0.with_value(|a| a.dispatch(input)) @@ -104,8 +104,8 @@ where /// The set of all submissions to this multi-action. #[cfg_attr( - any(debug_assertions, feature = "ssr"), - tracing::instrument(level = "trace", skip_all,) + feature = "tracing", + tracing::instrument(level = "trace", skip_all) )] pub fn submissions(&self) -> ReadSignal>> { self.0.with_value(|a| a.submissions()) @@ -119,8 +119,8 @@ where /// How many times an action has successfully resolved. #[cfg_attr( - any(debug_assertions, feature = "ssr"), - tracing::instrument(level = "trace", skip_all,) + feature = "tracing", + tracing::instrument(level = "trace", skip_all) )] pub fn version(&self) -> RwSignal { self.0.with_value(|a| a.version) @@ -129,8 +129,8 @@ where /// Associates the URL of the given server function with this action. /// This enables integration with the `MultiActionForm` component in `leptos_router`. #[cfg_attr( - any(debug_assertions, feature = "ssr"), - tracing::instrument(level = "trace", skip_all,) + feature = "tracing", + tracing::instrument(level = "trace", skip_all) )] pub fn using_server_fn(self) -> Self { self.0.update_value(|a| { @@ -201,8 +201,8 @@ where { /// Calls the `async` function with a reference to the input type as its argument. #[cfg_attr( - any(debug_assertions, feature = "ssr"), - tracing::instrument(level = "trace", skip_all,) + feature = "tracing", + tracing::instrument(level = "trace", skip_all) )] pub fn dispatch(&self, input: I) { if !is_suppressing_resource_load() { @@ -293,10 +293,7 @@ where /// create_multi_action(|input: &(usize, String)| async { todo!() }); /// # runtime.dispose(); /// ``` -#[cfg_attr( - any(debug_assertions, feature = "ssr"), - tracing::instrument(level = "trace", skip_all,) -)] +#[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))] pub fn create_multi_action(action_fn: F) -> MultiAction where I: 'static, @@ -333,10 +330,7 @@ where /// let my_server_multi_action = create_server_multi_action::(); /// # runtime.dispose(); /// ``` -#[cfg_attr( - any(debug_assertions, feature = "ssr"), - tracing::instrument(level = "trace", skip_all,) -)] +#[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))] pub fn create_server_multi_action( ) -> MultiAction>> where diff --git a/meta/Cargo.toml b/meta/Cargo.toml index bb2764824..f99aa2856 100644 --- a/meta/Cargo.toml +++ b/meta/Cargo.toml @@ -14,7 +14,7 @@ once_cell = "1.19" or_poisoned = { workspace = true } indexmap = "2.3" send_wrapper = "0.6.0" -tracing = "0.1.40" +tracing = { version = "0.1.40", optional = true } wasm-bindgen = "0.2.93" futures = "0.3.30" @@ -25,6 +25,10 @@ features = ["HtmlLinkElement", "HtmlMetaElement", "HtmlTitleElement"] [features] default = [] ssr = [] +tracing = ["dep:tracing"] [package.metadata.docs.rs] rustdoc-args = ["--generate-link-to-definition"] + +[package.metadata.cargo-all-features] +denylist = ["tracing"] diff --git a/meta/src/lib.rs b/meta/src/lib.rs index 7267d0e2c..3a1f4855c 100644 --- a/meta/src/lib.rs +++ b/meta/src/lib.rs @@ -342,10 +342,14 @@ where ); _ = cx.elements.send(buf); // fails only if the receiver is already dropped } else { - tracing::warn!( - "tried to use a leptos_meta component without `ServerMetaContext` \ - provided" - ); + let msg = "tried to use a leptos_meta component without \ + `ServerMetaContext` provided"; + + #[cfg(feature = "tracing")] + tracing::warn!("{}", msg); + + #[cfg(not(feature = "tracing"))] + eprintln!("{}", msg); } RegisteredMetaTag { el } diff --git a/reactive_graph/Cargo.toml b/reactive_graph/Cargo.toml index 23a41d264..5a03dea2b 100644 --- a/reactive_graph/Cargo.toml +++ b/reactive_graph/Cargo.toml @@ -44,3 +44,6 @@ sandboxed-arenas = [] [package.metadata.docs.rs] all-features = true rustdoc-args = ["--cfg", "docsrs"] + +[package.metadata.cargo-all-features] +denylist = ["tracing"] diff --git a/reactive_graph/src/computed/arc_memo.rs b/reactive_graph/src/computed/arc_memo.rs index 2d8470109..32036ae49 100644 --- a/reactive_graph/src/computed/arc_memo.rs +++ b/reactive_graph/src/computed/arc_memo.rs @@ -109,7 +109,7 @@ where #[track_caller] #[cfg_attr( feature = "tracing", - tracing::instrument(level = "trace", skip_all,) + tracing::instrument(level = "trace", skip_all) )] pub fn new(fun: impl Fn(Option<&T>) -> T + Send + Sync + 'static) -> Self where @@ -127,7 +127,7 @@ where #[track_caller] #[cfg_attr( feature = "tracing", - tracing::instrument(level = "trace", skip_all,) + tracing::instrument(level = "trace", skip_all) )] pub fn new_with_compare( fun: impl Fn(Option<&T>) -> T + Send + Sync + 'static, @@ -153,7 +153,7 @@ where #[track_caller] #[cfg_attr( feature = "tracing", - tracing::instrument(level = "trace", skip_all,) + tracing::instrument(level = "trace", skip_all) )] pub fn new_owning( fun: impl Fn(Option) -> (T, bool) + Send + Sync + 'static, diff --git a/reactive_graph/src/computed/memo.rs b/reactive_graph/src/computed/memo.rs index c07bbf122..52fe8d71e 100644 --- a/reactive_graph/src/computed/memo.rs +++ b/reactive_graph/src/computed/memo.rs @@ -149,7 +149,7 @@ where #[track_caller] #[cfg_attr( feature = "tracing", - tracing::instrument(level = "debug", skip_all,) + tracing::instrument(level = "debug", skip_all) )] /// Creates a new memoized, computed reactive value. /// @@ -184,7 +184,7 @@ where #[track_caller] #[cfg_attr( feature = "tracing", - tracing::instrument(level = "trace", skip_all,) + tracing::instrument(level = "trace", skip_all) )] /// Creates a new memo with a custom comparison function. By default, memos simply use /// [`PartialEq`] to compare the previous value to the new value. Passing a custom comparator @@ -218,7 +218,7 @@ where #[track_caller] #[cfg_attr( feature = "tracing", - tracing::instrument(level = "trace", skip_all,) + tracing::instrument(level = "trace", skip_all) )] pub fn new_owning( fun: impl Fn(Option) -> (T, bool) + Send + Sync + 'static, diff --git a/reactive_graph/src/signal/arc_rw.rs b/reactive_graph/src/signal/arc_rw.rs index ed9d366fb..508160e90 100644 --- a/reactive_graph/src/signal/arc_rw.rs +++ b/reactive_graph/src/signal/arc_rw.rs @@ -149,7 +149,7 @@ impl ArcRwSignal { /// Creates a new signal, taking the initial value as its argument. #[cfg_attr( feature = "tracing", - tracing::instrument(level = "trace", skip_all,) + tracing::instrument(level = "trace", skip_all) )] #[track_caller] pub fn new(value: T) -> Self { diff --git a/reactive_graph/src/signal/rw.rs b/reactive_graph/src/signal/rw.rs index 447bc8317..3ef5f9496 100644 --- a/reactive_graph/src/signal/rw.rs +++ b/reactive_graph/src/signal/rw.rs @@ -118,7 +118,7 @@ where /// Creates a new signal, taking the initial value as its argument. #[cfg_attr( feature = "tracing", - tracing::instrument(level = "trace", skip_all,) + tracing::instrument(level = "trace", skip_all) )] #[track_caller] pub fn new(value: T) -> Self { @@ -134,7 +134,7 @@ where /// Creates a new signal with the given arena storage method. #[cfg_attr( feature = "tracing", - tracing::instrument(level = "trace", skip_all,) + tracing::instrument(level = "trace", skip_all) )] #[track_caller] pub fn new_with_storage(value: T) -> Self { @@ -154,7 +154,7 @@ where /// this pins the value to the current thread. Accessing it from any other thread will panic. #[cfg_attr( feature = "tracing", - tracing::instrument(level = "trace", skip_all,) + tracing::instrument(level = "trace", skip_all) )] #[track_caller] pub fn new_local(value: T) -> Self { diff --git a/reactive_stores/src/lib.rs b/reactive_stores/src/lib.rs index 33e26961d..502801ad8 100644 --- a/reactive_stores/src/lib.rs +++ b/reactive_stores/src/lib.rs @@ -316,7 +316,7 @@ mod tests { assert_eq!(store.user().read_untracked().as_str(), "Bob"); Effect::new_sync({ let combined_count = Arc::clone(&combined_count); - move |prev| { + move |prev: Option<()>| { if prev.is_none() { println!("first run"); } else { @@ -360,7 +360,7 @@ mod tests { Effect::new_sync({ let combined_count = Arc::clone(&combined_count); - move |prev| { + move |prev: Option<()>| { if prev.is_none() { println!("first run"); } else { @@ -392,7 +392,7 @@ mod tests { Effect::new_sync({ let combined_count = Arc::clone(&combined_count); - move |prev| { + move |prev: Option<()>| { if prev.is_none() { println!("first run"); } else { @@ -429,7 +429,7 @@ mod tests { Effect::new_sync({ let combined_count = Arc::clone(&combined_count); - move |prev| { + move |prev: Option<()>| { if prev.is_none() { println!("first run"); } else { diff --git a/router/Cargo.toml b/router/Cargo.toml index 0128cfc85..1eae19287 100644 --- a/router/Cargo.toml +++ b/router/Cargo.toml @@ -64,3 +64,6 @@ nightly = [] [package.metadata.docs.rs] rustdoc-args = ["--generate-link-to-definition"] + +[package.metadata.cargo-all-features] +denylist = ["tracing"] diff --git a/tachys/Cargo.toml b/tachys/Cargo.toml index 705e28133..71afdab1a 100644 --- a/tachys/Cargo.toml +++ b/tachys/Cargo.toml @@ -178,3 +178,6 @@ testing = ["dep:slotmap"] reactive_graph = ["dep:reactive_graph", "dep:any_spawner"] sledgehammer = ["dep:sledgehammer_bindgen", "dep:sledgehammer_utils"] tracing = ["dep:tracing"] + +[package.metadata.cargo-all-features] +denylist = ["tracing"] diff --git a/tachys/src/html/element/mod.rs b/tachys/src/html/element/mod.rs index c4fc74229..0394454cd 100644 --- a/tachys/src/html/element/mod.rs +++ b/tachys/src/html/element/mod.rs @@ -562,7 +562,7 @@ mod tests { element::{em, ElementChild, Main}, }, renderer::mock_dom::MockDom, - view::{Render, RenderHtml}, + view::Render, }; #[test]