Compare commits

..

14 Commits

Author SHA1 Message Date
Naman Verma
c293310c93 fix: keep just a generic validation for space agg 2026-03-02 09:19:26 +05:30
Naman Verma
eac86bb51d fix: keep just a generic validation for space agg 2026-03-02 09:18:39 +05:30
Naman Verma
72c0cbaa0b fix: remove validation on time agg 2026-03-02 09:02:00 +05:30
Naman Verma
e8866057b5 Merge branch 'main' into nv/4074 2026-03-02 08:57:57 +05:30
Naman Verma
28661c8520 Merge branch 'main' into nv/4074 2026-02-27 09:30:43 +05:30
Naman Verma
60a02f7806 Merge branch 'main' into nv/4074 2026-02-26 17:29:17 +05:30
Naman Verma
404976b725 fix: wrong number changed earlier 2026-02-26 14:19:09 +05:30
Naman Verma
21e31bb157 test: cumulative histogram unit test should show start ts decrease by step interval 2026-02-26 14:10:10 +05:30
Naman Verma
40a3c7b919 test: pass time aggregation in histogram unit tests 2026-02-26 14:05:50 +05:30
Naman Verma
f80cdb71e3 Merge branch 'main' into nv/4074 2026-02-26 13:52:23 +05:30
Naman Verma
e6e484accf Merge branch 'main' into nv/4074 2026-02-26 13:40:15 +05:30
Naman Verma
fe3dfa5821 chore: check for orig time and space agg for histograms 2026-02-26 13:36:12 +05:30
Naman Verma
16e8245a1f chore: better error messages based on metric type 2026-02-26 13:34:54 +05:30
Naman Verma
22169487b1 fix: add validity check for spatial aggregation 2026-02-26 13:07:21 +05:30
5 changed files with 25 additions and 14 deletions

View File

@@ -242,9 +242,6 @@ func (q *promqlQuery) Execute(ctx context.Context) (*qbv5.Result, error) {
var s qbv5.TimeSeries
lbls := make([]*qbv5.Label, 0, len(v.Metric))
for name, value := range v.Metric.Copy().Map() {
if strings.HasPrefix(name, "__") || name == "fingerprint" {
continue
}
lbls = append(lbls, &qbv5.Label{
Key: telemetrytypes.TelemetryFieldKey{Name: name},
Value: value,

View File

@@ -5,7 +5,6 @@ import (
"fmt"
"log/slog"
"github.com/SigNoz/signoz/pkg/errors"
"github.com/SigNoz/signoz/pkg/factory"
"github.com/SigNoz/signoz/pkg/flagger"
"github.com/SigNoz/signoz/pkg/querybuilder"
@@ -523,13 +522,6 @@ func (b *MetricQueryStatementBuilder) buildSpatialAggregationCTE(
query qbtypes.QueryBuilderQuery[qbtypes.MetricAggregation],
_ map[string][]*telemetrytypes.TelemetryFieldKey,
) (string, []any, error) {
if query.Aggregations[0].SpaceAggregation.IsZero() {
return "", nil, errors.Newf(
errors.TypeInvalidInput,
errors.CodeInvalidInput,
"invalid space aggregation, should be one of the following: [`sum`, `avg`, `min`, `max`, `count`, `p50`, `p75`, `p90`, `p95`, `p99`]",
)
}
sb := sqlbuilder.NewSelectBuilder()
sb.Select("ts")

View File

@@ -122,7 +122,7 @@ func TestStatementBuilder(t *testing.T) {
expectedErr: nil,
},
{
name: "test_histogram_percentile",
name: "test_histogram_percentile1",
requestType: qbtypes.RequestTypeTimeSeries,
query: qbtypes.QueryBuilderQuery[qbtypes.MetricAggregation]{
Signal: telemetrytypes.SignalMetrics,
@@ -132,6 +132,7 @@ func TestStatementBuilder(t *testing.T) {
MetricName: "signoz_latency",
Type: metrictypes.HistogramType,
Temporality: metrictypes.Delta,
TimeAggregation: metrictypes.TimeAggregationRate,
SpaceAggregation: metrictypes.SpaceAggregationPercentile95,
},
},
@@ -187,7 +188,7 @@ func TestStatementBuilder(t *testing.T) {
expectedErr: nil,
},
{
name: "test_histogram_percentile",
name: "test_histogram_percentile2",
requestType: qbtypes.RequestTypeTimeSeries,
query: qbtypes.QueryBuilderQuery[qbtypes.MetricAggregation]{
Signal: telemetrytypes.SignalMetrics,
@@ -197,6 +198,7 @@ func TestStatementBuilder(t *testing.T) {
MetricName: "http_server_duration_bucket",
Type: metrictypes.HistogramType,
Temporality: metrictypes.Cumulative,
TimeAggregation: metrictypes.TimeAggregationRate,
SpaceAggregation: metrictypes.SpaceAggregationPercentile95,
},
},
@@ -211,7 +213,7 @@ func TestStatementBuilder(t *testing.T) {
},
expected: qbtypes.Statement{
Query: "WITH __temporal_aggregation_cte AS (SELECT ts, `service.name`, `le`, multiIf(row_number() OVER rate_window = 1, nan, (per_series_value - lagInFrame(per_series_value, 1) OVER rate_window) < 0, per_series_value / (ts - lagInFrame(ts, 1) OVER rate_window), (per_series_value - lagInFrame(per_series_value, 1) OVER rate_window) / (ts - lagInFrame(ts, 1) OVER rate_window)) AS per_series_value FROM (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), toIntervalSecond(30)) AS ts, `service.name`, `le`, max(value) AS per_series_value FROM signoz_metrics.distributed_samples_v4 AS points INNER JOIN (SELECT fingerprint, JSONExtractString(labels, 'service.name') AS `service.name`, JSONExtractString(labels, 'le') AS `le` FROM signoz_metrics.time_series_v4_6hrs WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli <= ? AND LOWER(temporality) LIKE LOWER(?) AND __normalized = ? GROUP BY fingerprint, `service.name`, `le`) AS filtered_time_series ON points.fingerprint = filtered_time_series.fingerprint WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli < ? GROUP BY fingerprint, ts, `service.name`, `le` ORDER BY fingerprint, ts) WINDOW rate_window AS (PARTITION BY fingerprint ORDER BY fingerprint, ts)), __spatial_aggregation_cte AS (SELECT ts, `service.name`, `le`, sum(per_series_value) AS value FROM __temporal_aggregation_cte WHERE isNaN(per_series_value) = ? GROUP BY ts, `service.name`, `le`) SELECT ts, `service.name`, histogramQuantile(arrayMap(x -> toFloat64(x), groupArray(le)), groupArray(value), 0.950) AS value FROM __spatial_aggregation_cte GROUP BY `service.name`, ts ORDER BY `service.name`, ts",
Args: []any{"http_server_duration_bucket", uint64(1747936800000), uint64(1747983420000), "cumulative", false, "http_server_duration_bucket", uint64(1747947390000), uint64(1747983420000), 0},
Args: []any{"http_server_duration_bucket", uint64(1747936800000), uint64(1747983420000), "cumulative", false, "http_server_duration_bucket", uint64(1747947360000), uint64(1747983420000), 0},
},
expectedErr: nil,
},

View File

@@ -3,6 +3,7 @@ package metrictypes
import (
"database/sql/driver"
"fmt"
"slices"
"strings"
"github.com/SigNoz/signoz/pkg/errors"
@@ -135,6 +136,10 @@ func (t *Type) Scan(src interface{}) error {
return nil
}
func (t Type) IsPercentileSpaceAggregationAllowed() bool {
return t == HistogramType || t == ExpHistogramType || t == SummaryType
}
var (
GaugeType = Type{valuer.NewString("gauge")}
SumType = Type{valuer.NewString("sum")}
@@ -185,6 +190,10 @@ func (TimeAggregation) Enum() []any {
}
}
func (t TimeAggregation) IsValid() bool {
return slices.ContainsFunc(t.Enum(), func(v any) bool { return v == t })
}
type SpaceAggregation struct {
valuer.String
}
@@ -218,6 +227,10 @@ func (SpaceAggregation) Enum() []any {
}
}
func (s SpaceAggregation) IsValid() bool {
return slices.ContainsFunc(s.Enum(), func(v any) bool { return v == s })
}
func (s SpaceAggregation) IsPercentile() bool {
return s == SpaceAggregationPercentile50 ||
s == SpaceAggregationPercentile75 ||

View File

@@ -215,6 +215,13 @@ func (q *QueryBuilderQuery[T]) validateAggregations(requestType RequestType) err
aggId,
)
}
if !v.SpaceAggregation.IsValid() {
return errors.Newf(
errors.TypeInvalidInput,
errors.CodeInvalidInput,
"invalid space aggregation, should be one of the following: [`sum`, `avg`, `min`, `max`, `count`, `p50`, `p75`, `p90`, `p95`, `p99`]",
)
}
case TraceAggregation:
if v.Expression == "" {
aggId := fmt.Sprintf("aggregation #%d", i+1)