Skip to content

Commit 9d2b331

Browse files
authored
Merge branch 'main' into feature/internal-logs
2 parents 1fa3d15 + 5d2a05e commit 9d2b331

File tree

6 files changed

+121
-7
lines changed

6 files changed

+121
-7
lines changed

opentelemetry-http/src/lib.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ impl Injector for HeaderInjector<'_> {
2222
}
2323
}
2424
}
25+
26+
/// Reserves capacity for at least `additional` more entries to be inserted.
27+
fn reserve(&mut self, additional: usize) {
28+
self.0.reserve(additional);
29+
}
2530
}
2631

2732
/// Helper for extracting headers from HTTP Requests. This is used for OpenTelemetry context
@@ -303,4 +308,52 @@ mod tests {
303308
assert!(got.contains(&"headername1"));
304309
assert!(got.contains(&"headername2"));
305310
}
311+
312+
#[test]
313+
fn http_headers_reserve() {
314+
let mut carrier = http::HeaderMap::new();
315+
316+
// Test that reserve doesn't panic and works correctly
317+
{
318+
let mut injector = HeaderInjector(&mut carrier);
319+
injector.reserve(10);
320+
321+
// Verify the HeaderMap still works after reserve
322+
injector.set("test-header", "test-value".to_string());
323+
}
324+
assert_eq!(
325+
HeaderExtractor(&carrier).get("test-header"),
326+
Some("test-value")
327+
);
328+
329+
// Test reserve with zero capacity
330+
{
331+
let mut injector = HeaderInjector(&mut carrier);
332+
injector.reserve(0);
333+
injector.set("another-header", "another-value".to_string());
334+
}
335+
assert_eq!(
336+
HeaderExtractor(&carrier).get("another-header"),
337+
Some("another-value")
338+
);
339+
340+
// Test that capacity is actually reserved (at least the requested amount)
341+
let mut new_carrier = http::HeaderMap::new();
342+
{
343+
let mut new_injector = HeaderInjector(&mut new_carrier);
344+
new_injector.reserve(5);
345+
}
346+
let initial_capacity = new_carrier.capacity();
347+
348+
// Add some headers and verify capacity doesn't decrease
349+
{
350+
let mut new_injector = HeaderInjector(&mut new_carrier);
351+
for i in 0..3 {
352+
new_injector.set(&format!("header-{}", i), format!("value-{}", i));
353+
}
354+
}
355+
356+
assert!(new_carrier.capacity() >= initial_capacity);
357+
assert!(new_carrier.capacity() >= 5);
358+
}
306359
}

opentelemetry/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## vNext
44

5+
- Add `reserve` method to `opentelemetry::propagation::Injector` to hint at the number of elements that will be added to avoid multiple resize operations of the underlying data structure. Has an empty default implementation.
6+
57
## v0.31.0
68

79
Released 2025-Sep-25

opentelemetry/src/common.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ impl fmt::Debug for Key {
8181
impl From<Key> for String {
8282
fn from(key: Key) -> Self {
8383
match key.0 {
84-
OtelString::Owned(s) => s.to_string(),
85-
OtelString::Static(s) => s.to_string(),
84+
OtelString::Owned(s) => s.into_string(),
85+
OtelString::Static(s) => s.to_owned(),
8686
OtelString::RefCounted(s) => s.to_string(),
8787
}
8888
}
@@ -268,8 +268,8 @@ impl StringValue {
268268
impl From<StringValue> for String {
269269
fn from(s: StringValue) -> Self {
270270
match s.0 {
271-
OtelString::Owned(s) => s.to_string(),
272-
OtelString::Static(s) => s.to_string(),
271+
OtelString::Owned(s) => s.into_string(),
272+
OtelString::Static(s) => s.to_owned(),
273273
OtelString::RefCounted(s) => s.to_string(),
274274
}
275275
}

opentelemetry/src/metrics/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::sync::Arc;
44

55
mod instruments;
66
mod meter;
7-
pub(crate) mod noop;
7+
pub mod noop;
88
pub use instruments::{
99
counter::{Counter, ObservableCounter},
1010
gauge::{Gauge, ObservableGauge},
@@ -14,6 +14,7 @@ pub use instruments::{
1414
SyncInstrument,
1515
};
1616
pub use meter::{Meter, MeterProvider};
17+
pub use noop::NoopMeterProvider;
1718

1819
/// SDK implemented trait for creating instruments
1920
pub trait InstrumentProvider {

opentelemetry/src/metrics/noop.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ use super::instruments::SyncInstrument;
1313

1414
/// A no-op instance of a `MetricProvider`
1515
#[derive(Debug, Default)]
16-
pub(crate) struct NoopMeterProvider {
16+
pub struct NoopMeterProvider {
1717
_private: (),
1818
}
1919

2020
impl NoopMeterProvider {
2121
/// Create a new no-op meter provider.
22-
pub(crate) fn new() -> Self {
22+
pub fn new() -> Self {
2323
NoopMeterProvider { _private: () }
2424
}
2525
}

opentelemetry/src/propagation/mod.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ pub use text_map_propagator::TextMapPropagator;
3131
pub trait Injector {
3232
/// Add a key and value to the underlying data.
3333
fn set(&mut self, key: &str, value: String);
34+
35+
#[allow(unused_variables)]
36+
/// Hint to reserve capacity for at least `additional` more entries to be inserted.
37+
fn reserve(&mut self, additional: usize) {}
3438
}
3539

3640
/// Extractor provides an interface for removing fields from an underlying struct like `HashMap`
@@ -52,6 +56,11 @@ impl<S: std::hash::BuildHasher> Injector for HashMap<String, String, S> {
5256
fn set(&mut self, key: &str, value: String) {
5357
self.insert(key.to_lowercase(), value);
5458
}
59+
60+
/// Reserves capacity for at least `additional` more entries to be inserted.
61+
fn reserve(&mut self, additional: usize) {
62+
self.reserve(additional);
63+
}
5564
}
5665

5766
impl<S: std::hash::BuildHasher> Extractor for HashMap<String, String, S> {
@@ -117,4 +126,53 @@ mod tests {
117126
assert!(got.contains(&"headername1"));
118127
assert!(got.contains(&"headername2"));
119128
}
129+
130+
#[test]
131+
fn hash_map_injector_reserve() {
132+
let mut carrier = HashMap::new();
133+
134+
// Test that reserve doesn't panic and works correctly
135+
Injector::reserve(&mut carrier, 10);
136+
137+
// Verify the HashMap still works after reserve
138+
Injector::set(&mut carrier, "test_key", "test_value".to_string());
139+
assert_eq!(Extractor::get(&carrier, "test_key"), Some("test_value"));
140+
141+
// Test reserve with zero capacity
142+
Injector::reserve(&mut carrier, 0);
143+
Injector::set(&mut carrier, "another_key", "another_value".to_string());
144+
assert_eq!(
145+
Extractor::get(&carrier, "another_key"),
146+
Some("another_value")
147+
);
148+
149+
// Test that capacity is actually reserved (at least the requested amount)
150+
let mut new_carrier = HashMap::new();
151+
Injector::reserve(&mut new_carrier, 5);
152+
let initial_capacity = new_carrier.capacity();
153+
154+
// Add some elements and verify capacity doesn't decrease
155+
for i in 0..3 {
156+
Injector::set(
157+
&mut new_carrier,
158+
&format!("key{}", i),
159+
format!("value{}", i),
160+
);
161+
}
162+
163+
assert!(new_carrier.capacity() >= initial_capacity);
164+
assert!(new_carrier.capacity() >= 5);
165+
}
166+
167+
#[test]
168+
fn injector_reserve() {
169+
// Test to have full line coverage of default method
170+
struct TestInjector();
171+
impl Injector for TestInjector {
172+
fn set(&mut self, _key: &str, _value: String) {}
173+
}
174+
let mut test_injector = TestInjector();
175+
Injector::reserve(&mut test_injector, 4711);
176+
Injector::set(&mut test_injector, "key", "value".to_string());
177+
}
120178
}

0 commit comments

Comments
 (0)