Skip to content

Commit 258ee35

Browse files
committed
fix(trace-agent): adapt stats concentrator to libdatadog v32.0.0
libdatadog v32.0.0 dropped the Eq/Hash derives on TracerMetadata (serializable-only), so it can no longer be used directly as a HashMap key. Project the discriminating fields (tracer language, service name, service env, service version, container id) into a new ConcentratorKey, and store the originating Arc<TracerMetadata> alongside the SpanConcentrator so flushed payloads still carry the full tracer context.
1 parent 6b9f73b commit 258ee35

1 file changed

Lines changed: 36 additions & 7 deletions

File tree

crates/datadog-trace-agent/src/stats_concentrator_service.rs

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,37 @@ fn new_concentrator() -> SpanConcentrator {
7070
)
7171
}
7272

73+
/// Hashable key derived from `TracerMetadata`.
74+
///
75+
/// `TracerMetadata` itself does not implement `Eq`/`Hash` (libdatadog v32
76+
/// removed those derives), so we project the fields used to discriminate
77+
/// concentrators into a separate key type.
78+
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
79+
struct ConcentratorKey {
80+
tracer_language: String,
81+
service_name: Option<String>,
82+
service_env: Option<String>,
83+
service_version: Option<String>,
84+
container_id: Option<String>,
85+
}
86+
87+
impl ConcentratorKey {
88+
fn from_metadata(metadata: &TracerMetadata) -> Self {
89+
Self {
90+
tracer_language: metadata.tracer_language.clone(),
91+
service_name: metadata.service_name.clone(),
92+
service_env: metadata.service_env.clone(),
93+
service_version: metadata.service_version.clone(),
94+
container_id: metadata.container_id.clone(),
95+
}
96+
}
97+
}
98+
7399
pub struct StatsConcentratorService {
74-
/// One concentrator per unique TracerMetadata.
75-
concentrators: HashMap<Arc<TracerMetadata>, SpanConcentrator>,
100+
/// One concentrator per unique TracerMetadata. Keyed by the projected
101+
/// fields, with the originating metadata kept alongside the concentrator
102+
/// so flushed payloads can carry the full tracer context.
103+
concentrators: HashMap<ConcentratorKey, (Arc<TracerMetadata>, SpanConcentrator)>,
76104
rx: mpsc::UnboundedReceiver<ConcentratorCommand>,
77105
config: Arc<Config>,
78106
}
@@ -99,13 +127,14 @@ impl StatsConcentratorService {
99127
// the base service and omits the version. A separate concentrator is kept per
100128
// unique metadata so that each payload's stats are flushed with the metadata
101129
// from the originating payload.
102-
let concentrator = self
130+
let key = ConcentratorKey::from_metadata(&metadata);
131+
let entry = self
103132
.concentrators
104-
.entry(Arc::clone(&metadata))
105-
.or_insert_with(new_concentrator);
133+
.entry(key)
134+
.or_insert_with(|| (Arc::clone(&metadata), new_concentrator()));
106135

107136
for span in &chunk.spans {
108-
concentrator.add_span(span);
137+
entry.1.add_span(span);
109138
}
110139
}
111140
ConcentratorCommand::Flush(force_flush, response_tx) => {
@@ -123,7 +152,7 @@ impl StatsConcentratorService {
123152
let payloads = self
124153
.concentrators
125154
.iter_mut()
126-
.filter_map(|(metadata, concentrator)| {
155+
.filter_map(|(_key, (metadata, concentrator))| {
127156
let stats_buckets = concentrator.flush(SystemTime::now(), force_flush);
128157
if stats_buckets.is_empty() {
129158
return None;

0 commit comments

Comments
 (0)