Skip to content

Commit

Permalink
Add a set_trace_context method to LogRecord trait (#2129)
Browse files Browse the repository at this point in the history
  • Loading branch information
KodrAus authored Oct 6, 2024
1 parent 9cbf693 commit 6aad3db
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 10 deletions.
2 changes: 2 additions & 0 deletions opentelemetry-sdk/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## vNext

- Implement `LogRecord::set_trace_context` for `LogRecord`. Respect any trace context set on a `LogRecord` when emitting through a `Logger`.

## v0.26.0
Released 2024-Sep-30

Expand Down
94 changes: 84 additions & 10 deletions opentelemetry-sdk/src/logs/log_emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,14 +256,17 @@ impl opentelemetry::logs::Logger for Logger {
fn emit(&self, mut record: Self::LogRecord) {
let provider = self.provider();
let processors = provider.log_processors();
let trace_context = Context::map_current(|cx| {
cx.has_active_span()
.then(|| TraceContext::from(cx.span().span_context()))
});

//let mut log_record = record;
if let Some(ref trace_context) = trace_context {
record.trace_context = Some(trace_context.clone());
if record.trace_context.is_none() {
let trace_context = Context::map_current(|cx| {
cx.has_active_span()
.then(|| TraceContext::from(cx.span().span_context()))
});

if let Some(ref trace_context) = trace_context {
record.trace_context = Some(trace_context.clone());
}
}
if record.observed_timestamp.is_none() {
record.observed_timestamp = Some(SystemTime::now());
Expand Down Expand Up @@ -293,13 +296,18 @@ impl opentelemetry::logs::Logger for Logger {

#[cfg(test)]
mod tests {
use crate::resource::{
SERVICE_NAME, TELEMETRY_SDK_LANGUAGE, TELEMETRY_SDK_NAME, TELEMETRY_SDK_VERSION,
use crate::{
resource::{
SERVICE_NAME, TELEMETRY_SDK_LANGUAGE, TELEMETRY_SDK_NAME, TELEMETRY_SDK_VERSION,
},
testing::logs::InMemoryLogsExporter,
trace::TracerProvider,
Resource,
};
use crate::Resource;

use super::*;
use opentelemetry::logs::{Logger, LoggerProvider as _};
use opentelemetry::logs::{AnyValue, LogRecord as _, Logger as _, LoggerProvider as _};
use opentelemetry::trace::{SpanId, TraceId, Tracer as _, TracerProvider as _};
use opentelemetry::{Key, KeyValue, Value};
use std::fmt::{Debug, Formatter};
use std::sync::atomic::AtomicU64;
Expand Down Expand Up @@ -461,6 +469,72 @@ mod tests {
assert_eq!(no_service_name.resource().len(), 0);
}

#[test]
fn trace_context_test() {
let exporter = InMemoryLogsExporter::default();

let logger_provider = LoggerProvider::builder()
.with_simple_exporter(exporter.clone())
.build();

let logger = logger_provider.logger("test-logger");

let tracer_provider = TracerProvider::builder().build();

let tracer = tracer_provider.tracer("test-tracer");

tracer.in_span("test-span", |cx| {
let ambient_ctxt = cx.span().span_context().clone();
let explicit_ctxt = TraceContext {
trace_id: TraceId::from_u128(13),
span_id: SpanId::from_u64(14),
trace_flags: None,
};

let mut ambient_ctxt_record = logger.create_log_record();
ambient_ctxt_record.set_body(AnyValue::String("ambient".into()));

let mut explicit_ctxt_record = logger.create_log_record();
explicit_ctxt_record.set_body(AnyValue::String("explicit".into()));
explicit_ctxt_record.set_trace_context(
explicit_ctxt.trace_id,
explicit_ctxt.span_id,
explicit_ctxt.trace_flags,
);

logger.emit(ambient_ctxt_record);
logger.emit(explicit_ctxt_record);

let emitted = exporter.get_emitted_logs().unwrap();

assert_eq!(
Some(AnyValue::String("ambient".into())),
emitted[0].record.body
);
assert_eq!(
ambient_ctxt.trace_id(),
emitted[0].record.trace_context.as_ref().unwrap().trace_id
);
assert_eq!(
ambient_ctxt.span_id(),
emitted[0].record.trace_context.as_ref().unwrap().span_id
);

assert_eq!(
Some(AnyValue::String("explicit".into())),
emitted[1].record.body
);
assert_eq!(
explicit_ctxt.trace_id,
emitted[1].record.trace_context.as_ref().unwrap().trace_id
);
assert_eq!(
explicit_ctxt.span_id,
emitted[1].record.trace_context.as_ref().unwrap().span_id
);
});
}

#[test]
fn shutdown_test() {
let counter = Arc::new(AtomicU64::new(0));
Expand Down
13 changes: 13 additions & 0 deletions opentelemetry-sdk/src/logs/record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,19 @@ impl opentelemetry::logs::LogRecord for LogRecord {
{
self.attributes.push(Some((key.into(), value.into())));
}

fn set_trace_context(
&mut self,
trace_id: TraceId,
span_id: SpanId,
trace_flags: Option<TraceFlags>,
) {
self.trace_context = Some(TraceContext {
trace_id,
span_id,
trace_flags,
});
}
}

impl LogRecord {
Expand Down
2 changes: 2 additions & 0 deletions opentelemetry/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## vNext

- Add `LogRecord::set_trace_context`; an optional method conditional on the `trace` feature for setting trace context on a log record.

## v0.26.0
Released 2024-Sep-30

Expand Down
17 changes: 17 additions & 0 deletions opentelemetry/src/logs/record.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
use crate::{Key, StringValue};

#[cfg(feature = "trace")]
use crate::trace::{SpanId, TraceFlags, TraceId};

use std::{borrow::Cow, collections::HashMap, time::SystemTime};

/// SDK implemented trait for managing log records
Expand Down Expand Up @@ -41,6 +45,19 @@ pub trait LogRecord {
where
K: Into<Key>,
V: Into<AnyValue>;

/// Sets the trace context of the log.
#[cfg(feature = "trace")]
fn set_trace_context(
&mut self,
trace_id: TraceId,
span_id: SpanId,
trace_flags: Option<TraceFlags>,
) {
let _ = trace_id;
let _ = span_id;
let _ = trace_flags;
}
}

/// Value types for representing arbitrary values in a log record.
Expand Down

0 comments on commit 6aad3db

Please sign in to comment.