@@ -25,7 +25,7 @@ use std::time::Duration;
2525#[ cfg( feature = "http-retry" ) ]
2626use crate :: retry_classification:: http:: classify_http_error;
2727#[ cfg( feature = "http-retry" ) ]
28- use opentelemetry_sdk:: retry:: RetryErrorType ;
28+ use opentelemetry_sdk:: retry:: { RetryErrorType , RetryPolicy } ;
2929
3030// Shared HTTP retry functionality
3131/// HTTP-specific error wrapper for retry classification
@@ -111,6 +111,10 @@ pub struct HttpConfig {
111111
112112 /// The compression algorithm to use when communicating with the OTLP endpoint.
113113 compression : Option < crate :: Compression > ,
114+
115+ /// The retry policy to use for HTTP requests.
116+ #[ cfg( feature = "http-retry" ) ]
117+ retry_policy : Option < RetryPolicy > ,
114118}
115119
116120/// Configuration for the OTLP HTTP exporter.
@@ -282,6 +286,8 @@ impl HttpExporterBuilder {
282286 self . exporter_config . protocol ,
283287 timeout,
284288 compression,
289+ #[ cfg( feature = "http-retry" ) ]
290+ self . http_config . retry_policy . take ( ) ,
285291 ) )
286292 }
287293
@@ -361,6 +367,8 @@ pub(crate) struct OtlpHttpClient {
361367 protocol : Protocol ,
362368 _timeout : Duration ,
363369 compression : Option < crate :: Compression > ,
370+ #[ cfg( feature = "http-retry" ) ]
371+ retry_policy : RetryPolicy ,
364372 #[ allow( dead_code) ]
365373 // <allow dead> would be removed once we support set_resource for metrics and traces.
366374 resource : opentelemetry_proto:: transform:: common:: tonic:: ResourceAttributesWithSchema ,
@@ -379,16 +387,9 @@ impl OtlpHttpClient {
379387 {
380388 #[ cfg( feature = "http-retry" ) ]
381389 {
382- use opentelemetry_sdk:: retry:: { retry_with_backoff, RetryPolicy } ;
390+ use opentelemetry_sdk:: retry:: retry_with_backoff;
383391 use opentelemetry_sdk:: runtime:: Tokio ;
384392
385- let policy = RetryPolicy {
386- max_retries : 3 ,
387- initial_delay_ms : 100 ,
388- max_delay_ms : 1600 ,
389- jitter_ms : 100 ,
390- } ;
391-
392393 // Build request body once before retry loop
393394 let ( body, content_type, content_encoding) = build_body_fn ( self , data)
394395 . map_err ( opentelemetry_sdk:: error:: OTelSdkError :: InternalFailure ) ?;
@@ -401,7 +402,7 @@ impl OtlpHttpClient {
401402
402403 retry_with_backoff (
403404 Tokio ,
404- policy ,
405+ self . retry_policy . clone ( ) ,
405406 classify_http_export_error,
406407 operation_name,
407408 || async {
@@ -544,6 +545,7 @@ impl OtlpHttpClient {
544545 protocol : Protocol ,
545546 timeout : Duration ,
546547 compression : Option < crate :: Compression > ,
548+ #[ cfg( feature = "http-retry" ) ] retry_policy : Option < RetryPolicy > ,
547549 ) -> Self {
548550 OtlpHttpClient {
549551 client : Mutex :: new ( Some ( client) ) ,
@@ -552,6 +554,13 @@ impl OtlpHttpClient {
552554 protocol,
553555 _timeout : timeout,
554556 compression,
557+ #[ cfg( feature = "http-retry" ) ]
558+ retry_policy : retry_policy. unwrap_or ( RetryPolicy {
559+ max_retries : 3 ,
560+ initial_delay_ms : 100 ,
561+ max_delay_ms : 1600 ,
562+ jitter_ms : 100 ,
563+ } ) ,
555564 resource : ResourceAttributesWithSchema :: default ( ) ,
556565 }
557566 }
@@ -722,6 +731,10 @@ pub trait WithHttpConfig {
722731
723732 /// Set the compression algorithm to use when communicating with the collector.
724733 fn with_compression ( self , compression : crate :: Compression ) -> Self ;
734+
735+ /// Set the retry policy for HTTP requests.
736+ #[ cfg( feature = "http-retry" ) ]
737+ fn with_retry_policy ( self , policy : RetryPolicy ) -> Self ;
725738}
726739
727740impl < B : HasHttpConfig > WithHttpConfig for B {
@@ -746,6 +759,12 @@ impl<B: HasHttpConfig> WithHttpConfig for B {
746759 self . http_client_config ( ) . compression = Some ( compression) ;
747760 self
748761 }
762+
763+ #[ cfg( feature = "http-retry" ) ]
764+ fn with_retry_policy ( mut self , policy : RetryPolicy ) -> Self {
765+ self . http_client_config ( ) . retry_policy = Some ( policy) ;
766+ self
767+ }
749768}
750769
751770#[ cfg( test) ]
@@ -991,6 +1010,8 @@ mod tests {
9911010 client : None ,
9921011 headers : Some ( initial_headers) ,
9931012 compression : None ,
1013+ #[ cfg( feature = "http-retry" ) ]
1014+ retry_policy : None ,
9941015 } ,
9951016 exporter_config : crate :: ExportConfig :: default ( ) ,
9961017 } ;
@@ -1057,6 +1078,8 @@ mod tests {
10571078 crate :: Protocol :: HttpBinary ,
10581079 std:: time:: Duration :: from_secs ( 10 ) ,
10591080 Some ( crate :: Compression :: Gzip ) ,
1081+ #[ cfg( feature = "http-retry" ) ]
1082+ None ,
10601083 ) ;
10611084
10621085 // Test with some sample data
@@ -1088,6 +1111,8 @@ mod tests {
10881111 crate :: Protocol :: HttpBinary ,
10891112 std:: time:: Duration :: from_secs ( 10 ) ,
10901113 Some ( crate :: Compression :: Zstd ) ,
1114+ #[ cfg( feature = "http-retry" ) ]
1115+ None ,
10911116 ) ;
10921117
10931118 // Test with some sample data
@@ -1116,6 +1141,8 @@ mod tests {
11161141 crate :: Protocol :: HttpBinary ,
11171142 std:: time:: Duration :: from_secs ( 10 ) ,
11181143 None , // No compression
1144+ #[ cfg( feature = "http-retry" ) ]
1145+ None ,
11191146 ) ;
11201147
11211148 let body = vec ! [ 1 , 2 , 3 , 4 ] ;
@@ -1137,6 +1164,8 @@ mod tests {
11371164 crate :: Protocol :: HttpBinary ,
11381165 std:: time:: Duration :: from_secs ( 10 ) ,
11391166 Some ( crate :: Compression :: Gzip ) ,
1167+ #[ cfg( feature = "http-retry" ) ]
1168+ None ,
11401169 ) ;
11411170
11421171 let body = vec ! [ 1 , 2 , 3 , 4 ] ;
@@ -1159,6 +1188,8 @@ mod tests {
11591188 crate :: Protocol :: HttpBinary ,
11601189 std:: time:: Duration :: from_secs ( 10 ) ,
11611190 Some ( crate :: Compression :: Zstd ) ,
1191+ #[ cfg( feature = "http-retry" ) ]
1192+ None ,
11621193 ) ;
11631194
11641195 let body = vec ! [ 1 , 2 , 3 , 4 ] ;
@@ -1221,6 +1252,8 @@ mod tests {
12211252 protocol,
12221253 std:: time:: Duration :: from_secs ( 10 ) ,
12231254 compression,
1255+ #[ cfg( feature = "http-retry" ) ]
1256+ None ,
12241257 )
12251258 }
12261259
@@ -1454,5 +1487,70 @@ mod tests {
14541487 Err ( ExporterBuildError :: UnsupportedCompressionAlgorithm ( _) )
14551488 ) ) ;
14561489 }
1490+
1491+ #[ cfg( feature = "http-retry" ) ]
1492+ #[ test]
1493+ fn test_with_retry_policy ( ) {
1494+ use super :: super :: HttpExporterBuilder ;
1495+ use crate :: WithHttpConfig ;
1496+ use opentelemetry_sdk:: retry:: RetryPolicy ;
1497+
1498+ let custom_policy = RetryPolicy {
1499+ max_retries : 5 ,
1500+ initial_delay_ms : 200 ,
1501+ max_delay_ms : 3200 ,
1502+ jitter_ms : 50 ,
1503+ } ;
1504+
1505+ let builder = HttpExporterBuilder :: default ( ) . with_retry_policy ( custom_policy) ;
1506+
1507+ // Verify the retry policy was set
1508+ let retry_policy = builder. http_config . retry_policy . as_ref ( ) . unwrap ( ) ;
1509+ assert_eq ! ( retry_policy. max_retries, 5 ) ;
1510+ assert_eq ! ( retry_policy. initial_delay_ms, 200 ) ;
1511+ assert_eq ! ( retry_policy. max_delay_ms, 3200 ) ;
1512+ assert_eq ! ( retry_policy. jitter_ms, 50 ) ;
1513+ }
1514+
1515+ #[ cfg( feature = "http-retry" ) ]
1516+ #[ test]
1517+ fn test_default_retry_policy_when_none_configured ( ) {
1518+ let client = create_test_client ( crate :: Protocol :: HttpBinary , None ) ;
1519+
1520+ // Verify default values are used
1521+ assert_eq ! ( client. retry_policy. max_retries, 3 ) ;
1522+ assert_eq ! ( client. retry_policy. initial_delay_ms, 100 ) ;
1523+ assert_eq ! ( client. retry_policy. max_delay_ms, 1600 ) ;
1524+ assert_eq ! ( client. retry_policy. jitter_ms, 100 ) ;
1525+ }
1526+
1527+ #[ cfg( feature = "http-retry" ) ]
1528+ #[ test]
1529+ fn test_custom_retry_policy_used ( ) {
1530+ use opentelemetry_sdk:: retry:: RetryPolicy ;
1531+
1532+ let custom_policy = RetryPolicy {
1533+ max_retries : 7 ,
1534+ initial_delay_ms : 500 ,
1535+ max_delay_ms : 5000 ,
1536+ jitter_ms : 200 ,
1537+ } ;
1538+
1539+ let client = OtlpHttpClient :: new (
1540+ std:: sync:: Arc :: new ( MockHttpClient ) ,
1541+ "http://localhost:4318" . parse ( ) . unwrap ( ) ,
1542+ HashMap :: new ( ) ,
1543+ crate :: Protocol :: HttpBinary ,
1544+ std:: time:: Duration :: from_secs ( 10 ) ,
1545+ None ,
1546+ Some ( custom_policy) ,
1547+ ) ;
1548+
1549+ // Verify custom values are used
1550+ assert_eq ! ( client. retry_policy. max_retries, 7 ) ;
1551+ assert_eq ! ( client. retry_policy. initial_delay_ms, 500 ) ;
1552+ assert_eq ! ( client. retry_policy. max_delay_ms, 5000 ) ;
1553+ assert_eq ! ( client. retry_policy. jitter_ms, 200 ) ;
1554+ }
14571555 }
14581556}
0 commit comments