Skip to content

Commit ea61575

Browse files
Add tonic for opentelemetry-otlp (open-telemetry#352)
Add support for the [tonic](https://github.com/hyperium/tonic) implementation of the gRPC transport layer to `opentelemetry-otlp`. - Use tonic as the underlying gRPC transport layer (default) - Optional: TLS support using rustls - Optional: Use the platform's native certificate store - Optional: Use an async client
1 parent bd17c16 commit ea61575

22 files changed

+652
-78
lines changed

CONTRIBUTING.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,14 @@ join the meeting or get in touch on
1515

1616
### Prerequisites
1717

18-
Crate `opentelemetry-otlp` uses gRPC. So you will need the following to build:
18+
Crate `opentelemetry-otlp` uses gRPC + Protocol Buffers.<br>
19+
You can provide the protocol compiler protoc path programmatically (only works with tonic) or build it from source
20+
21+
```sh
22+
export PROTOC=$(which protoc)
23+
```
24+
25+
Prerequisites to build the protocol compiler protoc from source
1926

2027
- [protoc](https://github.com/protocolbuffers/protobuf)
2128
- [cmake](https://cmake.org)

opentelemetry-otlp/Cargo.toml

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,34 @@ license = "Apache-2.0"
1616
edition = "2018"
1717
build = "build.rs"
1818

19+
[lib]
20+
doctest = false
21+
1922
[package.metadata.docs.rs]
2023
all-features = true
2124
rustdoc-args = ["--cfg", "docsrs"]
2225

2326
[dependencies]
2427
async-trait = "0.1"
2528
futures = "0.3"
26-
grpcio = "0.6"
29+
grpcio = { version = "0.7", optional = true }
2730
opentelemetry = { version = "0.10", default-features = false, features = ["trace"], path = "../opentelemetry" }
28-
protobuf = "2.18"
31+
prost = { version = "0.6", optional = true }
32+
protobuf = { version = "2.18", optional = true }
2933
thiserror = "1.0"
34+
tonic = { package = "tonic", version = "0.3", optional = true }
35+
tokio = { version = "0.2", features = ["full"], optional = true }
3036

3137
[features]
38+
async = ["default"]
39+
default = ["tonic", "tonic-build", "prost", "tokio"]
40+
grpc-sys = ["grpcio", "protobuf", "protobuf-codegen", "protoc-grpcio"]
41+
tls = ["tonic/tls"]
42+
tls-roots = ["tls", "tonic/tls-roots"]
3243
openssl = ["grpcio/openssl"]
3344
openssl-vendored = ["grpcio/openssl-vendored"]
3445

3546
[build-dependencies]
36-
protobuf-codegen = "2.16"
37-
protoc-grpcio = "2.0"
47+
protobuf-codegen = { version = "2.16", optional = true }
48+
protoc-grpcio = { version = "2.0", optional = true }
49+
tonic-build = { version = "0.3", optional = true }

opentelemetry-otlp/README.md

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -57,17 +57,33 @@ fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
5757
Ok(())
5858
}
5959
```
60+
61+
## Options
62+
63+
Multiple gRPC transport layers are available. [`tonic`](https://crates.io/crates/tonic) is the default gRPC transport
64+
layer and is enabled by default. [`grpcio`](https://crates.io/crates/grpcio) is optional.
65+
66+
| gRPC transport layer | [hyperium/tonic](https://github.com/hyperium/tonic) | [tikv/grpc-rs](https://github.com/tikv/grpc-rs) |
67+
|---|---|---|
68+
| Feature | --features=default | --features=grpc-sys |
69+
| gRPC library | [`tonic`](https://crates.io/crates/tonic) | [`grpcio`](https://crates.io/crates/grpcio) |
70+
| Transport | [hyperium/hyper](https://github.com/hyperium/hyper) (Rust) | [grpc/grpc](https://github.com/grpc/grpc) (C++ binding) |
71+
| TLS support | yes | yes |
72+
| TLS library | rustls | OpenSSL |
73+
| TLS optional | yes | yes |
74+
| Supported .proto generator | [`prost`](https://crates.io/crates/prost) | [`prost`](https://crates.io/crates/prost), [`protobuf`](https://crates.io/crates/protobuf) |
75+
6076
## Performance
6177

6278
For optimal performance, a batch exporter is recommended as the simple
63-
exporter will export each span synchronously on drop. You can enable the
64-
[`tokio`] or [`async-std`] features to have a batch exporter configured for
65-
you automatically for either executor when you install the pipeline.
79+
exporter will export each span synchronously on drop. Enable a runtime
80+
to have a batch exporter configured automatically for either executor
81+
when using the pipeline.
6682

6783
```toml
6884
[dependencies]
69-
opentelemetry = { version = "*", features = ["tokio"] }
70-
opentelemetry-otlp = "*"
85+
opentelemetry = { version = "*", features = ["async-std"] }
86+
opentelemetry-otlp = { version = "*", features = ["grpc-sys"] }
7187
```
7288

7389
[`tokio`]: https://tokio.rs
@@ -83,25 +99,31 @@ Example showing how to override all configuration options. See the
8399
```rust
84100
use opentelemetry::{KeyValue, Tracer};
85101
use opentelemetry::sdk::{trace, IdGenerator, Resource, Sampler};
86-
use opentelemetry_otlp::{Compression, Credentials, Protocol};
102+
use opentelemetry_otlp::{Protocol};
87103
use std::time::Duration;
104+
use tonic::{
105+
metadata::*,
106+
transport::{Certificate, ClientTlsConfig},
107+
};
88108

89109
fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
90-
let headers = vec![("X-Custom".to_string(), "Custom-Value".to_string())]
91-
.into_iter()
92-
.collect();
110+
let cert = std::fs::read_to_string("ca.pem")?;
111+
112+
let mut map = MetadataMap::with_capacity(3);
113+
114+
map.insert("x-host", "example.com".parse().unwrap());
115+
map.insert("x-number", "123".parse().unwrap());
116+
map.insert_bin("trace-proto-bin", MetadataValue::from_bytes(b"[binary data]"));
93117

94118
let (tracer, _uninstall) = opentelemetry_otlp::new_pipeline()
95119
.with_endpoint("localhost:55680")
96120
.with_protocol(Protocol::Grpc)
97-
.with_headers(headers)
98-
.with_compression(Compression::Gzip)
121+
.with_metadata(map)
99122
.with_timeout(Duration::from_secs(3))
100-
.with_completion_queue_count(2)
101-
.with_credentials(Credentials {
102-
cert: "tls.cert".to_string(),
103-
key: "tls.key".to_string(),
104-
})
123+
.with_tls_config(ClientTlsConfig::new()
124+
.ca_certificate(Certificate::from_pem(&cert))
125+
.domain_name("example.com".to_string())
126+
)
105127
.with_trace_config(
106128
trace::config()
107129
.with_default_sampler(Sampler::AlwaysOn)
@@ -120,16 +142,3 @@ fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
120142
Ok(())
121143
}
122144
```
123-
124-
## Feature flags
125-
126-
By default `opentelemetry-otlp` uses `boringssl` for grpc crypto. You can switch
127-
this to use `openssl` by enabling the `openssl` feature:
128-
129-
```toml
130-
[dependencies]
131-
opentelemetry-otlp = { version = "*", features = ["openssl"] }
132-
```
133-
134-
If you would like to use a vendored `openssl` version, use the `openssl-vendored` feature.
135-
For more info, see https://github.com/tikv/grpc-rs#feature-openssl-and-openssl-vendored.

opentelemetry-otlp/build.rs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,33 @@
1+
#[cfg(all(feature = "grpc-sys", not(feature = "tonic")))]
12
extern crate protoc_grpcio;
23

4+
#[cfg(all(feature = "grpc-sys", not(feature = "tonic")))]
35
use protobuf_codegen::Customize;
6+
7+
#[cfg(all(feature = "grpc-sys", not(feature = "tonic")))]
48
use protoc_grpcio::compile_grpc_protos;
59

610
fn main() {
11+
#[cfg(feature = "tonic")]
12+
tonic_build::configure()
13+
.build_server(false)
14+
.build_client(true)
15+
.format(false)
16+
.compile(
17+
&[
18+
"src/proto/opentelemetry-proto/opentelemetry/proto/common/v1/common.proto",
19+
"src/proto/opentelemetry-proto/opentelemetry/proto/resource/v1/resource.proto",
20+
"src/proto/opentelemetry-proto/opentelemetry/proto/trace/v1/trace.proto",
21+
"src/proto/opentelemetry-proto/opentelemetry/proto/trace/v1/trace_config.proto",
22+
"src/proto/opentelemetry-proto/opentelemetry/proto/collector/trace/v1/trace_service.proto",
23+
"src/proto/opentelemetry-proto/opentelemetry/proto/metrics/v1/metrics.proto",
24+
"src/proto/opentelemetry-proto/opentelemetry/proto/collector/metrics/v1/metrics_service.proto",
25+
],
26+
&["src/proto/opentelemetry-proto"],
27+
)
28+
.expect("Error generating protobuf");
29+
30+
#[cfg(all(feature = "grpc-sys", not(feature = "tonic")))]
731
compile_grpc_protos(
832
&[
933
"src/proto/opentelemetry-proto/opentelemetry/proto/common/v1/common.proto",
@@ -15,12 +39,12 @@ fn main() {
1539
"src/proto/opentelemetry-proto/opentelemetry/proto/collector/metrics/v1/metrics_service.proto",
1640
],
1741
&["src/proto/opentelemetry-proto/"],
18-
"src/proto",
42+
"src/proto/grpcio",
1943
Some(Customize {
2044
expose_fields: Some(true),
2145
serde_derive: Some(true),
2246
..Default::default()
2347
}),
24-
)
25-
.expect("Error generating protobuf");
48+
)
49+
.expect("Error generating protobuf");
2650
}

0 commit comments

Comments
 (0)