Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add an example on how to config multiple span processors. #539

Merged
merged 2 commits into from May 7, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Expand Up @@ -26,5 +26,6 @@ members = [
"examples/http",
"examples/tracing-grpc",
"examples/zipkin",
"examples/multiple-span-processors"
]
exclude = ["examples/external-otlp-grpcio-async-std"]
10 changes: 10 additions & 0 deletions 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"] }
17 changes: 17 additions & 0 deletions 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.
frigus02 marked this conversation as resolved.
Show resolved Hide resolved

4. Use `docker-compose down -v` to tear down the Jaeger and Zipkin backend.


19 changes: 19 additions & 0 deletions 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"
64 changes: 64 additions & 0 deletions 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<dyn std::error::Error + Send + Sync + 'static>> {
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(())
}
2 changes: 1 addition & 1 deletion opentelemetry-datadog/src/exporter/mod.rs
Expand Up @@ -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);
}
Expand Down
2 changes: 1 addition & 1 deletion opentelemetry-jaeger/src/exporter/mod.rs
Expand Up @@ -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)
}
Expand Down
2 changes: 1 addition & 1 deletion opentelemetry-otlp/src/lib.rs
Expand Up @@ -581,7 +581,7 @@ fn build_batch_with_exporter<R: Runtime>(
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);
}
Expand Down
11 changes: 7 additions & 4 deletions opentelemetry-zipkin/src/exporter/mod.rs
Expand Up @@ -84,7 +84,10 @@ impl Default for ZipkinPipelineBuilder {
}

impl ZipkinPipelineBuilder {
fn build_exporter(self) -> Result<Exporter, TraceError> {
/// 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<Exporter, TraceError> {
if let Some(client) = self.client {
let endpoint = Endpoint::new(self.service_name, self.service_addr);
let exporter = Exporter::new(
Expand All @@ -103,7 +106,7 @@ impl ZipkinPipelineBuilder {
/// Install the Zipkin trace exporter pipeline with a simple span processor.
pub fn install_simple(mut self) -> Result<sdk::trace::Tracer, TraceError> {
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 {
Expand All @@ -122,9 +125,9 @@ impl ZipkinPipelineBuilder {
runtime: R,
) -> Result<sdk::trace::Tracer, TraceError> {
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);
}
Expand Down
2 changes: 1 addition & 1 deletion opentelemetry/src/global/trace.rs
Expand Up @@ -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()
}

Expand Down
12 changes: 2 additions & 10 deletions opentelemetry/src/sdk/trace/provider.rs
Expand Up @@ -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<T: SpanExporter + 'static, R: Runtime>(
pub fn with_batch_exporter<T: SpanExporter + 'static, R: Runtime>(
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.
Expand Down
2 changes: 1 addition & 1 deletion opentelemetry/src/sdk/trace/span_processor.rs
Expand Up @@ -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);
Expand Down