From 3128875ff4de14527502be787e3f3eb480a11fc9 Mon Sep 17 00:00:00 2001 From: Chris Marchbanks Date: Fri, 13 Mar 2020 13:57:29 -0600 Subject: [PATCH] Fix panic when a remote read store errors (#6975) Signed-off-by: Chris Marchbanks --- storage/fanout.go | 1 + storage/fanout/fanout_test.go | 91 ++++++++++++++++++++++++++++++++++- 2 files changed, 91 insertions(+), 1 deletion(-) diff --git a/storage/fanout.go b/storage/fanout.go index bad6a8df1..f55f4c8dc 100644 --- a/storage/fanout.go +++ b/storage/fanout.go @@ -262,6 +262,7 @@ func (q *mergeQuerier) SelectSorted(params *SelectParams, matchers ...*labels.Ma } else { priErr = qryResult.selectError } + continue } seriesSets = append(seriesSets, qryResult.set) } diff --git a/storage/fanout/fanout_test.go b/storage/fanout/fanout_test.go index cede30cca..7afb04202 100644 --- a/storage/fanout/fanout_test.go +++ b/storage/fanout/fanout_test.go @@ -15,6 +15,7 @@ package storage import ( "context" + "errors" "github.com/prometheus/common/model" "github.com/prometheus/prometheus/pkg/labels" @@ -26,7 +27,6 @@ import ( ) func TestSelectSorted(t *testing.T) { - inputLabel := labels.FromStrings(model.MetricNameLabel, "a") outputLabel := labels.FromStrings(model.MetricNameLabel, "a") @@ -97,5 +97,94 @@ func TestSelectSorted(t *testing.T) { testutil.Equals(t, labelsResult, outputLabel) testutil.Equals(t, inputTotalSize, len(result)) +} + +func TestFanoutErrors(t *testing.T) { + workingStorage := teststorage.New(t) + defer workingStorage.Close() + + cases := []struct { + primary storage.Storage + secondary storage.Storage + warnings storage.Warnings + err error + }{ + { + primary: workingStorage, + secondary: errStorage{}, + warnings: storage.Warnings{errSelect}, + err: nil, + }, + { + primary: errStorage{}, + secondary: workingStorage, + warnings: nil, + err: errSelect, + }, + } + + for _, tc := range cases { + fanoutStorage := storage.NewFanout(nil, tc.primary, tc.secondary) + + querier, err := fanoutStorage.Querier(context.Background(), 0, 8000) + testutil.Ok(t, err) + defer querier.Close() + + matcher := labels.MustNewMatcher(labels.MatchEqual, "a", "b") + ss, warnings, err := querier.SelectSorted(nil, matcher) + testutil.Equals(t, tc.err, err) + testutil.Equals(t, tc.warnings, warnings) + + // Only test series iteration if there are no errors. + if err != nil { + continue + } + + for ss.Next() { + ss.At() + } + testutil.Ok(t, ss.Err()) + } +} + +var errSelect = errors.New("select error") + +type errStorage struct{} + +func (errStorage) Querier(_ context.Context, _, _ int64) (storage.Querier, error) { + return errQuerier{}, nil +} + +func (errStorage) Appender() storage.Appender { + return nil +} + +func (errStorage) StartTime() (int64, error) { + return 0, nil +} + +func (errStorage) Close() error { + return nil +} + +type errQuerier struct{} + +func (errQuerier) Select(*storage.SelectParams, ...*labels.Matcher) (storage.SeriesSet, storage.Warnings, error) { + return nil, nil, errSelect +} + +func (errQuerier) SelectSorted(*storage.SelectParams, ...*labels.Matcher) (storage.SeriesSet, storage.Warnings, error) { + return nil, nil, errSelect +} + +func (errQuerier) LabelValues(name string) ([]string, storage.Warnings, error) { + return nil, nil, errors.New("label values error") +} + +func (errQuerier) LabelNames() ([]string, storage.Warnings, error) { + return nil, nil, errors.New("label names error") +} +func (errQuerier) Close() error { + return nil }