Skip to content

Commit 8b838fc

Browse files
authored
Add tests for tracing appender (#1415)
1 parent cd23ec2 commit 8b838fc

File tree

3 files changed

+144
-1
lines changed

3 files changed

+144
-1
lines changed

opentelemetry-appender-tracing/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,4 @@ opentelemetry-stdout = { path = "../opentelemetry-stdout", features = ["logs"] }
2424
[features]
2525
logs_level_enabled = ["opentelemetry/logs_level_enabled", "opentelemetry_sdk/logs_level_enabled"]
2626
default = ["logs_level_enabled"]
27+
testing = ["opentelemetry_sdk/testing"]

opentelemetry-appender-tracing/src/layer.rs

+142
Original file line numberDiff line numberDiff line change
@@ -140,3 +140,145 @@ const fn severity_of_level(level: &Level) -> Severity {
140140
Level::ERROR => Severity::Error,
141141
}
142142
}
143+
144+
#[cfg(test)]
145+
mod tests {
146+
use crate::layer;
147+
use opentelemetry::logs::Severity;
148+
use opentelemetry::trace::TracerProvider as _;
149+
use opentelemetry::trace::{TraceContextExt, TraceFlags, Tracer};
150+
use opentelemetry::{logs::AnyValue, Key};
151+
use opentelemetry_sdk::logs::LoggerProvider;
152+
use opentelemetry_sdk::testing::logs::InMemoryLogsExporter;
153+
use opentelemetry_sdk::trace::{config, Sampler, TracerProvider};
154+
use tracing::error;
155+
use tracing_subscriber::layer::SubscriberExt;
156+
157+
// cargo test --features=testing
158+
#[test]
159+
fn tracing_appender_standalone() {
160+
// Arrange
161+
let exporter: InMemoryLogsExporter = InMemoryLogsExporter::default();
162+
let logger_provider = LoggerProvider::builder()
163+
.with_simple_exporter(exporter.clone())
164+
.build();
165+
166+
let layer = layer::OpenTelemetryTracingBridge::new(&logger_provider);
167+
let subscriber = tracing_subscriber::registry().with(layer);
168+
169+
// avoiding setting tracing subscriber as global as that does not
170+
// play well with unit tests.
171+
let _guard = tracing::subscriber::set_default(subscriber);
172+
173+
// Act
174+
error!(name: "my-event-name", target: "my-system", event_id = 20, user_name = "otel", user_email = "[email protected]");
175+
logger_provider.force_flush();
176+
177+
// Assert TODO: move to helper methods
178+
let exported_logs = exporter
179+
.get_emitted_logs()
180+
.expect("Logs are expected to be exported.");
181+
assert_eq!(exported_logs.len(), 1);
182+
let log = exported_logs
183+
.get(0)
184+
.expect("Atleast one log is expected to be present.");
185+
186+
// Validate common fields
187+
assert_eq!(log.instrumentation.name, "opentelemetry-appender-tracing");
188+
assert_eq!(log.record.severity_number, Some(Severity::Error));
189+
190+
// Validate trace context is none.
191+
assert!(log.record.trace_context.is_none());
192+
193+
// Validate attributes
194+
let attributes: Vec<(Key, AnyValue)> = log
195+
.record
196+
.attributes
197+
.clone()
198+
.expect("Attributes are expected");
199+
assert_eq!(attributes.len(), 4);
200+
assert!(attributes.contains(&(Key::new("name"), "my-event-name".into())));
201+
assert!(attributes.contains(&(Key::new("event_id"), 20.into())));
202+
assert!(attributes.contains(&(Key::new("user_name"), "otel".into())));
203+
assert!(attributes.contains(&(Key::new("user_email"), "[email protected]".into())));
204+
}
205+
206+
#[test]
207+
fn tracing_appender_inside_tracing_context() {
208+
// Arrange
209+
let exporter: InMemoryLogsExporter = InMemoryLogsExporter::default();
210+
let logger_provider = LoggerProvider::builder()
211+
.with_simple_exporter(exporter.clone())
212+
.build();
213+
214+
let layer = layer::OpenTelemetryTracingBridge::new(&logger_provider);
215+
let subscriber = tracing_subscriber::registry().with(layer);
216+
217+
// avoiding setting tracing subscriber as global as that does not
218+
// play well with unit tests.
219+
let _guard = tracing::subscriber::set_default(subscriber);
220+
221+
// setup tracing as well.
222+
let tracer_provider = TracerProvider::builder()
223+
.with_config(config().with_sampler(Sampler::AlwaysOn))
224+
.build();
225+
let tracer = tracer_provider.tracer("test-tracer");
226+
227+
// Act
228+
let (trace_id_expected, span_id_expected) = tracer.in_span("test-span", |cx| {
229+
let trace_id = cx.span().span_context().trace_id();
230+
let span_id = cx.span().span_context().span_id();
231+
232+
// logging is done inside span context.
233+
error!(name: "my-event-name", target: "my-system", event_id = 20, user_name = "otel", user_email = "[email protected]");
234+
(trace_id, span_id)
235+
});
236+
237+
logger_provider.force_flush();
238+
239+
// Assert TODO: move to helper methods
240+
let exported_logs = exporter
241+
.get_emitted_logs()
242+
.expect("Logs are expected to be exported.");
243+
assert_eq!(exported_logs.len(), 1);
244+
let log = exported_logs
245+
.get(0)
246+
.expect("Atleast one log is expected to be present.");
247+
248+
// validate common fields.
249+
assert_eq!(log.instrumentation.name, "opentelemetry-appender-tracing");
250+
assert_eq!(log.record.severity_number, Some(Severity::Error));
251+
252+
// validate trace context.
253+
assert!(log.record.trace_context.is_some());
254+
assert_eq!(
255+
log.record.trace_context.as_ref().unwrap().trace_id,
256+
trace_id_expected
257+
);
258+
assert_eq!(
259+
log.record.trace_context.as_ref().unwrap().span_id,
260+
span_id_expected
261+
);
262+
assert_eq!(
263+
log.record
264+
.trace_context
265+
.as_ref()
266+
.unwrap()
267+
.trace_flags
268+
.unwrap(),
269+
TraceFlags::SAMPLED
270+
);
271+
272+
// validate attributes.
273+
let attributes: Vec<(Key, AnyValue)> = log
274+
.record
275+
.attributes
276+
.clone()
277+
.expect("Attributes are expected");
278+
assert_eq!(attributes.len(), 4);
279+
assert!(attributes.contains(&(Key::new("name"), "my-event-name".into())));
280+
assert!(attributes.contains(&(Key::new("event_id"), 20.into())));
281+
assert!(attributes.contains(&(Key::new("user_name"), "otel".into())));
282+
assert!(attributes.contains(&(Key::new("user_email"), "[email protected]".into())));
283+
}
284+
}

opentelemetry/src/logs/record.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ impl From<&SpanContext> for TraceContext {
7575
}
7676

7777
/// Value types for representing arbitrary values in a log record.
78-
#[derive(Debug, Clone)]
78+
#[derive(Debug, Clone, PartialEq)]
7979
pub enum AnyValue {
8080
/// An integer value
8181
Int(i64),

0 commit comments

Comments
 (0)