Skip to content

Commit bd02848

Browse files
authored
chore: add sql migration for dashboards, alerts, and saved views (#8642)
## 📄 Summary To reliably migrate the alerts and dashboards, we need access to the telemetrystore to fetch some metadata and while doing migration, I need to log some stuff to fix stuff later. Key changes: - Modified the migration to include telemetrystore and a logging provider (open to using a standard logger instead) - To avoid the previous issues with imported dashboards failing during migration, I've ensured that imported JSON files are automatically transformed when migration is active - Implemented detailed logic to handle dashboard migration cleanly and prevent unnecessary errors - Separated the core migration logic from SQL migration code, as users from the dot metrics migration requested shareable code snippets for local migrations. This modular approach allows others to easily reuse the migration functionality. Known: I didn't register the migration yet in this PR, and will not merge this yet, so please review with that in mid.
1 parent b5016b0 commit bd02848

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+2241
-218
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ require (
7070
go.uber.org/zap v1.27.0
7171
golang.org/x/crypto v0.39.0
7272
golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac
73+
golang.org/x/net v0.41.0
7374
golang.org/x/oauth2 v0.30.0
7475
golang.org/x/sync v0.15.0
7576
golang.org/x/text v0.26.0
@@ -283,7 +284,6 @@ require (
283284
go.uber.org/atomic v1.11.0 // indirect
284285
go.uber.org/goleak v1.3.0 // indirect
285286
golang.org/x/mod v0.25.0 // indirect
286-
golang.org/x/net v0.41.0 // indirect
287287
golang.org/x/sys v0.33.0 // indirect
288288
golang.org/x/time v0.11.0 // indirect
289289
golang.org/x/tools v0.33.0 // indirect

pkg/apis/fields/api.go

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,15 +63,15 @@ func (api *API) GetFieldsKeys(w http.ResponseWriter, r *http.Request) {
6363
return
6464
}
6565

66-
keys, err := api.telemetryMetadataStore.GetKeys(ctx, fieldKeySelector)
66+
keys, complete, err := api.telemetryMetadataStore.GetKeys(ctx, fieldKeySelector)
6767
if err != nil {
6868
render.Error(w, err)
6969
return
7070
}
7171

7272
response := fieldKeysResponse{
7373
Keys: keys,
74-
Complete: len(keys) < fieldKeySelector.Limit,
74+
Complete: complete,
7575
}
7676

7777
render.Success(w, http.StatusOK, response)
@@ -94,13 +94,13 @@ func (api *API) GetFieldsValues(w http.ResponseWriter, r *http.Request) {
9494
return
9595
}
9696

97-
allValues, err := api.telemetryMetadataStore.GetAllValues(ctx, fieldValueSelector)
97+
allValues, allComplete, err := api.telemetryMetadataStore.GetAllValues(ctx, fieldValueSelector)
9898
if err != nil {
9999
render.Error(w, err)
100100
return
101101
}
102102

103-
relatedValues, err := api.telemetryMetadataStore.GetRelatedValues(ctx, fieldValueSelector)
103+
relatedValues, relatedComplete, err := api.telemetryMetadataStore.GetRelatedValues(ctx, fieldValueSelector)
104104
if err != nil {
105105
// we don't want to return error if we fail to get related values for some reason
106106
relatedValues = []string{}
@@ -113,11 +113,8 @@ func (api *API) GetFieldsValues(w http.ResponseWriter, r *http.Request) {
113113
}
114114

115115
response := fieldValuesResponse{
116-
Values: values,
117-
Complete: len(values.StringValues) < fieldValueSelector.Limit &&
118-
len(values.BoolValues) < fieldValueSelector.Limit &&
119-
len(values.NumberValues) < fieldValueSelector.Limit &&
120-
len(values.RelatedValues) < fieldValueSelector.Limit,
116+
Values: values,
117+
Complete: allComplete && relatedComplete,
121118
}
122119

123120
render.Success(w, http.StatusOK, response)

pkg/modules/dashboard/impldashboard/handler.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,24 @@ import (
77
"time"
88

99
"github.com/SigNoz/signoz/pkg/errors"
10+
"github.com/SigNoz/signoz/pkg/factory"
1011
"github.com/SigNoz/signoz/pkg/http/render"
1112
"github.com/SigNoz/signoz/pkg/modules/dashboard"
13+
"github.com/SigNoz/signoz/pkg/querybuilder"
14+
"github.com/SigNoz/signoz/pkg/transition"
1215
"github.com/SigNoz/signoz/pkg/types/authtypes"
1316
"github.com/SigNoz/signoz/pkg/types/dashboardtypes"
1417
"github.com/SigNoz/signoz/pkg/valuer"
1518
"github.com/gorilla/mux"
1619
)
1720

1821
type handler struct {
19-
module dashboard.Module
22+
module dashboard.Module
23+
providerSettings factory.ProviderSettings
2024
}
2125

22-
func NewHandler(module dashboard.Module) dashboard.Handler {
23-
return &handler{module: module}
26+
func NewHandler(module dashboard.Module, providerSettings factory.ProviderSettings) dashboard.Handler {
27+
return &handler{module: module, providerSettings: providerSettings}
2428
}
2529

2630
func (handler *handler) Create(rw http.ResponseWriter, r *http.Request) {
@@ -46,6 +50,13 @@ func (handler *handler) Create(rw http.ResponseWriter, r *http.Request) {
4650
return
4751
}
4852

53+
if querybuilder.QBV5Enabled {
54+
dashboardMigrator := transition.NewDashboardMigrateV5(handler.providerSettings.Logger, nil, nil)
55+
if req["version"] != "v5" {
56+
dashboardMigrator.Migrate(ctx, req)
57+
}
58+
}
59+
4960
dashboard, err := handler.module.Create(ctx, orgID, claims.Email, valuer.MustNewUUID(claims.UserID), req)
5061
if err != nil {
5162
render.Error(rw, err)

pkg/querier/querier.go

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ func (q *querier) run(
387387
}
388388
}
389389

390-
resp.Warning = qbtypes.QueryWarnData{
390+
resp.Warning = &qbtypes.QueryWarnData{
391391
Message: "Encountered warnings",
392392
Url: warningsDocURL,
393393
Warnings: warns,
@@ -501,23 +501,36 @@ func (q *querier) executeWithCache(ctx context.Context, orgID valuer.UUID, query
501501

502502
// createRangedQuery creates a copy of the query with a different time range
503503
func (q *querier) createRangedQuery(originalQuery qbtypes.Query, timeRange qbtypes.TimeRange) qbtypes.Query {
504+
// this is called in a goroutine, so we create a copy of the query to avoid race conditions
504505
switch qt := originalQuery.(type) {
505506
case *promqlQuery:
506-
return newPromqlQuery(q.logger, q.promEngine, qt.query, timeRange, qt.requestType, qt.vars)
507+
queryCopy := qt.query.Copy()
508+
return newPromqlQuery(q.logger, q.promEngine, queryCopy, timeRange, qt.requestType, qt.vars)
509+
507510
case *chSQLQuery:
508-
return newchSQLQuery(q.logger, q.telemetryStore, qt.query, qt.args, timeRange, qt.kind, qt.vars)
511+
queryCopy := qt.query.Copy()
512+
argsCopy := make([]any, len(qt.args))
513+
copy(argsCopy, qt.args)
514+
return newchSQLQuery(q.logger, q.telemetryStore, queryCopy, argsCopy, timeRange, qt.kind, qt.vars)
515+
509516
case *builderQuery[qbtypes.TraceAggregation]:
510-
qt.spec.ShiftBy = extractShiftFromBuilderQuery(qt.spec)
511-
adjustedTimeRange := adjustTimeRangeForShift(qt.spec, timeRange, qt.kind)
512-
return newBuilderQuery(q.telemetryStore, q.traceStmtBuilder, qt.spec, adjustedTimeRange, qt.kind, qt.variables)
517+
specCopy := qt.spec.Copy()
518+
specCopy.ShiftBy = extractShiftFromBuilderQuery(specCopy)
519+
adjustedTimeRange := adjustTimeRangeForShift(specCopy, timeRange, qt.kind)
520+
return newBuilderQuery(q.telemetryStore, q.traceStmtBuilder, specCopy, adjustedTimeRange, qt.kind, qt.variables)
521+
513522
case *builderQuery[qbtypes.LogAggregation]:
514-
qt.spec.ShiftBy = extractShiftFromBuilderQuery(qt.spec)
515-
adjustedTimeRange := adjustTimeRangeForShift(qt.spec, timeRange, qt.kind)
516-
return newBuilderQuery(q.telemetryStore, q.logStmtBuilder, qt.spec, adjustedTimeRange, qt.kind, qt.variables)
523+
specCopy := qt.spec.Copy()
524+
specCopy.ShiftBy = extractShiftFromBuilderQuery(specCopy)
525+
adjustedTimeRange := adjustTimeRangeForShift(specCopy, timeRange, qt.kind)
526+
return newBuilderQuery(q.telemetryStore, q.logStmtBuilder, specCopy, adjustedTimeRange, qt.kind, qt.variables)
527+
517528
case *builderQuery[qbtypes.MetricAggregation]:
518-
qt.spec.ShiftBy = extractShiftFromBuilderQuery(qt.spec)
519-
adjustedTimeRange := adjustTimeRangeForShift(qt.spec, timeRange, qt.kind)
520-
return newBuilderQuery(q.telemetryStore, q.metricStmtBuilder, qt.spec, adjustedTimeRange, qt.kind, qt.variables)
529+
specCopy := qt.spec.Copy()
530+
specCopy.ShiftBy = extractShiftFromBuilderQuery(specCopy)
531+
adjustedTimeRange := adjustTimeRangeForShift(specCopy, timeRange, qt.kind)
532+
return newBuilderQuery(q.telemetryStore, q.metricStmtBuilder, specCopy, adjustedTimeRange, qt.kind, qt.variables)
533+
521534
default:
522535
return nil
523536
}

pkg/query-service/rules/threshold_rule.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,11 @@ func (r *ThresholdRule) buildAndRunQueryV5(ctx context.Context, orgID valuer.UUI
543543
return resultVector, nil
544544
}
545545

546+
if queryResult == nil {
547+
r.logger.WarnContext(ctx, "query result is nil", "rule_name", r.Name(), "query_name", selectedQuery)
548+
return resultVector, nil
549+
}
550+
546551
for _, series := range queryResult.Series {
547552
smpl, shouldAlert := r.ShouldAlert(*series)
548553
if shouldAlert {

pkg/query-service/tests/integration/filter_suggestions_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ func NewFilterSuggestionsTestBed(t *testing.T) *FilterSuggestionsTestBed {
318318
emailing := emailingtest.New()
319319
analytics := analyticstest.New()
320320
modules := signoz.NewModules(testDB, jwt, emailing, providerSettings, orgGetter, alertmanager, analytics)
321-
handlers := signoz.NewHandlers(modules)
321+
handlers := signoz.NewHandlers(modules, providerSettings)
322322

323323
apiHandler, err := app.NewAPIHandler(app.APIHandlerOpts{
324324
Reader: reader,

pkg/query-service/tests/integration/logparsingpipeline_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ func NewTestbedWithoutOpamp(t *testing.T, sqlStore sqlstore.SQLStore) *LogPipeli
498498
emailing := emailingtest.New()
499499
analytics := analyticstest.New()
500500
modules := signoz.NewModules(sqlStore, jwt, emailing, providerSettings, orgGetter, alertmanager, analytics)
501-
handlers := signoz.NewHandlers(modules)
501+
handlers := signoz.NewHandlers(modules, providerSettings)
502502

503503
apiHandler, err := app.NewAPIHandler(app.APIHandlerOpts{
504504
LogsParsingPipelineController: controller,

pkg/query-service/tests/integration/signoz_cloud_integrations_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ func NewCloudIntegrationsTestBed(t *testing.T, testDB sqlstore.SQLStore) *CloudI
379379
emailing := emailingtest.New()
380380
analytics := analyticstest.New()
381381
modules := signoz.NewModules(testDB, jwt, emailing, providerSettings, orgGetter, alertmanager, analytics)
382-
handlers := signoz.NewHandlers(modules)
382+
handlers := signoz.NewHandlers(modules, providerSettings)
383383

384384
apiHandler, err := app.NewAPIHandler(app.APIHandlerOpts{
385385
Reader: reader,

pkg/query-service/tests/integration/signoz_integrations_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,7 @@ func NewIntegrationsTestBed(t *testing.T, testDB sqlstore.SQLStore) *Integration
594594
emailing := emailingtest.New()
595595
analytics := analyticstest.New()
596596
modules := signoz.NewModules(testDB, jwt, emailing, providerSettings, orgGetter, alertmanager, analytics)
597-
handlers := signoz.NewHandlers(modules)
597+
handlers := signoz.NewHandlers(modules, providerSettings)
598598

599599
apiHandler, err := app.NewAPIHandler(app.APIHandlerOpts{
600600
Reader: reader,

pkg/querybuilder/init.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package querybuilder
2+
3+
import (
4+
"os"
5+
"strings"
6+
)
7+
8+
var QBV5Enabled = false
9+
10+
func init() {
11+
v := os.Getenv("ENABLE_QB_V5")
12+
if strings.ToLower(v) == "true" || strings.ToLower(v) == "1" {
13+
QBV5Enabled = true
14+
}
15+
}

0 commit comments

Comments
 (0)