use std::time::Duration;
use opentelemetry_otlp::{MetricExporter, SpanExporter, WithExportConfig};
use opentelemetry_sdk::Resource;
use opentelemetry_sdk::metrics::{PeriodicReader, SdkMeterProvider};
use opentelemetry_sdk::trace::SdkTracerProvider;
pub struct OtlpBuilder {
endpoint: Option<String>,
export_interval: Duration,
}
impl Default for OtlpBuilder {
fn default() -> Self {
Self::new()
}
}
impl OtlpBuilder {
pub fn new() -> Self {
Self {
endpoint: None,
export_interval: Duration::from_secs(10),
}
}
pub fn with_endpoint(mut self, endpoint: impl Into<String>) -> Self {
self.endpoint = Some(endpoint.into());
self
}
pub fn with_export_interval(mut self, interval: Duration) -> Self {
self.export_interval = interval;
self
}
pub fn build(self) -> Option<SdkMeterProvider> {
let mut exporter_builder = MetricExporter::builder().with_http();
if let Some(endpoint) = self.endpoint {
exporter_builder = exporter_builder.with_endpoint(endpoint);
}
let exporter = exporter_builder.build().ok()?;
let reader = PeriodicReader::builder(exporter)
.with_interval(self.export_interval)
.build();
Some(SdkMeterProvider::builder().with_reader(reader).build())
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum OtlpProtocol {
HttpProtobuf,
Grpc,
}
impl OtlpProtocol {
pub fn from_env(s: Option<&str>) -> Self {
match s.map(str::trim).unwrap_or("") {
"grpc" => Self::Grpc,
_ => Self::HttpProtobuf,
}
}
}
pub struct ExporterOtlpHelper;
impl ExporterOtlpHelper {
pub fn build(
endpoint: Option<&str>,
protocol: OtlpProtocol,
resource: Resource,
) -> Option<(SdkMeterProvider, SdkTracerProvider)> {
let metric_exporter = {
let _ = protocol;
let mut b = MetricExporter::builder().with_http();
if let Some(ep) = endpoint {
b = b.with_endpoint(ep);
}
b.build().ok()?
};
let reader = PeriodicReader::builder(metric_exporter)
.with_interval(Duration::from_secs(10))
.build();
let meter_provider = SdkMeterProvider::builder()
.with_reader(reader)
.with_resource(resource.clone())
.build();
let span_exporter = {
let mut b = SpanExporter::builder().with_http();
if let Some(ep) = endpoint {
b = b.with_endpoint(ep);
}
b.build().ok()?
};
let tracer_provider = SdkTracerProvider::builder()
.with_batch_exporter(span_exporter)
.with_resource(resource)
.build();
Some((meter_provider, tracer_provider))
}
}