From 91d7175eaac18b00e370965f3a8186cc40bf9f55 Mon Sep 17 00:00:00 2001 From: Thomas Jackson Date: Mon, 17 Jun 2019 00:31:17 -0700 Subject: [PATCH] Add storage.Warnings to LabelValues and LabelNames (#5673) Fixes #5661 Signed-off-by: Thomas Jackson --- promql/engine_test.go | 14 ++++++++------ storage/fanout.go | 40 ++++++++++++++++++++++++++++++++-------- storage/interface.go | 4 ++-- storage/noop.go | 8 ++++---- storage/remote/read.go | 8 ++++---- storage/tsdb/tsdb.go | 12 +++++++++--- web/api/v1/api.go | 12 ++++++------ 7 files changed, 65 insertions(+), 33 deletions(-) diff --git a/promql/engine_test.go b/promql/engine_test.go index 5b64e8074..3ca4f92fb 100644 --- a/promql/engine_test.go +++ b/promql/engine_test.go @@ -173,9 +173,9 @@ type errQuerier struct { func (q *errQuerier) Select(*storage.SelectParams, ...*labels.Matcher) (storage.SeriesSet, storage.Warnings, error) { return errSeriesSet{err: q.err}, nil, q.err } -func (*errQuerier) LabelValues(name string) ([]string, error) { return nil, nil } -func (*errQuerier) LabelNames() ([]string, error) { return nil, nil } -func (*errQuerier) Close() error { return nil } +func (*errQuerier) LabelValues(name string) ([]string, storage.Warnings, error) { return nil, nil, nil } +func (*errQuerier) LabelNames() ([]string, storage.Warnings, error) { return nil, nil, nil } +func (*errQuerier) Close() error { return nil } // errSeriesSet implements storage.SeriesSet which always returns error. type errSeriesSet struct { @@ -242,9 +242,11 @@ func (q *paramCheckerQuerier) Select(sp *storage.SelectParams, _ ...*labels.Matc return errSeriesSet{err: nil}, nil, nil } -func (*paramCheckerQuerier) LabelValues(name string) ([]string, error) { return nil, nil } -func (*paramCheckerQuerier) LabelNames() ([]string, error) { return nil, nil } -func (*paramCheckerQuerier) Close() error { return nil } +func (*paramCheckerQuerier) LabelValues(name string) ([]string, storage.Warnings, error) { + return nil, nil, nil +} +func (*paramCheckerQuerier) LabelNames() ([]string, storage.Warnings, error) { return nil, nil, nil } +func (*paramCheckerQuerier) Close() error { return nil } func TestParamsSetCorrectly(t *testing.T) { opts := EngineOpts{ diff --git a/storage/fanout.go b/storage/fanout.go index 81ae99dd6..41ccff5a5 100644 --- a/storage/fanout.go +++ b/storage/fanout.go @@ -253,16 +253,28 @@ func (q *mergeQuerier) Select(params *SelectParams, matchers ...*labels.Matcher) } // LabelValues returns all potential values for a label name. -func (q *mergeQuerier) LabelValues(name string) ([]string, error) { +func (q *mergeQuerier) LabelValues(name string) ([]string, Warnings, error) { var results [][]string + var warnings Warnings for _, querier := range q.queriers { - values, err := querier.LabelValues(name) + values, wrn, err := querier.LabelValues(name) + + if wrn != nil { + warnings = append(warnings, wrn...) + } if err != nil { - return nil, err + q.failedQueriers[querier] = struct{}{} + // If the error source isn't the primary querier, return the error as a warning and continue. + if querier != q.primaryQuerier { + warnings = append(warnings, err) + continue + } else { + return nil, nil, err + } } results = append(results, values) } - return mergeStringSlices(results), nil + return mergeStringSlices(results), warnings, nil } func (q *mergeQuerier) IsFailedSet(set SeriesSet) bool { @@ -310,13 +322,25 @@ func mergeTwoStringSlices(a, b []string) []string { } // LabelNames returns all the unique label names present in the block in sorted order. -func (q *mergeQuerier) LabelNames() ([]string, error) { +func (q *mergeQuerier) LabelNames() ([]string, Warnings, error) { labelNamesMap := make(map[string]struct{}) + var warnings Warnings for _, b := range q.queriers { - names, err := b.LabelNames() + names, wrn, err := b.LabelNames() + if wrn != nil { + warnings = append(warnings, wrn...) + } + if err != nil { - return nil, errors.Wrap(err, "LabelNames() from Querier") + // If the error source isn't the primary querier, return the error as a warning and continue. + if b != q.primaryQuerier { + warnings = append(warnings, err) + continue + } else { + return nil, nil, errors.Wrap(err, "LabelNames() from Querier") + } } + for _, name := range names { labelNamesMap[name] = struct{}{} } @@ -328,7 +352,7 @@ func (q *mergeQuerier) LabelNames() ([]string, error) { } sort.Strings(labelNames) - return labelNames, nil + return labelNames, warnings, nil } // Close releases the resources of the Querier. diff --git a/storage/interface.go b/storage/interface.go index fea1c9166..688bad44c 100644 --- a/storage/interface.go +++ b/storage/interface.go @@ -55,10 +55,10 @@ type Querier interface { Select(*SelectParams, ...*labels.Matcher) (SeriesSet, Warnings, error) // LabelValues returns all potential values for a label name. - LabelValues(name string) ([]string, error) + LabelValues(name string) ([]string, Warnings, error) // LabelNames returns all the unique label names present in the block in sorted order. - LabelNames() ([]string, error) + LabelNames() ([]string, Warnings, error) // Close releases the resources of the Querier. Close() error diff --git a/storage/noop.go b/storage/noop.go index 1c1fed4fe..acdd79f4b 100644 --- a/storage/noop.go +++ b/storage/noop.go @@ -30,12 +30,12 @@ func (noopQuerier) Select(*SelectParams, ...*labels.Matcher) (SeriesSet, Warning return NoopSeriesSet(), nil, nil } -func (noopQuerier) LabelValues(name string) ([]string, error) { - return nil, nil +func (noopQuerier) LabelValues(name string) ([]string, Warnings, error) { + return nil, nil, nil } -func (noopQuerier) LabelNames() ([]string, error) { - return nil, nil +func (noopQuerier) LabelNames() ([]string, Warnings, error) { + return nil, nil, nil } func (noopQuerier) Close() error { diff --git a/storage/remote/read.go b/storage/remote/read.go index eefb826b5..6e97ced12 100644 --- a/storage/remote/read.go +++ b/storage/remote/read.go @@ -77,15 +77,15 @@ func (q *querier) Select(p *storage.SelectParams, matchers ...*labels.Matcher) ( } // LabelValues implements storage.Querier and is a noop. -func (q *querier) LabelValues(name string) ([]string, error) { +func (q *querier) LabelValues(name string) ([]string, storage.Warnings, error) { // TODO implement? - return nil, nil + return nil, nil, nil } // LabelNames implements storage.Querier and is a noop. -func (q *querier) LabelNames() ([]string, error) { +func (q *querier) LabelNames() ([]string, storage.Warnings, error) { // TODO implement? - return nil, nil + return nil, nil, nil } // Close implements storage.Querier and is a noop. diff --git a/storage/tsdb/tsdb.go b/storage/tsdb/tsdb.go index 10d15f706..55f59c8cb 100644 --- a/storage/tsdb/tsdb.go +++ b/storage/tsdb/tsdb.go @@ -253,9 +253,15 @@ func (q querier) Select(_ *storage.SelectParams, oms ...*labels.Matcher) (storag return seriesSet{set: set}, nil, nil } -func (q querier) LabelValues(name string) ([]string, error) { return q.q.LabelValues(name) } -func (q querier) LabelNames() ([]string, error) { return q.q.LabelNames() } -func (q querier) Close() error { return q.q.Close() } +func (q querier) LabelValues(name string) ([]string, storage.Warnings, error) { + v, err := q.q.LabelValues(name) + return v, nil, err +} +func (q querier) LabelNames() ([]string, storage.Warnings, error) { + v, err := q.q.LabelNames() + return v, nil, err +} +func (q querier) Close() error { return q.q.Close() } type seriesSet struct { set tsdb.SeriesSet diff --git a/web/api/v1/api.go b/web/api/v1/api.go index 465594f54..d4523eac4 100644 --- a/web/api/v1/api.go +++ b/web/api/v1/api.go @@ -410,11 +410,11 @@ func (api *API) labelNames(r *http.Request) apiFuncResult { } defer q.Close() - names, err := q.LabelNames() + names, warnings, err := q.LabelNames() if err != nil { - return apiFuncResult{nil, &apiError{errorExec, err}, nil, nil} + return apiFuncResult{nil, &apiError{errorExec, err}, warnings, nil} } - return apiFuncResult{names, nil, nil, nil} + return apiFuncResult{names, nil, warnings, nil} } func (api *API) labelValues(r *http.Request) apiFuncResult { @@ -430,12 +430,12 @@ func (api *API) labelValues(r *http.Request) apiFuncResult { } defer q.Close() - vals, err := q.LabelValues(name) + vals, warnings, err := q.LabelValues(name) if err != nil { - return apiFuncResult{nil, &apiError{errorExec, err}, nil, nil} + return apiFuncResult{nil, &apiError{errorExec, err}, warnings, nil} } - return apiFuncResult{vals, nil, nil, nil} + return apiFuncResult{vals, nil, warnings, nil} } var ( -- GitLab