-
Notifications
You must be signed in to change notification settings - Fork 440
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[opentelemetry-otlp] adds an example HTTP exporter backed by a Hyper …
…0.2 Client Resolves #1659
- Loading branch information
1 parent
406cc31
commit 3f585e8
Showing
6 changed files
with
280 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
20 changes: 20 additions & 0 deletions
20
opentelemetry-otlp/examples/basic-otlp-http-hyper/Cargo.toml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
[package] | ||
name = "basic-otlp-http-hyper" | ||
version = "0.1.0" | ||
edition = "2021" | ||
license = "Apache-2.0" | ||
publish = false | ||
|
||
[dependencies] | ||
async-trait = { workspace = true } | ||
bytes = { workspace = true } | ||
once_cell = { workspace = true } | ||
opentelemetry = { path = "../../../opentelemetry" } | ||
opentelemetry_sdk = { path = "../../../opentelemetry-sdk", features = ["rt-tokio"] } | ||
opentelemetry-http = { path = "../../../opentelemetry-http" } | ||
opentelemetry-otlp = { path = "../..", features = ["http-proto"] } | ||
opentelemetry-semantic-conventions = { path = "../../../opentelemetry-semantic-conventions" } | ||
|
||
http = { workspace = true } | ||
hyper = { workspace = true, features = ["client"] } | ||
tokio = { workspace = true, features = ["full"] } |
116 changes: 116 additions & 0 deletions
116
opentelemetry-otlp/examples/basic-otlp-http-hyper/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
# Basic OTLP exporter Example - Hyper 0.14 | ||
|
||
This example shows how to setup OpenTelemetry OTLP exporter for traces to exports them to the [OpenTelemetry | ||
Collector](https://github.com/open-telemetry/opentelemetry-collector) via OTLP | ||
over HTTP/protobuf. The Collector then sends the data to the appropriate | ||
backend, in this case, the logging Exporter, which displays data to console. | ||
|
||
This example uses a simple implementation of the `HttpClient` backed by a Hyper Client. | ||
|
||
## Usage | ||
|
||
### `docker-compose` | ||
|
||
By default runs against the `otel/opentelemetry-collector:latest` image, and uses `reqwest-client` | ||
as the http client, using http as the transport. | ||
|
||
```shell | ||
docker-compose up | ||
``` | ||
|
||
In another terminal run the application `cargo run` | ||
|
||
The docker-compose terminal will display traces. | ||
|
||
Press Ctrl+C to stop the collector, and then tear it down: | ||
|
||
```shell | ||
docker-compose down | ||
``` | ||
|
||
### Manual | ||
|
||
If you don't want to use `docker-compose`, you can manually run the `otel/opentelemetry-collector` container | ||
and inspect the logs to see traces being transferred. | ||
|
||
On Unix based systems use: | ||
|
||
```shell | ||
# From the current directory, run `opentelemetry-collector` | ||
docker run --rm -it -p 4318:4318 -v $(pwd):/cfg otel/opentelemetry-collector:latest --config=/cfg/otel-collector-config.yaml | ||
``` | ||
|
||
On Windows use: | ||
|
||
```shell | ||
# From the current directory, run `opentelemetry-collector` | ||
docker run --rm -it -p 4318:4318 -v "%cd%":/cfg otel/opentelemetry-collector:latest --config=/cfg/otel-collector-config.yaml | ||
``` | ||
|
||
Run the app which exports traces via OTLP to the collector | ||
|
||
```shell | ||
cargo run | ||
``` | ||
|
||
## View results | ||
|
||
You should be able to see something similar below with different time and ID in the same console that docker runs. | ||
|
||
### Span | ||
|
||
```text | ||
... | ||
2024-06-04T07:39:05.722Z info ResourceSpans #0 | ||
Resource SchemaURL: | ||
Resource attributes: | ||
-> service.name: Str(basic-otlp-http-hyper) | ||
ScopeSpans #0 | ||
ScopeSpans SchemaURL: | ||
InstrumentationScope basic | ||
Span #0 | ||
Trace ID : 0e833514074391284d809e71afd34931 | ||
Parent ID : b5ce8f2bdedd0698 | ||
ID : c2555b67b2072134 | ||
Name : Sub operation... | ||
Kind : Internal | ||
Start time : 2024-06-04 07:39:05.698201 +0000 UTC | ||
End time : 2024-06-04 07:39:05.698213 +0000 UTC | ||
Status code : Unset | ||
Status message : | ||
Attributes: | ||
-> another.key: Str(yes) | ||
Events: | ||
SpanEvent #0 | ||
-> Name: Sub span event | ||
-> Timestamp: 2024-06-04 07:39:05.698206 +0000 UTC | ||
-> DroppedAttributesCount: 0 | ||
ResourceSpans #1 | ||
Resource SchemaURL: | ||
Resource attributes: | ||
-> service.name: Str(basic-otlp-http-hyper) | ||
ScopeSpans #0 | ||
ScopeSpans SchemaURL: | ||
InstrumentationScope basic | ||
Span #0 | ||
Trace ID : 0e833514074391284d809e71afd34931 | ||
Parent ID : | ||
ID : b5ce8f2bdedd0698 | ||
Name : Main operation | ||
Kind : Internal | ||
Start time : 2024-06-04 07:39:05.698168 +0000 UTC | ||
End time : 2024-06-04 07:39:05.698223 +0000 UTC | ||
Status code : Unset | ||
Status message : | ||
Attributes: | ||
-> another.key: Str(yes) | ||
Events: | ||
SpanEvent #0 | ||
-> Name: Nice operation! | ||
-> Timestamp: 2024-06-04 07:39:05.698186 +0000 UTC | ||
-> DroppedAttributesCount: 0 | ||
-> Attributes:: | ||
-> bogons: Int(100) | ||
{"kind": "exporter", "data_type": "traces", "name": "logging"} | ||
... | ||
``` |
15 changes: 15 additions & 0 deletions
15
opentelemetry-otlp/examples/basic-otlp-http-hyper/docker-compose.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
version: "2" | ||
services: | ||
|
||
# Collector | ||
otel-collector: | ||
image: otel/opentelemetry-collector:latest | ||
command: ["--config=/etc/otel-collector-config.yaml", "${OTELCOL_ARGS}"] | ||
volumes: | ||
- ./otel-collector-config.yaml:/etc/otel-collector-config.yaml | ||
ports: | ||
- "4318:4318" # OTLP HTTP receiver | ||
|
||
|
||
|
||
|
21 changes: 21 additions & 0 deletions
21
opentelemetry-otlp/examples/basic-otlp-http-hyper/otel-collector-config.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# This is a configuration file for the OpenTelemetry Collector intended to be | ||
# used in conjunction with the opentelemetry-otlp example. | ||
# | ||
# For more information about the OpenTelemetry Collector see: | ||
# https://github.com/open-telemetry/opentelemetry-collector | ||
# | ||
receivers: | ||
otlp: | ||
protocols: | ||
grpc: | ||
http: | ||
|
||
exporters: | ||
logging: | ||
loglevel: debug | ||
|
||
service: | ||
pipelines: | ||
traces: | ||
receivers: [otlp] | ||
exporters: [logging] |
107 changes: 107 additions & 0 deletions
107
opentelemetry-otlp/examples/basic-otlp-http-hyper/src/main.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
use async_trait::async_trait; | ||
use bytes::Bytes; | ||
use http::{Request, Response}; | ||
use hyper::client::{connect::Connect, HttpConnector}; | ||
use hyper::{Body, Client}; | ||
use once_cell::sync::Lazy; | ||
use opentelemetry::{ | ||
global, | ||
trace::{TraceContextExt, TraceError, Tracer, TracerProvider as _}, | ||
Key, KeyValue, | ||
}; | ||
use opentelemetry_http::{HttpClient, HttpError, ResponseExt}; | ||
use opentelemetry_otlp::WithExportConfig; | ||
use opentelemetry_sdk::trace::{self as sdktrace, Config}; | ||
use opentelemetry_sdk::Resource; | ||
|
||
use std::error::Error; | ||
|
||
static RESOURCE: Lazy<Resource> = Lazy::new(|| { | ||
Resource::new(vec![KeyValue::new( | ||
opentelemetry_semantic_conventions::resource::SERVICE_NAME, | ||
"basic-otlp-http-hyper", | ||
)]) | ||
}); | ||
|
||
struct HyperClient<C> { | ||
inner: hyper::Client<C>, | ||
} | ||
|
||
impl Default for HyperClient<HttpConnector> { | ||
fn default() -> Self { | ||
Self { | ||
inner: Client::new(), | ||
} | ||
} | ||
} | ||
|
||
impl<C> std::fmt::Debug for HyperClient<C> { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
f.debug_struct("HyperClient") | ||
.field("inner", &self.inner) | ||
.finish() | ||
} | ||
} | ||
|
||
#[async_trait] | ||
impl<C: Connect + Clone + Send + Sync + 'static> HttpClient for HyperClient<C> { | ||
async fn send(&self, request: Request<Vec<u8>>) -> Result<Response<Bytes>, HttpError> { | ||
let request = request.map(Body::from); | ||
|
||
let (parts, body) = self | ||
.inner | ||
.request(request) | ||
.await? | ||
.error_for_status()? | ||
.into_parts(); | ||
let body = hyper::body::to_bytes(body).await?; | ||
|
||
Ok(Response::from_parts(parts, body)) | ||
} | ||
} | ||
|
||
fn init_tracer_provider() -> Result<sdktrace::TracerProvider, TraceError> { | ||
opentelemetry_otlp::new_pipeline() | ||
.tracing() | ||
.with_exporter( | ||
opentelemetry_otlp::new_exporter() | ||
.http() | ||
.with_http_client(HyperClient::default()) | ||
.with_endpoint("http://localhost:4318/v1/traces"), | ||
) | ||
.with_trace_config(Config::default().with_resource(RESOURCE.clone())) | ||
.install_batch(opentelemetry_sdk::runtime::Tokio) | ||
} | ||
|
||
#[tokio::main] | ||
async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> { | ||
let result = init_tracer_provider(); | ||
assert!( | ||
result.is_ok(), | ||
"Init tracer failed with error: {:?}", | ||
result.err() | ||
); | ||
|
||
let tracer_provider = result.unwrap(); | ||
global::set_tracer_provider(tracer_provider.clone()); | ||
|
||
let tracer = global::tracer_provider().tracer_builder("basic").build(); | ||
|
||
tracer.in_span("Main operation", |cx| { | ||
let span = cx.span(); | ||
span.add_event( | ||
"Nice operation!".to_string(), | ||
vec![Key::new("bogons").i64(100)], | ||
); | ||
span.set_attribute(KeyValue::new("another.key", "yes")); | ||
|
||
tracer.in_span("Sub operation...", |cx| { | ||
let span = cx.span(); | ||
span.set_attribute(KeyValue::new("another.key", "yes")); | ||
span.add_event("Sub span event", vec![]); | ||
}); | ||
}); | ||
|
||
global::shutdown_tracer_provider(); | ||
Ok(()) | ||
} |