1
1
// Copyright 2025-Present Datadog, Inc. https://www.datadoghq.com/
2
2
// SPDX-License-Identifier: Apache-2.0
3
3
4
- use std:: { collections:: HashMap , str:: FromStr } ;
5
-
6
- use lazy_static:: lazy_static;
7
- use regex:: Regex ;
4
+ use std:: { collections:: HashMap , str:: FromStr , sync:: LazyLock } ;
8
5
9
6
use crate :: {
10
7
carrier:: { Extractor , Injector } ,
@@ -31,22 +28,15 @@ const DATADOG_TAGS_KEY: &str = "x-datadog-tags";
31
28
const DATADOG_PROPAGATION_ERROR_KEY : & str = "_dd.propagation_error" ;
32
29
pub const DATADOG_LAST_PARENT_ID_KEY : & str = "_dd.parent_id" ;
33
30
34
- lazy_static ! {
35
- pub static ref INVALID_SEGMENT_REGEX : Regex =
36
- Regex :: new( r"^0+$" ) . expect( "failed creating regex" ) ;
37
- static ref VALID_SAMPLING_DECISION_REGEX : Regex =
38
- Regex :: new( r"^-([0-9])$" ) . expect( "failed creating regex" ) ;
39
- static ref TAG_KEY_REGEX : Regex = Regex :: new( r"^_dd\.p\.[\x21-\x2b\x2d-\x7e]+$" ) . expect( "failed creating regex" ) ; // ASCII minus spaces and commas
40
- static ref TAG_VALUE_REGEX : Regex = Regex :: new( r"^[\x20-\x2b\x2d-\x7e]*$" ) . expect( "failed creating regex" ) ; // ASCII minus commas
41
-
42
- static ref DATADOG_HEADER_KEYS : [ String ; 5 ] = [
31
+ static DATADOG_HEADER_KEYS : LazyLock < [ String ; 5 ] > = LazyLock :: new ( || {
32
+ [
43
33
DATADOG_TRACE_ID_KEY . to_owned ( ) ,
44
34
DATADOG_ORIGIN_KEY . to_owned ( ) ,
45
35
DATADOG_PARENT_ID_KEY . to_owned ( ) ,
46
36
DATADOG_SAMPLING_PRIORITY_KEY . to_owned ( ) ,
47
- DATADOG_TAGS_KEY . to_owned( )
48
- ] ;
49
- }
37
+ DATADOG_TAGS_KEY . to_owned ( ) ,
38
+ ]
39
+ } ) ;
50
40
51
41
pub fn inject ( context : & mut SpanContext , carrier : & mut dyn Injector , config : & Config ) {
52
42
let tags = & mut context. tags ;
@@ -168,11 +158,19 @@ fn get_propagation_tags(
168
158
}
169
159
170
160
fn validate_tag_key ( key : & str ) -> bool {
171
- TAG_KEY_REGEX . is_match ( key)
161
+ let Some ( tail) = key. strip_prefix ( "_dd.p." ) else {
162
+ return false ;
163
+ } ;
164
+ tail. as_bytes ( )
165
+ . iter ( )
166
+ . all ( |c| matches ! ( c, b'!' ..=b'+' | b'-' ..=b'~' ) )
172
167
}
173
168
174
169
fn validate_tag_value ( value : & str ) -> bool {
175
- TAG_VALUE_REGEX . is_match ( value)
170
+ value
171
+ . as_bytes ( )
172
+ . iter ( )
173
+ . all ( |c| matches ! ( c, b' ' ..=b'+' | b'-' ..=b'~' ) )
176
174
}
177
175
178
176
pub fn extract ( carrier : & dyn Extractor , config : & Config ) -> Option < SpanContext > {
@@ -238,14 +236,13 @@ fn extract_trace_id(carrier: &dyn Extractor) -> Result<Option<u64>, Error> {
238
236
None => return Ok ( None ) ,
239
237
} ;
240
238
241
- if INVALID_SEGMENT_REGEX . is_match ( trace_id) {
239
+ let trace_id = trace_id
240
+ . parse :: < u64 > ( )
241
+ . map_err ( |_| Error :: extract ( "Failed to decode `trace_id`" , "datadog" ) ) ?;
242
+ if trace_id == 0 {
242
243
return Err ( Error :: extract ( "Invalid `trace_id` found" , "datadog" ) ) ;
243
244
}
244
-
245
- trace_id
246
- . parse :: < u64 > ( )
247
- . map ( Some )
248
- . map_err ( |_| Error :: extract ( "Failed to decode `trace_id`" , "datadog" ) )
245
+ Ok ( Some ( trace_id) )
249
246
}
250
247
251
248
fn extract_parent_id ( carrier : & dyn Extractor ) -> Result < Option < u64 > , Error > {
@@ -324,7 +321,11 @@ fn validate_sampling_decision(tags: &mut HashMap<String, String>) {
324
321
let should_remove =
325
322
tags. get ( SAMPLING_DECISION_MAKER_TAG_KEY )
326
323
. is_some_and ( |sampling_decision| {
327
- let is_invalid = !VALID_SAMPLING_DECISION_REGEX . is_match ( sampling_decision) ;
324
+ let is_invalid = sampling_decision
325
+ . parse :: < i8 > ( )
326
+ . ok ( )
327
+ . map ( |m| m > 0 )
328
+ . unwrap_or ( true ) ;
328
329
if is_invalid {
329
330
dd_warn ! ( "Failed to decode `_dd.p.dm`: {}" , sampling_decision) ;
330
331
}
0 commit comments