Skip to content

Commit c05fc8b

Browse files
committed
handle labels
1 parent 26b0f6a commit c05fc8b

File tree

2 files changed

+135
-0
lines changed

2 files changed

+135
-0
lines changed
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
// Copyright 2023-Present Datadog, Inc. https://www.datadoghq.com/
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
use crate::collections::identifiable::Id;
5+
use crate::internal::Label as InternalLabel;
6+
use anyhow::{Result, Context};
7+
8+
/// Converts a datadog-profiling internal Label to an OpenTelemetry KeyValue
9+
///
10+
/// # Arguments
11+
/// * `label` - The internal label to convert
12+
/// * `string_table` - A slice of strings where StringIds index into
13+
///
14+
/// # Returns
15+
/// * `Ok(KeyValue)` if the conversion is successful
16+
/// * `Err` with context if the StringIds are out of bounds of the string table
17+
pub fn convert_label_to_key_value(
18+
label: &InternalLabel,
19+
string_table: &[String],
20+
) -> Result<datadog_profiling_otel::KeyValue> {
21+
// Get the key string
22+
let key_id = label.get_key().to_raw_id() as usize;
23+
let key = string_table
24+
.get(key_id)
25+
.with_context(|| format!("Key string index {} out of bounds (string table has {} elements)", key_id, string_table.len()))?
26+
.to_string();
27+
28+
match label.get_value() {
29+
crate::internal::LabelValue::Str(str_id) => {
30+
let str_value_id = str_id.to_raw_id() as usize;
31+
let str_value = string_table
32+
.get(str_value_id)
33+
.with_context(|| format!("Value string index {} out of bounds (string table has {} elements)", str_value_id, string_table.len()))?
34+
.to_string();
35+
36+
Ok(datadog_profiling_otel::KeyValue {
37+
key,
38+
value: Some(datadog_profiling_otel::key_value::Value::StringValue(str_value)),
39+
})
40+
}
41+
crate::internal::LabelValue::Num { num, num_unit: _ } => {
42+
// Note: OpenTelemetry KeyValue doesn't support units, so we only store the numeric value
43+
Ok(datadog_profiling_otel::KeyValue {
44+
key,
45+
value: Some(datadog_profiling_otel::key_value::Value::IntValue(*num)),
46+
})
47+
}
48+
}
49+
}
50+
51+
#[cfg(test)]
52+
mod tests {
53+
use super::*;
54+
use crate::collections::identifiable::StringId;
55+
56+
#[test]
57+
fn test_convert_string_label() {
58+
let string_table = vec![
59+
"".to_string(), // index 0
60+
"thread_id".to_string(), // index 1
61+
"main".to_string(), // index 2
62+
];
63+
64+
let label = InternalLabel::str(
65+
StringId::from_offset(1), // "thread_id"
66+
StringId::from_offset(2), // "main"
67+
);
68+
69+
let result = convert_label_to_key_value(&label, &string_table);
70+
assert!(result.is_ok());
71+
72+
let key_value = result.unwrap();
73+
assert_eq!(key_value.key, "thread_id");
74+
match key_value.value {
75+
Some(datadog_profiling_otel::key_value::Value::StringValue(s)) => {
76+
assert_eq!(s, "main");
77+
}
78+
_ => panic!("Expected StringValue"),
79+
}
80+
}
81+
82+
#[test]
83+
fn test_convert_numeric_label() {
84+
let string_table = vec![
85+
"".to_string(), // index 0
86+
"allocation_size".to_string(), // index 1
87+
"bytes".to_string(), // index 2
88+
];
89+
90+
let label = InternalLabel::num(
91+
StringId::from_offset(1), // "allocation_size"
92+
1024, // 1024 bytes
93+
StringId::from_offset(2), // "bytes"
94+
);
95+
96+
let result = convert_label_to_key_value(&label, &string_table);
97+
assert!(result.is_ok());
98+
99+
let key_value = result.unwrap();
100+
assert_eq!(key_value.key, "allocation_size");
101+
match key_value.value {
102+
Some(datadog_profiling_otel::key_value::Value::IntValue(n)) => {
103+
assert_eq!(n, 1024);
104+
}
105+
_ => panic!("Expected IntValue"),
106+
}
107+
}
108+
109+
#[test]
110+
fn test_convert_label_out_of_bounds() {
111+
let string_table = vec!["".to_string()]; // Only one string
112+
113+
let label = InternalLabel::str(
114+
StringId::from_offset(1), // This index doesn't exist
115+
StringId::from_offset(0), // This index exists
116+
);
117+
118+
let result = convert_label_to_key_value(&label, &string_table);
119+
assert!(result.is_err());
120+
}
121+
122+
#[test]
123+
fn test_convert_label_empty_string_table() {
124+
let string_table: Vec<String> = vec![];
125+
126+
let label = InternalLabel::str(
127+
StringId::from_offset(0), // Even index 0 is out of bounds
128+
StringId::from_offset(0),
129+
);
130+
131+
let result = convert_label_to_key_value(&label, &string_table);
132+
assert!(result.is_err());
133+
}
134+
}

datadog-profiling/src/internal/profile/otel_emitter/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ pub mod stack_trace;
1111
pub mod location;
1212
pub mod mapping;
1313
pub mod profile;
14+
pub mod label;
1415

0 commit comments

Comments
 (0)