Skip to content

Commit a56337c

Browse files
authored
Test otlp exporter in integration scenario (#424)
1 parent 04fa6d5 commit a56337c

File tree

5 files changed

+120
-8
lines changed

5 files changed

+120
-8
lines changed

opentelemetry-otlp/Cargo.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,16 @@ keywords = ["opentelemetry", "otlp", "logging", "tracing", "metrics"]
1515
license = "Apache-2.0"
1616
edition = "2018"
1717
build = "build.rs"
18+
autotests = false
1819

1920
[lib]
2021
doctest = false
2122

23+
[[test]]
24+
name = "smoke"
25+
path = "tests/smoke.rs"
26+
required-features = ["integration-testing"]
27+
2228
[package.metadata.docs.rs]
2329
all-features = true
2430
rustdoc-args = ["--cfg", "docsrs"]
@@ -47,6 +53,7 @@ tls = ["tonic/tls"]
4753
tls-roots = ["tls", "tonic/tls-roots"]
4854
openssl = ["grpcio/openssl"]
4955
openssl-vendored = ["grpcio/openssl-vendored"]
56+
integration-testing = ["tonic", "tonic-build", "prost", "tokio/full", "opentelemetry/trace"]
5057

5158
[build-dependencies]
5259
protobuf-codegen = { version = "2.16", optional = true }

opentelemetry-otlp/build.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use protoc_grpcio::compile_grpc_protos;
1010
fn main() {
1111
#[cfg(feature = "tonic")]
1212
tonic_build::configure()
13-
.build_server(false)
13+
.build_server(std::env::var_os("CARGO_FEATURE_INTEGRATION_TESTING").is_some())
1414
.build_client(true)
1515
.format(false)
1616
.compile(

opentelemetry-otlp/src/lib.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,15 +125,23 @@ use std::collections::HashMap;
125125

126126
use std::time::Duration;
127127

128-
#[cfg(feature = "tonic")]
128+
#[cfg(all(feature = "tonic", not(feature = "integration-testing")))]
129129
#[rustfmt::skip]
130130
#[allow(clippy::all, unreachable_pub)]
131131
mod proto;
132132

133-
#[cfg(all(feature = "grpc-sys", not(feature = "tonic")))]
133+
#[cfg(all(
134+
feature = "grpc-sys",
135+
not(feature = "tonic"),
136+
not(feature = "integration-testing")
137+
))]
134138
#[allow(clippy::all, unreachable_pub, dead_code)]
135139
mod proto;
136140

141+
#[cfg(feature = "integration-testing")]
142+
#[allow(missing_docs, unreachable_pub)]
143+
pub mod proto;
144+
137145
#[cfg(feature = "metrics")]
138146
#[allow(warnings)]
139147
mod metric;

opentelemetry-otlp/src/proto.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#[cfg(feature = "tonic")]
2-
pub(crate) mod collector {
2+
pub mod collector {
33
pub mod metrics {
44
pub mod v1 {
55
tonic::include_proto!("opentelemetry.proto.collector.metrics.v1");
@@ -14,28 +14,28 @@ pub(crate) mod collector {
1414
}
1515

1616
#[cfg(feature = "tonic")]
17-
pub(crate) mod common {
17+
pub mod common {
1818
pub mod v1 {
1919
tonic::include_proto!("opentelemetry.proto.common.v1");
2020
}
2121
}
2222

2323
#[cfg(feature = "tonic")]
24-
pub(crate) mod metrics {
24+
pub mod metrics {
2525
pub mod v1 {
2626
tonic::include_proto!("opentelemetry.proto.metrics.v1");
2727
}
2828
}
2929

3030
#[cfg(feature = "tonic")]
31-
pub(crate) mod resource {
31+
pub mod resource {
3232
pub mod v1 {
3333
tonic::include_proto!("opentelemetry.proto.resource.v1");
3434
}
3535
}
3636

3737
#[cfg(feature = "tonic")]
38-
pub(crate) mod trace {
38+
pub mod trace {
3939
pub mod v1 {
4040
tonic::include_proto!("opentelemetry.proto.trace.v1");
4141
}

opentelemetry-otlp/tests/smoke.rs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
use futures::StreamExt;
2+
use opentelemetry::trace::{Span, SpanKind, Tracer};
3+
use opentelemetry_otlp::proto::collector::trace::v1::{
4+
trace_service_server::{TraceService, TraceServiceServer},
5+
ExportTraceServiceRequest, ExportTraceServiceResponse,
6+
};
7+
use std::{net::SocketAddr, sync::Mutex};
8+
use tokio::sync::mpsc;
9+
10+
struct MockServer {
11+
tx: Mutex<mpsc::Sender<ExportTraceServiceRequest>>,
12+
}
13+
14+
impl MockServer {
15+
pub fn new(tx: mpsc::Sender<ExportTraceServiceRequest>) -> Self {
16+
Self { tx: Mutex::new(tx) }
17+
}
18+
}
19+
20+
#[tonic::async_trait]
21+
impl TraceService for MockServer {
22+
async fn export(
23+
&self,
24+
request: tonic::Request<ExportTraceServiceRequest>,
25+
) -> Result<tonic::Response<ExportTraceServiceResponse>, tonic::Status> {
26+
println!("Sending request into channel...");
27+
self.tx
28+
.lock()
29+
.unwrap()
30+
.try_send(request.into_inner())
31+
.expect("Channel full");
32+
Ok(tonic::Response::new(ExportTraceServiceResponse {}))
33+
}
34+
}
35+
36+
async fn setup() -> (SocketAddr, mpsc::Receiver<ExportTraceServiceRequest>) {
37+
let addr: SocketAddr = "[::1]:0".parse().unwrap();
38+
let listener = tokio::net::TcpListener::bind(addr)
39+
.await
40+
.expect("failed to bind");
41+
let addr = listener.local_addr().unwrap();
42+
let stream = listener.map(|s| {
43+
if let Ok(ref s) = s {
44+
println!("Got new conn at {}", s.peer_addr().unwrap());
45+
}
46+
s
47+
});
48+
49+
let (req_tx, req_rx) = mpsc::channel(10);
50+
let service = TraceServiceServer::new(MockServer::new(req_tx));
51+
tokio::task::spawn(async move {
52+
tonic::transport::Server::builder()
53+
.add_service(service)
54+
.serve_with_incoming(stream)
55+
.await
56+
.expect("Server failed");
57+
});
58+
(addr, req_rx)
59+
}
60+
61+
#[tokio::test(threaded_scheduler)]
62+
async fn smoke_tracer() {
63+
println!("Starting server setup...");
64+
let (addr, mut req_rx) = setup().await;
65+
66+
{
67+
println!("Installing tracer...");
68+
let (tracer, _uninstall) = opentelemetry_otlp::new_pipeline()
69+
.with_endpoint(format!("http://{}", addr))
70+
.install()
71+
.expect("failed to install");
72+
73+
println!("Sending span...");
74+
let span = tracer
75+
.span_builder("my-test-span")
76+
.with_kind(SpanKind::Server)
77+
.start(&tracer);
78+
span.add_event("my-test-event".into(), vec![]);
79+
span.end();
80+
}
81+
82+
println!("Waiting for request...");
83+
let req = req_rx.recv().await.expect("missing export request");
84+
let first_span = req
85+
.resource_spans
86+
.get(0)
87+
.unwrap()
88+
.instrumentation_library_spans
89+
.get(0)
90+
.unwrap()
91+
.spans
92+
.get(0)
93+
.unwrap();
94+
assert_eq!("my-test-span", first_span.name);
95+
let first_event = first_span.events.get(0).unwrap();
96+
assert_eq!("my-test-event", first_event.name);
97+
}

0 commit comments

Comments
 (0)