@@ -26,16 +26,17 @@ import (
26
26
)
27
27
28
28
type APIError struct {
29
- StatusCode int
30
- Title string
31
- Description string
29
+ Err error
30
+ StatusCode int
31
+ Retryable bool
32
32
}
33
33
34
34
func (e APIError ) Error () string {
35
- if e .Description != "" {
36
- return fmt .Sprintf ("%s: %s" , e .Title , e .Description )
37
- }
38
- return e .Title
35
+ return e .Err .Error ()
36
+ }
37
+
38
+ func (e APIError ) Unwrap () error {
39
+ return e .Err
39
40
}
40
41
41
42
const (
@@ -185,7 +186,7 @@ func (c *httpClient) Write(ctx context.Context, metrics []telegraf.Metric) error
185
186
}
186
187
187
188
batches [bucket ] = append (batches [bucket ], metric )
188
- batchIndices [c . bucket ] = append (batchIndices [c . bucket ], i )
189
+ batchIndices [bucket ] = append (batchIndices [bucket ], i )
189
190
}
190
191
}
191
192
@@ -201,10 +202,14 @@ func (c *httpClient) Write(ctx context.Context, metrics []telegraf.Metric) error
201
202
var apiErr * APIError
202
203
if errors .As (err , & apiErr ) {
203
204
if apiErr .StatusCode == http .StatusRequestEntityTooLarge {
205
+ // TODO: Need a testcase to verify rejected metrics are not retried...
204
206
return c .splitAndWriteBatch (ctx , c .bucket , metrics )
205
207
}
206
208
wErr .Err = err
207
- wErr .MetricsReject = append (wErr .MetricsReject , batchIndices [bucket ]... )
209
+ if ! apiErr .Retryable {
210
+ wErr .MetricsReject = append (wErr .MetricsReject , batchIndices [bucket ]... )
211
+ }
212
+ // TODO: Clarify if we should continue here to try the remaining buckets?
208
213
return & wErr
209
214
}
210
215
@@ -301,21 +306,19 @@ func (c *httpClient) writeBatch(ctx context.Context, bucket string, metrics []te
301
306
}
302
307
303
308
// We got an error and now try to decode further
309
+ var desc string
304
310
writeResp := & genericRespError {}
305
- err = json .NewDecoder (resp .Body ).Decode (writeResp )
306
- desc := writeResp .Error ()
307
- if err != nil {
308
- desc = resp .Status
311
+ if json .NewDecoder (resp .Body ).Decode (writeResp ) == nil {
312
+ desc = writeResp .Error ()
309
313
}
310
314
311
315
switch resp .StatusCode {
312
316
// request was too large, send back to try again
313
317
case http .StatusRequestEntityTooLarge :
314
318
c .log .Errorf ("Failed to write metric to %s, request was too large (413)" , bucket )
315
319
return & APIError {
316
- StatusCode : resp .StatusCode ,
317
- Title : resp .Status ,
318
- Description : desc ,
320
+ Err : fmt .Errorf ("%s: %s" , resp .Status , desc ),
321
+ StatusCode : resp .StatusCode ,
319
322
}
320
323
case
321
324
// request was malformed:
@@ -325,14 +328,10 @@ func (c *httpClient) writeBatch(ctx context.Context, bucket string, metrics []te
325
328
http .StatusUnprocessableEntity ,
326
329
http .StatusNotAcceptable :
327
330
328
- // Clients should *not* repeat the request and the metrics should be dropped.
329
- rejected := make ([]int , 0 , len (metrics ))
330
- for i := range len (metrics ) {
331
- rejected = append (rejected , i )
332
- }
333
- return & internal.PartialWriteError {
334
- Err : fmt .Errorf ("failed to write metric to %s (will be dropped: %s): %s" , bucket , resp .Status , desc ),
335
- MetricsReject : rejected ,
331
+ // Clients should *not* repeat the request and the metrics should be rejected.
332
+ return & APIError {
333
+ Err : fmt .Errorf ("failed to write metric to %s (will be dropped: %s): %s" , bucket , resp .Status , desc ),
334
+ StatusCode : resp .StatusCode ,
336
335
}
337
336
case http .StatusUnauthorized , http .StatusForbidden :
338
337
return fmt .Errorf ("failed to write metric to %s (%s): %s" , bucket , resp .Status , desc )
@@ -351,13 +350,9 @@ func (c *httpClient) writeBatch(ctx context.Context, bucket string, metrics []te
351
350
// if it's any other 4xx code, the client should not retry as it's the client's mistake.
352
351
// retrying will not make the request magically work.
353
352
if len (resp .Status ) > 0 && resp .Status [0 ] == '4' {
354
- rejected := make ([]int , 0 , len (metrics ))
355
- for i := range len (metrics ) {
356
- rejected = append (rejected , i )
357
- }
358
- return & internal.PartialWriteError {
359
- Err : fmt .Errorf ("failed to write metric to %s (will be dropped: %s): %s" , bucket , resp .Status , desc ),
360
- MetricsReject : rejected ,
353
+ return & APIError {
354
+ Err : fmt .Errorf ("failed to write metric to %s (will be dropped: %s): %s" , bucket , resp .Status , desc ),
355
+ StatusCode : resp .StatusCode ,
361
356
}
362
357
}
363
358
@@ -367,10 +362,14 @@ func (c *httpClient) writeBatch(ctx context.Context, bucket string, metrics []te
367
362
desc = fmt .Sprintf ("%s; %s" , desc , xErr )
368
363
}
369
364
365
+ if desc != "" {
366
+ desc = ": " + desc
367
+ }
368
+
370
369
return & APIError {
371
- StatusCode : resp .StatusCode ,
372
- Title : resp .Status ,
373
- Description : desc ,
370
+ Err : fmt . Errorf ( "failed to write metric to bucket %q: %s%s" , bucket , resp .Status , desc ) ,
371
+ StatusCode : resp .StatusCode ,
372
+ Retryable : true ,
374
373
}
375
374
}
376
375
0 commit comments