From 05fba53e57cddbfaeb475e65089df922f868760f Mon Sep 17 00:00:00 2001 From: Matthieu MOREL Date: Wed, 8 Nov 2023 04:49:39 +0100 Subject: [PATCH] web : use Go standard package Signed-off-by: Matthieu MOREL --- .golangci.yml | 7 ---- model/histogram/float_histogram.go | 10 +++--- model/histogram/generic.go | 18 +++-------- model/histogram/histogram.go | 19 ++++------- web/api/v1/api.go | 52 ++++++++++++++---------------- web/api/v1/api_test.go | 6 ++-- web/api/v1/errors_test.go | 2 +- web/federate.go | 4 +-- web/federate_test.go | 10 +++--- web/web.go | 3 +- 10 files changed, 51 insertions(+), 80 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 2d53106c01..666d22cbe4 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -41,13 +41,6 @@ issues: text: "import 'github.com/pkg/errors' is not allowed" linters: - depguard - - path: web/ - linters: - - errorlint - - path: web/ - text: "import 'github.com/pkg/errors' is not allowed" - linters: - - depguard - linters: - godot source: "^// ===" diff --git a/model/histogram/float_histogram.go b/model/histogram/float_histogram.go index fd6c2560f1..22d33f5a4e 100644 --- a/model/histogram/float_histogram.go +++ b/model/histogram/float_histogram.go @@ -17,8 +17,6 @@ import ( "fmt" "math" "strings" - - "github.com/pkg/errors" ) // FloatHistogram is similar to Histogram but uses float64 for all @@ -602,19 +600,19 @@ func (h *FloatHistogram) AllReverseBucketIterator() BucketIterator[float64] { // create false positives here. func (h *FloatHistogram) Validate() error { if err := checkHistogramSpans(h.NegativeSpans, len(h.NegativeBuckets)); err != nil { - return errors.Wrap(err, "negative side") + return fmt.Errorf("negative side: %w", err) } if err := checkHistogramSpans(h.PositiveSpans, len(h.PositiveBuckets)); err != nil { - return errors.Wrap(err, "positive side") + return fmt.Errorf("positive side: %w", err) } var nCount, pCount float64 err := checkHistogramBuckets(h.NegativeBuckets, &nCount, false) if err != nil { - return errors.Wrap(err, "negative side") + return fmt.Errorf("negative side: %w", err) } err = checkHistogramBuckets(h.PositiveBuckets, &pCount, false) if err != nil { - return errors.Wrap(err, "positive side") + return fmt.Errorf("positive side: %w", err) } return nil diff --git a/model/histogram/generic.go b/model/histogram/generic.go index 22048c44ef..7e4eb1ecb1 100644 --- a/model/histogram/generic.go +++ b/model/histogram/generic.go @@ -14,11 +14,10 @@ package histogram import ( + "errors" "fmt" "math" "strings" - - "github.com/pkg/errors" ) var ( @@ -361,18 +360,12 @@ func checkHistogramSpans(spans []Span, numBuckets int) error { var spanBuckets int for n, span := range spans { if n > 0 && span.Offset < 0 { - return errors.Wrap( - ErrHistogramSpanNegativeOffset, - fmt.Sprintf("span number %d with offset %d", n+1, span.Offset), - ) + return fmt.Errorf("span number %d with offset %d: %w", n+1, span.Offset, ErrHistogramSpanNegativeOffset) } spanBuckets += int(span.Length) } if spanBuckets != numBuckets { - return errors.Wrap( - ErrHistogramSpansBucketsMismatch, - fmt.Sprintf("spans need %d buckets, have %d buckets", spanBuckets, numBuckets), - ) + return fmt.Errorf("spans need %d buckets, have %d buckets: %w", spanBuckets, numBuckets, ErrHistogramSpansBucketsMismatch) } return nil } @@ -391,10 +384,7 @@ func checkHistogramBuckets[BC BucketCount, IBC InternalBucketCount](buckets []IB c = buckets[i] } if c < 0 { - return errors.Wrap( - ErrHistogramNegativeBucketCount, - fmt.Sprintf("bucket number %d has observation count of %v", i+1, c), - ) + return fmt.Errorf("bucket number %d has observation count of %v: %w", i+1, c, ErrHistogramNegativeBucketCount) } last = c *count += BC(c) diff --git a/model/histogram/histogram.go b/model/histogram/histogram.go index fa624841e3..30c23e5e79 100644 --- a/model/histogram/histogram.go +++ b/model/histogram/histogram.go @@ -18,7 +18,6 @@ import ( "math" "strings" - "github.com/pkg/errors" "golang.org/x/exp/slices" ) @@ -338,35 +337,29 @@ func (h *Histogram) ToFloat() *FloatHistogram { // the total h.Count). func (h *Histogram) Validate() error { if err := checkHistogramSpans(h.NegativeSpans, len(h.NegativeBuckets)); err != nil { - return errors.Wrap(err, "negative side") + return fmt.Errorf("negative side: %w", err) } if err := checkHistogramSpans(h.PositiveSpans, len(h.PositiveBuckets)); err != nil { - return errors.Wrap(err, "positive side") + return fmt.Errorf("positive side: %w", err) } var nCount, pCount uint64 err := checkHistogramBuckets(h.NegativeBuckets, &nCount, true) if err != nil { - return errors.Wrap(err, "negative side") + return fmt.Errorf("negative side: %w", err) } err = checkHistogramBuckets(h.PositiveBuckets, &pCount, true) if err != nil { - return errors.Wrap(err, "positive side") + return fmt.Errorf("positive side: %w", err) } sumOfBuckets := nCount + pCount + h.ZeroCount if math.IsNaN(h.Sum) { if sumOfBuckets > h.Count { - return errors.Wrap( - ErrHistogramCountNotBigEnough, - fmt.Sprintf("%d observations found in buckets, but the Count field is %d", sumOfBuckets, h.Count), - ) + return fmt.Errorf("%d observations found in buckets, but the Count field is %d: %w", sumOfBuckets, h.Count, ErrHistogramCountNotBigEnough) } } else { if sumOfBuckets != h.Count { - return errors.Wrap( - ErrHistogramCountMismatch, - fmt.Sprintf("%d observations found in buckets, but the Count field is %d", sumOfBuckets, h.Count), - ) + return fmt.Errorf("%d observations found in buckets, but the Count field is %d: %w", sumOfBuckets, h.Count, ErrHistogramCountMismatch) } } diff --git a/web/api/v1/api.go b/web/api/v1/api.go index 6c8128f3f1..34abe80aac 100644 --- a/web/api/v1/api.go +++ b/web/api/v1/api.go @@ -15,6 +15,7 @@ package v1 import ( "context" + "errors" "fmt" "math" "math/rand" @@ -33,7 +34,6 @@ import ( "github.com/grafana/regexp" jsoniter "github.com/json-iterator/go" "github.com/munnerz/goautoneg" - "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/common/model" "github.com/prometheus/common/route" @@ -317,7 +317,7 @@ func (api *API) ClearCodecs() { } func setUnavailStatusOnTSDBNotReady(r apiFuncResult) apiFuncResult { - if r.err != nil && errors.Cause(r.err.err) == tsdb.ErrNotReady { + if r.err != nil && errors.Is(r.err.err, tsdb.ErrNotReady) { r.err.typ = errorUnavailable } return r @@ -415,7 +415,7 @@ type QueryData struct { func invalidParamError(err error, parameter string) apiFuncResult { return apiFuncResult{nil, &apiError{ - errorBadData, errors.Wrapf(err, "invalid parameter %q", parameter), + errorBadData, fmt.Errorf("invalid parameter %q: %w", parameter, err), }, nil, nil} } @@ -624,17 +624,15 @@ func returnAPIError(err error) *apiError { return nil } - cause := errors.Unwrap(err) - if cause == nil { - cause = err - } - - switch cause.(type) { - case promql.ErrQueryCanceled: + var eqc promql.ErrQueryCanceled + var eqt promql.ErrQueryTimeout + var es promql.ErrStorage + switch { + case errors.As(err, &eqc): return &apiError{errorCanceled, err} - case promql.ErrQueryTimeout: + case errors.As(err, &eqt): return &apiError{errorTimeout, err} - case promql.ErrStorage: + case errors.As(err, &es): return &apiError{errorInternal, err} } @@ -709,7 +707,7 @@ func (api *API) labelValues(r *http.Request) (result apiFuncResult) { name := route.Param(ctx, "name") if !model.LabelNameRE.MatchString(name) { - return apiFuncResult{nil, &apiError{errorBadData, errors.Errorf("invalid label name: %q", name)}, nil, nil} + return apiFuncResult{nil, &apiError{errorBadData, fmt.Errorf("invalid label name: %q", name)}, nil, nil} } start, err := parseTimeParam(r, "start", MinTime) @@ -797,7 +795,7 @@ func (api *API) series(r *http.Request) (result apiFuncResult) { ctx := r.Context() if err := r.ParseForm(); err != nil { - return apiFuncResult{nil, &apiError{errorBadData, errors.Wrapf(err, "error parsing form values")}, nil, nil} + return apiFuncResult{nil, &apiError{errorBadData, fmt.Errorf("error parsing form values: %w", err)}, nil, nil} } if len(r.Form["match[]"]) == 0 { return apiFuncResult{nil, &apiError{errorBadData, errors.New("no match[] parameter provided")}, nil, nil} @@ -1028,7 +1026,7 @@ func (api *API) targets(r *http.Request) apiFuncResult { case err == nil && lastErrStr == "": return "" case err != nil: - return errors.Wrapf(err, lastErrStr).Error() + return fmt.Errorf("%s: %w", lastErrStr, err).Error() default: return lastErrStr } @@ -1347,7 +1345,7 @@ type RecordingRule struct { func (api *API) rules(r *http.Request) apiFuncResult { if err := r.ParseForm(); err != nil { - return apiFuncResult{nil, &apiError{errorBadData, errors.Wrapf(err, "error parsing form values")}, nil, nil} + return apiFuncResult{nil, &apiError{errorBadData, fmt.Errorf("error parsing form values: %w", err)}, nil, nil} } queryFormToSet := func(values []string) map[string]struct{} { @@ -1367,7 +1365,7 @@ func (api *API) rules(r *http.Request) apiFuncResult { typ := strings.ToLower(r.URL.Query().Get("type")) if typ != "" && typ != "alert" && typ != "record" { - return invalidParamError(errors.Errorf("not supported value %q", typ), "type") + return invalidParamError(fmt.Errorf("not supported value %q", typ), "type") } returnAlerts := typ == "" || typ == "alert" @@ -1453,7 +1451,7 @@ func (api *API) rules(r *http.Request) apiFuncResult { Type: "recording", } default: - err := errors.Errorf("failed to assert type of rule '%v'", rule.Name()) + err := fmt.Errorf("failed to assert type of rule '%v'", rule.Name()) return apiFuncResult{nil, &apiError{errorInternal, err}, nil, nil} } @@ -1560,7 +1558,7 @@ func (api *API) serveTSDBStatus(r *http.Request) apiFuncResult { } metrics, err := api.gatherer.Gather() if err != nil { - return apiFuncResult{nil, &apiError{errorInternal, fmt.Errorf("error gathering runtime status: %s", err)}, nil, nil} + return apiFuncResult{nil, &apiError{errorInternal, fmt.Errorf("error gathering runtime status: %w", err)}, nil, nil} } chunkCount := int64(math.NaN()) for _, mF := range metrics { @@ -1636,7 +1634,7 @@ func (api *API) deleteSeries(r *http.Request) apiFuncResult { return apiFuncResult{nil, &apiError{errorUnavailable, errors.New("admin APIs disabled")}, nil, nil} } if err := r.ParseForm(); err != nil { - return apiFuncResult{nil, &apiError{errorBadData, errors.Wrap(err, "error parsing form values")}, nil, nil} + return apiFuncResult{nil, &apiError{errorBadData, fmt.Errorf("error parsing form values: %w", err)}, nil, nil} } if len(r.Form["match[]"]) == 0 { return apiFuncResult{nil, &apiError{errorBadData, errors.New("no match[] parameter provided")}, nil, nil} @@ -1675,7 +1673,7 @@ func (api *API) snapshot(r *http.Request) apiFuncResult { if r.FormValue("skip_head") != "" { skipHead, err = strconv.ParseBool(r.FormValue("skip_head")) if err != nil { - return invalidParamError(errors.Wrapf(err, "unable to parse boolean"), "skip_head") + return invalidParamError(fmt.Errorf("unable to parse boolean: %w", err), "skip_head") } } @@ -1687,10 +1685,10 @@ func (api *API) snapshot(r *http.Request) apiFuncResult { dir = filepath.Join(snapdir, name) ) if err := os.MkdirAll(dir, 0o777); err != nil { - return apiFuncResult{nil, &apiError{errorInternal, errors.Wrap(err, "create snapshot directory")}, nil, nil} + return apiFuncResult{nil, &apiError{errorInternal, fmt.Errorf("create snapshot directory: %w", err)}, nil, nil} } if err := api.db.Snapshot(dir, !skipHead); err != nil { - return apiFuncResult{nil, &apiError{errorInternal, errors.Wrap(err, "create snapshot")}, nil, nil} + return apiFuncResult{nil, &apiError{errorInternal, fmt.Errorf("create snapshot: %w", err)}, nil, nil} } return apiFuncResult{struct { @@ -1805,7 +1803,7 @@ func parseTimeParam(r *http.Request, paramName string, defaultValue time.Time) ( } result, err := parseTime(val) if err != nil { - return time.Time{}, errors.Wrapf(err, "Invalid time value for '%s'", paramName) + return time.Time{}, fmt.Errorf("Invalid time value for '%s': %w", paramName, err) } return result, nil } @@ -1830,21 +1828,21 @@ func parseTime(s string) (time.Time, error) { case maxTimeFormatted: return MaxTime, nil } - return time.Time{}, errors.Errorf("cannot parse %q to a valid timestamp", s) + return time.Time{}, fmt.Errorf("cannot parse %q to a valid timestamp", s) } func parseDuration(s string) (time.Duration, error) { if d, err := strconv.ParseFloat(s, 64); err == nil { ts := d * float64(time.Second) if ts > float64(math.MaxInt64) || ts < float64(math.MinInt64) { - return 0, errors.Errorf("cannot parse %q to a valid duration. It overflows int64", s) + return 0, fmt.Errorf("cannot parse %q to a valid duration. It overflows int64", s) } return time.Duration(ts), nil } if d, err := model.ParseDuration(s); err == nil { return time.Duration(d), nil } - return 0, errors.Errorf("cannot parse %q to a valid duration", s) + return 0, fmt.Errorf("cannot parse %q to a valid duration", s) } func parseMatchersParam(matchers []string) ([][]*labels.Matcher, error) { diff --git a/web/api/v1/api_test.go b/web/api/v1/api_test.go index 320d174fce..a5dd8640b3 100644 --- a/web/api/v1/api_test.go +++ b/web/api/v1/api_test.go @@ -16,6 +16,7 @@ package v1 import ( "context" "encoding/json" + "errors" "fmt" "io" "net/http" @@ -33,7 +34,6 @@ import ( "github.com/prometheus/prometheus/util/stats" "github.com/go-kit/log" - "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" config_util "github.com/prometheus/common/config" "github.com/prometheus/common/model" @@ -2974,7 +2974,7 @@ func (f *fakeDB) WALReplayStatus() (tsdb.WALReplayStatus, error) { } func TestAdminEndpoints(t *testing.T) { - tsdb, tsdbWithError, tsdbNotReady := &fakeDB{}, &fakeDB{err: errors.New("some error")}, &fakeDB{err: errors.Wrap(tsdb.ErrNotReady, "wrap")} + tsdb, tsdbWithError, tsdbNotReady := &fakeDB{}, &fakeDB{err: errors.New("some error")}, &fakeDB{err: fmt.Errorf("wrap: %w", tsdb.ErrNotReady)} snapshotAPI := func(api *API) apiFunc { return api.snapshot } cleanAPI := func(api *API) apiFunc { return api.cleanTombstones } deleteAPI := func(api *API) apiFunc { return api.deleteSeries } @@ -3354,7 +3354,7 @@ func TestParseTimeParam(t *testing.T) { asTime: time.Time{}, asError: func() error { _, err := parseTime("baz") - return errors.Wrapf(err, "Invalid time value for '%s'", "foo") + return fmt.Errorf("Invalid time value for '%s': %w", "foo", err) }, }, }, diff --git a/web/api/v1/errors_test.go b/web/api/v1/errors_test.go index 38ca5b62c0..b6ec7d4e1f 100644 --- a/web/api/v1/errors_test.go +++ b/web/api/v1/errors_test.go @@ -15,6 +15,7 @@ package v1 import ( "context" + "errors" "fmt" "net/http" "net/http/httptest" @@ -24,7 +25,6 @@ import ( "github.com/go-kit/log" "github.com/grafana/regexp" - "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/common/route" "github.com/stretchr/testify/require" diff --git a/web/federate.go b/web/federate.go index babc97e55d..2b79d00532 100644 --- a/web/federate.go +++ b/web/federate.go @@ -14,6 +14,7 @@ package web import ( + "errors" "fmt" "net/http" "sort" @@ -21,7 +22,6 @@ import ( "github.com/go-kit/log/level" "github.com/gogo/protobuf/proto" - "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" dto "github.com/prometheus/client_model/go" "github.com/prometheus/common/expfmt" @@ -86,7 +86,7 @@ func (h *Handler) federation(w http.ResponseWriter, req *http.Request) { q, err := h.localStorage.Querier(mint, maxt) if err != nil { federationErrors.Inc() - if errors.Cause(err) == tsdb.ErrNotReady { + if errors.Is(err, tsdb.ErrNotReady) { http.Error(w, err.Error(), http.StatusServiceUnavailable) return } diff --git a/web/federate_test.go b/web/federate_test.go index ab93dcf281..80539861d9 100644 --- a/web/federate_test.go +++ b/web/federate_test.go @@ -16,6 +16,7 @@ package web import ( "bytes" "context" + "errors" "fmt" "io" "net/http" @@ -25,7 +26,6 @@ import ( "testing" "time" - "github.com/pkg/errors" "github.com/prometheus/common/model" "github.com/stretchr/testify/require" @@ -238,15 +238,15 @@ type notReadyReadStorage struct { } func (notReadyReadStorage) Querier(int64, int64) (storage.Querier, error) { - return nil, errors.Wrap(tsdb.ErrNotReady, "wrap") + return nil, fmt.Errorf("wrap: %w", tsdb.ErrNotReady) } func (notReadyReadStorage) StartTime() (int64, error) { - return 0, errors.Wrap(tsdb.ErrNotReady, "wrap") + return 0, fmt.Errorf("wrap: %w", tsdb.ErrNotReady) } func (notReadyReadStorage) Stats(string, int) (*tsdb.Stats, error) { - return nil, errors.Wrap(tsdb.ErrNotReady, "wrap") + return nil, fmt.Errorf("wrap: %w", tsdb.ErrNotReady) } // Regression test for https://github.com/prometheus/prometheus/issues/7181. @@ -396,7 +396,7 @@ func TestFederationWithNativeHistograms(t *testing.T) { l := labels.Labels{} for { et, err := p.Next() - if err == io.EOF { + if err != nil && errors.Is(err, io.EOF) { break } require.NoError(t, err) diff --git a/web/web.go b/web/web.go index ccf97805a4..43b79c235d 100644 --- a/web/web.go +++ b/web/web.go @@ -40,7 +40,6 @@ import ( "github.com/go-kit/log/level" "github.com/grafana/regexp" "github.com/mwitkow/go-conntrack" - "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" io_prometheus_client "github.com/prometheus/client_model/go" @@ -732,7 +731,7 @@ func (h *Handler) runtimeInfo() (api_v1.RuntimeInfo, error) { metrics, err := h.gatherer.Gather() if err != nil { - return status, errors.Errorf("error gathering runtime status: %s", err) + return status, fmt.Errorf("error gathering runtime status: %w", err) } for _, mF := range metrics { switch *mF.Name {