Replace hashicorp/go-multierror by own implementation
The own implementation is much easier as it only has to serve our one use case.
This commit is contained in:
parent
f0c45acc50
commit
1dc03a72f6
|
@ -82,18 +82,18 @@ func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler {
|
||||||
mfs, err := reg.Gather()
|
mfs, err := reg.Gather()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if opts.ErrorLog != nil {
|
if opts.ErrorLog != nil {
|
||||||
opts.ErrorLog.Println("error collecting metrics:", err)
|
opts.ErrorLog.Println("error gathering metrics:", err)
|
||||||
}
|
}
|
||||||
switch opts.ErrorHandling {
|
switch opts.ErrorHandling {
|
||||||
case PanicOnError:
|
case PanicOnError:
|
||||||
panic(err)
|
panic(err)
|
||||||
case ContinueOnError:
|
case ContinueOnError:
|
||||||
if len(mfs) == 0 {
|
if len(mfs) == 0 {
|
||||||
http.Error(w, "No metrics collected, last error:\n\n"+err.Error(), http.StatusInternalServerError)
|
http.Error(w, "No metrics gathered, last error:\n\n"+err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case HTTPErrorOnError:
|
case HTTPErrorOnError:
|
||||||
http.Error(w, "An error has occurred during metrics collection:\n\n"+err.Error(), http.StatusInternalServerError)
|
http.Error(w, "An error has occurred during metrics gathering:\n\n"+err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,14 +88,12 @@ func TestHandlerErrorHandling(t *testing.T) {
|
||||||
ErrorLog: logger,
|
ErrorLog: logger,
|
||||||
ErrorHandling: PanicOnError,
|
ErrorHandling: PanicOnError,
|
||||||
})
|
})
|
||||||
wantMsg := `error collecting metrics: 1 error(s) occurred:
|
wantMsg := `error gathering metrics: 1 error(s) occurred:
|
||||||
|
|
||||||
* error collecting metric Desc{fqName: "invalid_metric", help: "not helpful", constLabels: {}, variableLabels: []}: collect error
|
* error collecting metric Desc{fqName: "invalid_metric", help: "not helpful", constLabels: {}, variableLabels: []}: collect error
|
||||||
`
|
`
|
||||||
wantErrorBody := `An error has occurred during metrics collection:
|
wantErrorBody := `An error has occurred during metrics gathering:
|
||||||
|
|
||||||
1 error(s) occurred:
|
1 error(s) occurred:
|
||||||
|
|
||||||
* error collecting metric Desc{fqName: "invalid_metric", help: "not helpful", constLabels: {}, variableLabels: []}: collect error
|
* error collecting metric Desc{fqName: "invalid_metric", help: "not helpful", constLabels: {}, variableLabels: []}: collect error
|
||||||
`
|
`
|
||||||
wantOKBody := `# HELP name docstring
|
wantOKBody := `# HELP name docstring
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
package prometheus
|
package prometheus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
@ -21,7 +22,6 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
"github.com/hashicorp/go-multierror"
|
|
||||||
|
|
||||||
dto "github.com/prometheus/client_model/go"
|
dto "github.com/prometheus/client_model/go"
|
||||||
)
|
)
|
||||||
|
@ -220,6 +220,22 @@ func (err AlreadyRegisteredError) Error() string {
|
||||||
return "duplicate metrics collector registration attempted"
|
return "duplicate metrics collector registration attempted"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MultiError is a slice of errors implementing the error interface. It is used
|
||||||
|
// by a Gatherer to report multiple errors during MetricFamily gathering.
|
||||||
|
type MultiError []error
|
||||||
|
|
||||||
|
func (errs MultiError) Error() string {
|
||||||
|
if len(errs) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
fmt.Fprintf(buf, "%d error(s) occurred:", len(errs))
|
||||||
|
for _, err := range errs {
|
||||||
|
fmt.Fprintf(buf, "\n* %s", err)
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
// Registry registers Prometheus collectors, collects their metrics, and gathers
|
// Registry registers Prometheus collectors, collects their metrics, and gathers
|
||||||
// them into MetricFamilies for exposition. It implements Registerer and
|
// them into MetricFamilies for exposition. It implements Registerer and
|
||||||
// Gatherer. The zero value is not usable. Create instances with NewRegistry or
|
// Gatherer. The zero value is not usable. Create instances with NewRegistry or
|
||||||
|
@ -366,7 +382,7 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) {
|
||||||
metricChan = make(chan Metric, capMetricChan)
|
metricChan = make(chan Metric, capMetricChan)
|
||||||
metricHashes = map[uint64]struct{}{}
|
metricHashes = map[uint64]struct{}{}
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
errs error // The collected errors to return in the end.
|
errs MultiError // The collected errors to return in the end.
|
||||||
registeredDescIDs map[uint64]struct{} // Only used for pedantic checks
|
registeredDescIDs map[uint64]struct{} // Only used for pedantic checks
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -419,7 +435,7 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) {
|
||||||
}
|
}
|
||||||
dtoMetric := &dto.Metric{}
|
dtoMetric := &dto.Metric{}
|
||||||
if err := metric.Write(dtoMetric); err != nil {
|
if err := metric.Write(dtoMetric); err != nil {
|
||||||
errs = multierror.Append(errs, fmt.Errorf(
|
errs = append(errs, fmt.Errorf(
|
||||||
"error collecting metric %v: %s", desc, err,
|
"error collecting metric %v: %s", desc, err,
|
||||||
))
|
))
|
||||||
continue
|
continue
|
||||||
|
@ -438,13 +454,13 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) {
|
||||||
case dtoMetric.Histogram != nil:
|
case dtoMetric.Histogram != nil:
|
||||||
metricFamily.Type = dto.MetricType_HISTOGRAM.Enum()
|
metricFamily.Type = dto.MetricType_HISTOGRAM.Enum()
|
||||||
default:
|
default:
|
||||||
errs = multierror.Append(errs, fmt.Errorf(
|
errs = append(errs, fmt.Errorf(
|
||||||
"empty metric collected: %s", dtoMetric,
|
"empty metric collected: %s", dtoMetric,
|
||||||
))
|
))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := r.checkConsistency(metricFamily, dtoMetric, desc, metricHashes, registeredDescIDs); err != nil {
|
if err := r.checkConsistency(metricFamily, dtoMetric, desc, metricHashes, registeredDescIDs); err != nil {
|
||||||
errs = multierror.Append(errs, err)
|
errs = append(errs, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
metricFamily.Metric = append(metricFamily.Metric, dtoMetric)
|
metricFamily.Metric = append(metricFamily.Metric, dtoMetric)
|
||||||
|
@ -464,7 +480,7 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) {
|
||||||
}
|
}
|
||||||
for _, m := range mf.Metric {
|
for _, m := range mf.Metric {
|
||||||
if err := r.checkConsistency(existingMF, m, nil, metricHashes, nil); err != nil {
|
if err := r.checkConsistency(existingMF, m, nil, metricHashes, nil); err != nil {
|
||||||
errs = multierror.Append(errs, err)
|
errs = append(errs, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
existingMF.Metric = append(existingMF.Metric, m)
|
existingMF.Metric = append(existingMF.Metric, m)
|
||||||
|
@ -493,6 +509,11 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) {
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
result = append(result, metricFamiliesByName[name])
|
result = append(result, metricFamiliesByName[name])
|
||||||
}
|
}
|
||||||
|
// We cannot just `return result, errs`. Even if errs == nil, it will
|
||||||
|
// not be seen as nil through the error interface.
|
||||||
|
if len(errs) == 0 {
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
return result, errs
|
return result, errs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue