From 20e71ec08ae6a5cdc621e2807e9728fb78c1e8b6 Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Mon, 3 Jul 2023 13:30:37 +0530 Subject: [PATCH] fix: add support for {max/min/avg} of rate (#2951) --- .../app/metrics/v3/query_builder.go | 8 ++- .../app/metrics/v3/query_builder_test.go | 53 +++++++++++++++++++ 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/pkg/query-service/app/metrics/v3/query_builder.go b/pkg/query-service/app/metrics/v3/query_builder.go index dc5aadb618..780fbd3b89 100644 --- a/pkg/query-service/app/metrics/v3/query_builder.go +++ b/pkg/query-service/app/metrics/v3/query_builder.go @@ -37,6 +37,10 @@ var aggregateOperatorToSQLFunc = map[v3.AggregateOperator]string{ v3.AggregateOperatorRateAvg: "avg", v3.AggregateOperatorRateMax: "max", v3.AggregateOperatorRateMin: "min", + v3.AggregateOperatorSumRate: "sum", + v3.AggregateOperatorAvgRate: "avg", + v3.AggregateOperatorMaxRate: "max", + v3.AggregateOperatorMinRate: "min", } // See https://github.com/SigNoz/signoz/issues/2151#issuecomment-1467249056 @@ -212,7 +216,7 @@ func buildMetricQuery(start, end, step int64, mq *v3.BuilderQuery, tableName str query = fmt.Sprintf(query, "labels as fullLabels,", subQuery) return query, nil - case v3.AggregateOperatorSumRate: + case v3.AggregateOperatorSumRate, v3.AggregateOperatorAvgRate, v3.AggregateOperatorMaxRate, v3.AggregateOperatorMinRate: rateGroupBy := "fingerprint, " + groupBy rateGroupTags := "fingerprint, " + groupTags rateOrderBy := "fingerprint, " + orderBy @@ -222,7 +226,7 @@ func buildMetricQuery(start, end, step int64, mq *v3.BuilderQuery, tableName str ) // labels will be same so any should be fine query := `SELECT %s ts, ` + rateWithoutNegative + `as value FROM(%s) WHERE isNaN(value) = 0` query = fmt.Sprintf(query, groupTags, subQuery) - query = fmt.Sprintf(`SELECT %s ts, sum(value) as value FROM (%s) GROUP BY %s ORDER BY %s ts`, groupTags, query, groupBy, orderBy) + query = fmt.Sprintf(`SELECT %s ts, %s(value) as value FROM (%s) GROUP BY %s ORDER BY %s ts`, groupTags, aggregateOperatorToSQLFunc[mq.AggregateOperator], query, groupBy, orderBy) return query, nil case v3.AggregateOperatorRateSum, diff --git a/pkg/query-service/app/metrics/v3/query_builder_test.go b/pkg/query-service/app/metrics/v3/query_builder_test.go index ff35ed15f2..b07a788855 100644 --- a/pkg/query-service/app/metrics/v3/query_builder_test.go +++ b/pkg/query-service/app/metrics/v3/query_builder_test.go @@ -234,3 +234,56 @@ func TestBuildQueryOperators(t *testing.T) { }) } } + +func TestBuildQueryXRate(t *testing.T) { + t.Run("TestBuildQueryXRate", func(t *testing.T) { + + tmpl := `SELECT ts, %s(value) as value FROM (SELECT ts, if (runningDifference(value) < 0 OR runningDifference(ts) < 0, nan, runningDifference(value)/runningDifference(ts))as value FROM(SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(timestamp_ms, 1000)), INTERVAL 0 SECOND) as ts, max(value) as value FROM signoz_metrics.distributed_samples_v2 GLOBAL INNER JOIN (SELECT fingerprint FROM signoz_metrics.distributed_time_series_v2 WHERE metric_name = 'name') as filtered_time_series USING fingerprint WHERE metric_name = 'name' AND timestamp_ms >= 1650991982000 AND timestamp_ms <= 1651078382000 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WHERE isNaN(value) = 0) GROUP BY ts ORDER BY ts` + + cases := []struct { + aggregateOperator v3.AggregateOperator + expectedQuery string + }{ + { + aggregateOperator: v3.AggregateOperatorAvgRate, + expectedQuery: fmt.Sprintf(tmpl, aggregateOperatorToSQLFunc[v3.AggregateOperatorAvgRate]), + }, + { + aggregateOperator: v3.AggregateOperatorMaxRate, + expectedQuery: fmt.Sprintf(tmpl, aggregateOperatorToSQLFunc[v3.AggregateOperatorMaxRate]), + }, + { + aggregateOperator: v3.AggregateOperatorMinRate, + expectedQuery: fmt.Sprintf(tmpl, aggregateOperatorToSQLFunc[v3.AggregateOperatorMinRate]), + }, + { + aggregateOperator: v3.AggregateOperatorSumRate, + expectedQuery: fmt.Sprintf(tmpl, aggregateOperatorToSQLFunc[v3.AggregateOperatorSumRate]), + }, + } + + for _, c := range cases { + + q := &v3.QueryRangeParamsV3{ + Start: 1650991982000, + End: 1651078382000, + Step: 60, + CompositeQuery: &v3.CompositeQuery{ + BuilderQueries: map[string]*v3.BuilderQuery{ + "A": { + QueryName: "A", + AggregateAttribute: v3.AttributeKey{Key: "name"}, + AggregateOperator: c.aggregateOperator, + Expression: "A", + }, + }, + QueryType: v3.QueryTypeBuilder, + PanelType: v3.PanelTypeGraph, + }, + } + query, err := PrepareMetricQuery(q.Start, q.End, q.CompositeQuery.QueryType, q.CompositeQuery.PanelType, q.CompositeQuery.BuilderQueries["A"]) + require.NoError(t, err) + require.Equal(t, query, c.expectedQuery) + } + }) +}