Skip to content

Commit b7548a3

Browse files
authored
Udate baggage docs (#339)
1 parent 54a2d71 commit b7548a3

File tree

2 files changed

+104
-24
lines changed

2 files changed

+104
-24
lines changed

opentelemetry/src/api/baggage.rs

Lines changed: 92 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,47 @@
1-
//! OpenTelemetry Baggage API
1+
//! Primitives for sending name-value data across system boundaries.
2+
//!
3+
//! Main types in this module are:
4+
//!
5+
//! * [`Baggage`]: Baggage is used to annotate telemetry, adding context and
6+
//! information to metrics, traces, and logs.
7+
//! * [`BaggageExt`]: Extensions for managing `Baggage` in a [`Context`].
8+
//!
9+
//! Baggage can be sent between systems using the [`BaggagePropagator`] in
10+
//! accordance with the [W3C Baggage] specification.
11+
//!
12+
//! [`BaggagePropagator`]: crate::sdk::propagation::BaggagePropagator
13+
//! [W3C Baggage]: https://w3c.github.io/baggage
14+
//!
15+
//! # Examples
16+
//!
17+
//! ```
18+
//! use opentelemetry::{baggage::BaggageExt, Key, propagation::TextMapPropagator};
19+
//! use opentelemetry::sdk::propagation::BaggagePropagator;
20+
//! use std::collections::HashMap;
21+
//!
22+
//! // Example baggage value passed in externally via http headers
23+
//! let mut headers = HashMap::new();
24+
//! headers.insert("baggage".to_string(), "user_id=1".to_string());
25+
//!
26+
//! let propagator = BaggagePropagator::new();
27+
//! // can extract from any type that impls `Extractor`, usually an HTTP header map
28+
//! let cx = propagator.extract(&headers);
29+
//!
30+
//! // Iterate over extracted name-value pairs
31+
//! for (name, value) in cx.baggage() {
32+
//! // ...
33+
//! }
34+
//!
35+
//! // Add new baggage
36+
//! let cx_with_additions = cx.with_baggage(vec![Key::new("server_id").i64(42)]);
37+
//!
38+
//! // Inject baggage into http request
39+
//! propagator.inject_context(&cx_with_additions, &mut headers);
40+
//!
41+
//! let header_value = headers.get("baggage").expect("header is injected");
42+
//! assert!(header_value.contains("user_id=1"), "still contains previous name-value");
43+
//! assert!(header_value.contains("server_id=42"), "contains new name-value pair");
44+
//! ```
245
use crate::{Context, Key, KeyValue, Value};
346
#[cfg(feature = "serialize")]
447
use serde::{Deserialize, Serialize};
@@ -13,7 +56,29 @@ const MAX_KEY_VALUE_PAIRS: usize = 180;
1356
const MAX_BYTES_FOR_ONE_PAIR: usize = 4096;
1457
const MAX_LEN_OF_ALL_PAIRS: usize = 8192;
1558

16-
/// A set of name/value pairs describing user-defined properties across systems.
59+
/// A set of name-value pairs describing user-defined properties.
60+
///
61+
/// ### Baggage Names
62+
///
63+
/// * ASCII strings according to the token format, defined in [RFC2616, Section 2.2]
64+
///
65+
/// ### Baggage Values
66+
///
67+
/// * URL encoded UTF-8 strings.
68+
///
69+
/// ### Baggage Value Metadata
70+
///
71+
/// Additional metadata can be added to values in the form of a property set,
72+
/// represented as semi-colon `;` delimited list of names and/or name-value pairs,
73+
/// e.g. `;k1=v1;k2;k3=v3`.
74+
///
75+
/// ### Limits
76+
///
77+
/// * Maximum number of name-value pairs: `180`.
78+
/// * Maximum number of bytes per a single name-value pair: `4096`.
79+
/// * Maximum total length of all name-value pairs: `8192`.
80+
///
81+
/// [RFC2616, Section 2.2]: https://tools.ietf.org/html/rfc2616#section-2.2
1782
#[derive(Debug, Default)]
1883
pub struct Baggage {
1984
inner: HashMap<Key, (Value, BaggageMetadata)>,
@@ -143,6 +208,9 @@ impl Baggage {
143208
/// Determine whether the key value pair exceed one of the [limits](https://w3c.github.io/baggage/#limits).
144209
/// If not, update the total length of key values
145210
fn insertable(&mut self, key: &Key, value: &Value, metadata: &BaggageMetadata) -> bool {
211+
if !key.as_str().is_ascii() {
212+
return false;
213+
}
146214
let value = String::from(value);
147215
if key_value_metadata_bytes_size(key.as_str(), value.as_str(), metadata.as_str())
148216
< MAX_BYTES_FOR_ONE_PAIR
@@ -192,7 +260,7 @@ fn key_value_metadata_bytes_size(key: &str, value: &str, metadata: &str) -> usiz
192260
key.bytes().len() + value.bytes().len() + metadata.bytes().len()
193261
}
194262

195-
/// An iterator over the entries of a `Baggage`.
263+
/// An iterator over the entries of a [`Baggage`].
196264
#[derive(Debug)]
197265
pub struct Iter<'a>(hash_map::Iter<'a, Key, (Value, BaggageMetadata)>);
198266

@@ -245,7 +313,7 @@ impl FromIterator<KeyValueMetadata> for Baggage {
245313

246314
/// Methods for sorting and retrieving baggage data in a context.
247315
pub trait BaggageExt {
248-
/// Returns a clone of the given context with the included name / value pairs.
316+
/// Returns a clone of the given context with the included name-value pairs.
249317
///
250318
/// # Examples
251319
///
@@ -265,7 +333,7 @@ pub trait BaggageExt {
265333
baggage: T,
266334
) -> Self;
267335

268-
/// Returns a clone of the current context with the included name / value pairs.
336+
/// Returns a clone of the current context with the included name-value pairs.
269337
///
270338
/// # Examples
271339
///
@@ -283,7 +351,7 @@ pub trait BaggageExt {
283351
baggage: T,
284352
) -> Self;
285353

286-
/// Returns a clone of the given context with the included name / value pairs.
354+
/// Returns a clone of the given context with the included name-value pairs.
287355
///
288356
/// # Examples
289357
///
@@ -333,7 +401,11 @@ impl BaggageExt for Context {
333401
}
334402
}
335403

336-
/// `Metadata` uses by `KeyValue` pairs to represent related metadata.
404+
/// An optional property set that can be added to [`Baggage`] values.
405+
///
406+
/// `BaggageMetadata` can be added to values in the form of a property set,
407+
/// represented as semi-colon `;` delimited list of names and/or name-value
408+
/// pairs, e.g. `;k1=v1;k2;k3=v3`.
337409
#[cfg_attr(feature = "serialize", derive(Deserialize, Serialize))]
338410
#[derive(Clone, Debug, PartialOrd, PartialEq, Default)]
339411
pub struct BaggageMetadata(String);
@@ -357,7 +429,7 @@ impl From<&str> for BaggageMetadata {
357429
}
358430
}
359431

360-
/// `KeyValue` pairs with metadata
432+
/// [`Baggage`] name-value pairs with their associated metadata.
361433
#[cfg_attr(feature = "serialize", derive(Deserialize, Serialize))]
362434
#[derive(Clone, Debug, PartialEq)]
363435
pub struct KeyValueMetadata {
@@ -400,15 +472,23 @@ mod tests {
400472
use super::*;
401473
use std::iter::FromIterator;
402474

475+
#[test]
476+
fn insert_non_ascii_key() {
477+
let mut baggage = Baggage::new();
478+
baggage.insert("🚫", "not ascii key");
479+
assert_eq!(baggage.len(), 0, "did not insert invalid key");
480+
}
481+
403482
#[test]
404483
fn insert_too_much_baggage() {
405-
// too much key pairs
406-
let mut data = Vec::with_capacity(200);
407-
for i in 0..200 {
484+
// too many key pairs
485+
let over_limit = MAX_KEY_VALUE_PAIRS + 1;
486+
let mut data = Vec::with_capacity(over_limit);
487+
for i in 0..over_limit {
408488
data.push(KeyValue::new(format!("key{}", i), format!("key{}", i)))
409489
}
410490
let baggage = Baggage::from_iter(data.into_iter());
411-
assert_eq!(baggage.len(), 180)
491+
assert_eq!(baggage.len(), MAX_KEY_VALUE_PAIRS)
412492
}
413493

414494
#[test]

opentelemetry/src/sdk/propagation/baggage.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//!
33
//! Baggage is used to annotate telemetry, adding context and
44
//! information to metrics, traces, and logs. It is an abstract data type
5-
//! represented by a set of name/value pairs describing user-defined properties.
5+
//! represented by a set of name-value pairs describing user-defined properties.
66
//! Each name in a [`Baggage`] is associated with exactly one value.
77
//! `Baggage`s are serialized according to the editor's draft of
88
//! the [W3C Baggage] specification.
@@ -25,20 +25,20 @@
2525
//! // can extract from any type that impls `Extractor`, usually an HTTP header map
2626
//! let cx = propagator.extract(&headers);
2727
//!
28-
//! // Iterate over extracted name / value pairs
28+
//! // Iterate over extracted name-value pairs
2929
//! for (name, value) in cx.baggage() {
3030
//! // ...
3131
//! }
3232
//!
3333
//! // Add new baggage
3434
//! let cx_with_additions = cx.with_baggage(vec![Key::new("server_id").i64(42)]);
3535
//!
36-
//! // Inject aggage into http request
36+
//! // Inject baggage into http request
3737
//! propagator.inject_context(&cx_with_additions, &mut headers);
3838
//!
3939
//! let header_value = headers.get("baggage").expect("header is injected");
40-
//! assert!(header_value.contains("user_id=1"), "still contains previous name / value");
41-
//! assert!(header_value.contains("server_id=42"), "contains new name / value pair");
40+
//! assert!(header_value.contains("user_id=1"), "still contains previous name-value");
41+
//! assert!(header_value.contains("server_id=42"), "contains new name-value pair");
4242
//! ```
4343
use crate::{
4444
baggage::{BaggageExt, KeyValueMetadata},
@@ -55,11 +55,11 @@ lazy_static::lazy_static! {
5555
static ref BAGGAGE_FIELDS: [String; 1] = [BAGGAGE_HEADER.to_string()];
5656
}
5757

58-
/// Propagates name/value pairs in [W3C Baggage] format.
58+
/// Propagates name-value pairs in [W3C Baggage] format.
5959
///
6060
/// Baggage is used to annotate telemetry, adding context and
6161
/// information to metrics, traces, and logs. It is an abstract data type
62-
/// represented by a set of name/value pairs describing user-defined properties.
62+
/// represented by a set of name-value pairs describing user-defined properties.
6363
/// Each name in a [`Baggage`] is associated with exactly one value.
6464
/// `Baggage`s are serialized according to the editor's draft of
6565
/// the [W3C Baggage] specification.
@@ -82,20 +82,20 @@ lazy_static::lazy_static! {
8282
/// // can extract from any type that impls `Extractor`, usually an HTTP header map
8383
/// let cx = propagator.extract(&headers);
8484
///
85-
/// // Iterate over extracted name / value pairs
85+
/// // Iterate over extracted name-value pairs
8686
/// for (name, value) in cx.baggage() {
8787
/// // ...
8888
/// }
8989
///
9090
/// // Add new baggage
9191
/// let cx_with_additions = cx.with_baggage(vec![Key::new("server_id").i64(42)]);
9292
///
93-
/// // Inject aggage into http request
93+
/// // Inject baggage into http request
9494
/// propagator.inject_context(&cx_with_additions, &mut headers);
9595
///
9696
/// let header_value = headers.get("baggage").expect("header is injected");
97-
/// assert!(header_value.contains("user_id=1"), "still contains previous name / value");
98-
/// assert!(header_value.contains("server_id=42"), "contains new name / value pair");
97+
/// assert!(header_value.contains("user_id=1"), "still contains previous name-value");
98+
/// assert!(header_value.contains("server_id=42"), "contains new name-value pair");
9999
/// ```
100100
///
101101
/// [W3C Baggage]: https://w3c.github.io/baggage
@@ -163,7 +163,7 @@ impl TextMapPropagator for BaggagePropagator {
163163
decoded_props.as_str(),
164164
))
165165
} else {
166-
// Invalid name / value format
166+
// Invalid name-value format
167167
Err(())
168168
}
169169
} else {

0 commit comments

Comments
 (0)