@@ -9,6 +9,7 @@ use crate::{
9
9
health_metrics, health_metrics:: HealthMetric , span_concentrator:: SpanConcentrator ,
10
10
stats_exporter,
11
11
} ;
12
+ use anyhow:: Context ;
12
13
use arc_swap:: { ArcSwap , ArcSwapOption } ;
13
14
use bytes:: Bytes ;
14
15
use datadog_trace_utils:: msgpack_decoder:: { self , decode:: error:: DecodeError } ;
@@ -24,13 +25,12 @@ use dogstatsd_client::{new, Client, DogStatsDAction};
24
25
use either:: Either ;
25
26
use error:: BuilderErrorKind ;
26
27
use http_body_util:: BodyExt ;
27
- use hyper:: http:: uri:: PathAndQuery ;
28
- use hyper:: { header:: CONTENT_TYPE , Method , Uri } ;
28
+ use hyper:: { header:: CONTENT_TYPE , Method } ;
29
29
use log:: { error, info} ;
30
30
use std:: io;
31
31
use std:: sync:: { Arc , Mutex } ;
32
32
use std:: time:: Duration ;
33
- use std:: { borrow:: Borrow , collections:: HashMap , str :: FromStr , time} ;
33
+ use std:: { borrow:: Borrow , collections:: HashMap , time} ;
34
34
use tokio:: { runtime:: Runtime , task:: JoinHandle } ;
35
35
use tokio_util:: sync:: CancellationToken ;
36
36
@@ -67,56 +67,12 @@ pub enum TraceExporterOutputFormat {
67
67
68
68
impl TraceExporterOutputFormat {
69
69
/// Add the agent trace endpoint path to the URL.
70
- fn add_path ( & self , url : & Uri ) -> Uri {
71
- add_path (
72
- url,
73
- match self {
74
- TraceExporterOutputFormat :: V04 => "/v0.4/traces" ,
75
- TraceExporterOutputFormat :: V05 => "/v0.5/traces" ,
76
- } ,
77
- )
78
- }
79
-
80
- #[ cfg( feature = "test-utils" ) ]
81
- // This function is only intended for testing purposes so we don't need to go to all the trouble
82
- // of breaking the uri down and parsing it as rigorously as we would if we were using it in
83
- // production code.
84
- fn add_query ( & self , url : & Uri , query : & str ) -> Uri {
85
- let url = format ! ( "{}?{}" , url, query) ;
86
-
87
- // TODO: Properly handle non-OK states to prevent possible panics (APMSP-18190).
88
- #[ allow( clippy:: expect_used) ]
89
- Uri :: from_str ( & url) . expect ( "Failed to create Uri from string" )
90
- }
91
- }
92
-
93
- /// Add a path to the URL.
94
- ///
95
- /// # Arguments
96
- ///
97
- /// * `url` - The URL to which the path is to be added.
98
- /// * `path` - The path to be added to the URL.
99
- fn add_path ( url : & Uri , path : & str ) -> Uri {
100
- let p_and_q = url. path_and_query ( ) ;
101
-
102
- #[ allow( clippy:: unwrap_used) ]
103
- let new_p_and_q = match p_and_q {
104
- Some ( pq) => {
105
- let p = pq. path ( ) ;
106
- let mut p = p. strip_suffix ( '/' ) . unwrap_or ( p) . to_owned ( ) ;
107
- p. push_str ( path) ;
108
-
109
- PathAndQuery :: from_str ( p. as_str ( ) )
70
+ fn as_path ( & self ) -> & str {
71
+ match self {
72
+ TraceExporterOutputFormat :: V04 => "/v0.4/traces" ,
73
+ TraceExporterOutputFormat :: V05 => "/v0.5/traces" ,
110
74
}
111
- None => PathAndQuery :: from_str ( path) ,
112
75
}
113
- // TODO: Properly handle non-OK states to prevent possible panics (APMSP-18190).
114
- . unwrap ( ) ;
115
- let mut parts = url. clone ( ) . into_parts ( ) ;
116
- parts. path_and_query = Some ( new_p_and_q) ;
117
- // TODO: Properly handle non-OK states to prevent possible panics (APMSP-18190).
118
- #[ allow( clippy:: unwrap_used) ]
119
- Uri :: from_parts ( parts) . unwrap ( )
120
76
}
121
77
122
78
#[ derive( Clone , Default , Debug ) ]
@@ -208,8 +164,6 @@ pub struct TraceExporter {
208
164
agent_info : AgentInfoArc ,
209
165
previous_info_state : ArcSwapOption < String > ,
210
166
telemetry : Option < TelemetryClient > ,
211
- #[ cfg( feature = "test-utils" ) ]
212
- query_params : Option < String > ,
213
167
}
214
168
215
169
impl TraceExporter {
@@ -331,7 +285,9 @@ impl TraceExporter {
331
285
bucket_size,
332
286
stats_concentrator. clone ( ) ,
333
287
self . metadata . clone ( ) ,
334
- Endpoint :: from_url ( add_path ( & self . endpoint . url , STATS_ENDPOINT ) ) ,
288
+ self . endpoint
289
+ . try_to_path ( STATS_ENDPOINT )
290
+ . context ( "failed to create Endpoint" ) ?,
335
291
cancellation_token. clone ( ) ,
336
292
) ;
337
293
@@ -442,23 +398,26 @@ impl TraceExporter {
442
398
self . send_data_to_url (
443
399
data,
444
400
trace_count,
445
- self . output_format . add_path ( & self . endpoint . url ) ,
401
+ self . endpoint
402
+ . try_to_path ( self . output_format . as_path ( ) )
403
+ . map_err ( |e| {
404
+ TraceExporterError :: Builder ( BuilderErrorKind :: InvalidUri ( e. to_string ( ) ) )
405
+ } ) ?,
446
406
)
447
407
}
448
408
449
409
fn send_data_to_url (
450
410
& self ,
451
411
data : & [ u8 ] ,
452
412
trace_count : usize ,
453
- uri : Uri ,
413
+ endpoint : Endpoint ,
454
414
) -> Result < String , TraceExporterError > {
455
415
self . runtime . block_on ( async {
456
- let mut req_builder = hyper:: Request :: builder ( )
457
- . uri ( uri)
458
- . header (
459
- hyper:: header:: USER_AGENT ,
460
- concat ! ( "Tracer/" , env!( "CARGO_PKG_VERSION" ) ) ,
461
- )
416
+ // SAFETY: the user agent is a valid header value
417
+ #[ allow( clippy:: unwrap_used) ]
418
+ let mut req_builder = endpoint
419
+ . to_request_builder ( concat ! ( "Tracer/" , env!( "CARGO_PKG_VERSION" ) ) )
420
+ . unwrap ( )
462
421
. method ( Method :: POST ) ;
463
422
464
423
let headers: HashMap < & ' static str , String > = self . metadata . borrow ( ) . into ( ) ;
@@ -656,10 +615,12 @@ impl TraceExporter {
656
615
} ;
657
616
658
617
let chunks = payload. size ( ) ;
659
- let endpoint = Endpoint {
660
- url : self . get_agent_url ( ) ,
661
- ..self . endpoint . clone ( )
662
- } ;
618
+ let endpoint = self
619
+ . endpoint
620
+ . try_to_path ( self . output_format . as_path ( ) )
621
+ . map_err ( |e| {
622
+ TraceExporterError :: Builder ( BuilderErrorKind :: InvalidUri ( e. to_string ( ) ) )
623
+ } ) ?;
663
624
let mut headers: HashMap < & str , String > = header_tags. into ( ) ;
664
625
headers. insert ( DATADOG_SEND_REAL_HTTP_STATUS_STR , "1" . to_string ( ) ) ;
665
626
headers. insert ( DATADOG_TRACE_COUNT_STR , chunks. to_string ( ) ) ;
@@ -759,18 +720,6 @@ impl TraceExporter {
759
720
}
760
721
} )
761
722
}
762
-
763
- fn get_agent_url ( & self ) -> Uri {
764
- #[ cfg( feature = "test-utils" ) ]
765
- {
766
- if let Some ( query) = & self . query_params {
767
- let url = self . output_format . add_path ( & self . endpoint . url ) ;
768
- return self . output_format . add_query ( & url, query) ;
769
- }
770
- }
771
-
772
- self . output_format . add_path ( & self . endpoint . url )
773
- }
774
723
}
775
724
776
725
const DEFAULT_AGENT_URL : & str = "http://127.0.0.1:8126" ;
@@ -801,9 +750,6 @@ pub struct TraceExporterBuilder {
801
750
dogstatsd_url : Option < String > ,
802
751
client_computed_stats : bool ,
803
752
client_computed_top_level : bool ,
804
- #[ cfg( feature = "test-utils" ) ]
805
- /// not supported in production, but useful for interacting with the test-agent
806
- query_params : Option < String > ,
807
753
// Stats specific fields
808
754
/// A Some value enables stats-computation, None if it is disabled
809
755
stats_bucket_size : Option < Duration > ,
@@ -958,14 +904,6 @@ impl TraceExporterBuilder {
958
904
self
959
905
}
960
906
961
- #[ cfg( feature = "test-utils" ) ]
962
- /// Set query parameters to be used in the URL when communicating with the test-agent. This is
963
- /// not supported in production as the real agent doesn't accept query params.
964
- pub fn set_query_params ( & mut self , query_params : & str ) -> & mut Self {
965
- self . query_params = Some ( query_params. to_owned ( ) ) ;
966
- self
967
- }
968
-
969
907
#[ allow( missing_docs) ]
970
908
pub fn build ( self ) -> Result < TraceExporter , TraceExporterError > {
971
909
if !Self :: is_inputs_outputs_formats_compatible ( self . input_format , self . output_format ) {
@@ -992,11 +930,18 @@ impl TraceExporterBuilder {
992
930
TraceExporterError :: Builder ( BuilderErrorKind :: InvalidUri ( e. to_string ( ) ) )
993
931
} ) ?;
994
932
933
+ let endpoint = Endpoint {
934
+ url : agent_url,
935
+ ..Default :: default ( )
936
+ } ;
937
+
995
938
let libdatadog_version = tag ! ( "libdatadog_version" , env!( "CARGO_PKG_VERSION" ) ) ;
996
939
let mut stats = StatsComputationStatus :: Disabled ;
997
940
998
941
let info_fetcher = AgentInfoFetcher :: new (
999
- Endpoint :: from_url ( add_path ( & agent_url, INFO_ENDPOINT ) ) ,
942
+ endpoint. try_to_path ( INFO_ENDPOINT ) . map_err ( |e| {
943
+ TraceExporterError :: Builder ( BuilderErrorKind :: InvalidUri ( e. to_string ( ) ) )
944
+ } ) ?,
1000
945
Duration :: from_secs ( 5 * 60 ) ,
1001
946
) ;
1002
947
@@ -1038,7 +983,7 @@ impl TraceExporterBuilder {
1038
983
}
1039
984
1040
985
Ok ( TraceExporter {
1041
- endpoint : Endpoint :: from_url ( agent_url ) ,
986
+ endpoint,
1042
987
metadata : TracerMetadata {
1043
988
tracer_version : self . tracer_version ,
1044
989
language_version : self . language_version ,
@@ -1064,8 +1009,6 @@ impl TraceExporterBuilder {
1064
1009
agent_info,
1065
1010
previous_info_state : ArcSwapOption :: new ( None ) ,
1066
1011
telemetry,
1067
- #[ cfg( feature = "test-utils" ) ]
1068
- query_params : self . query_params ,
1069
1012
} )
1070
1013
}
1071
1014
@@ -1132,8 +1075,10 @@ mod tests {
1132
1075
1133
1076
assert_eq ! (
1134
1077
exporter
1135
- . output_format
1136
- . add_path( & exporter. endpoint. url)
1078
+ . endpoint
1079
+ . try_to_path( exporter. output_format. as_path( ) )
1080
+ . unwrap( )
1081
+ . url
1137
1082
. to_string( ) ,
1138
1083
"http://192.168.1.1:8127/v0.4/traces"
1139
1084
) ;
@@ -1156,8 +1101,10 @@ mod tests {
1156
1101
1157
1102
assert_eq ! (
1158
1103
exporter
1159
- . output_format
1160
- . add_path( & exporter. endpoint. url)
1104
+ . endpoint
1105
+ . try_to_path( exporter. output_format. as_path( ) )
1106
+ . unwrap( )
1107
+ . url
1161
1108
. to_string( ) ,
1162
1109
"http://127.0.0.1:8126/v0.4/traces"
1163
1110
) ;
0 commit comments