14
14
package prometheus
15
15
16
16
import (
17
+ "bytes"
17
18
"errors"
18
19
"fmt"
19
20
"os"
20
21
"sort"
21
22
"sync"
22
23
23
24
"github.com/golang/protobuf/proto"
24
- "github.com/hashicorp/go-multierror"
25
25
26
26
dto "github.com/prometheus/client_model/go"
27
27
)
@@ -220,6 +220,22 @@ func (err AlreadyRegisteredError) Error() string {
220
220
return "duplicate metrics collector registration attempted"
221
221
}
222
222
223
+ // MultiError is a slice of errors implementing the error interface. It is used
224
+ // by a Gatherer to report multiple errors during MetricFamily gathering.
225
+ type MultiError []error
226
+
227
+ func (errs MultiError ) Error () string {
228
+ if len (errs ) == 0 {
229
+ return ""
230
+ }
231
+ buf := & bytes.Buffer {}
232
+ fmt .Fprintf (buf , "%d error(s) occurred:" , len (errs ))
233
+ for _ , err := range errs {
234
+ fmt .Fprintf (buf , "\n * %s" , err )
235
+ }
236
+ return buf .String ()
237
+ }
238
+
223
239
// Registry registers Prometheus collectors, collects their metrics, and gathers
224
240
// them into MetricFamilies for exposition. It implements Registerer and
225
241
// Gatherer. The zero value is not usable. Create instances with NewRegistry or
@@ -366,7 +382,7 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) {
366
382
metricChan = make (chan Metric , capMetricChan )
367
383
metricHashes = map [uint64 ]struct {}{}
368
384
wg sync.WaitGroup
369
- errs error // The collected errors to return in the end.
385
+ errs MultiError // The collected errors to return in the end.
370
386
registeredDescIDs map [uint64 ]struct {} // Only used for pedantic checks
371
387
)
372
388
@@ -419,7 +435,7 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) {
419
435
}
420
436
dtoMetric := & dto.Metric {}
421
437
if err := metric .Write (dtoMetric ); err != nil {
422
- errs = multierror . Append (errs , fmt .Errorf (
438
+ errs = append (errs , fmt .Errorf (
423
439
"error collecting metric %v: %s" , desc , err ,
424
440
))
425
441
continue
@@ -438,13 +454,13 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) {
438
454
case dtoMetric .Histogram != nil :
439
455
metricFamily .Type = dto .MetricType_HISTOGRAM .Enum ()
440
456
default :
441
- errs = multierror . Append (errs , fmt .Errorf (
457
+ errs = append (errs , fmt .Errorf (
442
458
"empty metric collected: %s" , dtoMetric ,
443
459
))
444
460
continue
445
461
}
446
462
if err := r .checkConsistency (metricFamily , dtoMetric , desc , metricHashes , registeredDescIDs ); err != nil {
447
- errs = multierror . Append (errs , err )
463
+ errs = append (errs , err )
448
464
continue
449
465
}
450
466
metricFamily .Metric = append (metricFamily .Metric , dtoMetric )
@@ -464,7 +480,7 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) {
464
480
}
465
481
for _ , m := range mf .Metric {
466
482
if err := r .checkConsistency (existingMF , m , nil , metricHashes , nil ); err != nil {
467
- errs = multierror . Append (errs , err )
483
+ errs = append (errs , err )
468
484
continue
469
485
}
470
486
existingMF .Metric = append (existingMF .Metric , m )
@@ -493,6 +509,11 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) {
493
509
for _ , name := range names {
494
510
result = append (result , metricFamiliesByName [name ])
495
511
}
512
+ // We cannot just `return result, errs`. Even if errs == nil, it will
513
+ // not be seen as nil through the error interface.
514
+ if len (errs ) == 0 {
515
+ return result , nil
516
+ }
496
517
return result , errs
497
518
}
498
519
0 commit comments