pub mod tracing {
use tracing_subscriber::EnvFilter;
use crate::errors::Result;
pub fn init() -> Result<()> {
Ok(tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env())
.try_init()?)
}
}
pub mod otlp_tracing {
use opentelemetry::{global, trace::TracerProvider, KeyValue};
use opentelemetry_otlp::{Protocol, SpanExporter, WithExportConfig};
use opentelemetry_sdk::{
trace::{RandomIdGenerator, Sampler, SdkTracerProvider},
Resource,
};
use opentelemetry_semantic_conventions::resource::SERVICE_VERSION;
use serde::Deserialize;
use tracing::instrument;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};
use crate::errors::Result;
pub const DEFAULT_OTLP_GRPC_ENDPOINT: &str = "http://localhost:4317";
#[derive(Clone, Debug, Deserialize)]
#[serde(default)]
pub struct Configuration {
pub otlp_grpc_endpoint: String,
}
pub fn try_init(service_name: &'static str) -> Result<()> {
let configuration = Configuration::from_env()?;
let new_provider = SdkTracerProvider::builder()
.with_id_generator(RandomIdGenerator::default())
.with_sampler(Sampler::ParentBased(Box::new(Sampler::AlwaysOn)))
.with_resource(
Resource::builder()
.with_service_name(service_name)
.with_attribute(KeyValue::new(SERVICE_VERSION, env!("CARGO_PKG_VERSION")))
.build(),
)
.with_batch_exporter(
SpanExporter::builder()
.with_tonic()
.with_protocol(Protocol::Grpc)
.with_endpoint(configuration.otlp_grpc_endpoint)
.build()?,
)
.build();
let tracer = new_provider.tracer("tracing-otel-subscriber");
let _previous_global_tracer_provider = global::set_tracer_provider(new_provider);
tracing_subscriber::registry()
.with(EnvFilter::from_default_env())
.with(tracing_subscriber::fmt::layer())
.with(tracing_opentelemetry::layer().with_tracer(tracer))
.try_init()?;
Ok(())
}
impl Configuration {
#[instrument(err(Debug), ret, level = "trace")]
pub fn from_env() -> Result<Self> {
Ok(envy::prefixed("OBSERVABILITY_").from_env::<Self>()?)
}
}
impl Default for Configuration {
fn default() -> Self {
Self {
otlp_grpc_endpoint: DEFAULT_OTLP_GRPC_ENDPOINT.to_string(),
}
}
}
}
pub mod errors {
use std::{error::Error as StdError, result::Result as StdResult};
use derive_more::{Display, Error, From};
use envy::Error as EnvyError;
use opentelemetry_otlp::ExporterBuildError;
use tracing_subscriber::util::TryInitError;
#[derive(Debug, Display, Error, From)]
pub enum Error {
ExporterBuildError(ExporterBuildError),
ConfigurationDeserializationFromEnvironmentError(EnvyError),
SubscriberInitError(TryInitError),
Other(Box<dyn StdError + Send + Sync>),
}
pub type Result<T> = StdResult<T, Error>;
}