@@ -18,6 +18,11 @@ describe('metrics', () => {
1818 beforeEach ( ( ) => {
1919 jest . restoreAllMocks ( )
2020 mockedGetProxyDispatcher . mockReturnValue ( fakeDispatcher )
21+ delete process . env . DATADOG_API_KEY
22+ delete process . env . DD_API_KEY
23+ delete process . env . DATADOG_SITE
24+ delete process . env . DD_SITE
25+ delete process . env . DATADOG_API_HOST
2126 mockedHttpRequest . mockResolvedValue ( {
2227 config : { } ,
2328 data : { } ,
@@ -68,6 +73,29 @@ describe('metrics', () => {
6873 } )
6974 } )
7075
76+ test ( 'should strip an app. prefix from the configured site' , async ( ) => {
77+ const reporter = new UndiciDatadogReporter ( {
78+ apiKey : 'test-api-key' ,
79+ datadogSite : 'app.datadoghq.eu' ,
80+ } )
81+
82+ await reporter . report ( [ gaugeMetric ] )
83+
84+ expect ( mockedHttpRequest ) . toHaveBeenCalledWith ( {
85+ data : { series : [ gaugeMetric ] } ,
86+ dispatcher : fakeDispatcher ,
87+ headers : { 'DD-API-KEY' : 'test-api-key' } ,
88+ method : 'POST' ,
89+ url : 'https://api.datadoghq.eu/api/v1/series' ,
90+ } )
91+ } )
92+
93+ test ( 'should throw when no Datadog API key is configured' , ( ) => {
94+ expect ( ( ) => new UndiciDatadogReporter ( ) ) . toThrow (
95+ 'Datadog API key not found. You must specify one via the `apiKey` configuration option or the DATADOG_API_KEY or DD_API_KEY environment variable.'
96+ )
97+ } )
98+
7199 test ( 'should retry retryable request errors' , async ( ) => {
72100 jest . spyOn ( global , 'setTimeout' ) . mockImplementation ( ( handler : Parameters < typeof setTimeout > [ 0 ] ) => {
73101 if ( typeof handler === 'function' ) {
@@ -99,9 +127,63 @@ describe('metrics', () => {
99127 expect ( mockedHttpRequest ) . toHaveBeenCalledTimes ( 2 )
100128 } )
101129
130+ test ( 'should use the retry-after header when retrying 429 responses' , async ( ) => {
131+ const setTimeoutSpy = jest
132+ . spyOn ( global , 'setTimeout' )
133+ . mockImplementation ( ( handler : Parameters < typeof setTimeout > [ 0 ] ) => {
134+ if ( typeof handler === 'function' ) {
135+ handler ( )
136+ }
137+
138+ return { } as ReturnType < typeof setTimeout >
139+ } )
140+
141+ mockedHttpRequest
142+ . mockRejectedValueOnce (
143+ new RequestError ( 'Request failed' , { } as RequestConfig , {
144+ data : { } ,
145+ headers : { 'retry-after' : '3' } ,
146+ status : 429 ,
147+ statusText : 'Too Many Requests' ,
148+ } )
149+ )
150+ . mockResolvedValueOnce ( {
151+ config : { } ,
152+ data : { } ,
153+ headers : { } ,
154+ status : 202 ,
155+ statusText : 'Accepted' ,
156+ } )
157+
158+ const reporter = new UndiciDatadogReporter ( {
159+ apiKey : 'test-api-key' ,
160+ datadogSite : 'datadoghq.com' ,
161+ } )
162+
163+ await reporter . report ( [ gaugeMetric ] )
164+
165+ expect ( setTimeoutSpy ) . toHaveBeenCalledWith ( expect . any ( Function ) , 3000 )
166+ expect ( mockedHttpRequest ) . toHaveBeenCalledTimes ( 2 )
167+ } )
168+
169+ test ( 'should not retry unknown network errors without an upstream retryable code' , async ( ) => {
170+ const unknownNetworkError = new RequestError ( 'socket hang up' , { } as RequestConfig )
171+ ; ( unknownNetworkError as RequestError & { code ?: string } ) . code = 'UNKNOWN'
172+
173+ mockedHttpRequest . mockRejectedValue ( unknownNetworkError )
174+
175+ const reporter = new UndiciDatadogReporter ( {
176+ apiKey : 'test-api-key' ,
177+ datadogSite : 'datadoghq.com' ,
178+ } )
179+
180+ await expect ( reporter . report ( [ gaugeMetric ] ) ) . rejects . toThrow ( 'socket hang up' )
181+ expect ( mockedHttpRequest ) . toHaveBeenCalledTimes ( 1 )
182+ } )
183+
102184 test ( 'should not retry non-retryable request errors' , async ( ) => {
103185 mockedHttpRequest . mockRejectedValue (
104- new RequestError ( 'Request failed' , { } as RequestConfig , { data : { } , status : 403 , statusText : 'Forbidden ' } )
186+ new RequestError ( 'Request failed' , { } as RequestConfig , { data : { } , status : 413 , statusText : 'Too Large ' } )
105187 )
106188
107189 const reporter = new UndiciDatadogReporter ( {
@@ -112,6 +194,21 @@ describe('metrics', () => {
112194 await expect ( reporter . report ( [ gaugeMetric ] ) ) . rejects . toThrow ( 'Request failed' )
113195 expect ( mockedHttpRequest ) . toHaveBeenCalledTimes ( 1 )
114196 } )
197+
198+ test ( 'should wrap 403 responses with the default authorization error message' , async ( ) => {
199+ mockedHttpRequest . mockRejectedValue (
200+ new RequestError ( 'Request failed' , { } as RequestConfig , { data : { } , status : 403 , statusText : 'Forbidden' } )
201+ )
202+
203+ const reporter = new UndiciDatadogReporter ( {
204+ apiKey : 'test-api-key' ,
205+ datadogSite : 'datadoghq.com' ,
206+ } )
207+
208+ await expect ( reporter . report ( [ gaugeMetric ] ) ) . rejects . toThrow (
209+ 'Your Datadog API key is not authorized to send metrics.'
210+ )
211+ } )
115212 } )
116213
117214 describe ( 'getMetricsLogger' , ( ) => {
0 commit comments