rules: Test native histograms in recording rules
@@ -30,6 +30,7 @@ import (
"go.uber.org/goleak"
"gopkg.in/yaml.v2"
+ "github.com/prometheus/prometheus/model/histogram"
"github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/model/rulefmt"
"github.com/prometheus/prometheus/model/timestamp"
@@ -37,6 +38,7 @@ import (
"github.com/prometheus/prometheus/promql"
"github.com/prometheus/prometheus/promql/parser"
"github.com/prometheus/prometheus/storage"
+ "github.com/prometheus/prometheus/tsdb"
"github.com/prometheus/prometheus/tsdb/chunkenc"
"github.com/prometheus/prometheus/util/teststorage"
)
@@ -1331,3 +1333,68 @@ func TestUpdateMissedEvalMetrics(t *testing.T) {
testFunc(tst)
}
}
+
+func TestNativeHistogramsInRecordingRules(t *testing.T) {
+ suite, err := promql.NewTest(t, "")
+ require.NoError(t, err)
+ t.Cleanup(suite.Close)
+
+ err = suite.Run()
+ require.NoError(t, err)
+
+ // Add some histograms.
+ db := suite.TSDB()
+ hists := tsdb.GenerateTestHistograms(5)
+ ts := time.Now()
+ app := db.Appender(context.Background())
+ for i, h := range hists {
+ l := labels.FromStrings("__name__", "histogram_metric", "idx", fmt.Sprintf("%d", i))
+ _, err := app.AppendHistogram(0, l, ts.UnixMilli(), h.Copy(), nil)
+ require.NoError(t, err)
+ }
+ require.NoError(t, app.Commit())
+
+ opts := &ManagerOptions{
+ QueryFunc: EngineQueryFunc(suite.QueryEngine(), suite.Storage()),
+ Appendable: suite.Storage(),
+ Queryable: suite.Storage(),
+ Context: context.Background(),
+ Logger: log.NewNopLogger(),
+ }
+
+ expr, err := parser.ParseExpr("sum(histogram_metric)")
+ require.NoError(t, err)
+ rule := NewRecordingRule("sum:histogram_metric", expr, labels.Labels{})
+
+ group := NewGroup(GroupOptions{
+ Name: "default",
+ Interval: time.Hour,
+ Rules: []Rule{rule},
+ ShouldRestore: true,
+ Opts: opts,
+ })
+
+ group.Eval(context.Background(), ts.Add(10*time.Second))
+
+ q, err := db.Querier(context.Background(), ts.UnixMilli(), ts.Add(20*time.Second).UnixMilli())
+ require.NoError(t, err)
+ ss := q.Select(false, nil, labels.MustNewMatcher(labels.MatchEqual, "__name__", "sum:histogram_metric"))
+ require.True(t, ss.Next())
+ s := ss.At()
+ require.False(t, ss.Next())
+
+ require.Equal(t, labels.FromStrings("__name__", "sum:histogram_metric"), s.Labels())
+
+ expHist := hists[0].ToFloat()
+ for _, h := range hists[1:] {
+ expHist = expHist.Add(h.ToFloat())
+ }
+ expHist.CounterResetHint = histogram.GaugeType
+
+ it := s.Iterator(nil)
+ require.Equal(t, chunkenc.ValFloatHistogram, it.Next())
+ tsp, fh := it.AtFloatHistogram()
+ require.Equal(t, ts.Add(10*time.Second).UnixMilli(), tsp)
+ require.Equal(t, expHist, fh)
+ require.Equal(t, chunkenc.ValNone, it.Next())
+}
