diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c74dbcc78..f2133ce0fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,13 @@ NOTE: As semantic versioning states all 0.y.z releases can contain breaking chan We use *breaking* word for marking changes that are not backward compatible (relates only to v0.y.z releases.) +## [v0.10.1](https://github.com/thanos-io/thanos/releases/tag/v0.10.1) - 2020.01.23 + +### Fixed + +- [#2015](https://github.com/thanos-io/thanos/pull/2015) Sidecar: Querier /api/v1/series bug fixed when time range was ignored inside sidecar. +The bug was noticeable for example when using Grafana template variables. + ## [v0.10.0](https://github.com/thanos-io/thanos/releases/tag/v0.10.0) - 2020.01.13 ### Fixed diff --git a/VERSION b/VERSION index 78bc1abd14..71172b43ae 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.10.0 +0.10.1 \ No newline at end of file diff --git a/examples/alerts/alerts.md b/examples/alerts/alerts.md index c48b9868c3..14367defa7 100644 --- a/examples/alerts/alerts.md +++ b/examples/alerts/alerts.md @@ -263,9 +263,9 @@ rules: message: Thanos Querys {{$labels.job}} have {{ $value }} of failing DNS queries. expr: | ( - sum by (job) (rate(thanos_querier_store_apis_dns_failures_total{job=~"thanos-querier.*"}[5m])) + sum by (job) (rate(thanos_query_store_apis_dns_failures_total{job=~"thanos-querier.*"}[5m])) / - sum by (job) (rate(thanos_querier_store_apis_dns_lookups_total{job=~"thanos-querier.*"}[5m])) + sum by (job) (rate(thanos_query_store_apis_dns_lookups_total{job=~"thanos-querier.*"}[5m])) > 1 ) for: 15m diff --git a/examples/alerts/alerts.yaml b/examples/alerts/alerts.yaml index 3d9f8a50e5..23f10b655f 100644 --- a/examples/alerts/alerts.yaml +++ b/examples/alerts/alerts.yaml @@ -112,9 +112,9 @@ groups: message: Thanos Querys {{$labels.job}} have {{ $value }} of failing DNS queries. expr: | ( - sum by (job) (rate(thanos_querier_store_apis_dns_failures_total{job=~"thanos-querier.*"}[5m])) + sum by (job) (rate(thanos_query_store_apis_dns_failures_total{job=~"thanos-querier.*"}[5m])) / - sum by (job) (rate(thanos_querier_store_apis_dns_lookups_total{job=~"thanos-querier.*"}[5m])) + sum by (job) (rate(thanos_query_store_apis_dns_lookups_total{job=~"thanos-querier.*"}[5m])) > 1 ) for: 15m diff --git a/mixin/thanos/alerts/querier.libsonnet b/mixin/thanos/alerts/querier.libsonnet index f50100161b..38705aacf3 100644 --- a/mixin/thanos/alerts/querier.libsonnet +++ b/mixin/thanos/alerts/querier.libsonnet @@ -86,9 +86,9 @@ }, expr: ||| ( - sum by (job) (rate(thanos_querier_store_apis_dns_failures_total{%(selector)s}[5m])) + sum by (job) (rate(thanos_query_store_apis_dns_failures_total{%(selector)s}[5m])) / - sum by (job) (rate(thanos_querier_store_apis_dns_lookups_total{%(selector)s}[5m])) + sum by (job) (rate(thanos_query_store_apis_dns_lookups_total{%(selector)s}[5m])) > 1 ) ||| % thanos.querier, diff --git a/pkg/model/timeduration.go b/pkg/model/timeduration.go index bbe766043f..a40a6a78f4 100644 --- a/pkg/model/timeduration.go +++ b/pkg/model/timeduration.go @@ -42,7 +42,7 @@ func (tdv *TimeOrDurationValue) Set(s string) error { return nil } -// String returns either tume or duration. +// String returns either time or duration. func (tdv *TimeOrDurationValue) String() string { switch { case tdv.Time != nil: diff --git a/pkg/store/prometheus.go b/pkg/store/prometheus.go index 4012eceb9c..ff690e47e8 100644 --- a/pkg/store/prometheus.go +++ b/pkg/store/prometheus.go @@ -12,8 +12,10 @@ import ( "net/url" "path" "sort" + "strconv" "strings" "sync" + "time" "github.com/go-kit/kit/log" "github.com/go-kit/kit/log/level" @@ -23,6 +25,7 @@ import ( "github.com/pkg/errors" "github.com/prometheus/common/version" "github.com/prometheus/prometheus/pkg/labels" + "github.com/prometheus/prometheus/pkg/timestamp" "github.com/prometheus/prometheus/prompb" "github.com/prometheus/prometheus/storage/remote" "github.com/prometheus/prometheus/tsdb/chunkenc" @@ -662,9 +665,9 @@ func (p *PrometheusStore) seriesLabels(ctx context.Context, matchers []storepb.L } q.Add("match[]", metric) + q.Add("start", formatTime(timestamp.Time(startTime))) + q.Add("end", formatTime(timestamp.Time(endTime))) u.RawQuery = q.Encode() - q.Add("start", string(startTime)) - q.Add("end", string(endTime)) req, err := http.NewRequest("GET", u.String(), nil) if err != nil { @@ -714,3 +717,7 @@ func (p *PrometheusStore) seriesLabels(ctx context.Context, matchers []storepb.L return m.Data, nil } + +func formatTime(t time.Time) string { + return strconv.FormatFloat(float64(t.Unix())+float64(t.Nanosecond())/1e9, 'f', -1, 64) +} diff --git a/pkg/store/prometheus_test.go b/pkg/store/prometheus_test.go index 5db3ee75cc..9cbce21c70 100644 --- a/pkg/store/prometheus_test.go +++ b/pkg/store/prometheus_test.go @@ -198,6 +198,8 @@ func TestPrometheusStore_SeriesLabels_e2e(t *testing.T) { testutil.Ok(t, err) _, err = a.Add(labels.FromStrings("a", "d", "job", "test"), baseT+300, 3) testutil.Ok(t, err) + _, err = a.Add(labels.FromStrings("job", "test"), baseT+400, 4) + testutil.Ok(t, err) testutil.Ok(t, a.Commit()) ctx, cancel := context.WithCancel(context.Background()) @@ -208,14 +210,13 @@ func TestPrometheusStore_SeriesLabels_e2e(t *testing.T) { u, err := url.Parse(fmt.Sprintf("http://%s", p.Addr())) testutil.Ok(t, err) - limitMinT := int64(0) - proxy, err := NewPrometheusStore(nil, nil, u, component.Sidecar, + promStore, err := NewPrometheusStore(nil, nil, u, component.Sidecar, func() labels.Labels { return labels.FromStrings("region", "eu-west") }, - func() (int64, int64) { return limitMinT, -1 }) // Maxt does not matter. + func() (int64, int64) { return math.MinInt64/1000 + 62135596801, math.MaxInt64/1000 - 62135596801 }) testutil.Ok(t, err) { - res, err := proxy.seriesLabels(ctx, []storepb.LabelMatcher{ + res, err := promStore.seriesLabels(ctx, []storepb.LabelMatcher{ {Type: storepb.LabelMatcher_EQ, Name: "a", Value: "b"}, }, baseT, baseT+300) testutil.Ok(t, err) @@ -224,7 +225,7 @@ func TestPrometheusStore_SeriesLabels_e2e(t *testing.T) { testutil.Equals(t, labels.FromMap(res[0]), labels.Labels{{Name: "a", Value: "b"}}) } { - res, err := proxy.seriesLabels(ctx, []storepb.LabelMatcher{ + res, err := promStore.seriesLabels(ctx, []storepb.LabelMatcher{ {Type: storepb.LabelMatcher_EQ, Name: "job", Value: "foo"}, }, baseT, baseT+300) testutil.Ok(t, err) @@ -232,7 +233,7 @@ func TestPrometheusStore_SeriesLabels_e2e(t *testing.T) { testutil.Equals(t, len(res), 0) } { - res, err := proxy.seriesLabels(ctx, []storepb.LabelMatcher{ + res, err := promStore.seriesLabels(ctx, []storepb.LabelMatcher{ {Type: storepb.LabelMatcher_NEQ, Name: "a", Value: "b"}, {Type: storepb.LabelMatcher_EQ, Name: "job", Value: "test"}, }, baseT, baseT+300) @@ -246,7 +247,7 @@ func TestPrometheusStore_SeriesLabels_e2e(t *testing.T) { } } { - res, err := proxy.seriesLabels(ctx, []storepb.LabelMatcher{ + res, err := promStore.seriesLabels(ctx, []storepb.LabelMatcher{ {Type: storepb.LabelMatcher_EQ, Name: "job", Value: "test"}, }, baseT, baseT+300) testutil.Ok(t, err) @@ -258,6 +259,29 @@ func TestPrometheusStore_SeriesLabels_e2e(t *testing.T) { testutil.Equals(t, labels.FromMap(r).Get("job"), "test") } } + { + res, err := promStore.seriesLabels(ctx, []storepb.LabelMatcher{ + {Type: storepb.LabelMatcher_EQ, Name: "job", Value: "test"}, + }, baseT+400, baseT+400) + testutil.Ok(t, err) + + // In baseT + 400 we can just get one series. + testutil.Equals(t, len(res), 1) + testutil.Equals(t, len(res[0]), 1) + testutil.Equals(t, labels.FromMap(res[0]).Get("job"), "test") + } + // This test case is to test when start time and end time is not specified. + { + minTime, maxTime := promStore.timestamps() + res, err := promStore.seriesLabels(ctx, []storepb.LabelMatcher{ + {Type: storepb.LabelMatcher_EQ, Name: "job", Value: "test"}, + }, minTime, maxTime) + testutil.Ok(t, err) + testutil.Equals(t, len(res), 3) + for _, r := range res { + testutil.Equals(t, labels.FromMap(r).Get("job"), "test") + } + } } func TestPrometheusStore_LabelValues_e2e(t *testing.T) {