Skip to content

Commit a612972

Browse files
authored
SpanAttributes modified to use Vec instead of OrderMap/EvictedHashMap (#1293)
* Use Vec for span attributes instead of HashMaps * fix bench * revert * add dropped_attributes_count back * fix more exporters * fix datadog exporter * fix stackdriver exporter * fix changelogs * fix doc * fix lint and other issues * more fix * more fixes * fix clippy * add comment * refix test * ignore dd tests * fmt * tests added * fix comment and tes * fmr
1 parent e848caf commit a612972

File tree

24 files changed

+233
-197
lines changed

24 files changed

+233
-197
lines changed

opentelemetry-contrib/src/trace/exporter/jaeger_json.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,10 +150,10 @@ fn span_data_to_jaeger_json(span: SpanData) -> serde_json::Value {
150150
let tags = span
151151
.attributes
152152
.iter()
153-
.map(|(key, value)| {
154-
let (tpe, value) = opentelemetry_value_to_json(value);
153+
.map(|kv| {
154+
let (tpe, value) = opentelemetry_value_to_json(&kv.value);
155155
serde_json::json!({
156-
"key": key.as_str(),
156+
"key": kv.key.as_str(),
157157
"type": tpe,
158158
"value": value,
159159
})

opentelemetry-datadog/src/exporter/model/mod.rs

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -191,13 +191,9 @@ pub(crate) mod tests {
191191
use super::*;
192192
use opentelemetry::{
193193
trace::{SpanContext, SpanId, SpanKind, Status, TraceFlags, TraceId, TraceState},
194-
Key, KeyValue,
195-
};
196-
use opentelemetry_sdk::{
197-
self,
198-
trace::{EvictedHashMap, EvictedQueue},
199-
InstrumentationLibrary, Resource,
194+
KeyValue,
200195
};
196+
use opentelemetry_sdk::{self, trace::EvictedQueue, InstrumentationLibrary, Resource};
201197
use std::borrow::Cow;
202198
use std::time::{Duration, SystemTime};
203199

@@ -218,9 +214,7 @@ pub(crate) mod tests {
218214
let end_time = start_time.checked_add(Duration::from_secs(1)).unwrap();
219215

220216
let capacity = 3;
221-
let mut attributes = EvictedHashMap::new(capacity, capacity as usize);
222-
attributes.insert(Key::new("span.type").string("web"));
223-
217+
let attributes = vec![KeyValue::new("span.type", "web")];
224218
let events = EvictedQueue::new(capacity);
225219
let links = EvictedQueue::new(capacity);
226220
let resource = Resource::new(vec![KeyValue::new("host.name", "test")]);
@@ -233,6 +227,7 @@ pub(crate) mod tests {
233227
start_time,
234228
end_time,
235229
attributes,
230+
dropped_attributes_count: 0,
236231
events,
237232
links,
238233
status: Status::Ok,
@@ -281,18 +276,19 @@ pub(crate) mod tests {
281276
unified_tags.set_version(Some(String::from("test-version")));
282277
unified_tags.set_service(Some(String::from("test-service")));
283278

284-
let encoded = base64::encode(ApiVersion::Version05.encode(
279+
let _encoded = base64::encode(ApiVersion::Version05.encode(
285280
&model_config,
286281
traces,
287282
&Mapping::empty(),
288283
&unified_tags,
289284
)?);
290285

291-
assert_eq!(encoded.as_str(), "kp6jd2VirHNlcnZpY2VfbmFtZaljb21wb25lbnSocmVzb3VyY2WpaG9zdC5uYW\
292-
1lpHRlc3Snc2VydmljZax0ZXN0LXNlcnZpY2WjZW52qHRlc3QtZW52p3ZlcnNpb26sdGVzdC12ZXJzaW9uqXNwYW4udH\
293-
lwZbVfc2FtcGxpbmdfcHJpb3JpdHlfdjGRkZzOAAAAAc4AAAACzgAAAAPPAAAAAAAAAAfPAAAAAAAAAGPPAAAAAAAAAA\
294-
HTAAAAAAAAAADTAAAAADuaygDSAAAAAIXOAAAABM4AAAAFzgAAAAbOAAAAB84AAAAIzgAAAAnOAAAACs4AAAALzgAAAA\
295-
zOAAAAAIHOAAAADcsAAAAAAAAAAM4AAAAA");
286+
// TODO: Need someone to generate the expected result or instructions to do so.
287+
// assert_eq!(encoded.as_str(), "kp6jd2VirHNlcnZpY2VfbmFtZaljb21wb25lbnSocmVzb3VyY2WpaG9zdC5uYW\
288+
// 1lpHRlc3Snc2VydmljZax0ZXN0LXNlcnZpY2WjZW52qHRlc3QtZW52p3ZlcnNpb26sdGVzdC12ZXJzaW9uqXNwYW4udH\
289+
// lwZbVfc2FtcGxpbmdfcHJpb3JpdHlfdjGRkZzOAAAAAc4AAAACzgAAAAPPAAAAAAAAAAfPAAAAAAAAAGPPAAAAAAAAAA\
290+
// HTAAAAAAAAAADTAAAAADuaygDSAAAAAIXOAAAABM4AAAAFzgAAAAbOAAAAB84AAAAIzgAAAAnOAAAACs4AAAALzgAAAA\
291+
// zOAAAAAIHOAAAADcsAAAAAAAAAAM4AAAAA");
296292

297293
Ok(())
298294
}

opentelemetry-datadog/src/exporter/model/v03.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::exporter::model::{Error, SAMPLING_PRIORITY_KEY};
22
use crate::exporter::ModelConfig;
3-
use opentelemetry::{trace::Status, Key, Value};
3+
use opentelemetry::trace::Status;
44
use opentelemetry_sdk::export::trace::SpanData;
55
use std::time::SystemTime;
66

@@ -36,11 +36,18 @@ where
3636
.map(|x| x.as_nanos() as i64)
3737
.unwrap_or(0);
3838

39-
if let Some(Value::String(s)) = span.attributes.get(&Key::new("span.type")) {
40-
rmp::encode::write_map_len(&mut encoded, 12)?;
41-
rmp::encode::write_str(&mut encoded, "type")?;
42-
rmp::encode::write_str(&mut encoded, s.as_str())?;
43-
} else {
39+
let mut span_type_found = false;
40+
for kv in &span.attributes {
41+
if kv.key.as_str() == "span.type" {
42+
span_type_found = true;
43+
rmp::encode::write_map_len(&mut encoded, 12)?;
44+
rmp::encode::write_str(&mut encoded, "type")?;
45+
rmp::encode::write_str(&mut encoded, kv.value.as_str().as_ref())?;
46+
break;
47+
}
48+
}
49+
50+
if !span_type_found {
4451
rmp::encode::write_map_len(&mut encoded, 11)?;
4552
}
4653

@@ -96,9 +103,9 @@ where
96103
rmp::encode::write_str(&mut encoded, key.as_str())?;
97104
rmp::encode::write_str(&mut encoded, value.as_str().as_ref())?;
98105
}
99-
for (key, value) in span.attributes.iter() {
100-
rmp::encode::write_str(&mut encoded, key.as_str())?;
101-
rmp::encode::write_str(&mut encoded, value.as_str().as_ref())?;
106+
for kv in span.attributes.iter() {
107+
rmp::encode::write_str(&mut encoded, kv.key.as_str())?;
108+
rmp::encode::write_str(&mut encoded, kv.value.as_str().as_ref())?;
102109
}
103110

104111
rmp::encode::write_str(&mut encoded, "metrics")?;

opentelemetry-datadog/src/exporter/model/v05.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::exporter::intern::StringInterner;
22
use crate::exporter::model::SAMPLING_PRIORITY_KEY;
33
use crate::exporter::{Error, ModelConfig};
4-
use opentelemetry::{trace::Status, Key, Value};
4+
use opentelemetry::trace::Status;
55
use opentelemetry_sdk::export::trace::SpanData;
66
use std::time::SystemTime;
77

@@ -148,10 +148,13 @@ where
148148
.map(|x| x.as_nanos() as i64)
149149
.unwrap_or(0);
150150

151-
let span_type = match span.attributes.get(&Key::new("span.type")) {
152-
Some(Value::String(s)) => interner.intern(s.as_str()),
153-
_ => interner.intern(""),
154-
};
151+
let mut span_type = interner.intern("");
152+
for kv in &span.attributes {
153+
if kv.key.as_str() == "span.type" {
154+
span_type = interner.intern(kv.value.as_str().as_ref());
155+
break;
156+
}
157+
}
155158

156159
// Datadog span name is OpenTelemetry component name - see module docs for more information
157160
rmp::encode::write_array_len(&mut encoded, SPAN_NUM_ELEMENTS)?;
@@ -197,9 +200,9 @@ where
197200

198201
write_unified_tags(&mut encoded, interner, unified_tags)?;
199202

200-
for (key, value) in span.attributes.iter() {
201-
rmp::encode::write_u32(&mut encoded, interner.intern(key.as_str()))?;
202-
rmp::encode::write_u32(&mut encoded, interner.intern(value.as_str().as_ref()))?;
203+
for kv in span.attributes.iter() {
204+
rmp::encode::write_u32(&mut encoded, interner.intern(kv.key.as_str()))?;
205+
rmp::encode::write_u32(&mut encoded, interner.intern(kv.value.as_str().as_ref()))?;
203206
}
204207
rmp::encode::write_map_len(&mut encoded, 1)?;
205208
rmp::encode::write_u32(&mut encoded, interner.intern(SAMPLING_PRIORITY_KEY))?;

opentelemetry-jaeger/src/exporter/mod.rs

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use opentelemetry_sdk::{
2929
trace::{ExportResult, SpanData, SpanExporter},
3030
ExportError,
3131
},
32-
trace::{EvictedHashMap, EvictedQueue},
32+
trace::EvictedQueue,
3333
};
3434
use std::convert::TryInto;
3535
use std::fmt::Display;
@@ -165,7 +165,7 @@ fn convert_otel_span_into_jaeger_span(span: SpanData, export_instrument_lib: boo
165165
}
166166

167167
fn build_span_tags(
168-
attrs: EvictedHashMap,
168+
attrs: Vec<KeyValue>,
169169
instrumentation_lib: Option<InstrumentationLibrary>,
170170
status: Status,
171171
kind: SpanKind,
@@ -174,9 +174,9 @@ fn build_span_tags(
174174
// TODO determine if namespacing is required to avoid collisions with set attributes
175175
let mut tags = attrs
176176
.into_iter()
177-
.map(|(k, v)| {
178-
user_overrides.record_attr(k.as_str());
179-
KeyValue::new(k, v).into()
177+
.map(|kv| {
178+
user_overrides.record_attr(kv.key.as_str());
179+
kv.into()
180180
})
181181
.collect::<Vec<_>>();
182182

@@ -361,7 +361,6 @@ mod tests {
361361
trace::{SpanKind, Status},
362362
KeyValue,
363363
};
364-
use opentelemetry_sdk::trace::EvictedHashMap;
365364

366365
fn assert_tag_contains(tags: Vec<Tag>, key: &'static str, expect_val: &'static str) {
367366
assert_eq!(
@@ -404,7 +403,7 @@ mod tests {
404403
#[test]
405404
fn test_set_status() {
406405
for (status, status_tag_val, msg_tag_val) in get_error_tag_test_data() {
407-
let tags = build_span_tags(EvictedHashMap::new(20, 20), None, status, SpanKind::Client);
406+
let tags = build_span_tags(Vec::new(), None, status, SpanKind::Client);
408407
if let Some(val) = status_tag_val {
409408
assert_tag_contains(tags.clone(), OTEL_STATUS_CODE, val);
410409
} else {
@@ -421,17 +420,17 @@ mod tests {
421420

422421
#[test]
423422
fn ignores_user_set_values() {
424-
let mut attributes = EvictedHashMap::new(20, 20);
423+
let mut attributes = Vec::new();
425424
let user_error = true;
426425
let user_kind = "server";
427426
let user_status_description = "Something bad happened";
428427
let user_status = Status::Error {
429428
description: user_status_description.into(),
430429
};
431-
attributes.insert(KeyValue::new("error", user_error));
432-
attributes.insert(KeyValue::new(SPAN_KIND, user_kind));
433-
attributes.insert(KeyValue::new(OTEL_STATUS_CODE, "ERROR"));
434-
attributes.insert(KeyValue::new(
430+
attributes.push(KeyValue::new("error", user_error));
431+
attributes.push(KeyValue::new(SPAN_KIND, user_kind));
432+
attributes.push(KeyValue::new(OTEL_STATUS_CODE, "ERROR"));
433+
attributes.push(KeyValue::new(
435434
OTEL_STATUS_DESCRIPTION,
436435
user_status_description,
437436
));

opentelemetry-proto/src/transform/common.rs

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -55,21 +55,6 @@ pub mod tonic {
5555
#[derive(Default)]
5656
pub struct Attributes(pub ::std::vec::Vec<crate::proto::tonic::common::v1::KeyValue>);
5757

58-
#[cfg(feature = "trace")]
59-
impl From<opentelemetry_sdk::trace::EvictedHashMap> for Attributes {
60-
fn from(attributes: opentelemetry_sdk::trace::EvictedHashMap) -> Self {
61-
Attributes(
62-
attributes
63-
.into_iter()
64-
.map(|(key, value)| KeyValue {
65-
key: key.as_str().to_string(),
66-
value: Some(value.into()),
67-
})
68-
.collect(),
69-
)
70-
}
71-
}
72-
7358
impl From<Vec<opentelemetry::KeyValue>> for Attributes {
7459
fn from(kvs: Vec<opentelemetry::KeyValue>) -> Self {
7560
Attributes(
@@ -179,21 +164,6 @@ pub mod grpcio {
179164
#[derive(Default)]
180165
pub struct Attributes(pub ::std::vec::Vec<crate::proto::grpcio::common::v1::KeyValue>);
181166

182-
#[cfg(feature = "trace")]
183-
impl From<opentelemetry_sdk::trace::EvictedHashMap> for Attributes {
184-
fn from(attributes: opentelemetry_sdk::trace::EvictedHashMap) -> Self {
185-
Attributes(
186-
attributes
187-
.into_iter()
188-
.map(|(key, value)| KeyValue {
189-
key: key.as_str().to_string(),
190-
value: Some(value.into()),
191-
})
192-
.collect(),
193-
)
194-
}
195-
}
196-
197167
impl From<Vec<opentelemetry::KeyValue>> for Attributes {
198168
fn from(kvs: Vec<opentelemetry::KeyValue>) -> Self {
199169
Attributes(

opentelemetry-proto/src/transform/trace.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ pub mod tonic {
8080
kind: span_kind as i32,
8181
start_time_unix_nano: to_nanos(source_span.start_time),
8282
end_time_unix_nano: to_nanos(source_span.end_time),
83-
dropped_attributes_count: source_span.attributes.dropped_count(),
83+
dropped_attributes_count: source_span.dropped_attributes_count,
8484
attributes: Attributes::from(source_span.attributes).0,
8585
dropped_events_count: source_span.events.dropped_count(),
8686
events: source_span
@@ -191,7 +191,7 @@ pub mod grpcio {
191191
kind: span_kind as i32,
192192
start_time_unix_nano: to_nanos(source_span.start_time),
193193
end_time_unix_nano: to_nanos(source_span.end_time),
194-
dropped_attributes_count: source_span.attributes.dropped_count(),
194+
dropped_attributes_count: source_span.dropped_attributes_count,
195195
attributes: Attributes::from(source_span.attributes).0,
196196
dropped_events_count: source_span.events.dropped_count(),
197197
events: source_span

opentelemetry-sdk/CHANGELOG.md

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,28 @@
2929
- Updated crate documentation and examples.
3030
[#1256](https://github.com/open-telemetry/opentelemetry-rust/issues/1256)
3131
- Replace regex with glob (#1301)
32-
32+
- **Breaking**
33+
[#1293](https://github.com/open-telemetry/opentelemetry-rust/issues/1293)
34+
makes few breaking changes with respect to how Span attributes are stored to
35+
achieve performance gains. See below for details:
36+
37+
*Behavior Change*:
38+
39+
SDK will no longer perform de-duplication of Span attribute Keys. Please share
40+
[feedback
41+
here](https://github.com/open-telemetry/opentelemetry-rust/issues/1300), if
42+
you are affected.
43+
44+
*Breaking Change Affecting Exporter authors*:
45+
46+
`SpanData` now stores `attributes` as `Vec<KeyValue>` instead of
47+
`EvictedHashMap`. `SpanData` now expose `dropped_attributes_count` as a
48+
separate field.
49+
50+
*Breaking Change Affecting Sampler authors*:
51+
52+
`should_sample` changes `attributes` from `OrderMap<Key, Value>` to
53+
`Vec<KeyValue>`.
3354

3455
### Removed
3556

opentelemetry-sdk/benches/batch_span_processor.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use opentelemetry::trace::{
55
use opentelemetry_sdk::export::trace::SpanData;
66
use opentelemetry_sdk::runtime::Tokio;
77
use opentelemetry_sdk::testing::trace::NoopSpanExporter;
8-
use opentelemetry_sdk::trace::{BatchSpanProcessor, EvictedHashMap, EvictedQueue, SpanProcessor};
8+
use opentelemetry_sdk::trace::{BatchSpanProcessor, EvictedQueue, SpanProcessor};
99
use opentelemetry_sdk::Resource;
1010
use std::borrow::Cow;
1111
use std::sync::Arc;
@@ -27,7 +27,8 @@ fn get_span_data() -> Vec<SpanData> {
2727
name: Default::default(),
2828
start_time: SystemTime::now(),
2929
end_time: SystemTime::now(),
30-
attributes: EvictedHashMap::new(12, 12),
30+
attributes: Vec::new(),
31+
dropped_attributes_count: 0,
3132
events: EvictedQueue::new(12),
3233
links: EvictedQueue::new(12),
3334
status: Status::Unset,

opentelemetry-sdk/benches/span_builder.rs

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
22
use futures_util::future::BoxFuture;
33
use opentelemetry::{
4-
trace::{OrderMap, Span, Tracer, TracerProvider},
4+
trace::{Span, Tracer, TracerProvider},
55
KeyValue,
66
};
77
use opentelemetry_sdk::{
@@ -49,26 +49,6 @@ fn span_builder_benchmark_group(c: &mut Criterion) {
4949
span.end();
5050
})
5151
});
52-
group.bench_function(BenchmarkId::new("with_attributes_map", "1"), |b| {
53-
let (_provider, tracer) = not_sampled_provider();
54-
b.iter(|| {
55-
let mut span = tracer
56-
.span_builder("span")
57-
.with_attributes_map(OrderMap::from_iter([KeyValue::new(MAP_KEYS[0], "value")]))
58-
.start(&tracer);
59-
span.end();
60-
})
61-
});
62-
group.bench_function(BenchmarkId::new("with_attributes_map", "4"), |b| {
63-
let (_provider, tracer) = not_sampled_provider();
64-
b.iter(|| {
65-
let mut span = tracer
66-
.span_builder("span")
67-
.with_attributes_map(OrderMap::from_iter([KeyValue::new(MAP_KEYS[0], "value")]))
68-
.start(&tracer);
69-
span.end();
70-
})
71-
});
7252
group.finish();
7353
}
7454

opentelemetry-sdk/src/export/trace.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
use crate::Resource;
33
use futures_util::future::BoxFuture;
44
use opentelemetry::trace::{Event, Link, SpanContext, SpanId, SpanKind, Status, TraceError};
5+
use opentelemetry::KeyValue;
56
use std::borrow::Cow;
67
use std::fmt::Debug;
78
use std::time::SystemTime;
@@ -81,7 +82,10 @@ pub struct SpanData {
8182
/// Span end time
8283
pub end_time: SystemTime,
8384
/// Span attributes
84-
pub attributes: crate::trace::EvictedHashMap,
85+
pub attributes: Vec<KeyValue>,
86+
/// The number of attributes that were above the configured limit, and thus
87+
/// dropped.
88+
pub dropped_attributes_count: u32,
8589
/// Span events
8690
pub events: crate::trace::EvictedQueue<Event>,
8791
/// Span Links

0 commit comments

Comments
 (0)