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
+ //! ```
2
45
use crate :: { Context , Key , KeyValue , Value } ;
3
46
#[ cfg( feature = "serialize" ) ]
4
47
use serde:: { Deserialize , Serialize } ;
@@ -13,7 +56,29 @@ const MAX_KEY_VALUE_PAIRS: usize = 180;
13
56
const MAX_BYTES_FOR_ONE_PAIR : usize = 4096 ;
14
57
const MAX_LEN_OF_ALL_PAIRS : usize = 8192 ;
15
58
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
17
82
#[ derive( Debug , Default ) ]
18
83
pub struct Baggage {
19
84
inner : HashMap < Key , ( Value , BaggageMetadata ) > ,
@@ -143,6 +208,9 @@ impl Baggage {
143
208
/// Determine whether the key value pair exceed one of the [limits](https://w3c.github.io/baggage/#limits).
144
209
/// If not, update the total length of key values
145
210
fn insertable ( & mut self , key : & Key , value : & Value , metadata : & BaggageMetadata ) -> bool {
211
+ if !key. as_str ( ) . is_ascii ( ) {
212
+ return false ;
213
+ }
146
214
let value = String :: from ( value) ;
147
215
if key_value_metadata_bytes_size ( key. as_str ( ) , value. as_str ( ) , metadata. as_str ( ) )
148
216
< MAX_BYTES_FOR_ONE_PAIR
@@ -192,7 +260,7 @@ fn key_value_metadata_bytes_size(key: &str, value: &str, metadata: &str) -> usiz
192
260
key. bytes ( ) . len ( ) + value. bytes ( ) . len ( ) + metadata. bytes ( ) . len ( )
193
261
}
194
262
195
- /// An iterator over the entries of a `Baggage`.
263
+ /// An iterator over the entries of a [ `Baggage`] .
196
264
#[ derive( Debug ) ]
197
265
pub struct Iter < ' a > ( hash_map:: Iter < ' a , Key , ( Value , BaggageMetadata ) > ) ;
198
266
@@ -245,7 +313,7 @@ impl FromIterator<KeyValueMetadata> for Baggage {
245
313
246
314
/// Methods for sorting and retrieving baggage data in a context.
247
315
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.
249
317
///
250
318
/// # Examples
251
319
///
@@ -265,7 +333,7 @@ pub trait BaggageExt {
265
333
baggage : T ,
266
334
) -> Self ;
267
335
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.
269
337
///
270
338
/// # Examples
271
339
///
@@ -283,7 +351,7 @@ pub trait BaggageExt {
283
351
baggage : T ,
284
352
) -> Self ;
285
353
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.
287
355
///
288
356
/// # Examples
289
357
///
@@ -333,7 +401,11 @@ impl BaggageExt for Context {
333
401
}
334
402
}
335
403
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`.
337
409
#[ cfg_attr( feature = "serialize" , derive( Deserialize , Serialize ) ) ]
338
410
#[ derive( Clone , Debug , PartialOrd , PartialEq , Default ) ]
339
411
pub struct BaggageMetadata ( String ) ;
@@ -357,7 +429,7 @@ impl From<&str> for BaggageMetadata {
357
429
}
358
430
}
359
431
360
- /// `KeyValue` pairs with metadata
432
+ /// [`Baggage`] name-value pairs with their associated metadata.
361
433
#[ cfg_attr( feature = "serialize" , derive( Deserialize , Serialize ) ) ]
362
434
#[ derive( Clone , Debug , PartialEq ) ]
363
435
pub struct KeyValueMetadata {
@@ -400,15 +472,23 @@ mod tests {
400
472
use super :: * ;
401
473
use std:: iter:: FromIterator ;
402
474
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
+
403
482
#[ test]
404
483
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 {
408
488
data. push ( KeyValue :: new ( format ! ( "key{}" , i) , format ! ( "key{}" , i) ) )
409
489
}
410
490
let baggage = Baggage :: from_iter ( data. into_iter ( ) ) ;
411
- assert_eq ! ( baggage. len( ) , 180 )
491
+ assert_eq ! ( baggage. len( ) , MAX_KEY_VALUE_PAIRS )
412
492
}
413
493
414
494
#[ test]
0 commit comments