Compare commits

...

1 Commits

Author SHA1 Message Date
Kristina Demeshchik
f1b63e4d29 add migration loggers when json drops by more thatn 20% 2026-01-06 16:19:22 -05:00
2 changed files with 39 additions and 0 deletions

View File

@@ -1,6 +1,7 @@
package conversion
import (
"encoding/json"
"errors"
"fmt"
@@ -82,6 +83,17 @@ type dashboardStats struct {
annotationCount int
linkCount int
variableCount int
jsonSize int
}
// getJSONSize returns the size of an object when serialized to JSON
// This is a generic way to detect content loss without knowing the specific structure
func getJSONSize(v interface{}) int {
data, err := json.Marshal(v)
if err != nil {
return 0
}
return len(data)
}
// countPanelsV0V1 counts panels in v0alpha1 or v1beta1 dashboard spec (unstructured JSON)
@@ -238,6 +250,7 @@ func collectStatsV0V1(spec map[string]interface{}) dashboardStats {
annotationCount: countAnnotationsV0V1(spec),
linkCount: countLinksV0V1(spec),
variableCount: countVariablesV0V1(spec),
jsonSize: getJSONSize(spec),
}
}
@@ -289,6 +302,7 @@ func collectStatsV2alpha1(spec dashv2alpha1.DashboardSpec) dashboardStats {
annotationCount: countAnnotationsV2(spec.Annotations),
linkCount: countLinksV2(spec.Links),
variableCount: countVariablesV2(spec.Variables),
jsonSize: getJSONSize(spec),
}
}
@@ -340,6 +354,7 @@ func collectStatsV2beta1(spec dashv2beta1.DashboardSpec) dashboardStats {
annotationCount: countAnnotationsV2beta1(spec.Annotations),
linkCount: countLinksV2beta1(spec.Links),
variableCount: countVariablesV2beta1(spec.Variables),
jsonSize: getJSONSize(spec),
}
}
@@ -400,6 +415,20 @@ func detectConversionDataLoss(sourceStats, targetStats dashboardStats, sourceFun
))
}
// JSON size: detect significant decrease (>20%) which may indicate content loss
// This catches cases like text panel content being replaced with defaults
if sourceStats.jsonSize > 0 && targetStats.jsonSize > 0 {
decreasePercent := float64(sourceStats.jsonSize-targetStats.jsonSize) / float64(sourceStats.jsonSize) * 100
if decreasePercent > 20 {
errors = append(errors, fmt.Sprintf(
"JSON size decreased significantly: source=%d bytes, target=%d bytes (%.1f%% decrease, possible content loss)",
sourceStats.jsonSize,
targetStats.jsonSize,
decreasePercent,
))
}
}
if len(errors) > 0 {
errorMsg := fmt.Sprintf("%v", errors)
// Note: sourceAPIVersion and targetAPIVersion are passed from checkConversionDataLoss

View File

@@ -189,6 +189,8 @@ func withConversionMetrics(sourceVersionAPI, targetVersionAPI string, conversion
"annotationsLost", math.Max(0, float64(sourceStats.annotationCount-targetStats.annotationCount)),
"linksLost", math.Max(0, float64(sourceStats.linkCount-targetStats.linkCount)),
"variablesLost", math.Max(0, float64(sourceStats.variableCount-targetStats.variableCount)),
"sourceJSONSize", sourceStats.jsonSize,
"targetJSONSize", targetStats.jsonSize,
)
}
@@ -222,11 +224,19 @@ func withConversionMetrics(sourceVersionAPI, targetVersionAPI string, conversion
).Inc()
// Log success (debug level to avoid spam)
// Collect stats for logging
sourceStats := collectDashboardStats(a)
targetStats := collectDashboardStats(b)
// Build base log fields for success
successLogFields := []interface{}{
"sourceVersionAPI", sourceVersionAPI,
"targetVersionAPI", targetVersionAPI,
"dashboardUID", dashboardUID,
"panelCount", targetStats.panelCount,
"queryCount", targetStats.queryCount,
"sourceJsonSize", sourceStats.jsonSize,
"targetJsonSize", targetStats.jsonSize,
}
// Add schema version fields only if we have them (v0/v1 dashboards)