diff --git a/pkg/loghttp/series.go b/pkg/loghttp/series.go index abbac0fefafe3..b4601ed3402de 100644 --- a/pkg/loghttp/series.go +++ b/pkg/loghttp/series.go @@ -2,6 +2,7 @@ package loghttp import ( "net/http" + "sort" "github.com/grafana/loki/pkg/logproto" ) @@ -18,10 +19,15 @@ func ParseSeriesQuery(r *http.Request) (*logproto.SeriesRequest, error) { } xs := r.Form["match"] + // Prometheus encodes with `match[]`; we use both for compatibility. + ys := r.Form["match[]"] + + deduped := union(xs, ys) + sort.Strings(deduped) // ensure matchers are valid before fanning out to ingesters/store as well as returning valuable parsing errors // instead of 500s - _, err = Match(xs) + _, err = Match(deduped) if err != nil { return nil, err } @@ -29,7 +35,24 @@ func ParseSeriesQuery(r *http.Request) (*logproto.SeriesRequest, error) { return &logproto.SeriesRequest{ Start: start, End: end, - Groups: xs, + Groups: deduped, }, nil } + +func union(cols ...[]string) []string { + m := map[string]struct{}{} + + for _, col := range cols { + for _, s := range col { + m[s] = struct{}{} + } + } + + res := make([]string, 0, len(m)) + for k := range m { + res = append(res, k) + } + + return res +} diff --git a/pkg/loghttp/series_test.go b/pkg/loghttp/series_test.go index 885a653c868e2..8f0792a5eead4 100644 --- a/pkg/loghttp/series_test.go +++ b/pkg/loghttp/series_test.go @@ -41,6 +41,28 @@ func TestParseSeriesQuery(t *testing.T) { false, mkSeriesRequest(t, "1000", "2000", []string{`{a="1"}`, `{b="2", c=~"3", d!="4"}`}), }, + { + "mixes match encodings", + withForm(url.Values{ + "start": []string{"1000"}, + "end": []string{"2000"}, + "match": []string{`{a="1"}`}, + "match[]": []string{`{b="2"}`}, + }), + false, + mkSeriesRequest(t, "1000", "2000", []string{`{a="1"}`, `{b="2"}`}), + }, + { + "dedupes match encodings", + withForm(url.Values{ + "start": []string{"1000"}, + "end": []string{"2000"}, + "match": []string{`{a="1"}`, `{b="2"}`}, + "match[]": []string{`{b="2"}`, `{c="3"}`}, + }), + false, + mkSeriesRequest(t, "1000", "2000", []string{`{a="1"}`, `{b="2"}`, `{c="3"}`}), + }, } { t.Run(tc.desc, func(t *testing.T) { out, err := ParseSeriesQuery(tc.input)