From 7a5ef78c04e4c36260f98052a335bff4eade7407 Mon Sep 17 00:00:00 2001 From: Dylan Guedes Date: Mon, 2 Mar 2026 07:36:43 -0300 Subject: [PATCH] fix(querytee): Compare parsed labels instead of structured metadata (#21018) --- .../comparator/response_comparator.go | 2 +- .../comparator/response_comparator_test.go | 70 +++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/pkg/querytee/comparator/response_comparator.go b/pkg/querytee/comparator/response_comparator.go index 9c81d48b98..1f59628897 100644 --- a/pkg/querytee/comparator/response_comparator.go +++ b/pkg/querytee/comparator/response_comparator.go @@ -459,7 +459,7 @@ func compareStreams(expectedRaw, actualRaw json.RawMessage, evaluationTime time. return &ComparisonSummary{MismatchCause: CauseParsedLabelsCountMismatch}, fmt.Errorf("expected %d parsed label pairs for timestamp %v but got %d pairs for stream %s: %w", expectedSamplePair.Parsed.Len(), expectedSamplePair.Timestamp.UnixNano(), actualSamplePair.Parsed.Len(), expectedStream.Labels, ErrComparisonMismatch) } - if !labels.Equal(expectedSamplePair.StructuredMetadata, actualSamplePair.StructuredMetadata) { + if !labels.Equal(expectedSamplePair.Parsed, actualSamplePair.Parsed) { return &ComparisonSummary{MismatchCause: CauseParsedLabelsMismatch}, fmt.Errorf("expected parsed labels %v for timestamp %v but got %v for stream %s: %w", expectedSamplePair.Parsed.String(), expectedSamplePair.Timestamp.UnixNano(), actualSamplePair.Parsed.String(), expectedStream.Labels, ErrComparisonMismatch) } diff --git a/pkg/querytee/comparator/response_comparator_test.go b/pkg/querytee/comparator/response_comparator_test.go index 04f1edb7ec..9263e33396 100644 --- a/pkg/querytee/comparator/response_comparator_test.go +++ b/pkg/querytee/comparator/response_comparator_test.go @@ -632,6 +632,76 @@ func TestCompareStreams(t *testing.T) { } } +func TestCompareStreams_ParsedLabels(t *testing.T) { + for _, tc := range []struct { + name string + expected json.RawMessage + actual json.RawMessage + err error + expectMismatch bool + mismatchCause string + }{ + { + name: "matching parsed labels", + expected: json.RawMessage(`[ + {"stream":{"foo":"bar"},"values":[["1","line1",{"structuredMetadata":{"trace":"123"},"parsed":{"level":"info"}}]]} + ]`), + actual: json.RawMessage(`[ + {"stream":{"foo":"bar"},"values":[["1","line1",{"structuredMetadata":{"trace":"123"},"parsed":{"level":"info"}}]]} + ]`), + }, + { + name: "different parsed labels count", + expected: json.RawMessage(`[ + {"stream":{"foo":"bar"},"values":[["1","line1",{"structuredMetadata":{"trace":"123"},"parsed":{"level":"info","msg":"hello"}}]]} + ]`), + actual: json.RawMessage(`[ + {"stream":{"foo":"bar"},"values":[["1","line1",{"structuredMetadata":{"trace":"123"},"parsed":{"level":"info"}}]]} + ]`), + err: errors.New("expected 2 parsed label pairs for timestamp 1 but got 1 pairs for stream"), + expectMismatch: true, + mismatchCause: CauseParsedLabelsCountMismatch, + }, + { + name: "different parsed labels values", + expected: json.RawMessage(`[ + {"stream":{"foo":"bar"},"values":[["1","line1",{"structuredMetadata":{"trace":"123"},"parsed":{"level":"info"}}]]} + ]`), + actual: json.RawMessage(`[ + {"stream":{"foo":"bar"},"values":[["1","line1",{"structuredMetadata":{"trace":"123"},"parsed":{"level":"error"}}]]} + ]`), + err: errors.New("expected parsed labels"), + expectMismatch: true, + mismatchCause: CauseParsedLabelsMismatch, + }, + { + name: "same structured metadata but different parsed labels", + expected: json.RawMessage(`[ + {"stream":{"foo":"bar"},"values":[["1","line1",{"structuredMetadata":{"trace":"123"},"parsed":{"level":"info"}}]]} + ]`), + actual: json.RawMessage(`[ + {"stream":{"foo":"bar"},"values":[["1","line1",{"structuredMetadata":{"trace":"123"},"parsed":{"level":"warn"}}]]} + ]`), + err: errors.New("expected parsed labels"), + expectMismatch: true, + mismatchCause: CauseParsedLabelsMismatch, + }, + } { + t.Run(tc.name, func(t *testing.T) { + summary, err := compareStreams(tc.expected, tc.actual, time.Now(), SampleComparisonOptions{}) + if tc.err == nil { + require.NoError(t, err) + return + } + assertError(t, err, tc.err, tc.expectMismatch) + if tc.mismatchCause != "" { + require.NotNil(t, summary) + require.Equal(t, tc.mismatchCause, summary.MismatchCause) + } + }) + } +} + func TestCompareStreams_SamplesOutsideComparableWindow(t *testing.T) { for _, tc := range []struct { name string