From 38630b883173634b401905c3ec4e0c9f9ef21d54 Mon Sep 17 00:00:00 2001 From: "zhongyang.wu" Date: Tue, 4 May 2021 21:12:49 -0400 Subject: [PATCH 1/2] feat: add an example on how to config multiple span processors. * Add an example that export spans to both Jaeger and Zipkin to show how to config multiple span processors/exporters. * Remove the `with_batch_exporter` function in `TracerProviderBuilder` as it's the same as the `with_span_processor`. * Rename the `with_default_batch_exporter` function in `TracerProvderBuilder` to `with_batch_exporter` to keep it consistent with the `with_simple_exporter`. * Add `init_exporter` method in Zipkin's builder to allow user build a zipkin exporter --- Cargo.toml | 1 + examples/multiple-span-processors/Cargo.toml | 10 +++ examples/multiple-span-processors/README.md | 17 +++++ .../docker-compose.yaml | 19 ++++++ examples/multiple-span-processors/src/main.rs | 64 +++++++++++++++++++ opentelemetry-datadog/src/exporter/mod.rs | 2 +- opentelemetry-jaeger/src/exporter/mod.rs | 2 +- opentelemetry-otlp/src/lib.rs | 2 +- opentelemetry-zipkin/src/exporter/mod.rs | 11 ++-- opentelemetry/src/global/trace.rs | 2 +- opentelemetry/src/sdk/trace/provider.rs | 12 +--- opentelemetry/src/sdk/trace/span_processor.rs | 2 +- 12 files changed, 125 insertions(+), 19 deletions(-) create mode 100644 examples/multiple-span-processors/Cargo.toml create mode 100644 examples/multiple-span-processors/README.md create mode 100644 examples/multiple-span-processors/docker-compose.yaml create mode 100644 examples/multiple-span-processors/src/main.rs diff --git a/Cargo.toml b/Cargo.toml index c2b8907e07..5ecb7cf3e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,5 +26,6 @@ members = [ "examples/http", "examples/tracing-grpc", "examples/zipkin", + "examples/multiple-span-processors" ] exclude = ["examples/external-otlp-grpcio-async-std"] diff --git a/examples/multiple-span-processors/Cargo.toml b/examples/multiple-span-processors/Cargo.toml new file mode 100644 index 0000000000..380e8c5cfd --- /dev/null +++ b/examples/multiple-span-processors/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "multiple-span-processors" +version = "0.1.0" +edition = "2018" + +[dependencies] +opentelemetry = { path = "../../opentelemetry", features = ["rt-tokio"] } +opentelemetry-zipkin = { path = "../../opentelemetry-zipkin", default-features=false, features=["reqwest-client"]} +opentelemetry-jaeger = { path = "../../opentelemetry-jaeger", features = ["tokio"] } +tokio = { version = "1.0", features = ["full"] } diff --git a/examples/multiple-span-processors/README.md b/examples/multiple-span-processors/README.md new file mode 100644 index 0000000000..77fddc50d1 --- /dev/null +++ b/examples/multiple-span-processors/README.md @@ -0,0 +1,17 @@ +# Work with multiple span processors + +Opentelemetry supports export spans into multiple different destinations. One way to do so is to use multiple span processors. + +In this example, we demonstrate how to send spans to both Jaeger and Zipkin backend. + +To run this example. + +1. Start the Jaeger and Zipkin. Run `docker-compose up` + +2. Use `cargo run` to run the example. + +3. Check the output in Jaeger and Zipkin. The console should also output the SpanData in json format. + +4. Use `docker-compose down -v` to tear down the Jaeger and Zipkin backend. + + diff --git a/examples/multiple-span-processors/docker-compose.yaml b/examples/multiple-span-processors/docker-compose.yaml new file mode 100644 index 0000000000..46292f572b --- /dev/null +++ b/examples/multiple-span-processors/docker-compose.yaml @@ -0,0 +1,19 @@ +version: "3" +services: + # Jaeger + jaeger-all-in-one: + image: jaegertracing/all-in-one:1.22 + ports: + - "16686:16686" + - "5775:5775/udp" + - "5775:5775/tcp" + - "6831:6831/udp" + - "6832:6832/udp" + - "5778:5778" + - "14628:14628" + - "14250:14250" + + zipkin: + image: openzipkin/zipkin + ports: + - "9411:9411" diff --git a/examples/multiple-span-processors/src/main.rs b/examples/multiple-span-processors/src/main.rs new file mode 100644 index 0000000000..dacc113700 --- /dev/null +++ b/examples/multiple-span-processors/src/main.rs @@ -0,0 +1,64 @@ +use opentelemetry::global::{self, shutdown_tracer_provider}; +use opentelemetry::sdk::export::trace::stdout::Exporter as StdoutExporter; +use opentelemetry::sdk::trace::{BatchSpanProcessor, TracerProvider}; +use opentelemetry::trace::{mark_span_as_active, TraceError, Tracer}; +use opentelemetry::KeyValue; +use std::io::stdout; +use std::time::Duration; + +fn init_tracer() -> Result<(), TraceError> { + // build a jaeger batch span processor + let jaeger_processor = BatchSpanProcessor::builder( + opentelemetry_jaeger::new_pipeline() + .with_service_name("trace-demo") + .with_tags(vec![KeyValue::new("exporter", "jaeger")]) + .init_exporter()?, + opentelemetry::runtime::Tokio, + ) + .build(); + + // build a zipkin exporter + let zipkin_exporter = opentelemetry_zipkin::new_pipeline() + .with_service_name("trace-demo") + .init_exporter()?; + + let provider = TracerProvider::builder() + // We can build a span processor and pass it into provider. + .with_span_processor(jaeger_processor) + // For batch span processor, we can also provide the exporter and runtime and use this + // helper function to build a batch span processor + .with_batch_exporter(zipkin_exporter, opentelemetry::runtime::Tokio) + // Same helper function is also available to build a simple span processor. + .with_simple_exporter(StdoutExporter::new(stdout(), true)) + .build(); + + let _ = global::set_tracer_provider(provider); + + Ok(()) +} + +#[tokio::main] +async fn main() -> Result<(), Box> { + init_tracer()?; + + let tracer = global::tracer("jaeger-and-zipkin"); + + { + let span = tracer.start("first span"); + let _guard = mark_span_as_active(span); + { + let _inner = tracer.start("first sub span"); + tokio::time::sleep(Duration::from_millis(15)).await; + } + { + let _inner = tracer.start("second sub span"); + tokio::time::sleep(Duration::from_millis(15)).await; + } + } + + tokio::time::sleep(Duration::from_millis(15)).await; + + shutdown_tracer_provider(); + + Ok(()) +} diff --git a/opentelemetry-datadog/src/exporter/mod.rs b/opentelemetry-datadog/src/exporter/mod.rs index 6bd4c8fbb7..79dfcdcdbf 100644 --- a/opentelemetry-datadog/src/exporter/mod.rs +++ b/opentelemetry-datadog/src/exporter/mod.rs @@ -134,7 +134,7 @@ impl DatadogPipelineBuilder { let trace_config = self.trace_config.take(); let exporter = self.build_exporter()?; let mut provider_builder = - sdk::trace::TracerProvider::builder().with_default_batch_exporter(exporter, runtime); + sdk::trace::TracerProvider::builder().with_batch_exporter(exporter, runtime); if let Some(config) = trace_config { provider_builder = provider_builder.with_config(config); } diff --git a/opentelemetry-jaeger/src/exporter/mod.rs b/opentelemetry-jaeger/src/exporter/mod.rs index ee9dc72919..5333e2ef7e 100644 --- a/opentelemetry-jaeger/src/exporter/mod.rs +++ b/opentelemetry-jaeger/src/exporter/mod.rs @@ -297,7 +297,7 @@ impl PipelineBuilder { let config = self.config.take(); let exporter = self.init_exporter()?; let mut builder = - sdk::trace::TracerProvider::builder().with_default_batch_exporter(exporter, runtime); + sdk::trace::TracerProvider::builder().with_batch_exporter(exporter, runtime); if let Some(config) = config { builder = builder.with_config(config) } diff --git a/opentelemetry-otlp/src/lib.rs b/opentelemetry-otlp/src/lib.rs index 97b136d83a..7d8e780ee9 100644 --- a/opentelemetry-otlp/src/lib.rs +++ b/opentelemetry-otlp/src/lib.rs @@ -581,7 +581,7 @@ fn build_batch_with_exporter( runtime: R, ) -> sdk::trace::Tracer { let mut provider_builder = - sdk::trace::TracerProvider::builder().with_default_batch_exporter(exporter, runtime); + sdk::trace::TracerProvider::builder().with_batch_exporter(exporter, runtime); if let Some(config) = trace_config { provider_builder = provider_builder.with_config(config); } diff --git a/opentelemetry-zipkin/src/exporter/mod.rs b/opentelemetry-zipkin/src/exporter/mod.rs index 751d69a288..b21688ed69 100644 --- a/opentelemetry-zipkin/src/exporter/mod.rs +++ b/opentelemetry-zipkin/src/exporter/mod.rs @@ -84,7 +84,10 @@ impl Default for ZipkinPipelineBuilder { } impl ZipkinPipelineBuilder { - fn build_exporter(self) -> Result { + /// Initial a Zipkin span exporter. + /// + /// Returns error if the endpoint is not valid or if no http client is provided. + pub fn init_exporter(self) -> Result { if let Some(client) = self.client { let endpoint = Endpoint::new(self.service_name, self.service_addr); let exporter = Exporter::new( @@ -103,7 +106,7 @@ impl ZipkinPipelineBuilder { /// Install the Zipkin trace exporter pipeline with a simple span processor. pub fn install_simple(mut self) -> Result { let config = self.trace_config.take(); - let exporter = self.build_exporter()?; + let exporter = self.init_exporter()?; let mut provider_builder = sdk::trace::TracerProvider::builder().with_simple_exporter(exporter); if let Some(config) = config { @@ -122,9 +125,9 @@ impl ZipkinPipelineBuilder { runtime: R, ) -> Result { let config = self.trace_config.take(); - let exporter = self.build_exporter()?; + let exporter = self.init_exporter()?; let mut provider_builder = - sdk::trace::TracerProvider::builder().with_default_batch_exporter(exporter, runtime); + sdk::trace::TracerProvider::builder().with_batch_exporter(exporter, runtime); if let Some(config) = config { provider_builder = provider_builder.with_config(config); } diff --git a/opentelemetry/src/global/trace.rs b/opentelemetry/src/global/trace.rs index 7f3bae226d..5a37d00c46 100644 --- a/opentelemetry/src/global/trace.rs +++ b/opentelemetry/src/global/trace.rs @@ -486,7 +486,7 @@ mod tests { use crate::sdk::trace::TracerProvider; let exporter = crate::sdk::export::trace::stdout::Exporter::new(assert_writer, true); TracerProvider::builder() - .with_default_batch_exporter(exporter, runtime) + .with_batch_exporter(exporter, runtime) .build() } diff --git a/opentelemetry/src/sdk/trace/provider.rs b/opentelemetry/src/sdk/trace/provider.rs index 0659cad23f..7ed35eec14 100644 --- a/opentelemetry/src/sdk/trace/provider.rs +++ b/opentelemetry/src/sdk/trace/provider.rs @@ -114,22 +114,14 @@ impl Builder { Builder { processors, ..self } } - /// The `BatchProcessor` that this provider should use. - pub fn with_batch_exporter(self, processor: sdk::trace::BatchSpanProcessor) -> Self { - let mut processors = self.processors; - processors.push(Box::new(processor)); - - Builder { processors, ..self } - } - /// The `SpanExporter` setup using a default `BatchSpanProcessor` that this provider should use. - pub fn with_default_batch_exporter( + pub fn with_batch_exporter( self, exporter: T, runtime: R, ) -> Self { let batch = sdk::trace::BatchSpanProcessor::builder(exporter, runtime).build(); - self.with_batch_exporter(batch) + self.with_span_processor(batch) } /// The `SpanProcessor` that this provider should use. diff --git a/opentelemetry/src/sdk/trace/span_processor.rs b/opentelemetry/src/sdk/trace/span_processor.rs index 37b2ff78ca..1605587a0f 100644 --- a/opentelemetry/src/sdk/trace/span_processor.rs +++ b/opentelemetry/src/sdk/trace/span_processor.rs @@ -200,7 +200,7 @@ impl SpanProcessor for SimpleSpanProcessor { /// /// // Then use the `with_batch_exporter` method to have the provider export spans in batches. /// let provider = sdktrace::TracerProvider::builder() -/// .with_batch_exporter(batch) +/// .with_span_processor(batch) /// .build(); /// /// let _ = global::set_tracer_provider(provider); From 0fc186f64adee3fe9a35134a32a05ca4eefe9407 Mon Sep 17 00:00:00 2001 From: Zhongyang Wu Date: Thu, 6 May 2021 00:32:03 -0400 Subject: [PATCH 2/2] Update README.md --- examples/multiple-span-processors/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/multiple-span-processors/README.md b/examples/multiple-span-processors/README.md index 77fddc50d1..64f33e3735 100644 --- a/examples/multiple-span-processors/README.md +++ b/examples/multiple-span-processors/README.md @@ -10,7 +10,7 @@ To run this example. 2. Use `cargo run` to run the example. -3. Check the output in Jaeger and Zipkin. The console should also output the SpanData in json format. +3. Check the output in Jaeger and Zipkin. The console should also output the SpanData. 4. Use `docker-compose down -v` to tear down the Jaeger and Zipkin backend.