@@ -25,7 +25,7 @@ use std::time::Duration;
25
25
#[ cfg( feature = "http-retry" ) ]
26
26
use crate :: retry_classification:: http:: classify_http_error;
27
27
#[ cfg( feature = "http-retry" ) ]
28
- use opentelemetry_sdk:: retry:: RetryErrorType ;
28
+ use opentelemetry_sdk:: retry:: { RetryErrorType , RetryPolicy } ;
29
29
30
30
// Shared HTTP retry functionality
31
31
/// HTTP-specific error wrapper for retry classification
@@ -111,6 +111,10 @@ pub struct HttpConfig {
111
111
112
112
/// The compression algorithm to use when communicating with the OTLP endpoint.
113
113
compression : Option < crate :: Compression > ,
114
+
115
+ /// The retry policy to use for HTTP requests.
116
+ #[ cfg( feature = "http-retry" ) ]
117
+ retry_policy : Option < RetryPolicy > ,
114
118
}
115
119
116
120
/// Configuration for the OTLP HTTP exporter.
@@ -282,6 +286,8 @@ impl HttpExporterBuilder {
282
286
self . exporter_config . protocol ,
283
287
timeout,
284
288
compression,
289
+ #[ cfg( feature = "http-retry" ) ]
290
+ self . http_config . retry_policy . take ( ) ,
285
291
) )
286
292
}
287
293
@@ -361,6 +367,8 @@ pub(crate) struct OtlpHttpClient {
361
367
protocol : Protocol ,
362
368
_timeout : Duration ,
363
369
compression : Option < crate :: Compression > ,
370
+ #[ cfg( feature = "http-retry" ) ]
371
+ retry_policy : RetryPolicy ,
364
372
#[ allow( dead_code) ]
365
373
// <allow dead> would be removed once we support set_resource for metrics and traces.
366
374
resource : opentelemetry_proto:: transform:: common:: tonic:: ResourceAttributesWithSchema ,
@@ -379,16 +387,9 @@ impl OtlpHttpClient {
379
387
{
380
388
#[ cfg( feature = "http-retry" ) ]
381
389
{
382
- use opentelemetry_sdk:: retry:: { retry_with_backoff, RetryPolicy } ;
390
+ use opentelemetry_sdk:: retry:: retry_with_backoff;
383
391
use opentelemetry_sdk:: runtime:: Tokio ;
384
392
385
- let policy = RetryPolicy {
386
- max_retries : 3 ,
387
- initial_delay_ms : 100 ,
388
- max_delay_ms : 1600 ,
389
- jitter_ms : 100 ,
390
- } ;
391
-
392
393
// Build request body once before retry loop
393
394
let ( body, content_type, content_encoding) = build_body_fn ( self , data)
394
395
. map_err ( opentelemetry_sdk:: error:: OTelSdkError :: InternalFailure ) ?;
@@ -401,7 +402,7 @@ impl OtlpHttpClient {
401
402
402
403
retry_with_backoff (
403
404
Tokio ,
404
- policy ,
405
+ self . retry_policy . clone ( ) ,
405
406
classify_http_export_error,
406
407
operation_name,
407
408
|| async {
@@ -544,6 +545,7 @@ impl OtlpHttpClient {
544
545
protocol : Protocol ,
545
546
timeout : Duration ,
546
547
compression : Option < crate :: Compression > ,
548
+ #[ cfg( feature = "http-retry" ) ] retry_policy : Option < RetryPolicy > ,
547
549
) -> Self {
548
550
OtlpHttpClient {
549
551
client : Mutex :: new ( Some ( client) ) ,
@@ -552,6 +554,13 @@ impl OtlpHttpClient {
552
554
protocol,
553
555
_timeout : timeout,
554
556
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
+ } ) ,
555
564
resource : ResourceAttributesWithSchema :: default ( ) ,
556
565
}
557
566
}
@@ -722,6 +731,10 @@ pub trait WithHttpConfig {
722
731
723
732
/// Set the compression algorithm to use when communicating with the collector.
724
733
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 ;
725
738
}
726
739
727
740
impl < B : HasHttpConfig > WithHttpConfig for B {
@@ -746,6 +759,12 @@ impl<B: HasHttpConfig> WithHttpConfig for B {
746
759
self . http_client_config ( ) . compression = Some ( compression) ;
747
760
self
748
761
}
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
+ }
749
768
}
750
769
751
770
#[ cfg( test) ]
@@ -991,6 +1010,8 @@ mod tests {
991
1010
client : None ,
992
1011
headers : Some ( initial_headers) ,
993
1012
compression : None ,
1013
+ #[ cfg( feature = "http-retry" ) ]
1014
+ retry_policy : None ,
994
1015
} ,
995
1016
exporter_config : crate :: ExportConfig :: default ( ) ,
996
1017
} ;
@@ -1057,6 +1078,8 @@ mod tests {
1057
1078
crate :: Protocol :: HttpBinary ,
1058
1079
std:: time:: Duration :: from_secs ( 10 ) ,
1059
1080
Some ( crate :: Compression :: Gzip ) ,
1081
+ #[ cfg( feature = "http-retry" ) ]
1082
+ None ,
1060
1083
) ;
1061
1084
1062
1085
// Test with some sample data
@@ -1088,6 +1111,8 @@ mod tests {
1088
1111
crate :: Protocol :: HttpBinary ,
1089
1112
std:: time:: Duration :: from_secs ( 10 ) ,
1090
1113
Some ( crate :: Compression :: Zstd ) ,
1114
+ #[ cfg( feature = "http-retry" ) ]
1115
+ None ,
1091
1116
) ;
1092
1117
1093
1118
// Test with some sample data
@@ -1116,6 +1141,8 @@ mod tests {
1116
1141
crate :: Protocol :: HttpBinary ,
1117
1142
std:: time:: Duration :: from_secs ( 10 ) ,
1118
1143
None , // No compression
1144
+ #[ cfg( feature = "http-retry" ) ]
1145
+ None ,
1119
1146
) ;
1120
1147
1121
1148
let body = vec ! [ 1 , 2 , 3 , 4 ] ;
@@ -1137,6 +1164,8 @@ mod tests {
1137
1164
crate :: Protocol :: HttpBinary ,
1138
1165
std:: time:: Duration :: from_secs ( 10 ) ,
1139
1166
Some ( crate :: Compression :: Gzip ) ,
1167
+ #[ cfg( feature = "http-retry" ) ]
1168
+ None ,
1140
1169
) ;
1141
1170
1142
1171
let body = vec ! [ 1 , 2 , 3 , 4 ] ;
@@ -1159,6 +1188,8 @@ mod tests {
1159
1188
crate :: Protocol :: HttpBinary ,
1160
1189
std:: time:: Duration :: from_secs ( 10 ) ,
1161
1190
Some ( crate :: Compression :: Zstd ) ,
1191
+ #[ cfg( feature = "http-retry" ) ]
1192
+ None ,
1162
1193
) ;
1163
1194
1164
1195
let body = vec ! [ 1 , 2 , 3 , 4 ] ;
@@ -1221,6 +1252,8 @@ mod tests {
1221
1252
protocol,
1222
1253
std:: time:: Duration :: from_secs ( 10 ) ,
1223
1254
compression,
1255
+ #[ cfg( feature = "http-retry" ) ]
1256
+ None ,
1224
1257
)
1225
1258
}
1226
1259
@@ -1453,5 +1486,70 @@ mod tests {
1453
1486
Err ( ExporterBuildError :: UnsupportedCompressionAlgorithm ( _) )
1454
1487
) ) ;
1455
1488
}
1489
+
1490
+ #[ cfg( feature = "http-retry" ) ]
1491
+ #[ test]
1492
+ fn test_with_retry_policy ( ) {
1493
+ use super :: super :: HttpExporterBuilder ;
1494
+ use crate :: WithHttpConfig ;
1495
+ use opentelemetry_sdk:: retry:: RetryPolicy ;
1496
+
1497
+ let custom_policy = RetryPolicy {
1498
+ max_retries : 5 ,
1499
+ initial_delay_ms : 200 ,
1500
+ max_delay_ms : 3200 ,
1501
+ jitter_ms : 50 ,
1502
+ } ;
1503
+
1504
+ let builder = HttpExporterBuilder :: default ( ) . with_retry_policy ( custom_policy) ;
1505
+
1506
+ // Verify the retry policy was set
1507
+ let retry_policy = builder. http_config . retry_policy . as_ref ( ) . unwrap ( ) ;
1508
+ assert_eq ! ( retry_policy. max_retries, 5 ) ;
1509
+ assert_eq ! ( retry_policy. initial_delay_ms, 200 ) ;
1510
+ assert_eq ! ( retry_policy. max_delay_ms, 3200 ) ;
1511
+ assert_eq ! ( retry_policy. jitter_ms, 50 ) ;
1512
+ }
1513
+
1514
+ #[ cfg( feature = "http-retry" ) ]
1515
+ #[ test]
1516
+ fn test_default_retry_policy_when_none_configured ( ) {
1517
+ let client = create_test_client ( crate :: Protocol :: HttpBinary , None ) ;
1518
+
1519
+ // Verify default values are used
1520
+ assert_eq ! ( client. retry_policy. max_retries, 3 ) ;
1521
+ assert_eq ! ( client. retry_policy. initial_delay_ms, 100 ) ;
1522
+ assert_eq ! ( client. retry_policy. max_delay_ms, 1600 ) ;
1523
+ assert_eq ! ( client. retry_policy. jitter_ms, 100 ) ;
1524
+ }
1525
+
1526
+ #[ cfg( feature = "http-retry" ) ]
1527
+ #[ test]
1528
+ fn test_custom_retry_policy_used ( ) {
1529
+ use opentelemetry_sdk:: retry:: RetryPolicy ;
1530
+
1531
+ let custom_policy = RetryPolicy {
1532
+ max_retries : 7 ,
1533
+ initial_delay_ms : 500 ,
1534
+ max_delay_ms : 5000 ,
1535
+ jitter_ms : 200 ,
1536
+ } ;
1537
+
1538
+ let client = OtlpHttpClient :: new (
1539
+ std:: sync:: Arc :: new ( MockHttpClient ) ,
1540
+ "http://localhost:4318" . parse ( ) . unwrap ( ) ,
1541
+ HashMap :: new ( ) ,
1542
+ crate :: Protocol :: HttpBinary ,
1543
+ std:: time:: Duration :: from_secs ( 10 ) ,
1544
+ None ,
1545
+ Some ( custom_policy) ,
1546
+ ) ;
1547
+
1548
+ // Verify custom values are used
1549
+ assert_eq ! ( client. retry_policy. max_retries, 7 ) ;
1550
+ assert_eq ! ( client. retry_policy. initial_delay_ms, 500 ) ;
1551
+ assert_eq ! ( client. retry_policy. max_delay_ms, 5000 ) ;
1552
+ assert_eq ! ( client. retry_policy. jitter_ms, 200 ) ;
1553
+ }
1456
1554
}
1457
1555
}
0 commit comments