@@ -34,6 +34,56 @@ describe("OTLPExporter", () => {
3434 ) ;
3535 } ) ;
3636
37+ // Bug: retry delay used retryDelayMs * attempt (linear) but JSDoc promised "doubles each attempt".
38+ // With maxRetries=3 the 3rd retry diverges: linear gives 300ms, exponential gives 400ms.
39+ it ( "should use exponential backoff — delay doubles each retry attempt" , async ( ) => {
40+ const capturedDelays : number [ ] = [ ] ;
41+ const origSetTimeout = globalThis . setTimeout ;
42+ // Capture delay values; fire immediately so the test doesn't actually wait
43+ ( globalThis as any ) . setTimeout = function ( fn : ( ) => void , ms ?: number ) {
44+ if ( typeof ms === "number" && ms >= 100 ) capturedDelays . push ( ms ) ;
45+ return origSetTimeout ( fn , 0 ) ;
46+ } ;
47+
48+ const requestMock = mock . method ( https , "request" , ( _opts : unknown , callback ?: unknown ) => {
49+ const reqMock = new EventEmitter ( ) as any ;
50+ reqMock . write = ( ) => { } ;
51+ reqMock . end = ( ) => { } ;
52+ reqMock . destroy = ( ) => { } ;
53+ const resMock = new EventEmitter ( ) as any ;
54+ resMock . statusCode = 503 ; // always retryable
55+ process . nextTick ( ( ) => {
56+ if ( typeof callback === "function" ) callback ( resMock ) ;
57+ resMock . emit ( "end" ) ;
58+ } ) ;
59+ return reqMock ;
60+ } ) ;
61+
62+ const exporter = new OTLPExporter ( {
63+ endpointUrl : "https://example.com/v1/traces" ,
64+ key : "k" ,
65+ cert : "c" ,
66+ ca : "ca" ,
67+ maxRetries : 3 ,
68+ retryDelayMs : 100 ,
69+ } ) ;
70+
71+ try {
72+ await exporter . export ( [
73+ { id : "1" , metricName : "lag" , value : 50 , payload : { timestamp : Date . now ( ) } } ,
74+ ] ) ;
75+ } catch {
76+ // all 4 attempts failed — expected
77+ } finally {
78+ ( globalThis as any ) . setTimeout = origSetTimeout ;
79+ requestMock . mock . restore ( ) ;
80+ }
81+
82+ // attempt 1: 100*2^0=100 attempt 2: 100*2^1=200 attempt 3: 100*2^2=400
83+ // (linear would give 100, 200, 300 — fails on the last value)
84+ assert . deepStrictEqual ( capturedDelays , [ 100 , 200 , 400 ] , "delays must be exponential" ) ;
85+ } ) ;
86+
3787 it ( "should construct mTLS options using node:https request correctly" , async ( ) => {
3888 const mockRequest = mock . method ( https , "request" , ( options : any , callback ?: any ) => {
3989 // Assert mTLS options are populated exactly
0 commit comments