Skip to content

Commit

Permalink
Merge branch 'master' into patch-1
Browse files Browse the repository at this point in the history
  • Loading branch information
jtescher committed Dec 2, 2020
2 parents 941f6e7 + 89882c6 commit 62f322b
Show file tree
Hide file tree
Showing 49 changed files with 926 additions and 311 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Expand Up @@ -52,7 +52,7 @@ jobs:
override: true
- name: Run tests
run: cargo --version &&
cargo test --verbose --manifest-path=opentelemetry/Cargo.toml --features trace,metrics,serialize,tokio,async-std,serde,http,tonic,reqwest &&
cargo test --verbose --manifest-path=opentelemetry/Cargo.toml --features trace,metrics,serialize,tokio,serde,http,tonic,reqwest &&
cargo test --manifest-path=opentelemetry-jaeger/Cargo.toml &&
cargo test --manifest-path=opentelemetry-zipkin/Cargo.toml
meta:
Expand Down
7 changes: 7 additions & 0 deletions CONTRIBUTING.md
Expand Up @@ -93,6 +93,13 @@ patterns in the spec.
For a deeper discussion, see:
https://github.com/open-telemetry/opentelemetry-specification/issues/165

### Error Handling
Currently, the Opentelemetry Rust SDK has two ways to handle errors. In the situation where errors are not allowed to return. One should call global error handler to process the errors. Otherwise, one should return the errors.

The Opentelemetry Rust SDK comes with an error type `openetelemetry::Error`. For different function, one error has been defined. All error returned by trace module MUST be wrapped in `opentelemetry::trace::TraceError`. All errors returned by metrics module MUST be wrapped in `opentelemetry::metrics::MetricsError`.

For users that want to implement their own exporters. It's RECOMMENDED to wrap all errors from the exporter into a crate-level error type, and implement `ExporterError` trait.

## Style Guide

* Run `cargo clippy --all` - this will catch common mistakes and improve
Expand Down
5 changes: 3 additions & 2 deletions Cargo.toml
Expand Up @@ -7,15 +7,16 @@ members = [
"opentelemetry-prometheus",
"opentelemetry-semantic-conventions",
"opentelemetry-zipkin",
"examples/actix-udp",
"examples/actix-http",
"examples/actix-http-tracing",
"examples/actix-udp",
"examples/async",
"examples/aws-xray",
"examples/basic",
"examples/basic-otlp",
"examples/datadog",
"examples/grpc",
"examples/http",
"examples/tracing-grpc",
"examples/zipkin",
"examples/tracing-grpc"
]
15 changes: 15 additions & 0 deletions examples/actix-http-tracing/Cargo.toml
@@ -0,0 +1,15 @@
[package]
name = "actix-http-tracing"
version = "0.1.0"
edition = "2018"
publish = false

[dependencies]
actix-web = "3.2"
actix-web-opentelemetry = { version = "0.8", features = ["metrics"] }
opentelemetry = { version = "0.10", features = ["metrics", "tokio"] }
opentelemetry-jaeger = { version = "0.9", features = ["tokio"] }
opentelemetry-prometheus = "0.3.0"
tracing = "0.1"
tracing-opentelemetry = "0.9"
tracing-subscriber = "0.2"
72 changes: 72 additions & 0 deletions examples/actix-http-tracing/README.md
@@ -0,0 +1,72 @@
# Actix Web with Tracing example

This example shows how to export data to [Jaeger] and [Prometheus] from an
[actix-web] app instrumented using the [tracing] API and ecosystem.

[Jaeger]: https://www.jaegertracing.io
[Prometheus]: https://prometheus.io
[actix-web]: https://github.com/actix/actix-web
[tracing]: https://github.com/tokio-rs/tracing

## Setup

```shell
# Run jaeger in background
$ docker run -d -p6831:6831/udp -p6832:6832/udp -p16686:16686 -p14268:14268 jaegertracing/all-in-one:latest

# Start the actix web server
$ cargo run

# (from another terminal window)
$ curl localhost:8080/users/@ferris
=> Hello @ferris

# View spans (see the image below)
$ firefox http://localhost:16686/
```

## Generated Telemetry

### Jaeger

After completing the steps above, the following trace information is now
available:

![Jaeger UI](trace.png)

### Prometheus (Optional)

Optional request metrics information is now exposed via `/metrics`:

```shell
$ curl localhost:8080/metrics

# HELP http_requests_duration HTTP request duration per route
# TYPE http_requests_duration histogram
http_requests_duration_bucket{method="GET",route="/users/{username}",status="200",le="0.5"} 1
http_requests_duration_bucket{method="GET",route="/users/{username}",status="200",le="0.9"} 1
http_requests_duration_bucket{method="GET",route="/users/{username}",status="200",le="0.99"} 1
http_requests_duration_bucket{method="GET",route="/users/{username}",status="200",le="+Inf"} 1
http_requests_duration_sum{method="GET",route="/users/{username}",status="200"} 0.001289
http_requests_duration_count{method="GET",route="/users/{username}",status="200"} 1
# HELP http_requests_total HTTP requests per route
# TYPE http_requests_total counter
http_requests_total{method="GET",route="/users/{username}",status="200"} 1
```

### Logs

[tracing] has been configured to report `INFO` and above level logs to stdout
via [`tracing_subscriber::fmt`] and [`tracing_subscriber::EnvFilter`] to produce
the output below:

```shell
Nov 29 13:08:04.932 INFO actix_server::builder: Starting 16 workers
Nov 29 13:08:04.933 INFO actix_server::builder: Starting "actix-web-service-127.0.0.1:8080" service on 127.0.0.1:8080
Nov 29 13:08:08.740 INFO greet_user{username="@ferris"}: actix_http_tracing: preparing to greet user
Nov 29 13:08:08.740 INFO actix_web::middleware::logger: 127.0.0.1:63418 "GET /users/@ferris HTTP/1.1" 200 13 "-" "curl/7.64.1" 0.000758
```

[tracing]: https://github.com/tokio-rs/tracing
[`tracing_subscriber::fmt`]: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/fmt/index.html
[`tracing_subscriber::EnvFilter`]: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html
56 changes: 56 additions & 0 deletions examples/actix-http-tracing/src/main.rs
@@ -0,0 +1,56 @@
use actix_web::middleware::Logger;
use actix_web::{web, App, HttpServer};
use actix_web_opentelemetry::RequestTracing;
use opentelemetry::{global, sdk::propagation::TraceContextPropagator};
use std::io;
use tracing_subscriber::prelude::*;
use tracing_subscriber::Registry;

async fn index(username: actix_web::web::Path<String>) -> String {
greet_user(username.as_ref())
}

#[tracing::instrument]
fn greet_user(username: &str) -> String {
tracing::info!("preparing to greet user");
format!("Hello {}", username)
}

#[actix_web::main]
async fn main() -> io::Result<()> {
// Start an (optional) otel prometheus metrics pipeline
let metrics_exporter = opentelemetry_prometheus::exporter().init();
let request_metrics = actix_web_opentelemetry::RequestMetrics::new(
opentelemetry::global::meter("actix_http_tracing"),
Some(|req: &actix_web::dev::ServiceRequest| {
req.path() == "/metrics" && req.method() == actix_web::http::Method::GET
}),
Some(metrics_exporter),
);

// Start an otel jaeger trace pipeline
global::set_text_map_propagator(TraceContextPropagator::new());
let (tracer, _uninstall) = opentelemetry_jaeger::new_pipeline()
.with_service_name("app_name")
.install()
.unwrap();

// Initialize `tracing` using `opentelemetry-tracing` and configure logging
Registry::default()
.with(tracing_subscriber::EnvFilter::new("INFO"))
.with(tracing_subscriber::fmt::layer())
.with(tracing_opentelemetry::layer().with_tracer(tracer))
.init();

// Start actix web with otel and tracing middlewares
HttpServer::new(move || {
App::new()
.wrap(Logger::default())
.wrap(RequestTracing::new())
.wrap(request_metrics.clone())
.service(web::resource("/users/{username}").to(index))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
Binary file added examples/actix-http-tracing/trace.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 2 additions & 5 deletions examples/actix-http/src/main.rs
@@ -1,17 +1,14 @@
use actix_service::Service;
use actix_web::middleware::Logger;
use actix_web::{web, App, HttpServer};
use opentelemetry::trace::TraceError;
use opentelemetry::{global, sdk::trace as sdktrace};
use opentelemetry::{
trace::{FutureExt, TraceContextExt, Tracer},
Key,
};
use std::error::Error;

fn init_tracer() -> Result<
(sdktrace::Tracer, opentelemetry_jaeger::Uninstall),
Box<dyn Error + Send + Sync + 'static>,
> {
fn init_tracer() -> Result<(sdktrace::Tracer, opentelemetry_jaeger::Uninstall), TraceError> {
opentelemetry_jaeger::new_pipeline()
.with_collector_endpoint("http://127.0.0.1:14268/api/traces")
.with_service_name("trace-http-demo")
Expand Down
7 changes: 2 additions & 5 deletions examples/actix-udp/src/main.rs
@@ -1,17 +1,14 @@
use actix_service::Service;
use actix_web::middleware::Logger;
use actix_web::{web, App, HttpServer};
use opentelemetry::trace::TraceError;
use opentelemetry::{global, sdk::trace as sdktrace};
use opentelemetry::{
trace::{FutureExt, TraceContextExt, Tracer},
Key,
};
use std::error::Error;

fn init_tracer() -> Result<
(sdktrace::Tracer, opentelemetry_jaeger::Uninstall),
Box<dyn Error + Send + Sync + 'static>,
> {
fn init_tracer() -> Result<(sdktrace::Tracer, opentelemetry_jaeger::Uninstall), TraceError> {
opentelemetry_jaeger::new_pipeline()
.with_agent_endpoint("localhost:6831")
.with_service_name("trace-udp-demo")
Expand Down
6 changes: 2 additions & 4 deletions examples/async/src/main.rs
Expand Up @@ -17,6 +17,7 @@
//! cargo run --example async_fn
//!
//! [`hello_world`]: https://github.com/tokio-rs/tokio/blob/132e9f1da5965530b63554d7a1c59824c3de4e30/tokio/examples/hello_world.rs
use opentelemetry::trace::TraceError;
use opentelemetry::{
global,
sdk::trace as sdktrace,
Expand Down Expand Up @@ -52,10 +53,7 @@ async fn run(addr: &SocketAddr) -> io::Result<usize> {
write(&mut stream).with_context(cx).await
}

fn init_tracer() -> Result<
(sdktrace::Tracer, opentelemetry_jaeger::Uninstall),
Box<dyn Error + Send + Sync + 'static>,
> {
fn init_tracer() -> Result<(sdktrace::Tracer, opentelemetry_jaeger::Uninstall), TraceError> {
opentelemetry_jaeger::new_pipeline()
.with_service_name("trace-demo")
.install()
Expand Down
5 changes: 2 additions & 3 deletions examples/basic-otlp/src/main.rs
@@ -1,6 +1,7 @@
use futures::stream::{Stream, StreamExt};
use opentelemetry::exporter;
use opentelemetry::sdk::metrics::PushController;
use opentelemetry::trace::TraceError;
use opentelemetry::{
baggage::BaggageExt,
metrics::{self, MetricsError, ObserverResult},
Expand All @@ -11,9 +12,7 @@ use opentelemetry::{global, sdk::trace as sdktrace};
use std::error::Error;
use std::time::Duration;

fn init_tracer(
) -> Result<(sdktrace::Tracer, opentelemetry_otlp::Uninstall), Box<dyn Error + Send + Sync + 'static>>
{
fn init_tracer() -> Result<(sdktrace::Tracer, opentelemetry_otlp::Uninstall), TraceError> {
opentelemetry_otlp::new_pipeline().install()
}

Expand Down
6 changes: 2 additions & 4 deletions examples/basic/src/main.rs
Expand Up @@ -2,6 +2,7 @@ use futures::stream::{Stream, StreamExt};
use opentelemetry::exporter;
use opentelemetry::global;
use opentelemetry::sdk::{metrics::PushController, trace as sdktrace};
use opentelemetry::trace::TraceError;
use opentelemetry::{
baggage::BaggageExt,
metrics::{self, MetricsError, ObserverResult},
Expand All @@ -11,10 +12,7 @@ use opentelemetry::{
use std::error::Error;
use std::time::Duration;

fn init_tracer() -> Result<
(sdktrace::Tracer, opentelemetry_jaeger::Uninstall),
Box<dyn Error + Send + Sync + 'static>,
> {
fn init_tracer() -> Result<(sdktrace::Tracer, opentelemetry_jaeger::Uninstall), TraceError> {
opentelemetry_jaeger::new_pipeline()
.with_service_name("trace-demo")
.with_tags(vec![
Expand Down
6 changes: 2 additions & 4 deletions examples/grpc/src/client.rs
Expand Up @@ -2,19 +2,17 @@ use hello_world::greeter_client::GreeterClient;
use hello_world::HelloRequest;
use opentelemetry::global;
use opentelemetry::sdk::propagation::TraceContextPropagator;
use opentelemetry::trace::TraceError;
use opentelemetry::{
trace::{TraceContextExt, Tracer},
Context, KeyValue,
};
use std::error::Error;

pub mod hello_world {
tonic::include_proto!("helloworld");
}

fn tracing_init(
) -> Result<(impl Tracer, opentelemetry_jaeger::Uninstall), Box<dyn Error + Send + Sync + 'static>>
{
fn tracing_init() -> Result<(impl Tracer, opentelemetry_jaeger::Uninstall), TraceError> {
global::set_text_map_propagator(TraceContextPropagator::new());
opentelemetry_jaeger::new_pipeline()
.with_service_name("grpc-client")
Expand Down
5 changes: 2 additions & 3 deletions examples/grpc/src/server.rs
Expand Up @@ -4,6 +4,7 @@ use hello_world::greeter_server::{Greeter, GreeterServer};
use hello_world::{HelloReply, HelloRequest};
use opentelemetry::global;
use opentelemetry::sdk::propagation::TraceContextPropagator;
use opentelemetry::trace::TraceError;
use opentelemetry::{
trace::{Span, Tracer},
KeyValue,
Expand Down Expand Up @@ -36,9 +37,7 @@ impl Greeter for MyGreeter {
}
}

fn tracing_init(
) -> Result<(impl Tracer, opentelemetry_jaeger::Uninstall), Box<dyn Error + Send + Sync + 'static>>
{
fn tracing_init() -> Result<(impl Tracer, opentelemetry_jaeger::Uninstall), TraceError> {
global::set_text_map_propagator(TraceContextPropagator::new());
opentelemetry_jaeger::new_pipeline()
.with_service_name("grpc-server")
Expand Down
3 changes: 2 additions & 1 deletion opentelemetry-contrib/Cargo.toml
Expand Up @@ -22,7 +22,7 @@ rustdoc-args = ["--cfg", "docsrs"]
default = []
base64_format = ["base64", "binary_propagator"]
binary_propagator = []
datadog = ["indexmap", "rmp", "async-trait"]
datadog = ["indexmap", "rmp", "async-trait", "thiserror"]
reqwest-blocking-client = ["reqwest/blocking", "opentelemetry/reqwest"]
reqwest-client = ["reqwest", "opentelemetry/reqwest"]
surf-client = ["surf", "opentelemetry/surf"]
Expand All @@ -37,6 +37,7 @@ reqwest = { version = "0.10", optional = true }
surf = { version = "2.0", optional = true }
http = "0.2"
base64 = { version = "0.13", optional = true }
thiserror = { version = "1.0", optional = true }

[dev-dependencies]
base64 = "0.13"
Expand Down

0 comments on commit 62f322b

Please sign in to comment.