#[cfg(feature = "grpc-tonic")]
use crate::exporter::tonic::TonicExporterBuilder;
#[cfg(feature = "http-proto")]
use crate::exporter::http::HttpExporterBuilder;
use crate::{NoExporterConfig, OtlpPipeline};
use async_trait::async_trait;
use std::fmt::Debug;
use opentelemetry::logs::LogError;
use opentelemetry_sdk::{export::logs::LogData, runtime::RuntimeChannel, Resource};
pub const OTEL_EXPORTER_OTLP_LOGS_COMPRESSION: &str = "OTEL_EXPORTER_OTLP_LOGS_COMPRESSION";
pub const OTEL_EXPORTER_OTLP_LOGS_ENDPOINT: &str = "OTEL_EXPORTER_OTLP_LOGS_ENDPOINT";
pub const OTEL_EXPORTER_OTLP_LOGS_TIMEOUT: &str = "OTEL_EXPORTER_OTLP_LOGS_TIMEOUT";
pub const OTEL_EXPORTER_OTLP_LOGS_HEADERS: &str = "OTEL_EXPORTER_OTLP_LOGS_HEADERS";
impl OtlpPipeline {
pub fn logging(self) -> OtlpLogPipeline<NoExporterConfig> {
OtlpLogPipeline {
resource: None,
exporter_builder: NoExporterConfig(()),
batch_config: None,
}
}
}
#[derive(Debug)]
#[allow(clippy::large_enum_variant)]
#[non_exhaustive]
pub enum LogExporterBuilder {
#[cfg(feature = "grpc-tonic")]
Tonic(TonicExporterBuilder),
#[cfg(feature = "http-proto")]
Http(HttpExporterBuilder),
}
impl LogExporterBuilder {
pub fn build_log_exporter(self) -> Result<LogExporter, LogError> {
match self {
#[cfg(feature = "grpc-tonic")]
LogExporterBuilder::Tonic(builder) => builder.build_log_exporter(),
#[cfg(feature = "http-proto")]
LogExporterBuilder::Http(builder) => builder.build_log_exporter(),
}
}
}
#[cfg(feature = "grpc-tonic")]
impl From<TonicExporterBuilder> for LogExporterBuilder {
fn from(exporter: TonicExporterBuilder) -> Self {
LogExporterBuilder::Tonic(exporter)
}
}
#[cfg(feature = "http-proto")]
impl From<HttpExporterBuilder> for LogExporterBuilder {
fn from(exporter: HttpExporterBuilder) -> Self {
LogExporterBuilder::Http(exporter)
}
}
#[derive(Debug)]
pub struct LogExporter {
client: Box<dyn opentelemetry_sdk::export::logs::LogExporter>,
}
impl LogExporter {
pub fn new(client: impl opentelemetry_sdk::export::logs::LogExporter + 'static) -> Self {
LogExporter {
client: Box::new(client),
}
}
}
#[async_trait]
impl opentelemetry_sdk::export::logs::LogExporter for LogExporter {
async fn export<'a>(
&mut self,
batch: Vec<std::borrow::Cow<'a, LogData>>,
) -> opentelemetry::logs::LogResult<()> {
self.client.export(batch).await
}
fn set_resource(&mut self, resource: &opentelemetry_sdk::Resource) {
self.client.set_resource(resource);
}
}
#[derive(Debug)]
pub struct OtlpLogPipeline<EB> {
exporter_builder: EB,
resource: Option<Resource>,
batch_config: Option<opentelemetry_sdk::logs::BatchConfig>,
}
impl<EB> OtlpLogPipeline<EB> {
pub fn with_resource(self, resource: Resource) -> Self {
OtlpLogPipeline {
resource: Some(resource),
..self
}
}
pub fn with_batch_config(mut self, batch_config: opentelemetry_sdk::logs::BatchConfig) -> Self {
self.batch_config = Some(batch_config);
self
}
}
impl OtlpLogPipeline<NoExporterConfig> {
pub fn with_exporter<B: Into<LogExporterBuilder>>(
self,
pipeline: B,
) -> OtlpLogPipeline<LogExporterBuilder> {
OtlpLogPipeline {
exporter_builder: pipeline.into(),
resource: self.resource,
batch_config: self.batch_config,
}
}
}
impl OtlpLogPipeline<LogExporterBuilder> {
pub fn install_simple(self) -> Result<opentelemetry_sdk::logs::LoggerProvider, LogError> {
Ok(build_simple_with_exporter(
self.exporter_builder.build_log_exporter()?,
self.resource,
))
}
pub fn install_batch<R: RuntimeChannel>(
self,
runtime: R,
) -> Result<opentelemetry_sdk::logs::LoggerProvider, LogError> {
Ok(build_batch_with_exporter(
self.exporter_builder.build_log_exporter()?,
self.resource,
runtime,
self.batch_config,
))
}
}
fn build_simple_with_exporter(
exporter: LogExporter,
resource: Option<Resource>,
) -> opentelemetry_sdk::logs::LoggerProvider {
let mut provider_builder =
opentelemetry_sdk::logs::LoggerProvider::builder().with_simple_exporter(exporter);
if let Some(resource) = resource {
provider_builder = provider_builder.with_resource(resource);
}
provider_builder.build()
}
fn build_batch_with_exporter<R: RuntimeChannel>(
exporter: LogExporter,
resource: Option<Resource>,
runtime: R,
batch_config: Option<opentelemetry_sdk::logs::BatchConfig>,
) -> opentelemetry_sdk::logs::LoggerProvider {
let mut provider_builder = opentelemetry_sdk::logs::LoggerProvider::builder();
let batch_processor = opentelemetry_sdk::logs::BatchLogProcessor::builder(exporter, runtime)
.with_batch_config(batch_config.unwrap_or_default())
.build();
provider_builder = provider_builder.with_log_processor(batch_processor);
if let Some(resource) = resource {
provider_builder = provider_builder.with_resource(resource);
}
provider_builder.build()
}