mirror of
https://github.com/grafana/loki.git
synced 2026-03-13 09:33:58 +08:00
fix(goldfish): support nulls in mismatch_cause (#21082)
mismatch_cause can be NULL, in this case goldfish ui API (e.g., /ui/api/v1/goldfish/queries) will return {"error":"failed to retrieve sampled queries"} due to a failure of converting NULL to string value.
This commit is contained in:
@@ -301,9 +301,9 @@ func (s *MySQLStorage) GetSampledQueries(ctx context.Context, page, pageSize int
|
||||
var cellAResultURI, cellBResultURI sql.NullString
|
||||
var cellAResultCompression, cellBResultCompression sql.NullString
|
||||
var cellAResultSize, cellBResultSize sql.NullInt64
|
||||
var mismatchCause sql.NullString
|
||||
|
||||
err := rows.Scan(
|
||||
|
||||
&q.CorrelationID, &q.TenantID, &q.User, &q.Issuer, &q.Query, &q.QueryType, &q.StartTime, &q.EndTime, &stepDurationMs,
|
||||
&q.CellAStats.ExecTimeMs, &q.CellBStats.ExecTimeMs, &q.CellAStats.QueueTimeMs, &q.CellBStats.QueueTimeMs,
|
||||
&q.CellAStats.BytesProcessed, &q.CellBStats.BytesProcessed, &q.CellAStats.LinesProcessed, &q.CellBStats.LinesProcessed,
|
||||
@@ -318,7 +318,7 @@ func (s *MySQLStorage) GetSampledQueries(ctx context.Context, page, pageSize int
|
||||
&cellASpanID, &cellBSpanID,
|
||||
&q.CellAUsedNewEngine, &q.CellBUsedNewEngine,
|
||||
&q.SampledAt, &createdAt,
|
||||
&q.ComparisonStatus, &q.MatchWithinTolerance, &q.MismatchCause,
|
||||
&q.ComparisonStatus, &q.MatchWithinTolerance, &mismatchCause,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -349,6 +349,9 @@ func (s *MySQLStorage) GetSampledQueries(ctx context.Context, page, pageSize int
|
||||
if cellBResultCompression.Valid {
|
||||
q.CellBResultCompression = cellBResultCompression.String
|
||||
}
|
||||
if mismatchCause.Valid {
|
||||
q.MismatchCause = mismatchCause.String
|
||||
}
|
||||
|
||||
// Convert step duration from milliseconds to Duration
|
||||
q.Step = time.Duration(stepDurationMs) * time.Millisecond
|
||||
@@ -405,6 +408,7 @@ func (s *MySQLStorage) GetQueryByCorrelationID(ctx context.Context, correlationI
|
||||
var cellAResultURI, cellBResultURI sql.NullString
|
||||
var cellAResultCompression, cellBResultCompression sql.NullString
|
||||
var cellAResultSize, cellBResultSize sql.NullInt64
|
||||
var mismatchCause sql.NullString
|
||||
|
||||
err := s.db.QueryRowContext(ctx, query, correlationID).Scan(
|
||||
&q.CorrelationID, &q.TenantID, &q.User, &q.Issuer, &q.Query, &q.QueryType, &q.StartTime, &q.EndTime, &stepDurationMs,
|
||||
@@ -420,7 +424,7 @@ func (s *MySQLStorage) GetQueryByCorrelationID(ctx context.Context, correlationI
|
||||
&q.CellATraceID, &q.CellBTraceID,
|
||||
&cellASpanID, &cellBSpanID,
|
||||
&q.CellAUsedNewEngine, &q.CellBUsedNewEngine,
|
||||
&q.SampledAt, &createdAt, &q.ComparisonStatus, &q.MatchWithinTolerance, &q.MismatchCause,
|
||||
&q.SampledAt, &createdAt, &q.ComparisonStatus, &q.MatchWithinTolerance, &mismatchCause,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
@@ -455,6 +459,9 @@ func (s *MySQLStorage) GetQueryByCorrelationID(ctx context.Context, correlationI
|
||||
if cellBResultCompression.Valid {
|
||||
q.CellBResultCompression = cellBResultCompression.String
|
||||
}
|
||||
if mismatchCause.Valid {
|
||||
q.MismatchCause = mismatchCause.String
|
||||
}
|
||||
|
||||
// Convert step duration from milliseconds to Duration
|
||||
q.Step = time.Duration(stepDurationMs) * time.Millisecond
|
||||
|
||||
@@ -101,6 +101,7 @@ type SampledQuery struct {
|
||||
// Comparison outcome - computed by backend logic
|
||||
ComparisonStatus string `json:"comparisonStatus" db:"comparison_status"`
|
||||
MatchWithinTolerance bool `json:"matchWithinTolerance" db:"match_within_tolerance"`
|
||||
MismatchCause string `json:"mismatchCause" db:"mismatch_cause"`
|
||||
|
||||
// UI-only fields - generated based on configuration, not stored in database
|
||||
CellATraceLink *string `json:"cellATraceLink,omitempty"`
|
||||
@@ -258,6 +259,7 @@ func (s *Service) GetSampledQueriesWithContext(ctx context.Context, page, pageSi
|
||||
// Use comparison status and match within tolerance from database
|
||||
uiQuery.ComparisonStatus = string(q.ComparisonStatus)
|
||||
uiQuery.MatchWithinTolerance = q.MatchWithinTolerance
|
||||
uiQuery.MismatchCause = q.MismatchCause
|
||||
|
||||
// Add trace ID explore links if explore is configured
|
||||
if s.cfg.Goldfish.GrafanaURL != "" && s.cfg.Goldfish.TracesDatasourceUID != "" {
|
||||
|
||||
@@ -105,6 +105,7 @@ func TestSampledQueryJSONMarshaling(t *testing.T) {
|
||||
CellATraceLink: strPtr("https://grafana.com/explore?trace-a"),
|
||||
CellBTraceLink: strPtr("https://grafana.com/explore?trace-b"),
|
||||
ComparisonStatus: "mismatch",
|
||||
MismatchCause: "stream_entry_count_mismatch",
|
||||
}
|
||||
|
||||
// Marshal to JSON
|
||||
@@ -122,6 +123,7 @@ func TestSampledQueryJSONMarshaling(t *testing.T) {
|
||||
require.Equal(t, "{job=\"test\"}", result["query"])
|
||||
require.Equal(t, "range", result["queryType"])
|
||||
require.Equal(t, "mismatch", result["comparisonStatus"])
|
||||
require.Equal(t, "stream_entry_count_mismatch", result["mismatchCause"])
|
||||
|
||||
// Verify performance stats are flattened
|
||||
require.Equal(t, float64(100), result["cellAExecTimeMs"])
|
||||
|
||||
Reference in New Issue
Block a user