mirror of
https://github.com/SigNoz/signoz.git
synced 2026-08-25 05:50:55 +01:00
Some checks failed
build-staging / prepare (push) Has been cancelled
build-staging / js-build (push) Has been cancelled
build-staging / go-build (push) Has been cancelled
build-staging / staging (push) Has been cancelled
cacheci / tests (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
<!--A few plain bullets saying what changed and why, for a reviewer skimming it - not a wall of text, not a restatement of the diff, not generated boilerplate.--> #### Description AWS Cloud Integration's Lambda dashboard was missing FunctionName variable, this PR adds that variable for better UX. <!--Reference issues using `Closes #issue-number` to enable automatic closure on merge. --> #### Issues closed by this PR Closes https://github.com/SigNoz/platform-pod/issues/2988 <!--If applicable, include screenshots or screen recordings that clearly show the behavior before the change and the result after the change. --> #### Screenshots / Screen Recordings <img width="1503" height="815" alt="image" src="https://github.com/user-attachments/assets/56203f8d-1f06-4c39-b3c1-c1dabf028045" /> --------- Co-authored-by: Vikrant Gupta <vikrant@signoz.io>
161 lines
4.5 KiB
Go
161 lines
4.5 KiB
Go
package sqlmigration
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"embed"
|
|
"encoding/json"
|
|
"time"
|
|
|
|
"github.com/SigNoz/signoz/pkg/factory"
|
|
"github.com/uptrace/bun"
|
|
"github.com/uptrace/bun/migrate"
|
|
)
|
|
|
|
//go:embed 116_migrate_lambda_dashboards
|
|
var lambdaDashboardFiles embed.FS
|
|
|
|
// These values mirror the cloud integration and dashboard packages but are duplicated
|
|
// here so this migration keeps targeting and writing the same rows even if those
|
|
// constants are later renamed or changed.
|
|
const (
|
|
lambdaDashboardFile = "116_migrate_lambda_dashboards/aws/lambda/overview.json"
|
|
|
|
lambdaDashboardSlug = "aws-lambda-overview"
|
|
cloudIntegrationDashboardProvider = "cloud_integration"
|
|
integrationDashboardSource = "integration"
|
|
dashboardSchemaVersion = "v6"
|
|
)
|
|
|
|
type migrateLambdaDashboards struct{}
|
|
|
|
type lambdaDashboardRow struct {
|
|
bun.BaseModel `bun:"table:dashboard,alias:dashboard"`
|
|
|
|
ID string `bun:"id"`
|
|
Data string `bun:"data"`
|
|
}
|
|
|
|
// lambdaDashboardDefinition is the part of the embedded dashboard this migration reads:
|
|
// its spec, which is what the cloud integration stores under data.spec.
|
|
type lambdaDashboardDefinition struct {
|
|
Spec map[string]any `json:"spec"`
|
|
}
|
|
|
|
func NewMigrateLambdaDashboardsFactory() factory.ProviderFactory[SQLMigration, Config] {
|
|
return factory.NewProviderFactory(
|
|
factory.MustNewName("migrate_lambda_dashboards"),
|
|
func(ctx context.Context, ps factory.ProviderSettings, c Config) (SQLMigration, error) {
|
|
return &migrateLambdaDashboards{}, nil
|
|
},
|
|
)
|
|
}
|
|
|
|
func (m *migrateLambdaDashboards) Register(migrations *migrate.Migrations) error {
|
|
return migrations.Register(m.Up, m.Down)
|
|
}
|
|
|
|
// Up rewrites the spec of every provisioned AWS Lambda overview dashboard to the
|
|
// embedded revision that added the FunctionName variable. Cloud integration dashboards
|
|
// are provisioned once and never updated afterwards, so existing installs only pick up
|
|
// this change through a migration. Only the spec is replaced; the row keeps its id, name,
|
|
// tags and metadata, so the dashboard is updated in place rather than recreated.
|
|
func (m *migrateLambdaDashboards) Up(ctx context.Context, db *bun.DB) error {
|
|
spec, err := m.loadSpec()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
tx, err := db.BeginTx(ctx, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer func() { _ = tx.Rollback() }()
|
|
|
|
var rows []*lambdaDashboardRow
|
|
if err := tx.NewSelect().
|
|
Model(&rows).
|
|
Join("JOIN integration_dashboard AS id ON id.dashboard_id = dashboard.id").
|
|
Where("id.provider = ?", cloudIntegrationDashboardProvider).
|
|
Where("id.slug = ?", lambdaDashboardSlug).
|
|
Where("dashboard.source = ?", integrationDashboardSource).
|
|
Scan(ctx); err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, row := range rows {
|
|
data := map[string]any{}
|
|
if err := json.Unmarshal([]byte(row.Data), &data); err != nil {
|
|
return err
|
|
}
|
|
|
|
// The embedded spec is v6-shaped, so only rewrite a row already carrying a v6 spec;
|
|
// anything else is left alone rather than turned into a broken mix of versions.
|
|
if !m.hasV6Spec(data) {
|
|
continue
|
|
}
|
|
data["spec"] = spec
|
|
|
|
encoded, err := m.marshalUnescaped(data)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// Skip rows already carrying this spec so a re-run does not needlessly rewrite them.
|
|
if string(encoded) == row.Data {
|
|
continue
|
|
}
|
|
|
|
if _, err := tx.NewUpdate().
|
|
Model((*lambdaDashboardRow)(nil)).
|
|
Set("data = ?", string(encoded)).
|
|
Set("updated_at = ?", time.Now()).
|
|
Where("id = ?", row.ID).
|
|
Exec(ctx); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return tx.Commit()
|
|
}
|
|
|
|
func (m *migrateLambdaDashboards) Down(context.Context, *bun.DB) error {
|
|
return nil
|
|
}
|
|
|
|
// hasV6Spec reports whether the stored data is a v6 dashboard with a spec object, which
|
|
// is the shape whose spec this migration replaces.
|
|
func (m *migrateLambdaDashboards) hasV6Spec(data map[string]any) bool {
|
|
metadata, _ := data["metadata"].(map[string]any)
|
|
version, _ := metadata["schemaVersion"].(string)
|
|
if version != dashboardSchemaVersion {
|
|
return false
|
|
}
|
|
_, ok := data["spec"].(map[string]any)
|
|
return ok
|
|
}
|
|
|
|
func (m *migrateLambdaDashboards) marshalUnescaped(v any) ([]byte, error) {
|
|
var buf bytes.Buffer
|
|
encoder := json.NewEncoder(&buf)
|
|
encoder.SetEscapeHTML(false)
|
|
if err := encoder.Encode(v); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return bytes.TrimRight(buf.Bytes(), "\n"), nil
|
|
}
|
|
|
|
func (m *migrateLambdaDashboards) loadSpec() (map[string]any, error) {
|
|
raw, err := lambdaDashboardFiles.ReadFile(lambdaDashboardFile)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var dashboard lambdaDashboardDefinition
|
|
if err := json.Unmarshal(raw, &dashboard); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return dashboard.Spec, nil
|
|
}
|