opentelemetry_otlp/
lib.rs

1//! # OpenTelemetry OTLP Exporter
2//!
3//! The OTLP Exporter enables exporting telemetry data (logs, metrics, and traces) in the
4//! OpenTelemetry Protocol (OTLP) format to compatible backends. These backends include:
5//!
6//! - OpenTelemetry Collector
7//! - Open-source observability tools (Prometheus, Jaeger, etc.)
8//! - Vendor-specific monitoring platforms
9//!
10//! This crate supports sending OTLP data via:
11//! - gRPC
12//! - HTTP (binary protobuf or JSON)
13//!
14//! ## Quickstart with OpenTelemetry Collector
15//!
16//! ### HTTP Transport (Port 4318)
17//!
18//! Run the OpenTelemetry Collector:
19//!
20//! ```shell
21//! $ docker run -p 4318:4318 otel/opentelemetry-collector:latest
22//! ```
23//!
24//! Configure your application to export traces via HTTP:
25//!
26//! ```no_run
27//! # #[cfg(all(feature = "trace", feature = "http-proto"))]
28//! # {
29//! use opentelemetry::global;
30//! use opentelemetry::trace::Tracer;
31//! use opentelemetry_otlp::Protocol;
32//! use opentelemetry_otlp::WithExportConfig;
33//!
34//! fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
35//!     // Initialize OTLP exporter using HTTP binary protocol
36//!     let otlp_exporter = opentelemetry_otlp::SpanExporter::builder()
37//!         .with_http()
38//!         .with_protocol(Protocol::HttpBinary)
39//!         .build()?;
40//!
41//!     // Create a tracer provider with the exporter
42//!     let _ = opentelemetry_sdk::trace::SdkTracerProvider::builder()
43//!         .with_simple_exporter(otlp_exporter)
44//!         .build();
45//!
46//!     // Get a tracer and create spans
47//!     let tracer = global::tracer("my_tracer");
48//!     tracer.in_span("doing_work", |_cx| {
49//!         // Your application logic here...
50//!     });
51//!
52//!     Ok(())
53//! # }
54//! }
55//! ```
56//!
57//! ### gRPC Transport (Port 4317)
58//!
59//! Run the OpenTelemetry Collector:
60//!
61//! ```shell
62//! $ docker run -p 4317:4317 otel/opentelemetry-collector:latest
63//! ```
64//!
65//! Configure your application to export traces via gRPC:
66//!
67//! ```no_run
68//! # #[cfg(all(feature = "trace", feature = "grpc-tonic"))]
69//! # {
70//! use opentelemetry::global;
71//! use opentelemetry::trace::Tracer;
72//!
73//! fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
74//!     // Initialize OTLP exporter using gRPC (Tonic)
75//!     let otlp_exporter = opentelemetry_otlp::SpanExporter::builder()
76//!         .with_tonic()
77//!         .build()?;
78//!
79//!     // Create a tracer provider with the exporter
80//!     let _ = opentelemetry_sdk::trace::SdkTracerProvider::builder()
81//!         .with_simple_exporter(otlp_exporter)
82//!         .build();
83//!
84//!     // Get a tracer and create spans
85//!     let tracer = global::tracer("my_tracer");
86//!     tracer.in_span("doing_work", |_cx| {
87//!         // Your application logic here...
88//!     });
89//!
90//!     Ok(())
91//! # }
92//! }
93//! ```
94//!
95//! ## Using with Jaeger
96//!
97//! Jaeger natively supports the OTLP protocol, making it easy to send traces directly:
98//!
99//! ```shell
100//! $ docker run -p 16686:16686 -p 4317:4317 -e COLLECTOR_OTLP_ENABLED=true jaegertracing/all-in-one:latest
101//! ```
102//!
103//! After running your application configured with the OTLP exporter, view traces at:
104//! `http://localhost:16686`
105//!
106//! ## Using with Prometheus
107//!
108//! Prometheus natively supports accepting metrics via the OTLP protocol
109//! (HTTP/protobuf). You can [run
110//! Prometheus](https://prometheus.io/docs/prometheus/latest/installation/) with
111//! the following command:
112//!
113//! ```shell
114//! docker run -p 9090:9090 -v ./prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus --config.file=/etc/prometheus/prometheus.yml --web.enable-otlp-receiver
115//! ```
116//!
117//! (An empty prometheus.yml file is sufficient for this example.)
118//!
119//! Modify your application to export metrics via OTLP:
120//!
121//! ```no_run
122//! # #[cfg(all(feature = "metrics", feature = "http-proto"))]
123//! # {
124//! use opentelemetry::global;
125//! use opentelemetry::metrics::Meter;
126//! use opentelemetry::KeyValue;
127//! use opentelemetry_otlp::Protocol;
128//! use opentelemetry_otlp::WithExportConfig;
129//!
130//! fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
131//!     // Initialize OTLP exporter using HTTP binary protocol
132//!     let exporter = opentelemetry_otlp::MetricExporter::builder()
133//!         .with_http()
134//!         .with_protocol(Protocol::HttpBinary)
135//!         .with_endpoint("http://localhost:9090/api/v1/otlp/v1/metrics")
136//!         .build()?;
137//!
138//!     // Create a meter provider with the OTLP Metric exporter
139//!     let meter_provider = opentelemetry_sdk::metrics::SdkMeterProvider::builder()
140//!         .with_periodic_exporter(exporter)
141//!         .build();
142//!     global::set_meter_provider(meter_provider.clone());
143//!
144//!     // Get a meter
145//!     let meter = global::meter("my_meter");
146//!
147//!     // Create a metric
148//!     let counter = meter.u64_counter("my_counter").build();
149//!     counter.add(1, &[KeyValue::new("key", "value")]);
150//!
151//!     // Shutdown the meter provider. This will trigger an export of all metrics.
152//!     meter_provider.shutdown()?;
153//!
154//!     Ok(())
155//! # }
156//! }
157//! ```
158//!
159//! After running your application configured with the OTLP exporter, view metrics at:
160//! `http://localhost:9090`
161//! ## Show Logs, Metrics too (TODO)
162//!
163//! ## Performance
164//!
165//! For optimal performance, a batch exporting processor is recommended as the simple
166//! processor will export each span synchronously on dropping, and is only good
167//! for test/debug purposes.
168//!
169//! ```toml
170//! [dependencies]
171//! opentelemetry-otlp = { version = "*", features = ["grpc-tonic"] }
172//! ```
173//!
174//! ```no_run
175//! # #[cfg(all(feature = "trace", feature = "grpc-tonic"))]
176//! # {
177//! use opentelemetry::global;
178//! use opentelemetry::trace::Tracer;
179//!
180//! fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
181//!     // First, create a OTLP exporter builder. Configure it as you need.
182//!     let otlp_exporter = opentelemetry_otlp::SpanExporter::builder().with_tonic().build()?;
183//!     // Then pass it into provider builder
184//!     let _ = opentelemetry_sdk::trace::SdkTracerProvider::builder()
185//!         .with_batch_exporter(otlp_exporter)
186//!         .build();
187//!     let tracer = global::tracer("my_tracer");
188//!     tracer.in_span("doing_work", |cx| {
189//!         // Traced app logic here...
190//!     });
191//!
192//!     Ok(())
193//!   # }
194//! }
195//! ```
196//!
197//! [`tokio`]: https://tokio.rs
198//!
199//! # Feature Flags
200//! The following feature flags can enable exporters for different telemetry signals:
201//!
202//! * `trace`: Includes the trace exporters.
203//! * `metrics`: Includes the metrics exporters.
204//! * `logs`: Includes the logs exporters.
205//!
206//! The following feature flags generate additional code and types:
207//! * `serialize`: Enables serialization support for type defined in this crate via `serde`.
208//!
209//! The following feature flags offer additional configurations on gRPC:
210//!
211//! For users using `tonic` as grpc layer:
212//! * `grpc-tonic`: Use `tonic` as grpc layer.
213//! * `gzip-tonic`: Use gzip compression for `tonic` grpc layer.
214//! * `zstd-tonic`: Use zstd compression for `tonic` grpc layer.
215//! * `tls-roots`: Adds system trust roots to rustls-based gRPC clients using the rustls-native-certs crate
216//! * `tls-webpki-roots`: Embeds Mozilla's trust roots to rustls-based gRPC clients using the webpki-roots crate
217//!
218//! The following feature flags offer additional configurations on http:
219//!
220//! * `http-proto`: Use http as transport layer, protobuf as body format. This feature is enabled by default.
221//! * `reqwest-blocking-client`: Use reqwest blocking http client. This feature is enabled by default.
222//! * `reqwest-client`: Use reqwest http client.
223//! * `reqwest-rustls`: Use reqwest with TLS with system trust roots via `rustls-native-certs` crate.
224//! * `reqwest-rustls-webpki-roots`: Use reqwest with TLS with Mozilla's trust roots via `webpki-roots` crate.
225//!
226//! # Kitchen Sink Full Configuration
227//!
228//! Example showing how to override all configuration options.
229//!
230//! Generally there are two parts of configuration. One is the exporter, the other is the provider.
231//! Users can configure the exporter using [SpanExporter::builder()] for traces,
232//! and [MetricExporter::builder()] + [opentelemetry_sdk::metrics::PeriodicReader::builder()] for metrics.
233//! Once you have an exporter, you can add it to either a [opentelemetry_sdk::trace::SdkTracerProvider::builder()] for traces,
234//! or [opentelemetry_sdk::metrics::SdkMeterProvider::builder()] for metrics.
235//!
236//! ```no_run
237//! use opentelemetry::{global, KeyValue, trace::Tracer};
238//! use opentelemetry_sdk::{trace::{self, RandomIdGenerator, Sampler}, Resource};
239//! # #[cfg(feature = "metrics")]
240//! use opentelemetry_sdk::metrics::Temporality;
241//! use opentelemetry_otlp::{Protocol, WithExportConfig, WithTonicConfig};
242//! use std::time::Duration;
243//! # #[cfg(feature = "grpc-tonic")]
244//! use tonic::metadata::*;
245//!
246//! fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
247//!     # #[cfg(all(feature = "trace", feature = "grpc-tonic"))]
248//!     # let tracer = {
249//!     let mut map = MetadataMap::with_capacity(3);
250//!
251//!     map.insert("x-host", "example.com".parse().unwrap());
252//!     map.insert("x-number", "123".parse().unwrap());
253//!     map.insert_bin("trace-proto-bin", MetadataValue::from_bytes(b"[binary data]"));
254//!     let exporter = opentelemetry_otlp::SpanExporter::builder()
255//!         .with_tonic()
256//!         .with_endpoint("http://localhost:4317")
257//!         .with_timeout(Duration::from_secs(3))
258//!         .with_metadata(map)
259//!         .build()?;
260//!
261//!     let tracer_provider = opentelemetry_sdk::trace::SdkTracerProvider::builder()
262//!         .with_batch_exporter(exporter)
263//!         .with_sampler(Sampler::AlwaysOn)
264//!         .with_id_generator(RandomIdGenerator::default())
265//!         .with_max_events_per_span(64)
266//!         .with_max_attributes_per_span(16)
267//!         .with_resource(Resource::builder_empty().with_attributes([KeyValue::new("service.name", "example")]).build())
268//!         .build();
269//!     global::set_tracer_provider(tracer_provider.clone());
270//!     let tracer = global::tracer("tracer-name");
271//!         # tracer
272//!     # };
273//!
274//!     # #[cfg(all(feature = "metrics", feature = "grpc-tonic"))]
275//!     # {
276//!     let exporter = opentelemetry_otlp::MetricExporter::builder()
277//!        .with_tonic()
278//!        .with_endpoint("http://localhost:4318/v1/metrics")
279//!        .with_protocol(Protocol::Grpc)
280//!        .with_timeout(Duration::from_secs(3))
281//!        .build()
282//!        .unwrap();
283//!
284//!    let provider = opentelemetry_sdk::metrics::SdkMeterProvider::builder()
285//!         .with_periodic_exporter(exporter)
286//!         .with_resource(Resource::builder_empty().with_attributes([KeyValue::new("service.name", "example")]).build())
287//!         .build();
288//!     # }
289//!
290//! # #[cfg(all(feature = "trace", feature = "grpc-tonic"))]
291//! # {
292//!     tracer.in_span("doing_work", |cx| {
293//!         // Traced app logic here...
294//!     });
295//! # }
296//!
297//!     Ok(())
298//! }
299//! ```
300#![warn(
301    future_incompatible,
302    missing_debug_implementations,
303    missing_docs,
304    nonstandard_style,
305    rust_2018_idioms,
306    unreachable_pub,
307    unused
308)]
309#![allow(elided_lifetimes_in_paths)]
310#![cfg_attr(
311    docsrs,
312    feature(doc_cfg, doc_auto_cfg),
313    deny(rustdoc::broken_intra_doc_links)
314)]
315#![cfg_attr(test, deny(warnings))]
316
317mod exporter;
318#[cfg(feature = "logs")]
319#[cfg(any(feature = "http-proto", feature = "http-json", feature = "grpc-tonic"))]
320mod logs;
321#[cfg(feature = "metrics")]
322#[cfg(any(feature = "http-proto", feature = "http-json", feature = "grpc-tonic"))]
323mod metric;
324#[cfg(feature = "trace")]
325#[cfg(any(feature = "http-proto", feature = "http-json", feature = "grpc-tonic"))]
326mod span;
327
328pub use crate::exporter::Compression;
329pub use crate::exporter::ExportConfig;
330pub use crate::exporter::ExporterBuildError;
331#[cfg(feature = "trace")]
332#[cfg(any(feature = "http-proto", feature = "http-json", feature = "grpc-tonic"))]
333pub use crate::span::{
334    SpanExporter, OTEL_EXPORTER_OTLP_TRACES_COMPRESSION, OTEL_EXPORTER_OTLP_TRACES_ENDPOINT,
335    OTEL_EXPORTER_OTLP_TRACES_HEADERS, OTEL_EXPORTER_OTLP_TRACES_TIMEOUT,
336};
337
338#[cfg(feature = "metrics")]
339#[cfg(any(feature = "http-proto", feature = "http-json", feature = "grpc-tonic"))]
340pub use crate::metric::{
341    MetricExporter, OTEL_EXPORTER_OTLP_METRICS_COMPRESSION, OTEL_EXPORTER_OTLP_METRICS_ENDPOINT,
342    OTEL_EXPORTER_OTLP_METRICS_HEADERS, OTEL_EXPORTER_OTLP_METRICS_TIMEOUT,
343};
344
345#[cfg(feature = "logs")]
346#[cfg(any(feature = "http-proto", feature = "http-json", feature = "grpc-tonic"))]
347pub use crate::logs::{
348    LogExporter, OTEL_EXPORTER_OTLP_LOGS_COMPRESSION, OTEL_EXPORTER_OTLP_LOGS_ENDPOINT,
349    OTEL_EXPORTER_OTLP_LOGS_HEADERS, OTEL_EXPORTER_OTLP_LOGS_TIMEOUT,
350};
351
352#[cfg(any(feature = "http-proto", feature = "http-json"))]
353pub use crate::exporter::http::{HasHttpConfig, WithHttpConfig};
354
355#[cfg(feature = "grpc-tonic")]
356pub use crate::exporter::tonic::{HasTonicConfig, WithTonicConfig};
357
358pub use crate::exporter::{
359    HasExportConfig, WithExportConfig, OTEL_EXPORTER_OTLP_COMPRESSION, OTEL_EXPORTER_OTLP_ENDPOINT,
360    OTEL_EXPORTER_OTLP_ENDPOINT_DEFAULT, OTEL_EXPORTER_OTLP_HEADERS, OTEL_EXPORTER_OTLP_PROTOCOL,
361    OTEL_EXPORTER_OTLP_PROTOCOL_DEFAULT, OTEL_EXPORTER_OTLP_TIMEOUT,
362    OTEL_EXPORTER_OTLP_TIMEOUT_DEFAULT,
363};
364
365/// Type to indicate the builder does not have a client set.
366#[derive(Debug, Default, Clone)]
367pub struct NoExporterBuilderSet;
368
369/// Type to hold the [TonicExporterBuilder] and indicate it has been set.
370///
371/// Allowing access to [TonicExporterBuilder] specific configuration methods.
372#[cfg(feature = "grpc-tonic")]
373#[derive(Debug, Default)]
374pub struct TonicExporterBuilderSet(TonicExporterBuilder);
375
376/// Type to hold the [HttpExporterBuilder] and indicate it has been set.
377///
378/// Allowing access to [HttpExporterBuilder] specific configuration methods.
379#[cfg(any(feature = "http-proto", feature = "http-json"))]
380#[derive(Debug, Default)]
381pub struct HttpExporterBuilderSet(HttpExporterBuilder);
382
383#[cfg(any(feature = "http-proto", feature = "http-json"))]
384pub use crate::exporter::http::HttpExporterBuilder;
385
386#[cfg(feature = "grpc-tonic")]
387pub use crate::exporter::tonic::{TonicConfig, TonicExporterBuilder};
388
389#[cfg(feature = "serialize")]
390use serde::{Deserialize, Serialize};
391
392/// The communication protocol to use when exporting data.
393#[cfg_attr(feature = "serialize", derive(Deserialize, Serialize))]
394#[derive(Clone, Copy, Debug, Eq, PartialEq)]
395pub enum Protocol {
396    /// GRPC protocol
397    Grpc,
398    /// HTTP protocol with binary protobuf
399    HttpBinary,
400    /// HTTP protocol with JSON payload
401    HttpJson,
402}
403
404#[derive(Debug, Default)]
405#[doc(hidden)]
406/// Placeholder type when no exporter pipeline has been configured in telemetry pipeline.
407pub struct NoExporterConfig(());