use std::time::Duration;
use opentelemetry::{global, KeyValue};
use opentelemetry_otlp::WithExportConfig;
use opentelemetry_sdk::{
metrics::{MeterProviderBuilder, PeriodicReader, SdkMeterProvider},
trace::{RandomIdGenerator, Sampler, SdkTracerProvider},
Resource,
};
use opentelemetry_semantic_conventions::{
attribute::{DEPLOYMENT_ENVIRONMENT_NAME, SERVICE_NAME, SERVICE_VERSION},
SCHEMA_URL,
};
use crate::LoggerError;
fn resource(service_name: &str, version: Option<String>, environment: Option<String>) -> Resource {
let mut attributes = vec![KeyValue::new(SERVICE_NAME, service_name.to_owned())];
if let Some(version) = version {
attributes.push(KeyValue::new(SERVICE_VERSION, version));
}
if let Some(environment) = environment {
attributes.push(KeyValue::new(DEPLOYMENT_ENVIRONMENT_NAME, environment));
}
Resource::builder()
.with_service_name(service_name.to_owned())
.with_schema_url(attributes, SCHEMA_URL)
.build()
}
pub(crate) fn init_tracer_provider(
service_name: &str,
url: &str,
version: Option<String>,
environment: Option<String>,
) -> Result<SdkTracerProvider, LoggerError> {
let otlp_exporter = opentelemetry_otlp::SpanExporter::builder()
.with_tonic()
.with_endpoint(url.to_owned())
.with_timeout(Duration::from_secs(3))
.build()
.map_err(|e| {
LoggerError::Otlp(format!(
"Failed to create OTLP provider exporter. Make sure the endpoint is correct and \
the server is running: {e}"
))
})?;
let tracer_provider = SdkTracerProvider::builder()
.with_batch_exporter(otlp_exporter)
.with_id_generator(RandomIdGenerator::default())
.with_sampler(Sampler::AlwaysOn)
.with_resource(resource(service_name, version, environment))
.with_max_events_per_span(64)
.with_max_attributes_per_span(16)
.build();
global::set_tracer_provider(tracer_provider.clone());
Ok(tracer_provider)
}
pub(crate) fn init_meter_provider(
service_name: &str,
url: &str,
version: Option<String>,
environment: Option<String>,
) -> Result<SdkMeterProvider, LoggerError> {
let exporter = opentelemetry_otlp::MetricExporter::builder()
.with_tonic()
.with_temporality(opentelemetry_sdk::metrics::Temporality::default())
.with_endpoint(url.to_owned())
.build()
.map_err(|e| {
LoggerError::Otlp(format!(
"Failed to create OTLP meter exporter. Make sure the endpoint is correct and the \
server is running: {e}"
))
})?;
let reader = PeriodicReader::builder(exporter)
.with_interval(Duration::from_secs(30))
.build();
let stdout_reader =
PeriodicReader::builder(opentelemetry_stdout::MetricExporter::default()).build();
let meter_provider = MeterProviderBuilder::default()
.with_resource(resource(service_name, version, environment))
.with_reader(reader)
.with_reader(stdout_reader)
.build();
global::set_meter_provider(meter_provider.clone());
Ok(meter_provider)
}