Skip to content

Commit 6aad3db

Browse files
authored
Add a set_trace_context method to LogRecord trait (#2129)
1 parent 9cbf693 commit 6aad3db

File tree

5 files changed

+118
-10
lines changed

5 files changed

+118
-10
lines changed

opentelemetry-sdk/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## vNext
44

5+
- Implement `LogRecord::set_trace_context` for `LogRecord`. Respect any trace context set on a `LogRecord` when emitting through a `Logger`.
6+
57
## v0.26.0
68
Released 2024-Sep-30
79

opentelemetry-sdk/src/logs/log_emitter.rs

Lines changed: 84 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -256,14 +256,17 @@ impl opentelemetry::logs::Logger for Logger {
256256
fn emit(&self, mut record: Self::LogRecord) {
257257
let provider = self.provider();
258258
let processors = provider.log_processors();
259-
let trace_context = Context::map_current(|cx| {
260-
cx.has_active_span()
261-
.then(|| TraceContext::from(cx.span().span_context()))
262-
});
263259

264260
//let mut log_record = record;
265-
if let Some(ref trace_context) = trace_context {
266-
record.trace_context = Some(trace_context.clone());
261+
if record.trace_context.is_none() {
262+
let trace_context = Context::map_current(|cx| {
263+
cx.has_active_span()
264+
.then(|| TraceContext::from(cx.span().span_context()))
265+
});
266+
267+
if let Some(ref trace_context) = trace_context {
268+
record.trace_context = Some(trace_context.clone());
269+
}
267270
}
268271
if record.observed_timestamp.is_none() {
269272
record.observed_timestamp = Some(SystemTime::now());
@@ -293,13 +296,18 @@ impl opentelemetry::logs::Logger for Logger {
293296

294297
#[cfg(test)]
295298
mod tests {
296-
use crate::resource::{
297-
SERVICE_NAME, TELEMETRY_SDK_LANGUAGE, TELEMETRY_SDK_NAME, TELEMETRY_SDK_VERSION,
299+
use crate::{
300+
resource::{
301+
SERVICE_NAME, TELEMETRY_SDK_LANGUAGE, TELEMETRY_SDK_NAME, TELEMETRY_SDK_VERSION,
302+
},
303+
testing::logs::InMemoryLogsExporter,
304+
trace::TracerProvider,
305+
Resource,
298306
};
299-
use crate::Resource;
300307

301308
use super::*;
302-
use opentelemetry::logs::{Logger, LoggerProvider as _};
309+
use opentelemetry::logs::{AnyValue, LogRecord as _, Logger as _, LoggerProvider as _};
310+
use opentelemetry::trace::{SpanId, TraceId, Tracer as _, TracerProvider as _};
303311
use opentelemetry::{Key, KeyValue, Value};
304312
use std::fmt::{Debug, Formatter};
305313
use std::sync::atomic::AtomicU64;
@@ -461,6 +469,72 @@ mod tests {
461469
assert_eq!(no_service_name.resource().len(), 0);
462470
}
463471

472+
#[test]
473+
fn trace_context_test() {
474+
let exporter = InMemoryLogsExporter::default();
475+
476+
let logger_provider = LoggerProvider::builder()
477+
.with_simple_exporter(exporter.clone())
478+
.build();
479+
480+
let logger = logger_provider.logger("test-logger");
481+
482+
let tracer_provider = TracerProvider::builder().build();
483+
484+
let tracer = tracer_provider.tracer("test-tracer");
485+
486+
tracer.in_span("test-span", |cx| {
487+
let ambient_ctxt = cx.span().span_context().clone();
488+
let explicit_ctxt = TraceContext {
489+
trace_id: TraceId::from_u128(13),
490+
span_id: SpanId::from_u64(14),
491+
trace_flags: None,
492+
};
493+
494+
let mut ambient_ctxt_record = logger.create_log_record();
495+
ambient_ctxt_record.set_body(AnyValue::String("ambient".into()));
496+
497+
let mut explicit_ctxt_record = logger.create_log_record();
498+
explicit_ctxt_record.set_body(AnyValue::String("explicit".into()));
499+
explicit_ctxt_record.set_trace_context(
500+
explicit_ctxt.trace_id,
501+
explicit_ctxt.span_id,
502+
explicit_ctxt.trace_flags,
503+
);
504+
505+
logger.emit(ambient_ctxt_record);
506+
logger.emit(explicit_ctxt_record);
507+
508+
let emitted = exporter.get_emitted_logs().unwrap();
509+
510+
assert_eq!(
511+
Some(AnyValue::String("ambient".into())),
512+
emitted[0].record.body
513+
);
514+
assert_eq!(
515+
ambient_ctxt.trace_id(),
516+
emitted[0].record.trace_context.as_ref().unwrap().trace_id
517+
);
518+
assert_eq!(
519+
ambient_ctxt.span_id(),
520+
emitted[0].record.trace_context.as_ref().unwrap().span_id
521+
);
522+
523+
assert_eq!(
524+
Some(AnyValue::String("explicit".into())),
525+
emitted[1].record.body
526+
);
527+
assert_eq!(
528+
explicit_ctxt.trace_id,
529+
emitted[1].record.trace_context.as_ref().unwrap().trace_id
530+
);
531+
assert_eq!(
532+
explicit_ctxt.span_id,
533+
emitted[1].record.trace_context.as_ref().unwrap().span_id
534+
);
535+
});
536+
}
537+
464538
#[test]
465539
fn shutdown_test() {
466540
let counter = Arc::new(AtomicU64::new(0));

opentelemetry-sdk/src/logs/record.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,19 @@ impl opentelemetry::logs::LogRecord for LogRecord {
102102
{
103103
self.attributes.push(Some((key.into(), value.into())));
104104
}
105+
106+
fn set_trace_context(
107+
&mut self,
108+
trace_id: TraceId,
109+
span_id: SpanId,
110+
trace_flags: Option<TraceFlags>,
111+
) {
112+
self.trace_context = Some(TraceContext {
113+
trace_id,
114+
span_id,
115+
trace_flags,
116+
});
117+
}
105118
}
106119

107120
impl LogRecord {

opentelemetry/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## vNext
44

5+
- Add `LogRecord::set_trace_context`; an optional method conditional on the `trace` feature for setting trace context on a log record.
6+
57
## v0.26.0
68
Released 2024-Sep-30
79

opentelemetry/src/logs/record.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
use crate::{Key, StringValue};
2+
3+
#[cfg(feature = "trace")]
4+
use crate::trace::{SpanId, TraceFlags, TraceId};
5+
26
use std::{borrow::Cow, collections::HashMap, time::SystemTime};
37

48
/// SDK implemented trait for managing log records
@@ -41,6 +45,19 @@ pub trait LogRecord {
4145
where
4246
K: Into<Key>,
4347
V: Into<AnyValue>;
48+
49+
/// Sets the trace context of the log.
50+
#[cfg(feature = "trace")]
51+
fn set_trace_context(
52+
&mut self,
53+
trace_id: TraceId,
54+
span_id: SpanId,
55+
trace_flags: Option<TraceFlags>,
56+
) {
57+
let _ = trace_id;
58+
let _ = span_id;
59+
let _ = trace_flags;
60+
}
4461
}
4562

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

0 commit comments

Comments
 (0)