Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: add OpentelemetryLogBuilder #60

Merged
merged 2 commits into from
Sep 18, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 58 additions & 41 deletions src/append/opentelemetry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,61 +38,70 @@ use crate::append::Append;
#[non_exhaustive]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum OpentelemetryWireProtocol {
/// GRPC protocol
Grpc,
/// HTTP protocol with binary protobuf
HttpBinary,
/// HTTP protocol with JSON payload
HttpJson,
}

/// An appender that sends log records to opentelemetry.
#[derive(Debug)]
pub struct OpentelemetryLog {
/// A builder to configure and create an [`OpentelemetryLog`] appender.
pub struct OpentelemetryLogBuilder {
name: String,
library: Arc<InstrumentationLibrary>,
provider: LoggerProvider,
endpoint: String,
protocol: Protocol,
labels: Vec<(Cow<'static, str>, Cow<'static, str>)>,
}

impl OpentelemetryLog {
pub fn new(
name: impl Into<String>,
otlp_endpoint: impl Into<String>,
protocol: OpentelemetryWireProtocol,
) -> Result<Self, opentelemetry::logs::LogError> {
Self::new_with_labels(name, otlp_endpoint, protocol, [])
impl OpentelemetryLogBuilder {
/// Create a new builder with the given name and OTLP endpoint.
pub fn new(name: impl Into<String>, otlp_endpoint: impl Into<String>) -> Self {
OpentelemetryLogBuilder {
name: name.into(),
endpoint: otlp_endpoint.into(),
protocol: Protocol::Grpc,
labels: vec![],
}
}

/// Set the protocol to use when exporting data to opentelemetry.
///
/// Default to [`Grpc`].
///
/// [`Grpc`]: OpentelemetryWireProtocol::Grpc
pub fn with_protocol(mut self, protocol: OpentelemetryWireProtocol) -> Self {
self.protocol = match protocol {
OpentelemetryWireProtocol::Grpc => Protocol::Grpc,
OpentelemetryWireProtocol::HttpBinary => Protocol::HttpBinary,
OpentelemetryWireProtocol::HttpJson => Protocol::HttpJson,
};
self
}

/// Add a label to the resource.
pub fn add_label(mut self, key: impl Into<Cow<'static, str>>, value: impl Into<Cow<'static, str>>) -> Self {
self.labels.push((key.into(), value.into()));
self
}

pub fn new_with_labels(
name: impl Into<String>,
otlp_endpoint: impl Into<String>,
protocol: OpentelemetryWireProtocol,
labels: impl IntoIterator<Item = (Cow<'static, str>, Cow<'static, str>)>,
) -> Result<Self, opentelemetry::logs::LogError> {
let name = name.into();
let otlp_endpoint = otlp_endpoint.into();
/// Build the [`OpentelemetryLog`] appender.
pub fn build(self) -> Result<OpentelemetryLog, opentelemetry::logs::LogError> {
let OpentelemetryLogBuilder { name, endpoint, protocol, labels } = self;

let collector_timeout = Duration::from_secs(opentelemetry_otlp::OTEL_EXPORTER_OTLP_TIMEOUT_DEFAULT);
let exporter = match protocol {
OpentelemetryWireProtocol::Grpc => opentelemetry_otlp::new_exporter()
Protocol::Grpc => opentelemetry_otlp::new_exporter()
.tonic()
.with_endpoint(otlp_endpoint)
.with_protocol(Protocol::Grpc)
.with_timeout(Duration::from_secs(
opentelemetry_otlp::OTEL_EXPORTER_OTLP_TIMEOUT_DEFAULT,
))
.with_endpoint(endpoint)
.with_protocol(protocol)
.with_timeout(collector_timeout)
.build_log_exporter(),
OpentelemetryWireProtocol::HttpBinary => opentelemetry_otlp::new_exporter()
Protocol::HttpBinary | Protocol::HttpJson => opentelemetry_otlp::new_exporter()
.http()
.with_endpoint(otlp_endpoint)
.with_protocol(Protocol::HttpBinary)
.with_timeout(Duration::from_secs(
opentelemetry_otlp::OTEL_EXPORTER_OTLP_TIMEOUT_DEFAULT,
))
.build_log_exporter(),
OpentelemetryWireProtocol::HttpJson => opentelemetry_otlp::new_exporter()
.http()
.with_endpoint(otlp_endpoint)
.with_protocol(Protocol::HttpJson)
.with_timeout(Duration::from_secs(
opentelemetry_otlp::OTEL_EXPORTER_OTLP_TIMEOUT_DEFAULT,
))
.with_endpoint(endpoint)
.with_protocol(protocol)
.with_timeout(collector_timeout)
.build_log_exporter(),
}?;

Expand All @@ -108,14 +117,22 @@ impl OpentelemetryLog {

let library = Arc::new(InstrumentationLibrary::builder(name.clone()).build());

Ok(Self {
Ok(OpentelemetryLog {
name,
library,
provider,
})
}
}

/// An appender that sends log records to opentelemetry.
#[derive(Debug)]
pub struct OpentelemetryLog {
name: String,
library: Arc<InstrumentationLibrary>,
provider: LoggerProvider,
}

impl Append for OpentelemetryLog {
fn append(&self, log_record: &Record) -> anyhow::Result<()> {
let provider = self.provider.clone();
Expand Down