From 2cbd34ca6f762a5a7c8ebc9adb46885f77ecb91d Mon Sep 17 00:00:00 2001 From: hi-rustin Date: Fri, 1 Dec 2023 22:03:33 +0800 Subject: [PATCH 01/15] feat: add new API to support grpc-web Signed-off-by: hi-rustin --- Cargo.lock | 45 +++++++ console-subscriber/Cargo.toml | 8 ++ console-subscriber/examples/grpc_web.rs | 165 ++++++++++++++++++++++++ console-subscriber/src/builder.rs | 34 ++++- console-subscriber/src/lib.rs | 34 ++++- 5 files changed, 284 insertions(+), 2 deletions(-) create mode 100644 console-subscriber/examples/grpc_web.rs diff --git a/Cargo.lock b/Cargo.lock index 0b1341c7d..fadd4c0b9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -337,6 +337,7 @@ dependencies = [ "tokio", "tokio-stream", "tonic", + "tonic-web", "tower", "tracing", "tracing-core", @@ -755,6 +756,12 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "http-range-header" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" + [[package]] name = "httparse" version = "1.8.0" @@ -1879,6 +1886,26 @@ dependencies = [ "syn 2.0.33", ] +[[package]] +name = "tonic-web" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fddb2a37b247e6adcb9f239f4e5cefdcc5ed526141a416b943929f13aea2cce" +dependencies = [ + "base64 0.21.0", + "bytes", + "http", + "http-body", + "hyper", + "pin-project", + "tokio-stream", + "tonic", + "tower-http", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "tower" version = "0.4.13" @@ -1899,6 +1926,24 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower-http" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c5bb1d698276a2443e5ecfabc1008bf15a36c12e6a7176e7bf089ea9131140" +dependencies = [ + "bitflags 2.4.0", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-range-header", + "pin-project-lite", + "tower-layer", + "tower-service", +] + [[package]] name = "tower-layer" version = "0.3.2" diff --git a/console-subscriber/Cargo.toml b/console-subscriber/Cargo.toml index 7bdf8c8ef..a4b053390 100644 --- a/console-subscriber/Cargo.toml +++ b/console-subscriber/Cargo.toml @@ -28,6 +28,7 @@ keywords = [ default = ["env-filter"] parking_lot = ["parking_lot_crate", "tracing-subscriber/parking_lot"] env-filter = ["tracing-subscriber/env-filter"] +grpc-web = ["tonic-web"] [dependencies] @@ -54,6 +55,9 @@ serde = { version = "1", features = ["derive"] } serde_json = "1" crossbeam-channel = "0.5" +# Only for the web feature: +tonic-web = { version = "0.10.2", optional = true } + [dev-dependencies] tokio = { version = "^1.21", features = ["full", "rt-multi-thread"] } tower = { version = "0.4", default-features = false } @@ -62,3 +66,7 @@ futures = "0.3" [package.metadata.docs.rs] all-features = true rustdoc-args = ["--cfg", "docsrs"] + +[[example]] +name = "grpc_web" +required-features = ["grpc-web"] diff --git a/console-subscriber/examples/grpc_web.rs b/console-subscriber/examples/grpc_web.rs new file mode 100644 index 000000000..021033b42 --- /dev/null +++ b/console-subscriber/examples/grpc_web.rs @@ -0,0 +1,165 @@ +//! Example of using the console subscriber with tonic-web. +//! This example requires the `grpc-web` feature to be enabled. +//! Run with: +//! ```sh +//! cargo run --example grpc_web --features grpc-web +//! ``` +use std::time::Duration; + +use console_subscriber::ConsoleLayer; + +static HELP: &str = r#" +Example console-instrumented app + +USAGE: + app [OPTIONS] + +OPTIONS: + -h, help prints this message + blocks Includes a (misbehaving) blocking task + burn Includes a (misbehaving) task that spins CPU with self-wakes + coma Includes a (misbehaving) task that forgets to register a waker + noyield Includes a (misbehaving) task that spawns tasks that never yield +"#; + +#[tokio::main] +async fn main() -> Result<(), Box> { + ConsoleLayer::builder() + .with_default_env() + .enable_grpc_web(true) + .init(); + // spawn optional extras from CLI args + // skip first which is command name + for opt in std::env::args().skip(1) { + match &*opt { + "blocks" => { + tokio::task::Builder::new() + .name("blocks") + .spawn(double_sleepy(1, 10)) + .unwrap(); + } + "coma" => { + tokio::task::Builder::new() + .name("coma") + .spawn(std::future::pending::<()>()) + .unwrap(); + } + "burn" => { + tokio::task::Builder::new() + .name("burn") + .spawn(burn(1, 10)) + .unwrap(); + } + "noyield" => { + tokio::task::Builder::new() + .name("noyield") + .spawn(no_yield(20)) + .unwrap(); + } + "blocking" => { + tokio::task::Builder::new() + .name("spawns_blocking") + .spawn(spawn_blocking(5)) + .unwrap(); + } + "help" | "-h" => { + eprintln!("{}", HELP); + return Ok(()); + } + wat => { + return Err( + format!("unknown option: {:?}, run with '-h' to see options", wat).into(), + ) + } + } + } + + let task1 = tokio::task::Builder::new() + .name("task1") + .spawn(spawn_tasks(1, 10)) + .unwrap(); + let task2 = tokio::task::Builder::new() + .name("task2") + .spawn(spawn_tasks(10, 30)) + .unwrap(); + + let result = tokio::try_join! { + task1, + task2, + }; + result?; + + Ok(()) +} + +#[tracing::instrument] +async fn spawn_tasks(min: u64, max: u64) { + loop { + for i in min..max { + tracing::trace!(i, "spawning wait task"); + tokio::task::Builder::new() + .name("wait") + .spawn(wait(i)) + .unwrap(); + + let sleep = Duration::from_secs(max) - Duration::from_secs(i); + tracing::trace!(?sleep, "sleeping..."); + tokio::time::sleep(sleep).await; + } + } +} + +#[tracing::instrument] +async fn wait(seconds: u64) { + tracing::debug!("waiting..."); + tokio::time::sleep(Duration::from_secs(seconds)).await; + tracing::trace!("done!"); +} + +#[tracing::instrument] +async fn double_sleepy(min: u64, max: u64) { + loop { + for i in min..max { + // woops! + std::thread::sleep(Duration::from_secs(i)); + tokio::time::sleep(Duration::from_secs(max - i)).await; + } + } +} + +#[tracing::instrument] +async fn burn(min: u64, max: u64) { + loop { + for i in min..max { + for _ in 0..i { + tokio::task::yield_now().await; + } + tokio::time::sleep(Duration::from_secs(i - min)).await; + } + } +} + +#[tracing::instrument] +async fn no_yield(seconds: u64) { + loop { + let handle = tokio::task::Builder::new() + .name("greedy") + .spawn(async move { + std::thread::sleep(Duration::from_secs(seconds)); + }) + .expect("Couldn't spawn greedy task"); + + _ = handle.await; + } +} + +#[tracing::instrument] +async fn spawn_blocking(seconds: u64) { + loop { + let seconds = seconds; + _ = tokio::task::spawn_blocking(move || { + std::thread::sleep(Duration::from_secs(seconds)); + }) + .await; + } +} diff --git a/console-subscriber/src/builder.rs b/console-subscriber/src/builder.rs index 58c5d9535..358bc4327 100644 --- a/console-subscriber/src/builder.rs +++ b/console-subscriber/src/builder.rs @@ -56,6 +56,10 @@ pub struct Builder { /// Any scheduled times exceeding this duration will be clamped to this /// value. Higher values will result in more memory usage. pub(super) scheduled_duration_max: Duration, + + #[cfg(feature = "grpc-web")] + /// Whether to enable gRPC web support. + enable_grpc_web: bool, } impl Default for Builder { @@ -71,6 +75,8 @@ impl Default for Builder { recording_path: None, filter_env_var: "RUST_LOG".to_string(), self_trace: false, + #[cfg(feature = "grpc-web")] + enable_grpc_web: false, } } } @@ -268,6 +274,17 @@ impl Builder { Self { self_trace, ..self } } + #[cfg(feature = "grpc-web")] + /// Sets whether to enable gRPC web support. + /// + /// By default, gRPC web support is disabled. + pub fn enable_grpc_web(self, enable_grpc_web: bool) -> Self { + Self { + enable_grpc_web, + ..self + } + } + /// Completes the builder, returning a [`ConsoleLayer`] and [`Server`] task. pub fn build(self) -> (ConsoleLayer, Server) { ConsoleLayer::build(self) @@ -481,6 +498,8 @@ impl Builder { } let self_trace = self.self_trace; + #[cfg(feature = "grpc-web")] + let enable_grpc_web = self.enable_grpc_web; let (layer, server) = self.build(); let filter = @@ -501,8 +520,21 @@ impl Builder { .enable_time() .build() .expect("console subscriber runtime initialization failed"); - runtime.block_on(async move { + #[cfg(feature = "grpc-web")] + if enable_grpc_web { + server + .serve_with_grpc_web() + .await + .expect("console subscriber server failed") + } else { + server + .serve() + .await + .expect("console subscriber server failed") + } + + #[cfg(not(feature = "grpc-web"))] server .serve() .await diff --git a/console-subscriber/src/lib.rs b/console-subscriber/src/lib.rs index fde18af8d..31b11447e 100644 --- a/console-subscriber/src/lib.rs +++ b/console-subscriber/src/lib.rs @@ -922,7 +922,39 @@ impl Server { /// ``` /// [`serve_with`]: Server::serve_with pub async fn serve(self) -> Result<(), Box> { - self.serve_with(tonic::transport::Server::default()).await + self.serve_with(tonic::transport::Server::builder()).await + } + + #[cfg(feature = "grpc-web")] + /// Starts the gRPC service with the default gRPC settings and gRPC-Web + /// support. + pub async fn serve_with_grpc_web( + self, + ) -> Result<(), Box> { + let builder = tonic::transport::Server::builder(); + let addr = self.addr.clone(); + let ServerParts { + instrument_server, + aggregator, + } = self.into_parts(); + let aggregate = spawn_named(aggregator.run(), "console::aggregate"); + let router = builder + .accept_http1(true) + .add_service(tonic_web::enable(instrument_server)); + let res = match addr { + ServerAddr::Tcp(addr) => { + let serve = router.serve(addr); + spawn_named(serve, "console::serve").await + } + #[cfg(unix)] + ServerAddr::Unix(path) => { + let incoming = UnixListener::bind(path)?; + let serve = router.serve_with_incoming(UnixListenerStream::new(incoming)); + spawn_named(serve, "console::serve").await + } + }; + aggregate.abort(); + res?.map_err(Into::into) } /// Starts the gRPC service with the given [`tonic`] gRPC transport server From 884f153eefa9c7953925115db9c8a5e03345c084 Mon Sep 17 00:00:00 2001 From: hi-rustin Date: Mon, 22 Jan 2024 23:33:41 +0800 Subject: [PATCH 02/15] feat: add cors layer Signed-off-by: hi-rustin --- Cargo.lock | 2 ++ console-subscriber/Cargo.toml | 4 +++- console-subscriber/examples/grpc_web.rs | 28 ++++++++++++++++++++++++- console-subscriber/src/builder.rs | 19 +++++++---------- console-subscriber/src/lib.rs | 5 ++++- 5 files changed, 44 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fadd4c0b9..a92522293 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -327,6 +327,7 @@ dependencies = [ "futures", "futures-task", "hdrhistogram", + "http", "humantime", "parking_lot", "prost", @@ -339,6 +340,7 @@ dependencies = [ "tonic", "tonic-web", "tower", + "tower-http", "tracing", "tracing-core", "tracing-subscriber", diff --git a/console-subscriber/Cargo.toml b/console-subscriber/Cargo.toml index a4b053390..ae7201e40 100644 --- a/console-subscriber/Cargo.toml +++ b/console-subscriber/Cargo.toml @@ -28,7 +28,7 @@ keywords = [ default = ["env-filter"] parking_lot = ["parking_lot_crate", "tracing-subscriber/parking_lot"] env-filter = ["tracing-subscriber/env-filter"] -grpc-web = ["tonic-web"] +grpc-web = ["tonic-web", "tower-http"] [dependencies] @@ -57,11 +57,13 @@ crossbeam-channel = "0.5" # Only for the web feature: tonic-web = { version = "0.10.2", optional = true } +tower-http = { version = "0.4", features = ["cors"], optional = true } [dev-dependencies] tokio = { version = "^1.21", features = ["full", "rt-multi-thread"] } tower = { version = "0.4", default-features = false } futures = "0.3" +http = "0.2" [package.metadata.docs.rs] all-features = true diff --git a/console-subscriber/examples/grpc_web.rs b/console-subscriber/examples/grpc_web.rs index 021033b42..c9643f7c7 100644 --- a/console-subscriber/examples/grpc_web.rs +++ b/console-subscriber/examples/grpc_web.rs @@ -7,6 +7,8 @@ use std::time::Duration; use console_subscriber::ConsoleLayer; +use http::header::HeaderName; +use tower_http::cors::{AllowOrigin, CorsLayer}; static HELP: &str = r#" Example console-instrumented app @@ -22,11 +24,35 @@ OPTIONS: noyield Includes a (misbehaving) task that spawns tasks that never yield "#; +const DEFAULT_MAX_AGE: Duration = Duration::from_secs(24 * 60 * 60); +const DEFAULT_EXPOSED_HEADERS: [&str; 3] = + ["grpc-status", "grpc-message", "grpc-status-details-bin"]; +const DEFAULT_ALLOW_HEADERS: [&str; 4] = + ["x-grpc-web", "content-type", "x-user-agent", "grpc-timeout"]; + #[tokio::main] async fn main() -> Result<(), Box> { + let cors = CorsLayer::new() + .allow_origin(AllowOrigin::mirror_request()) + .allow_credentials(true) + .max_age(DEFAULT_MAX_AGE) + .expose_headers( + DEFAULT_EXPOSED_HEADERS + .iter() + .cloned() + .map(HeaderName::from_static) + .collect::>(), + ) + .allow_headers( + DEFAULT_ALLOW_HEADERS + .iter() + .cloned() + .map(HeaderName::from_static) + .collect::>(), + ); ConsoleLayer::builder() .with_default_env() - .enable_grpc_web(true) + .with_cors(cors) .init(); // spawn optional extras from CLI args // skip first which is command name diff --git a/console-subscriber/src/builder.rs b/console-subscriber/src/builder.rs index 358bc4327..b3f434988 100644 --- a/console-subscriber/src/builder.rs +++ b/console-subscriber/src/builder.rs @@ -58,8 +58,8 @@ pub struct Builder { pub(super) scheduled_duration_max: Duration, #[cfg(feature = "grpc-web")] - /// Whether to enable gRPC web support. - enable_grpc_web: bool, + /// Cors layer for grpc-web. + cors_layer: Option, } impl Default for Builder { @@ -76,7 +76,7 @@ impl Default for Builder { filter_env_var: "RUST_LOG".to_string(), self_trace: false, #[cfg(feature = "grpc-web")] - enable_grpc_web: false, + cors_layer: None, } } } @@ -275,12 +275,9 @@ impl Builder { } #[cfg(feature = "grpc-web")] - /// Sets whether to enable gRPC web support. - /// - /// By default, gRPC web support is disabled. - pub fn enable_grpc_web(self, enable_grpc_web: bool) -> Self { + pub fn with_cors(self, cors: tower_http::cors::CorsLayer) -> Self { Self { - enable_grpc_web, + cors_layer: Some(cors), ..self } } @@ -499,7 +496,7 @@ impl Builder { let self_trace = self.self_trace; #[cfg(feature = "grpc-web")] - let enable_grpc_web = self.enable_grpc_web; + let cors_layer = self.cors_layer.clone(); let (layer, server) = self.build(); let filter = @@ -522,9 +519,9 @@ impl Builder { .expect("console subscriber runtime initialization failed"); runtime.block_on(async move { #[cfg(feature = "grpc-web")] - if enable_grpc_web { + if cors_layer.is_some() { server - .serve_with_grpc_web() + .serve_with_grpc_web(cors_layer.unwrap()) .await .expect("console subscriber server failed") } else { diff --git a/console-subscriber/src/lib.rs b/console-subscriber/src/lib.rs index 31b11447e..4c9c9fb5a 100644 --- a/console-subscriber/src/lib.rs +++ b/console-subscriber/src/lib.rs @@ -930,6 +930,7 @@ impl Server { /// support. pub async fn serve_with_grpc_web( self, + cors: tower_http::cors::CorsLayer, ) -> Result<(), Box> { let builder = tonic::transport::Server::builder(); let addr = self.addr.clone(); @@ -940,7 +941,9 @@ impl Server { let aggregate = spawn_named(aggregator.run(), "console::aggregate"); let router = builder .accept_http1(true) - .add_service(tonic_web::enable(instrument_server)); + .layer(cors) + .layer(tonic_web::GrpcWebLayer::new()) + .add_service(instrument_server); let res = match addr { ServerAddr::Tcp(addr) => { let serve = router.serve(addr); From 1f6c9510a43f4f7cddc62a7e069c1968637488bf Mon Sep 17 00:00:00 2001 From: hi-rustin Date: Tue, 23 Jan 2024 22:20:22 +0800 Subject: [PATCH 03/15] refactor: reuse code Signed-off-by: hi-rustin --- console-subscriber/Cargo.toml | 3 ++- console-subscriber/src/lib.rs | 40 +++++++++++++---------------------- 2 files changed, 17 insertions(+), 26 deletions(-) diff --git a/console-subscriber/Cargo.toml b/console-subscriber/Cargo.toml index ae7201e40..d7f3655cd 100644 --- a/console-subscriber/Cargo.toml +++ b/console-subscriber/Cargo.toml @@ -28,7 +28,7 @@ keywords = [ default = ["env-filter"] parking_lot = ["parking_lot_crate", "tracing-subscriber/parking_lot"] env-filter = ["tracing-subscriber/env-filter"] -grpc-web = ["tonic-web", "tower-http"] +grpc-web = ["tonic-web", "tower-http", "tower"] [dependencies] @@ -58,6 +58,7 @@ crossbeam-channel = "0.5" # Only for the web feature: tonic-web = { version = "0.10.2", optional = true } tower-http = { version = "0.4", features = ["cors"], optional = true } +tower = { version = "0.4", default-features = false, optional = true} [dev-dependencies] tokio = { version = "^1.21", features = ["full", "rt-multi-thread"] } diff --git a/console-subscriber/src/lib.rs b/console-subscriber/src/lib.rs index 4c9c9fb5a..52ee0cedb 100644 --- a/console-subscriber/src/lib.rs +++ b/console-subscriber/src/lib.rs @@ -21,6 +21,7 @@ use tokio::{ }; #[cfg(unix)] use tokio_stream::wrappers::UnixListenerStream; + use tracing_core::{ span::{self, Id}, subscriber::{self, Subscriber}, @@ -908,6 +909,7 @@ impl Server { /// [environment variable]: `Builder::with_default_env` pub const DEFAULT_PORT: u16 = 6669; + #[cfg(not(feature = "grpc-web"))] /// Starts the gRPC service with the default gRPC settings. /// /// To configure gRPC server settings before starting the server, use @@ -932,32 +934,11 @@ impl Server { self, cors: tower_http::cors::CorsLayer, ) -> Result<(), Box> { - let builder = tonic::transport::Server::builder(); - let addr = self.addr.clone(); - let ServerParts { - instrument_server, - aggregator, - } = self.into_parts(); - let aggregate = spawn_named(aggregator.run(), "console::aggregate"); - let router = builder + let builder = tonic::transport::Server::builder() .accept_http1(true) .layer(cors) - .layer(tonic_web::GrpcWebLayer::new()) - .add_service(instrument_server); - let res = match addr { - ServerAddr::Tcp(addr) => { - let serve = router.serve(addr); - spawn_named(serve, "console::serve").await - } - #[cfg(unix)] - ServerAddr::Unix(path) => { - let incoming = UnixListener::bind(path)?; - let serve = router.serve_with_incoming(UnixListenerStream::new(incoming)); - spawn_named(serve, "console::serve").await - } - }; - aggregate.abort(); - res?.map_err(Into::into) + .layer(tonic_web::GrpcWebLayer::new()); + self.serve_with(builder).await } /// Starts the gRPC service with the given [`tonic`] gRPC transport server @@ -972,7 +953,16 @@ impl Server { /// [`tonic`]: https://docs.rs/tonic/ pub async fn serve_with( self, - mut builder: tonic::transport::Server, + #[cfg(not(feature = "grpc-web"))] mut builder: tonic::transport::Server, + #[cfg(feature = "grpc-web")] mut builder: tonic::transport::Server< + tower::layer::util::Stack< + tonic_web::GrpcWebLayer, + tower::layer::util::Stack< + tower_http::cors::CorsLayer, + tower::layer::util::Identity, + >, + >, + >, ) -> Result<(), Box> { let addr = self.addr.clone(); let ServerParts { From 37acf978591121961938ac41517b1d81c793a09d Mon Sep 17 00:00:00 2001 From: hi-rustin Date: Tue, 30 Jan 2024 22:33:59 +0800 Subject: [PATCH 04/15] fix: do not change server_with Signed-off-by: hi-rustin --- console-subscriber/Cargo.toml | 4 +--- console-subscriber/src/builder.rs | 14 +++++------ console-subscriber/src/lib.rs | 39 ++++++++++++++++++++----------- 3 files changed, 32 insertions(+), 25 deletions(-) diff --git a/console-subscriber/Cargo.toml b/console-subscriber/Cargo.toml index d7f3655cd..cf5ae3a79 100644 --- a/console-subscriber/Cargo.toml +++ b/console-subscriber/Cargo.toml @@ -28,10 +28,9 @@ keywords = [ default = ["env-filter"] parking_lot = ["parking_lot_crate", "tracing-subscriber/parking_lot"] env-filter = ["tracing-subscriber/env-filter"] -grpc-web = ["tonic-web", "tower-http", "tower"] +grpc-web = ["tonic-web", "tower-http"] [dependencies] - crossbeam-utils = "0.8.7" tokio = { version = "^1.21", features = ["sync", "time", "macros", "tracing"] } tokio-stream = { version = "0.1", features = ["net"] } @@ -58,7 +57,6 @@ crossbeam-channel = "0.5" # Only for the web feature: tonic-web = { version = "0.10.2", optional = true } tower-http = { version = "0.4", features = ["cors"], optional = true } -tower = { version = "0.4", default-features = false, optional = true} [dev-dependencies] tokio = { version = "^1.21", features = ["full", "rt-multi-thread"] } diff --git a/console-subscriber/src/builder.rs b/console-subscriber/src/builder.rs index b3f434988..e7348b915 100644 --- a/console-subscriber/src/builder.rs +++ b/console-subscriber/src/builder.rs @@ -521,17 +521,15 @@ impl Builder { #[cfg(feature = "grpc-web")] if cors_layer.is_some() { server - .serve_with_grpc_web(cors_layer.unwrap()) + .serve_with_grpc_web( + tonic::transport::Server::builder(), + cors_layer.unwrap(), + ) .await - .expect("console subscriber server failed") - } else { - server - .serve() - .await - .expect("console subscriber server failed") + .expect("console subscriber server failed"); + return; } - #[cfg(not(feature = "grpc-web"))] server .serve() .await diff --git a/console-subscriber/src/lib.rs b/console-subscriber/src/lib.rs index 52ee0cedb..839e6bd69 100644 --- a/console-subscriber/src/lib.rs +++ b/console-subscriber/src/lib.rs @@ -909,7 +909,6 @@ impl Server { /// [environment variable]: `Builder::with_default_env` pub const DEFAULT_PORT: u16 = 6669; - #[cfg(not(feature = "grpc-web"))] /// Starts the gRPC service with the default gRPC settings. /// /// To configure gRPC server settings before starting the server, use @@ -932,13 +931,34 @@ impl Server { /// support. pub async fn serve_with_grpc_web( self, + builder: tonic::transport::Server, cors: tower_http::cors::CorsLayer, ) -> Result<(), Box> { - let builder = tonic::transport::Server::builder() + let addr = self.addr.clone(); + let ServerParts { + instrument_server, + aggregator, + } = self.into_parts(); + let router = builder .accept_http1(true) .layer(cors) - .layer(tonic_web::GrpcWebLayer::new()); - self.serve_with(builder).await + .layer(tonic_web::GrpcWebLayer::new()) + .add_service(instrument_server); + let aggregate = spawn_named(aggregator.run(), "console::aggregate"); + let res = match addr { + ServerAddr::Tcp(addr) => { + let serve = router.serve(addr); + spawn_named(serve, "console::serve").await + } + #[cfg(unix)] + ServerAddr::Unix(path) => { + let incoming = UnixListener::bind(path)?; + let serve = router.serve_with_incoming(UnixListenerStream::new(incoming)); + spawn_named(serve, "console::serve").await + } + }; + aggregate.abort(); + res?.map_err(Into::into) } /// Starts the gRPC service with the given [`tonic`] gRPC transport server @@ -953,16 +973,7 @@ impl Server { /// [`tonic`]: https://docs.rs/tonic/ pub async fn serve_with( self, - #[cfg(not(feature = "grpc-web"))] mut builder: tonic::transport::Server, - #[cfg(feature = "grpc-web")] mut builder: tonic::transport::Server< - tower::layer::util::Stack< - tonic_web::GrpcWebLayer, - tower::layer::util::Stack< - tower_http::cors::CorsLayer, - tower::layer::util::Identity, - >, - >, - >, + mut builder: tonic::transport::Server, ) -> Result<(), Box> { let addr = self.addr.clone(); let ServerParts { From 54642d497a808dc4059787433ff2d1e5aab2c631 Mon Sep 17 00:00:00 2001 From: hi-rustin Date: Tue, 30 Jan 2024 23:18:58 +0800 Subject: [PATCH 05/15] docs: update desc Signed-off-by: hi-rustin --- console-subscriber/examples/grpc_web.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/console-subscriber/examples/grpc_web.rs b/console-subscriber/examples/grpc_web.rs index c9643f7c7..e55bab6c3 100644 --- a/console-subscriber/examples/grpc_web.rs +++ b/console-subscriber/examples/grpc_web.rs @@ -11,7 +11,7 @@ use http::header::HeaderName; use tower_http::cors::{AllowOrigin, CorsLayer}; static HELP: &str = r#" -Example console-instrumented app +Example console-instrumented app with gRPC-Web support. USAGE: app [OPTIONS] From 6dde80304cfbecf8bb0ddd1a5e0b5c799f5719c8 Mon Sep 17 00:00:00 2001 From: hi-rustin Date: Sun, 4 Feb 2024 22:44:56 +0800 Subject: [PATCH 06/15] fix: do not depend on cors Signed-off-by: hi-rustin --- console-subscriber/Cargo.toml | 4 +- console-subscriber/examples/grpc_web.rs | 195 ++++++++---------------- console-subscriber/src/builder.rs | 19 +-- console-subscriber/src/lib.rs | 47 +++--- 4 files changed, 95 insertions(+), 170 deletions(-) diff --git a/console-subscriber/Cargo.toml b/console-subscriber/Cargo.toml index cf5ae3a79..6e7e48cd4 100644 --- a/console-subscriber/Cargo.toml +++ b/console-subscriber/Cargo.toml @@ -28,7 +28,7 @@ keywords = [ default = ["env-filter"] parking_lot = ["parking_lot_crate", "tracing-subscriber/parking_lot"] env-filter = ["tracing-subscriber/env-filter"] -grpc-web = ["tonic-web", "tower-http"] +grpc-web = ["tonic-web"] [dependencies] crossbeam-utils = "0.8.7" @@ -56,13 +56,13 @@ crossbeam-channel = "0.5" # Only for the web feature: tonic-web = { version = "0.10.2", optional = true } -tower-http = { version = "0.4", features = ["cors"], optional = true } [dev-dependencies] tokio = { version = "^1.21", features = ["full", "rt-multi-thread"] } tower = { version = "0.4", default-features = false } futures = "0.3" http = "0.2" +tower-http = { version = "0.4", features = ["cors"] } [package.metadata.docs.rs] all-features = true diff --git a/console-subscriber/examples/grpc_web.rs b/console-subscriber/examples/grpc_web.rs index e55bab6c3..3d90ac819 100644 --- a/console-subscriber/examples/grpc_web.rs +++ b/console-subscriber/examples/grpc_web.rs @@ -4,101 +4,80 @@ //! ```sh //! cargo run --example grpc_web --features grpc-web //! ``` -use std::time::Duration; +use std::{thread, time::Duration}; -use console_subscriber::ConsoleLayer; +use console_subscriber::{ConsoleLayer, ServerParts}; use http::header::HeaderName; +use tonic_web::GrpcWebLayer; use tower_http::cors::{AllowOrigin, CorsLayer}; - -static HELP: &str = r#" -Example console-instrumented app with gRPC-Web support. - -USAGE: - app [OPTIONS] - -OPTIONS: - -h, help prints this message - blocks Includes a (misbehaving) blocking task - burn Includes a (misbehaving) task that spins CPU with self-wakes - coma Includes a (misbehaving) task that forgets to register a waker - noyield Includes a (misbehaving) task that spawns tasks that never yield -"#; +use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; const DEFAULT_MAX_AGE: Duration = Duration::from_secs(24 * 60 * 60); const DEFAULT_EXPOSED_HEADERS: [&str; 3] = ["grpc-status", "grpc-message", "grpc-status-details-bin"]; -const DEFAULT_ALLOW_HEADERS: [&str; 4] = - ["x-grpc-web", "content-type", "x-user-agent", "grpc-timeout"]; +const DEFAULT_ALLOW_HEADERS: [&str; 5] = [ + "x-grpc-web", + "content-type", + "x-user-agent", + "grpc-timeout", + "user-agent", +]; #[tokio::main] async fn main() -> Result<(), Box> { - let cors = CorsLayer::new() - .allow_origin(AllowOrigin::mirror_request()) - .allow_credentials(true) - .max_age(DEFAULT_MAX_AGE) - .expose_headers( - DEFAULT_EXPOSED_HEADERS - .iter() - .cloned() - .map(HeaderName::from_static) - .collect::>(), - ) - .allow_headers( - DEFAULT_ALLOW_HEADERS - .iter() - .cloned() - .map(HeaderName::from_static) - .collect::>(), - ); - ConsoleLayer::builder() - .with_default_env() - .with_cors(cors) - .init(); - // spawn optional extras from CLI args - // skip first which is command name - for opt in std::env::args().skip(1) { - match &*opt { - "blocks" => { - tokio::task::Builder::new() - .name("blocks") - .spawn(double_sleepy(1, 10)) - .unwrap(); - } - "coma" => { - tokio::task::Builder::new() - .name("coma") - .spawn(std::future::pending::<()>()) - .unwrap(); - } - "burn" => { - tokio::task::Builder::new() - .name("burn") - .spawn(burn(1, 10)) - .unwrap(); - } - "noyield" => { - tokio::task::Builder::new() - .name("noyield") - .spawn(no_yield(20)) - .unwrap(); - } - "blocking" => { - tokio::task::Builder::new() - .name("spawns_blocking") - .spawn(spawn_blocking(5)) - .unwrap(); - } - "help" | "-h" => { - eprintln!("{}", HELP); - return Ok(()); - } - wat => { - return Err( - format!("unknown option: {:?}, run with '-h' to see options", wat).into(), + let (console_layer, server) = ConsoleLayer::builder().with_default_env().build(); + thread::Builder::new() + .name("subscriber".into()) + .spawn(move || { + // Do not trace anything in this thread. + let _subscriber_guard; + _subscriber_guard = + tracing::subscriber::set_default(tracing_core::subscriber::NoSubscriber::default()); + // Custom CORS configuration. + let cors = CorsLayer::new() + .allow_origin(AllowOrigin::mirror_request()) + .allow_credentials(true) + .max_age(DEFAULT_MAX_AGE) + .expose_headers( + DEFAULT_EXPOSED_HEADERS + .iter() + .cloned() + .map(HeaderName::from_static) + .collect::>(), ) - } - } - } + .allow_headers( + DEFAULT_ALLOW_HEADERS + .iter() + .cloned() + .map(HeaderName::from_static) + .collect::>(), + ); + let runtime = tokio::runtime::Builder::new_current_thread() + .enable_all() + .build() + .expect("console subscriber runtime initialization failed"); + runtime.block_on(async move { + let ServerParts { + instrument_server, + aggregator, + .. + } = server.into_parts(); + tokio::spawn(aggregator.run()); + let router = tonic::transport::Server::builder() + // Accept gRPC-Web requests and enable CORS. + .accept_http1(true) + .layer(cors) + .layer(GrpcWebLayer::new()) + .add_service(instrument_server); + let serve = router.serve(std::net::SocketAddr::new( + std::net::IpAddr::V4(std::net::Ipv4Addr::new(127, 0, 0, 1)), + 9999, + )); + serve.await.expect("console subscriber server failed"); + }); + }) + .expect("console subscriber could not spawn thread"); + tracing_subscriber::registry().with(console_layer).init(); let task1 = tokio::task::Builder::new() .name("task1") @@ -141,51 +120,3 @@ async fn wait(seconds: u64) { tokio::time::sleep(Duration::from_secs(seconds)).await; tracing::trace!("done!"); } - -#[tracing::instrument] -async fn double_sleepy(min: u64, max: u64) { - loop { - for i in min..max { - // woops! - std::thread::sleep(Duration::from_secs(i)); - tokio::time::sleep(Duration::from_secs(max - i)).await; - } - } -} - -#[tracing::instrument] -async fn burn(min: u64, max: u64) { - loop { - for i in min..max { - for _ in 0..i { - tokio::task::yield_now().await; - } - tokio::time::sleep(Duration::from_secs(i - min)).await; - } - } -} - -#[tracing::instrument] -async fn no_yield(seconds: u64) { - loop { - let handle = tokio::task::Builder::new() - .name("greedy") - .spawn(async move { - std::thread::sleep(Duration::from_secs(seconds)); - }) - .expect("Couldn't spawn greedy task"); - - _ = handle.await; - } -} - -#[tracing::instrument] -async fn spawn_blocking(seconds: u64) { - loop { - let seconds = seconds; - _ = tokio::task::spawn_blocking(move || { - std::thread::sleep(Duration::from_secs(seconds)); - }) - .await; - } -} diff --git a/console-subscriber/src/builder.rs b/console-subscriber/src/builder.rs index e7348b915..15ca149fa 100644 --- a/console-subscriber/src/builder.rs +++ b/console-subscriber/src/builder.rs @@ -58,8 +58,8 @@ pub struct Builder { pub(super) scheduled_duration_max: Duration, #[cfg(feature = "grpc-web")] - /// Cors layer for grpc-web. - cors_layer: Option, + /// Whether to enable the grpc-web support. + enable_grpc_web: bool, } impl Default for Builder { @@ -76,7 +76,7 @@ impl Default for Builder { filter_env_var: "RUST_LOG".to_string(), self_trace: false, #[cfg(feature = "grpc-web")] - cors_layer: None, + enable_grpc_web: false, } } } @@ -275,9 +275,9 @@ impl Builder { } #[cfg(feature = "grpc-web")] - pub fn with_cors(self, cors: tower_http::cors::CorsLayer) -> Self { + pub fn enable_grpc_web(self, enable_grpc_web: bool) -> Self { Self { - cors_layer: Some(cors), + enable_grpc_web, ..self } } @@ -496,7 +496,7 @@ impl Builder { let self_trace = self.self_trace; #[cfg(feature = "grpc-web")] - let cors_layer = self.cors_layer.clone(); + let enable_grpc_web = self.enable_grpc_web; let (layer, server) = self.build(); let filter = @@ -519,12 +519,9 @@ impl Builder { .expect("console subscriber runtime initialization failed"); runtime.block_on(async move { #[cfg(feature = "grpc-web")] - if cors_layer.is_some() { + if enable_grpc_web { server - .serve_with_grpc_web( - tonic::transport::Server::builder(), - cors_layer.unwrap(), - ) + .serve_with_grpc_web(tonic::transport::Server::builder()) .await .expect("console subscriber server failed"); return; diff --git a/console-subscriber/src/lib.rs b/console-subscriber/src/lib.rs index 839e6bd69..c524aed64 100644 --- a/console-subscriber/src/lib.rs +++ b/console-subscriber/src/lib.rs @@ -923,28 +923,30 @@ impl Server { /// ``` /// [`serve_with`]: Server::serve_with pub async fn serve(self) -> Result<(), Box> { - self.serve_with(tonic::transport::Server::builder()).await + self.serve_with(tonic::transport::Server::default()).await } - #[cfg(feature = "grpc-web")] - /// Starts the gRPC service with the default gRPC settings and gRPC-Web - /// support. - pub async fn serve_with_grpc_web( + /// Starts the gRPC service with the given [`tonic`] gRPC transport server + /// `builder`. + /// + /// The `builder` parameter may be used to configure gRPC-specific settings + /// prior to starting the server. + /// + /// This spawns both the server task and the event aggregation worker + /// task on the current async runtime. + /// + /// [`tonic`]: https://docs.rs/tonic/ + pub async fn serve_with( self, - builder: tonic::transport::Server, - cors: tower_http::cors::CorsLayer, + mut builder: tonic::transport::Server, ) -> Result<(), Box> { let addr = self.addr.clone(); let ServerParts { instrument_server, aggregator, } = self.into_parts(); - let router = builder - .accept_http1(true) - .layer(cors) - .layer(tonic_web::GrpcWebLayer::new()) - .add_service(instrument_server); let aggregate = spawn_named(aggregator.run(), "console::aggregate"); + let router = builder.add_service(instrument_server); let res = match addr { ServerAddr::Tcp(addr) => { let serve = router.serve(addr); @@ -961,27 +963,22 @@ impl Server { res?.map_err(Into::into) } - /// Starts the gRPC service with the given [`tonic`] gRPC transport server - /// `builder`. - /// - /// The `builder` parameter may be used to configure gRPC-specific settings - /// prior to starting the server. - /// - /// This spawns both the server task and the event aggregation worker - /// task on the current async runtime. - /// - /// [`tonic`]: https://docs.rs/tonic/ - pub async fn serve_with( + #[cfg(feature = "grpc-web")] + /// Starts the gRPC service with the default gRPC settings and gRPC-Web + /// support. + pub async fn serve_with_grpc_web( self, - mut builder: tonic::transport::Server, + builder: tonic::transport::Server, ) -> Result<(), Box> { let addr = self.addr.clone(); let ServerParts { instrument_server, aggregator, } = self.into_parts(); + let router = builder + .accept_http1(true) + .add_service(tonic_web::enable(instrument_server)); let aggregate = spawn_named(aggregator.run(), "console::aggregate"); - let router = builder.add_service(instrument_server); let res = match addr { ServerAddr::Tcp(addr) => { let serve = router.serve(addr); From 9b7c210900239f01539f1ab355cfce977fa9fb87 Mon Sep 17 00:00:00 2001 From: hi-rustin Date: Sun, 4 Feb 2024 22:58:25 +0800 Subject: [PATCH 07/15] chore: remove new line Signed-off-by: hi-rustin --- console-subscriber/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/console-subscriber/src/lib.rs b/console-subscriber/src/lib.rs index c524aed64..403771056 100644 --- a/console-subscriber/src/lib.rs +++ b/console-subscriber/src/lib.rs @@ -21,7 +21,6 @@ use tokio::{ }; #[cfg(unix)] use tokio_stream::wrappers::UnixListenerStream; - use tracing_core::{ span::{self, Id}, subscriber::{self, Subscriber}, From 96e5c0df60b2a4374c6247b40aa76644be3c70ea Mon Sep 17 00:00:00 2001 From: hi-rustin Date: Sat, 10 Feb 2024 10:15:18 +0800 Subject: [PATCH 08/15] docs: add docs for enable_grpc_web Signed-off-by: hi-rustin --- console-subscriber/examples/grpc_web.rs | 3 +-- console-subscriber/src/builder.rs | 10 ++++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/console-subscriber/examples/grpc_web.rs b/console-subscriber/examples/grpc_web.rs index 3d90ac819..c49cf4608 100644 --- a/console-subscriber/examples/grpc_web.rs +++ b/console-subscriber/examples/grpc_web.rs @@ -30,8 +30,7 @@ async fn main() -> Result<(), Box> { .name("subscriber".into()) .spawn(move || { // Do not trace anything in this thread. - let _subscriber_guard; - _subscriber_guard = + let _subscriber_guard = tracing::subscriber::set_default(tracing_core::subscriber::NoSubscriber::default()); // Custom CORS configuration. let cors = CorsLayer::new() diff --git a/console-subscriber/src/builder.rs b/console-subscriber/src/builder.rs index 15ca149fa..71a2707d0 100644 --- a/console-subscriber/src/builder.rs +++ b/console-subscriber/src/builder.rs @@ -275,6 +275,16 @@ impl Builder { } #[cfg(feature = "grpc-web")] + /// Sets whether to enable the grpc-web support. + /// + /// By default, this is `false`. If enabled, the console subscriber will + /// serve the gRPC-Web protocol in addition to the standard gRPC protocol. + /// This is useful for serving the console subscriber to web clients. + /// + /// [serve_with_grpc_web] is used to provide more advanced configuration + /// for the gRPC-Web server. + /// + /// [serve_with_grpc_web]: crate::Server::serve_with_grpc_web pub fn enable_grpc_web(self, enable_grpc_web: bool) -> Self { Self { enable_grpc_web, From fa50b4ce296d40190329e60227ac1bb6b42d5dff Mon Sep 17 00:00:00 2001 From: hi-rustin Date: Sat, 10 Feb 2024 10:54:55 +0800 Subject: [PATCH 09/15] docs: add examples for serve_with_grpc_web Signed-off-by: hi-rustin --- console-subscriber/examples/grpc_web.rs | 1 + console-subscriber/src/lib.rs | 95 +++++++++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/console-subscriber/examples/grpc_web.rs b/console-subscriber/examples/grpc_web.rs index c49cf4608..db2820d47 100644 --- a/console-subscriber/examples/grpc_web.rs +++ b/console-subscriber/examples/grpc_web.rs @@ -70,6 +70,7 @@ async fn main() -> Result<(), Box> { .add_service(instrument_server); let serve = router.serve(std::net::SocketAddr::new( std::net::IpAddr::V4(std::net::Ipv4Addr::new(127, 0, 0, 1)), + // 6669 is a restricted port on Chrome, so we cannot use it. We use a different port instead. 9999, )); serve.await.expect("console subscriber server failed"); diff --git a/console-subscriber/src/lib.rs b/console-subscriber/src/lib.rs index 403771056..46233d9ab 100644 --- a/console-subscriber/src/lib.rs +++ b/console-subscriber/src/lib.rs @@ -965,6 +965,101 @@ impl Server { #[cfg(feature = "grpc-web")] /// Starts the gRPC service with the default gRPC settings and gRPC-Web /// support. + /// + /// # Examples + /// + /// To serve the instrument server with gRPC-Web support with the default + /// settings: + /// + /// ```rust + /// # async fn docs() -> Result<(), Box> { + /// # let (_, server) = console_subscriber::ConsoleLayer::new(); + /// server.serve_with_grpc_web(tonic::transport::Server::default()).await + /// # } + /// ``` + /// + /// To serve the instrument server with gRPC-Web support and a custom CORS configuration, use the + /// following code: + /// + /// ```rust + /// # use std::{thread, time::Duration}; + /// # + /// use console_subscriber::{ConsoleLayer, ServerParts}; + /// use tonic_web::GrpcWebLayer; + /// use tower_web::cors::{CorsLayer, AllowOrigin}; + /// use http::header::HeaderName; + /// # use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; + /// # const DEFAULT_MAX_AGE: Duration = Duration::from_secs(24 * 60 * 60); + /// # const DEFAULT_EXPOSED_HEADERS: [&str; 3] = + /// # ["grpc-status", "grpc-message", "grpc-status-details-bin"]; + /// # const DEFAULT_ALLOW_HEADERS: [&str; 5] = [ + /// # "x-grpc-web", + /// # "content-type", + /// # "x-user-agent", + /// # "grpc-timeout", + /// # "user-agent", + /// # ]; + /// + /// let (console_layer, server) = ConsoleLayer::builder().with_default_env().build(); + /// # thread::Builder::new() + /// # .name("subscriber".into()) + /// # .spawn(move || { + /// // Customize the CORS configuration. + /// let cors = CorsLayer::new() + /// .allow_origin(AllowOrigin::mirror_request()) + /// .allow_credentials(true) + /// .max_age(DEFAULT_MAX_AGE) + /// .expose_headers( + /// DEFAULT_EXPOSED_HEADERS + /// .iter() + /// .cloned() + /// .map(HeaderName::from_static) + /// .collect::>(), + /// ) + /// .allow_headers( + /// DEFAULT_ALLOW_HEADERS + /// .iter() + /// .cloned() + /// .map(HeaderName::from_static) + /// .collect::>(), + /// ); + /// # let runtime = tokio::runtime::Builder::new_current_thread() + /// # .enable_all() + /// # .build() + /// # .expect("console subscriber runtime initialization failed"); + /// # runtime.block_on(async move { + /// + /// let ServerParts { + /// instrument_server, + /// aggregator, + /// .. + /// } = server.into_parts(); + /// tokio::spawn(aggregator.run()); + /// + /// // Serve the instrument server with gRPC-Web support and the CORS configuration. + /// let router = tonic::transport::Server::builder() + /// .accept_http1(true) + /// .layer(cors) + /// .layer(GrpcWebLayer::new()) + /// .add_service(instrument_server); + /// let serve = router.serve(std::net::SocketAddr::new( + /// std::net::IpAddr::V4(std::net::Ipv4Addr::new(127, 0, 0, 1)), + /// // 6669 is a restricted port on Chrome, so we cannot use it. We use a different port instead. + /// 9999, + /// )); + /// + /// // Finally, spawn the server. + /// serve.await.expect("console subscriber server failed"); + /// # }); + /// # }) + /// # .expect("console subscriber could not spawn thread"); + /// # tracing_subscriber::registry().with(console_layer).init(); + /// ``` + /// + /// For a comprehensive understanding and complete code example, + /// please refer to the `grpc-web` example in the examples directory. + /// + /// [`Router::serve`]: fn@tonic::transport::server::Router::serve pub async fn serve_with_grpc_web( self, builder: tonic::transport::Server, From a5a741c7b84bd0eee06205888d1061cb3e866b95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E6=89=8B=E6=8E=89=E5=8C=85=E5=B7=A5=E7=A8=8B?= =?UTF-8?q?=E5=B8=88?= Date: Tue, 13 Feb 2024 22:08:50 +0800 Subject: [PATCH 10/15] Update console-subscriber/src/builder.rs Co-authored-by: Hayden Stainsby --- console-subscriber/src/builder.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/console-subscriber/src/builder.rs b/console-subscriber/src/builder.rs index 71a2707d0..ea41c5f92 100644 --- a/console-subscriber/src/builder.rs +++ b/console-subscriber/src/builder.rs @@ -281,10 +281,10 @@ impl Builder { /// serve the gRPC-Web protocol in addition to the standard gRPC protocol. /// This is useful for serving the console subscriber to web clients. /// - /// [serve_with_grpc_web] is used to provide more advanced configuration + /// [`serve_with_grpc_web`] is used to provide more advanced configuration /// for the gRPC-Web server. /// - /// [serve_with_grpc_web]: crate::Server::serve_with_grpc_web + /// [`serve_with_grpc_web`]: crate::Server::serve_with_grpc_web pub fn enable_grpc_web(self, enable_grpc_web: bool) -> Self { Self { enable_grpc_web, From 8246b95422796c108917ae367fdf672d905b0289 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E6=89=8B=E6=8E=89=E5=8C=85=E5=B7=A5=E7=A8=8B?= =?UTF-8?q?=E5=B8=88?= Date: Tue, 13 Feb 2024 22:09:10 +0800 Subject: [PATCH 11/15] Update console-subscriber/src/builder.rs Co-authored-by: Hayden Stainsby --- console-subscriber/src/builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/console-subscriber/src/builder.rs b/console-subscriber/src/builder.rs index ea41c5f92..b3ceb8527 100644 --- a/console-subscriber/src/builder.rs +++ b/console-subscriber/src/builder.rs @@ -57,8 +57,8 @@ pub struct Builder { /// value. Higher values will result in more memory usage. pub(super) scheduled_duration_max: Duration, - #[cfg(feature = "grpc-web")] /// Whether to enable the grpc-web support. + #[cfg(feature = "grpc-web")] enable_grpc_web: bool, } From 22cc8f56a41c679da89ed3f7b21107ce53fcd558 Mon Sep 17 00:00:00 2001 From: hi-rustin Date: Tue, 13 Feb 2024 22:14:13 +0800 Subject: [PATCH 12/15] fix: move feature flag below comments Signed-off-by: hi-rustin --- console-subscriber/src/builder.rs | 2 +- console-subscriber/src/lib.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/console-subscriber/src/builder.rs b/console-subscriber/src/builder.rs index b3ceb8527..852e770c5 100644 --- a/console-subscriber/src/builder.rs +++ b/console-subscriber/src/builder.rs @@ -274,7 +274,6 @@ impl Builder { Self { self_trace, ..self } } - #[cfg(feature = "grpc-web")] /// Sets whether to enable the grpc-web support. /// /// By default, this is `false`. If enabled, the console subscriber will @@ -285,6 +284,7 @@ impl Builder { /// for the gRPC-Web server. /// /// [`serve_with_grpc_web`]: crate::Server::serve_with_grpc_web + #[cfg(feature = "grpc-web")] pub fn enable_grpc_web(self, enable_grpc_web: bool) -> Self { Self { enable_grpc_web, diff --git a/console-subscriber/src/lib.rs b/console-subscriber/src/lib.rs index 46233d9ab..a308b5123 100644 --- a/console-subscriber/src/lib.rs +++ b/console-subscriber/src/lib.rs @@ -1060,6 +1060,7 @@ impl Server { /// please refer to the `grpc-web` example in the examples directory. /// /// [`Router::serve`]: fn@tonic::transport::server::Router::serve + #[cfg(feature = "grpc-web")] pub async fn serve_with_grpc_web( self, builder: tonic::transport::Server, From 95ba1ca250bf09861bf25a731459925b1d830512 Mon Sep 17 00:00:00 2001 From: hi-rustin Date: Tue, 13 Feb 2024 22:19:57 +0800 Subject: [PATCH 13/15] docs: add comments about default port Signed-off-by: hi-rustin --- console-subscriber/src/builder.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/console-subscriber/src/builder.rs b/console-subscriber/src/builder.rs index 852e770c5..85406c8ec 100644 --- a/console-subscriber/src/builder.rs +++ b/console-subscriber/src/builder.rs @@ -279,6 +279,10 @@ impl Builder { /// By default, this is `false`. If enabled, the console subscriber will /// serve the gRPC-Web protocol in addition to the standard gRPC protocol. /// This is useful for serving the console subscriber to web clients. + /// Please be aware that the current default server port is set to 6669. + /// However, certain browsers may restrict this port due to security reasons. + /// If you encounter issues with this, consider changing the port to an + /// alternative one that is not commonly blocked by browsers. /// /// [`serve_with_grpc_web`] is used to provide more advanced configuration /// for the gRPC-Web server. From a6e881a85991927838629f4608e42b4cbf31b942 Mon Sep 17 00:00:00 2001 From: hi-rustin Date: Tue, 13 Feb 2024 22:39:33 +0800 Subject: [PATCH 14/15] fix: remove duplication Signed-off-by: hi-rustin --- console-subscriber/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/console-subscriber/src/lib.rs b/console-subscriber/src/lib.rs index a308b5123..ad863f444 100644 --- a/console-subscriber/src/lib.rs +++ b/console-subscriber/src/lib.rs @@ -962,7 +962,6 @@ impl Server { res?.map_err(Into::into) } - #[cfg(feature = "grpc-web")] /// Starts the gRPC service with the default gRPC settings and gRPC-Web /// support. /// From 0fd9df4f537874f85cc0d88aa82b464c9fdd9966 Mon Sep 17 00:00:00 2001 From: Hayden Stainsby Date: Tue, 13 Feb 2024 17:46:18 +0100 Subject: [PATCH 15/15] Update console-subscriber/src/lib.rs --- console-subscriber/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/console-subscriber/src/lib.rs b/console-subscriber/src/lib.rs index ad863f444..0e45ed6f9 100644 --- a/console-subscriber/src/lib.rs +++ b/console-subscriber/src/lib.rs @@ -1043,7 +1043,7 @@ impl Server { /// .add_service(instrument_server); /// let serve = router.serve(std::net::SocketAddr::new( /// std::net::IpAddr::V4(std::net::Ipv4Addr::new(127, 0, 0, 1)), - /// // 6669 is a restricted port on Chrome, so we cannot use it. We use a different port instead. + /// // 6669 is a restricted port on Chrome, so we cannot use it. We use a different port instead. /// 9999, /// )); ///