Skip to content

Commit fe35ab6

Browse files
committed
Make TraceChunk generic on the span text for easier migration
1 parent 8f9c6d9 commit fe35ab6

File tree

7 files changed

+51
-41
lines changed

7 files changed

+51
-41
lines changed

data-pipeline/src/trace_exporter/mod.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -624,10 +624,9 @@ impl TraceExporter {
624624
unreachable!("Codepath invalid for proxy mode",)
625625
}
626626
};
627-
let payload: tracer_payload::TraceChunks =
628-
trace_utils::collect_trace_chunks(traces, use_v05_format).map_err(|e| {
629-
TraceExporterError::Deserialization(DecodeError::InvalidFormat(e.to_string()))
630-
})?;
627+
let payload = trace_utils::collect_trace_chunks(traces, use_v05_format).map_err(|e| {
628+
TraceExporterError::Deserialization(DecodeError::InvalidFormat(e.to_string()))
629+
})?;
631630

632631
let chunks = payload.size();
633632
let endpoint = Endpoint {

trace-utils/src/span/mod.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,16 @@ pub mod v05;
66

77
use serde::ser::SerializeStruct;
88
use serde::Serialize;
9+
use v05::dict::SharedDict;
910
use std::borrow::Borrow;
1011
use std::collections::HashMap;
1112
use std::fmt;
1213
use std::hash::Hash;
1314
use std::str::FromStr;
1415
use tinybytes::{Bytes, BytesString};
1516

17+
use crate::tracer_payload::TraceChunks;
18+
1619
#[derive(Debug, PartialEq)]
1720
pub enum SpanKey {
1821
Service,
@@ -60,9 +63,9 @@ impl FromStr for SpanKey {
6063
/// Trait representing the requirements for a type to be used as a Span "string" type.
6164
/// Note: Borrow<str> is not required by the derived traits, but allows to access HashMap elements
6265
/// from a static str and check if the string is empty.
63-
pub trait SpanText: Eq + Hash + Borrow<str> + Serialize {}
66+
pub trait SpanText: Eq + Hash + Borrow<str> + Serialize + Default + Clone {}
6467
/// Implement the SpanText trait for any type which satisfies the sub traits.
65-
impl<T: Eq + Hash + Borrow<str> + Serialize> SpanText for T {}
68+
impl<T: Eq + Hash + Borrow<str> + Serialize + Default + Clone> SpanText for T {}
6669

6770
/// Checks if the `value` represents an empty string. Used to skip serializing empty strings
6871
/// with serde.
@@ -259,6 +262,10 @@ pub type SpanEventSlice<'a> = SpanEvent<&'a str>;
259262
pub type AttributeAnyValueSlice<'a> = AttributeAnyValue<&'a str>;
260263
pub type AttributeArrayValueSlice<'a> = AttributeArrayValue<&'a str>;
261264

265+
pub type TraceChunksBytes = TraceChunks<BytesString>;
266+
267+
pub type SharedDictBytes = SharedDict<BytesString>;
268+
262269
impl SpanSlice<'_> {
263270
/// Converts a borrowed `SpanSlice` into an owned `SpanBytes`, by resolving all internal
264271
/// references into slices of the provided `Bytes` buffer. Returns `None` if any slice is

trace-utils/src/span/v05/dict.rs

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,58 +2,60 @@
22
// SPDX-License-Identifier: Apache-2.0
33

44
use std::collections::HashMap;
5-
use tinybytes::{Bytes, BytesString};
5+
6+
use crate::span::SpanText;
67

78
/// This struct represents the shared dictionary used for interning all the strings belonging to a
89
/// v05 trace chunk.
9-
pub struct SharedDict {
10+
pub struct SharedDict<T> {
1011
/// Map strings with their index (O(1) retrieval complexity).
11-
string_map: HashMap<BytesString, usize>,
12+
string_map: HashMap<T, usize>,
1213
/// Since the collection needs to be ordered an additional vector to keep the insertion order.
13-
dict: Vec<BytesString>,
14+
dict: Vec<T>,
1415
}
1516

16-
impl SharedDict {
17+
impl<T: SpanText> SharedDict<T> {
1718
/// Gets the index of the interned string. If the string is not part of the dictionary it is
1819
/// added and its corresponding index returned.
1920
///
2021
/// # Arguments:
2122
///
2223
/// * `str`: string to look up in the dictionary.
23-
pub fn get_or_insert(&mut self, str: &BytesString) -> Result<u32, std::num::TryFromIntError> {
24-
if let Some(index) = self.string_map.get(str) {
24+
pub fn get_or_insert(&mut self, s: &T) -> Result<u32, std::num::TryFromIntError> {
25+
if let Some(index) = self.string_map.get(s.borrow()) {
2526
(*index).try_into()
2627
} else {
2728
let index = self.dict.len();
28-
self.dict.push(str.clone());
29-
self.string_map.insert(str.clone(), index);
29+
self.dict.push(s.clone());
30+
self.string_map.insert(s.clone(), index);
3031
index.try_into()
3132
}
3233
}
3334

3435
/// Returns the dictionary. This method consumes the structure.
35-
pub fn dict(mut self) -> Vec<BytesString> {
36+
pub fn dict(mut self) -> Vec<T> {
3637
std::mem::take(&mut self.dict)
3738
}
3839
}
3940

40-
impl Default for SharedDict {
41+
impl<T: SpanText> Default for SharedDict<T> {
4142
fn default() -> Self {
42-
let empty_str = unsafe { BytesString::from_bytes_unchecked(Bytes::from_static(b"")) };
4343
Self {
44-
string_map: HashMap::from([(empty_str.clone(), 0)]),
45-
dict: vec![empty_str.clone()],
44+
string_map: HashMap::from([(T::default(), 0)]),
45+
dict: vec![T::default()],
4646
}
4747
}
4848
}
4949

5050
#[cfg(test)]
5151
mod tests {
52+
use tinybytes::{Bytes, BytesString};
53+
5254
use super::*;
5355

5456
#[test]
5557
fn default_test() {
56-
let dict = SharedDict::default();
58+
let dict: SharedDict<BytesString> = SharedDict::default();
5759

5860
assert_eq!(dict.string_map.len(), 1);
5961
assert_eq!(dict.dict.len(), 1);

trace-utils/src/span/v05/mod.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33

44
pub mod dict;
55

6-
use crate::span::v05::dict::SharedDict;
7-
use crate::span::SpanBytes;
6+
use crate::span::{v05::dict::SharedDict, SpanText};
87
use anyhow::Result;
98
use serde::Serialize;
109
use std::collections::HashMap;
@@ -29,7 +28,10 @@ pub struct Span {
2928
pub r#type: u32,
3029
}
3130

32-
pub fn from_span_bytes(span: &SpanBytes, dict: &mut SharedDict) -> Result<Span> {
31+
pub fn from_span<T: SpanText>(
32+
span: &crate::span::Span<T>,
33+
dict: &mut SharedDict<T>,
34+
) -> Result<Span> {
3335
Ok(Span {
3436
service: dict.get_or_insert(&span.service)?,
3537
name: dict.get_or_insert(&span.name)?,
@@ -61,6 +63,7 @@ pub fn from_span_bytes(span: &SpanBytes, dict: &mut SharedDict) -> Result<Span>
6163
#[cfg(test)]
6264
mod tests {
6365
use super::*;
66+
use crate::span::SpanBytes;
6467
use tinybytes::BytesString;
6568

6669
#[test]
@@ -87,7 +90,7 @@ mod tests {
8790
};
8891

8992
let mut dict = SharedDict::default();
90-
let v05_span = from_span_bytes(&span, &mut dict).unwrap();
93+
let v05_span = from_span(&span, &mut dict).unwrap();
9194

9295
let dict = dict.dict();
9396

trace-utils/src/test_utils/mod.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ use std::collections::HashMap;
1515
use std::time::Duration;
1616

1717
use crate::send_data::SendData;
18-
use crate::span::v05;
19-
use crate::span::v05::dict::SharedDict;
18+
use crate::span::{v05, SharedDictBytes};
2019
use crate::span::SpanBytes;
2120
use crate::trace_utils::TracerHeaderTags;
2221
use crate::tracer_payload::TracerPayloadCollection;
@@ -230,7 +229,7 @@ pub fn create_test_v05_span(
230229
parent_id: u64,
231230
start: i64,
232231
is_top_level: bool,
233-
dict: &mut SharedDict,
232+
dict: &mut SharedDictBytes,
234233
metrics: Option<Vec<(String, f64)>>,
235234
) -> v05::Span {
236235
let mut meta = HashMap::from([

trace-utils/src/trace_utils.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
pub use crate::send_data::send_data_result::SendDataResult;
55
pub use crate::send_data::SendData;
6-
use crate::span::v05;
6+
use crate::span::{v05, SpanText};
77
use crate::span::v05::dict::SharedDict;
88
pub use crate::tracer_header_tags::TracerHeaderTags;
99
use crate::tracer_payload::TracerPayloadCollection;
@@ -597,18 +597,18 @@ macro_rules! parse_root_span_tags {
597597
}
598598
}
599599

600-
pub fn collect_trace_chunks(
601-
traces: Vec<Vec<crate::span::SpanBytes>>,
600+
pub fn collect_trace_chunks<T: SpanText>(
601+
traces: Vec<Vec<crate::span::Span<T>>>,
602602
use_v05_format: bool,
603-
) -> anyhow::Result<TraceChunks> {
603+
) -> anyhow::Result<TraceChunks<T>> {
604604
if use_v05_format {
605605
let mut shared_dict = SharedDict::default();
606606
let mut v05_traces: Vec<Vec<v05::Span>> = Vec::with_capacity(traces.len());
607607
for trace in traces {
608608
let v05_trace = trace.iter().try_fold(
609609
Vec::with_capacity(trace.len()),
610610
|mut acc, span| -> anyhow::Result<Vec<v05::Span>> {
611-
acc.push(v05::from_span_bytes(span, &mut shared_dict)?);
611+
acc.push(v05::from_span(span, &mut shared_dict)?);
612612
Ok(acc)
613613
},
614614
)?;

trace-utils/src/tracer_payload.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
// Copyright 2024-Present Datadog, Inc. https://www.datadoghq.com/
22
// SPDX-License-Identifier: Apache-2.0
33

4-
use crate::span::{v05, SpanBytes};
4+
use crate::span::{v05, Span, SpanBytes, SpanText};
55
use crate::trace_utils::collect_trace_chunks;
66
use crate::{msgpack_decoder, trace_utils::cmp_send_data_payloads};
77
use datadog_trace_protobuf::pb;
88
use std::cmp::Ordering;
99
use std::iter::Iterator;
10-
use tinybytes;
10+
use tinybytes::{self, BytesString};
1111

1212
pub type TracerPayloadV04 = Vec<SpanBytes>;
1313
pub type TracerPayloadV05 = Vec<v05::Span>;
@@ -22,14 +22,14 @@ pub enum TraceEncoding {
2222
}
2323

2424
#[derive(Debug, Clone)]
25-
pub enum TraceChunks {
25+
pub enum TraceChunks<T: SpanText> {
2626
/// Collection of TraceChunkSpan.
27-
V04(Vec<Vec<SpanBytes>>),
27+
V04(Vec<Vec<Span<T>>>),
2828
/// Collection of TraceChunkSpan with de-duplicated strings.
29-
V05((Vec<tinybytes::BytesString>, Vec<Vec<v05::Span>>)),
29+
V05((Vec<T>, Vec<Vec<v05::Span>>)),
3030
}
3131

32-
impl TraceChunks {
32+
impl TraceChunks<BytesString> {
3333
pub fn into_tracer_payload_collection(self) -> TracerPayloadCollection {
3434
match self {
3535
TraceChunks::V04(traces) => TracerPayloadCollection::V04(traces),
@@ -38,7 +38,7 @@ impl TraceChunks {
3838
}
3939
}
4040

41-
impl TraceChunks {
41+
impl<T: SpanText> TraceChunks<T> {
4242
/// Returns the number of traces in the chunk
4343
pub fn size(&self) -> usize {
4444
match self {
@@ -222,7 +222,7 @@ impl TraceChunkProcessor for DefaultTraceChunkProcessor {
222222
pub fn decode_to_trace_chunks(
223223
data: tinybytes::Bytes,
224224
encoding_type: TraceEncoding,
225-
) -> Result<(TraceChunks, usize), anyhow::Error> {
225+
) -> Result<(TraceChunks<BytesString>, usize), anyhow::Error> {
226226
let (data, size) = match encoding_type {
227227
TraceEncoding::V04 => msgpack_decoder::v04::from_bytes(data),
228228
TraceEncoding::V05 => msgpack_decoder::v05::from_bytes(data),

0 commit comments

Comments
 (0)