Skip to content

Commit 42875fe

Browse files
authored
Merge branch 'main' into sem-conv-v1.27.0
2 parents f496eea + fe10ab1 commit 42875fe

File tree

13 files changed

+497
-212
lines changed

13 files changed

+497
-212
lines changed

opentelemetry-appender-log/src/lib.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -938,10 +938,9 @@ mod tests {
938938
);
939939

940940
let logs = exporter.get_emitted_logs().unwrap();
941-
let attributes = &logs[0].record.attributes.as_ref().unwrap();
942941

943-
let get = |needle: &str| {
944-
attributes.iter().find_map(|(k, v)| {
942+
let get = |needle: &str| -> Option<AnyValue> {
943+
logs[0].record.attributes_iter().find_map(|(k, v)| {
945944
if k.as_str() == needle {
946945
Some(v.clone())
947946
} else {

opentelemetry-appender-tracing/CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## vNext
44

5+
- Reduce heap allocation by using `&'static str` for `SeverityText`.
6+
57
## v0.5.0
68

79
- [1869](https://github.com/open-telemetry/opentelemetry-rust/pull/1869) Utilize the `LogRecord::set_target()` method to pass the tracing target to the SDK.

opentelemetry-appender-tracing/benches/logs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
| noop_layer_disabled | 12 ns |
1111
| noop_layer_enabled | 25 ns |
1212
| ot_layer_disabled | 19 ns |
13-
| ot_layer_enabled | 305 ns |
13+
| ot_layer_enabled | 280 ns |
1414
*/
1515

1616
use async_trait::async_trait;

opentelemetry-appender-tracing/src/layer.rs

+104-64
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ where
168168
log_record.set_target(meta.target().to_string());
169169
log_record.set_event_name(meta.name());
170170
log_record.set_severity_number(severity_of_level(meta.level()));
171-
log_record.set_severity_text(meta.level().to_string().into());
171+
log_record.set_severity_text(meta.level().as_str().into());
172172
let mut visitor = EventVisitor::new(&mut log_record);
173173
#[cfg(feature = "experimental_metadata_attributes")]
174174
visitor.visit_experimental_metadata(meta);
@@ -208,13 +208,19 @@ mod tests {
208208
use opentelemetry::trace::TracerProvider as _;
209209
use opentelemetry::trace::{TraceContextExt, TraceFlags, Tracer};
210210
use opentelemetry::{logs::AnyValue, Key};
211-
use opentelemetry_sdk::logs::LoggerProvider;
211+
use opentelemetry_sdk::logs::{LogRecord, LoggerProvider};
212212
use opentelemetry_sdk::testing::logs::InMemoryLogsExporter;
213213
use opentelemetry_sdk::trace;
214214
use opentelemetry_sdk::trace::{Sampler, TracerProvider};
215215
use tracing::error;
216216
use tracing_subscriber::layer::SubscriberExt;
217217

218+
pub fn attributes_contains(log_record: &LogRecord, key: &Key, value: &AnyValue) -> bool {
219+
log_record
220+
.attributes_iter()
221+
.any(|(k, v)| k == key && v == value)
222+
}
223+
218224
// cargo test --features=testing
219225
#[test]
220226
fn tracing_appender_standalone() {
@@ -252,29 +258,45 @@ mod tests {
252258
assert!(log.record.trace_context.is_none());
253259

254260
// Validate attributes
255-
let attributes: Vec<(Key, AnyValue)> = log
256-
.record
257-
.attributes
258-
.clone()
259-
.expect("Attributes are expected");
260261
#[cfg(not(feature = "experimental_metadata_attributes"))]
261-
assert_eq!(attributes.len(), 3);
262+
assert_eq!(log.record.attributes_iter().count(), 3);
262263
#[cfg(feature = "experimental_metadata_attributes")]
263-
assert_eq!(attributes.len(), 8);
264-
assert!(attributes.contains(&(Key::new("event_id"), 20.into())));
265-
assert!(attributes.contains(&(Key::new("user_name"), "otel".into())));
266-
assert!(attributes.contains(&(Key::new("user_email"), "otel@opentelemetry.io".into())));
264+
assert_eq!(log.record.attributes_iter().count(), 8);
265+
assert!(attributes_contains(
266+
&log.record,
267+
&Key::new("event_id"),
268+
&AnyValue::Int(20)
269+
));
270+
assert!(attributes_contains(
271+
&log.record,
272+
&Key::new("user_name"),
273+
&AnyValue::String("otel".into())
274+
));
275+
assert!(attributes_contains(
276+
&log.record,
277+
&Key::new("user_email"),
278+
&AnyValue::String("otel@opentelemetry.io".into())
279+
));
267280
#[cfg(feature = "experimental_metadata_attributes")]
268281
{
269-
assert!(attributes.contains(&(Key::new("code.filename"), "layer.rs".into())));
270-
assert!(attributes.contains(&(
271-
Key::new("code.namespace"),
272-
"opentelemetry_appender_tracing::layer::tests".into()
273-
)));
282+
assert!(attributes_contains(
283+
&log.record,
284+
&Key::new("code.filename"),
285+
&AnyValue::String("layer.rs".into())
286+
));
287+
assert!(attributes_contains(
288+
&log.record,
289+
&Key::new("code.namespace"),
290+
&AnyValue::String("opentelemetry_appender_tracing::layer::tests".into())
291+
));
274292
// The other 3 experimental_metadata_attributes are too unstable to check their value.
275293
// Ex.: The path will be different on a Windows and Linux machine.
276294
// Ex.: The line can change easily if someone makes changes in this source file.
277-
let attributes_key: Vec<Key> = attributes.iter().map(|(key, _)| key.clone()).collect();
295+
let attributes_key: Vec<Key> = log
296+
.record
297+
.attributes_iter()
298+
.map(|(key, _)| key.clone())
299+
.collect();
278300
assert!(attributes_key.contains(&Key::new("code.filepath")));
279301
assert!(attributes_key.contains(&Key::new("code.lineno")));
280302
assert!(attributes_key.contains(&Key::new("log.target")));
@@ -348,29 +370,45 @@ mod tests {
348370
);
349371

350372
// validate attributes.
351-
let attributes: Vec<(Key, AnyValue)> = log
352-
.record
353-
.attributes
354-
.clone()
355-
.expect("Attributes are expected");
356373
#[cfg(not(feature = "experimental_metadata_attributes"))]
357-
assert_eq!(attributes.len(), 3);
374+
assert_eq!(log.record.attributes_iter().count(), 3);
358375
#[cfg(feature = "experimental_metadata_attributes")]
359-
assert_eq!(attributes.len(), 8);
360-
assert!(attributes.contains(&(Key::new("event_id"), 20.into())));
361-
assert!(attributes.contains(&(Key::new("user_name"), "otel".into())));
362-
assert!(attributes.contains(&(Key::new("user_email"), "otel@opentelemetry.io".into())));
376+
assert_eq!(log.record.attributes_iter().count(), 8);
377+
assert!(attributes_contains(
378+
&log.record,
379+
&Key::new("event_id"),
380+
&AnyValue::Int(20.into())
381+
));
382+
assert!(attributes_contains(
383+
&log.record,
384+
&Key::new("user_name"),
385+
&AnyValue::String("otel".into())
386+
));
387+
assert!(attributes_contains(
388+
&log.record,
389+
&Key::new("user_email"),
390+
&AnyValue::String("otel@opentelemetry.io".into())
391+
));
363392
#[cfg(feature = "experimental_metadata_attributes")]
364393
{
365-
assert!(attributes.contains(&(Key::new("code.filename"), "layer.rs".into())));
366-
assert!(attributes.contains(&(
367-
Key::new("code.namespace"),
368-
"opentelemetry_appender_tracing::layer::tests".into()
369-
)));
394+
assert!(attributes_contains(
395+
&log.record,
396+
&Key::new("code.filename"),
397+
&AnyValue::String("layer.rs".into())
398+
));
399+
assert!(attributes_contains(
400+
&log.record,
401+
&Key::new("code.namespace"),
402+
&AnyValue::String("opentelemetry_appender_tracing::layer::tests".into())
403+
));
370404
// The other 3 experimental_metadata_attributes are too unstable to check their value.
371405
// Ex.: The path will be different on a Windows and Linux machine.
372406
// Ex.: The line can change easily if someone makes changes in this source file.
373-
let attributes_key: Vec<Key> = attributes.iter().map(|(key, _)| key.clone()).collect();
407+
let attributes_key: Vec<Key> = log
408+
.record
409+
.attributes_iter()
410+
.map(|(key, _)| key.clone())
411+
.collect();
374412
assert!(attributes_key.contains(&Key::new("code.filepath")));
375413
assert!(attributes_key.contains(&Key::new("code.lineno")));
376414
assert!(attributes_key.contains(&Key::new("log.target")));
@@ -413,29 +451,30 @@ mod tests {
413451
// Validate trace context is none.
414452
assert!(log.record.trace_context.is_none());
415453

416-
// Validate attributes
417-
#[cfg(feature = "experimental_metadata_attributes")]
418-
let attributes: Vec<(Key, AnyValue)> = log
419-
.record
420-
.attributes
421-
.clone()
422-
.expect("Attributes are expected");
423-
424454
// Attributes can be polluted when we don't use this feature.
425455
#[cfg(feature = "experimental_metadata_attributes")]
426-
assert_eq!(attributes.len(), 5);
456+
assert_eq!(log.record.attributes_iter().count(), 5);
427457

428458
#[cfg(feature = "experimental_metadata_attributes")]
429459
{
430-
assert!(attributes.contains(&(Key::new("code.filename"), "layer.rs".into())));
431-
assert!(attributes.contains(&(
432-
Key::new("code.namespace"),
433-
"opentelemetry_appender_tracing::layer::tests".into()
434-
)));
460+
assert!(attributes_contains(
461+
&log.record,
462+
&Key::new("code.filename"),
463+
&AnyValue::String("layer.rs".into())
464+
));
465+
assert!(attributes_contains(
466+
&log.record,
467+
&Key::new("code.namespace"),
468+
&AnyValue::String("opentelemetry_appender_tracing::layer::tests".into())
469+
));
435470
// The other 3 experimental_metadata_attributes are too unstable to check their value.
436471
// Ex.: The path will be different on a Windows and Linux machine.
437472
// Ex.: The line can change easily if someone makes changes in this source file.
438-
let attributes_key: Vec<Key> = attributes.iter().map(|(key, _)| key.clone()).collect();
473+
let attributes_key: Vec<Key> = log
474+
.record
475+
.attributes_iter()
476+
.map(|(key, _)| key.clone())
477+
.collect();
439478
assert!(attributes_key.contains(&Key::new("code.filepath")));
440479
assert!(attributes_key.contains(&Key::new("code.lineno")));
441480
assert!(attributes_key.contains(&Key::new("log.target")));
@@ -509,29 +548,30 @@ mod tests {
509548
TraceFlags::SAMPLED
510549
);
511550

512-
// validate attributes.
513-
#[cfg(feature = "experimental_metadata_attributes")]
514-
let attributes: Vec<(Key, AnyValue)> = log
515-
.record
516-
.attributes
517-
.clone()
518-
.expect("Attributes are expected");
519-
520551
// Attributes can be polluted when we don't use this feature.
521552
#[cfg(feature = "experimental_metadata_attributes")]
522-
assert_eq!(attributes.len(), 5);
553+
assert_eq!(log.record.attributes_iter().count(), 5);
523554

524555
#[cfg(feature = "experimental_metadata_attributes")]
525556
{
526-
assert!(attributes.contains(&(Key::new("code.filename"), "layer.rs".into())));
527-
assert!(attributes.contains(&(
528-
Key::new("code.namespace"),
529-
"opentelemetry_appender_tracing::layer::tests".into()
530-
)));
557+
assert!(attributes_contains(
558+
&log.record,
559+
&Key::new("code.filename"),
560+
&AnyValue::String("layer.rs".into())
561+
));
562+
assert!(attributes_contains(
563+
&log.record,
564+
&Key::new("code.namespace"),
565+
&AnyValue::String("opentelemetry_appender_tracing::layer::tests".into())
566+
));
531567
// The other 3 experimental_metadata_attributes are too unstable to check their value.
532568
// Ex.: The path will be different on a Windows and Linux machine.
533569
// Ex.: The line can change easily if someone makes changes in this source file.
534-
let attributes_key: Vec<Key> = attributes.iter().map(|(key, _)| key.clone()).collect();
570+
let attributes_key: Vec<Key> = log
571+
.record
572+
.attributes_iter()
573+
.map(|(key, _)| key.clone())
574+
.collect();
535575
assert!(attributes_key.contains(&Key::new("code.filepath")));
536576
assert!(attributes_key.contains(&Key::new("code.lineno")));
537577
assert!(attributes_key.contains(&Key::new("log.target")));

opentelemetry-proto/src/transform/logs.rs

+13-10
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ pub mod tonic {
88
},
99
logs::v1::{LogRecord, ResourceLogs, ScopeLogs, SeverityNumber},
1010
resource::v1::Resource,
11-
Attributes,
1211
},
1312
transform::common::{to_nanos, tonic::ResourceAttributesWithSchema},
1413
};
@@ -89,25 +88,29 @@ pub mod tonic {
8988
LogRecord {
9089
time_unix_nano: log_record.timestamp.map(to_nanos).unwrap_or_default(),
9190
observed_time_unix_nano: to_nanos(log_record.observed_timestamp.unwrap()),
92-
severity_number: severity_number.into(),
93-
severity_text: log_record.severity_text.map(Into::into).unwrap_or_default(),
94-
body: log_record.body.map(Into::into),
9591
attributes: {
96-
let mut attributes = log_record
97-
.attributes
98-
.map(Attributes::from_iter)
99-
.unwrap_or_default()
100-
.0;
92+
let mut attributes: Vec<KeyValue> = log_record
93+
.attributes_iter()
94+
.map(|kv| KeyValue {
95+
key: kv.0.to_string(),
96+
value: Some(AnyValue {
97+
value: Some(kv.1.clone().into()),
98+
}),
99+
})
100+
.collect();
101101
if let Some(event_name) = log_record.event_name.as_ref() {
102102
attributes.push(KeyValue {
103103
key: "name".into(),
104104
value: Some(AnyValue {
105105
value: Some(Value::StringValue(event_name.to_string())),
106106
}),
107-
})
107+
});
108108
}
109109
attributes
110110
},
111+
severity_number: severity_number.into(),
112+
severity_text: log_record.severity_text.map(Into::into).unwrap_or_default(),
113+
body: log_record.body.map(Into::into),
111114
dropped_attributes_count: 0,
112115
flags: trace_context
113116
.map(|ctx| {

opentelemetry-sdk/CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111
first interval instead of doing it right away.
1212
[#1970](https://github.com/open-telemetry/opentelemetry-rust/pull/1970)
1313
[#1973](https://github.com/open-telemetry/opentelemetry-rust/pull/1973)
14+
- **Breaking** [#1985](https://github.com/open-telemetry/opentelemetry-rust/pull/1985)
15+
Hide LogRecord attributes Implementation Details from processors and exporters.
16+
The custom exporters and processors can't directly access the `LogData::LogRecord::attributes`, as
17+
these are private to opentelemetry-sdk. Instead, they would now use LogRecord::attributes_iter()
18+
method to access them.
1419

1520

1621
## v0.24.1

opentelemetry-sdk/benches/log.rs

+36
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,17 @@
22
//! So to run test named "full-log-with-attributes/with-context" you would run `$ cargo bench --bench log -- --exact full-log-with-attributes/with-context`
33
//! To run all tests for logs you would run `$ cargo bench --bench log`
44
//!
5+
/*
6+
The benchmark results:
7+
criterion = "0.5.1"
8+
OS: Ubuntu 22.04.3 LTS (5.15.146.1-microsoft-standard-WSL2)
9+
Hardware: AMD EPYC 7763 64-Core Processor - 2.44 GHz, 16vCPUs,
10+
RAM: 64.0 GB
11+
| Test | Average time|
12+
|--------------------------------|-------------|
13+
| Logger_Creation | 30 ns |
14+
| LoggerProvider_Creation | 909 ns |
15+
*/
516

617
use std::collections::HashMap;
718
use std::time::SystemTime;
@@ -80,7 +91,32 @@ fn log_benchmark_group<F: Fn(&Logger)>(c: &mut Criterion, name: &str, f: F) {
8091
group.finish();
8192
}
8293

94+
fn log_provider_creation(c: &mut Criterion) {
95+
c.bench_function("LoggerProvider_Creation", |b| {
96+
b.iter(|| {
97+
let _provider = LoggerProvider::builder()
98+
.with_log_processor(NoopProcessor {})
99+
.build();
100+
});
101+
});
102+
}
103+
104+
fn logger_creation(c: &mut Criterion) {
105+
// Provider is created once, outside of the benchmark
106+
let provider = LoggerProvider::builder()
107+
.with_log_processor(NoopProcessor {})
108+
.build();
109+
110+
c.bench_function("Logger_Creation", |b| {
111+
b.iter(|| {
112+
let _logger = provider.logger("benchmark");
113+
});
114+
});
115+
}
116+
83117
fn criterion_benchmark(c: &mut Criterion) {
118+
logger_creation(c);
119+
log_provider_creation(c);
84120
log_benchmark_group(c, "simple-log", |logger| {
85121
let mut log_record = logger.create_log_record();
86122
log_record.set_body("simple log".into());

0 commit comments

Comments
 (0)