Compare commits

...

1 Commits

Author SHA1 Message Date
Naman Verma
934f5f4ad3 fix: add meter source during migration 2026-07-29 13:20:44 +05:30
2 changed files with 52 additions and 1 deletions

View File

@@ -189,7 +189,9 @@ func (d *v1Decoder) collectV1QueryEnvelopes(widget map[string]any, panelKind Pan
queries = dropUnrenderableQueries(queries)
for _, q := range queries {
name := d.readString(q, "queryName")
out = append(out, qb.WrapInV5Envelope(name, q, string(qb.QueryTypeBuilder.StringValue())))
env := qb.WrapInV5Envelope(name, q, string(qb.QueryTypeBuilder.StringValue()))
carryQuerySource(env, q)
out = append(out, env)
if signal.IsZero() {
signal = signalFromDataSource(q["dataSource"])
}
@@ -446,3 +448,16 @@ func signalFromDataSource(raw any) telemetrytypes.Signal {
}
return telemetrytypes.Signal{}
}
// carryQuerySource copies a v1 builder query's meter source onto the v5 spec.
// WrapInV5Envelope maps dataSource→signal but ignores the separate `source` field, so a
// meter query (dataSource metrics + source "meter") would otherwise migrate as plain
// metrics and read the wrong data. Only "meter" is carried through — the sole non-empty
// source the v1 UI produces and v5 accepts; anything else stays unspecified.
func carryQuerySource(env, query map[string]any) {
if source, _ := query["source"].(string); source == telemetrytypes.SourceMeter.StringValue() {
if spec, ok := env["spec"].(map[string]any); ok {
spec["source"] = source
}
}
}

View File

@@ -10,6 +10,7 @@ import (
"github.com/SigNoz/signoz/pkg/types/coretypes"
qb "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
"github.com/SigNoz/signoz/pkg/types/tagtypes"
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
"github.com/SigNoz/signoz/pkg/valuer"
"github.com/perses/spec/go/dashboard"
"github.com/perses/spec/go/dashboard/variable"
@@ -1779,6 +1780,41 @@ func TestConvertV1WidgetQueryRewritesUnknownMetricValueOrderKey(t *testing.T) {
assert.Equal(t, "service.name", spec.Order[1].Key.Name, "valid group-by order key left alone")
}
// A v1 meter query is dataSource "metrics" with a separate source "meter". The signal
// maps to metrics, and the meter source must survive onto the v5 spec — otherwise the
// panel migrates as a plain metrics query and reads the wrong data.
func TestConvertV1WidgetQueryCarriesMeterSource(t *testing.T) {
widget := map[string]any{
"id": "meter-1",
"panelTypes": "graph",
"query": map[string]any{
"queryType": "builder",
"builder": map[string]any{
"queryData": []any{
map[string]any{
"queryName": "A",
"expression": "A",
"dataSource": "metrics",
"source": "meter",
"aggregations": []any{map[string]any{"metricName": "signoz.meter.log.size", "spaceAggregation": "sum"}},
},
},
},
},
}
queries := (&v1Decoder{}).convertV1WidgetQuery(widget, PanelKindTimeSeries)
require.Len(t, queries, 1)
wrapper, ok := queries[0].Spec.Plugin.Spec.(*BuilderQuerySpec)
require.True(t, ok)
spec, ok := wrapper.Spec.(qb.QueryBuilderQuery[qb.MetricAggregation])
require.True(t, ok, "meter query should dispatch to MetricAggregation, got %T", wrapper.Spec)
assert.Equal(t, telemetrytypes.SignalMetrics, spec.Signal, "signal maps from dataSource")
assert.Equal(t, telemetrytypes.SourceMeter, spec.Source, "meter source carried onto the v5 spec")
}
func TestConvertV1WidgetQueryInjectsCountForNoopOnAggregationPanel(t *testing.T) {
// A logs query with the list-style "noop" operator placed on an aggregation
// panel (graph). createAggregationsShapeSafe drops noop, leaving no aggregation;