github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/cmd/querytee/response_comparator.go (about)

     1  package main
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  
     7  	"github.com/go-kit/log/level"
     8  	jsoniter "github.com/json-iterator/go"
     9  
    10  	"github.com/grafana/loki/pkg/loghttp"
    11  	util_log "github.com/grafana/loki/pkg/util/log"
    12  	"github.com/grafana/loki/tools/querytee"
    13  )
    14  
    15  func compareStreams(expectedRaw, actualRaw json.RawMessage, opts querytee.SampleComparisonOptions) error {
    16  	var expected, actual loghttp.Streams
    17  
    18  	err := jsoniter.Unmarshal(expectedRaw, &expected)
    19  	if err != nil {
    20  		return err
    21  	}
    22  	err = jsoniter.Unmarshal(actualRaw, &actual)
    23  	if err != nil {
    24  		return err
    25  	}
    26  
    27  	if len(expected) != len(actual) {
    28  		return fmt.Errorf("expected %d streams but got %d", len(expected), len(actual))
    29  	}
    30  
    31  	streamLabelsToIndexMap := make(map[string]int, len(expected))
    32  	for i, actualStream := range actual {
    33  		streamLabelsToIndexMap[actualStream.Labels.String()] = i
    34  	}
    35  
    36  	for _, expectedStream := range expected {
    37  		actualStreamIndex, ok := streamLabelsToIndexMap[expectedStream.Labels.String()]
    38  		if !ok {
    39  			return fmt.Errorf("expected stream %s missing from actual response", expectedStream.Labels)
    40  		}
    41  
    42  		actualStream := actual[actualStreamIndex]
    43  		expectedValuesLen := len(expectedStream.Entries)
    44  		actualValuesLen := len(actualStream.Entries)
    45  
    46  		if expectedValuesLen != actualValuesLen {
    47  			err := fmt.Errorf("expected %d values for stream %s but got %d", expectedValuesLen,
    48  				expectedStream.Labels, actualValuesLen)
    49  			if expectedValuesLen > 0 && actualValuesLen > 0 {
    50  				level.Error(util_log.Logger).Log("msg", err.Error(), "oldest-expected-ts", expectedStream.Entries[0].Timestamp.UnixNano(),
    51  					"newest-expected-ts", expectedStream.Entries[expectedValuesLen-1].Timestamp.UnixNano(),
    52  					"oldest-actual-ts", actualStream.Entries[0].Timestamp.UnixNano(), "newest-actual-ts", actualStream.Entries[actualValuesLen-1].Timestamp.UnixNano())
    53  			}
    54  			return err
    55  		}
    56  
    57  		for i, expectedSamplePair := range expectedStream.Entries {
    58  			actualSamplePair := actualStream.Entries[i]
    59  			if !expectedSamplePair.Timestamp.Equal(actualSamplePair.Timestamp) {
    60  				return fmt.Errorf("expected timestamp %v but got %v for stream %s", expectedSamplePair.Timestamp.UnixNano(),
    61  					actualSamplePair.Timestamp.UnixNano(), expectedStream.Labels)
    62  			}
    63  			if expectedSamplePair.Line != actualSamplePair.Line {
    64  				return fmt.Errorf("expected line %s for timestamp %v but got %s for stream %s", expectedSamplePair.Line,
    65  					expectedSamplePair.Timestamp.UnixNano(), actualSamplePair.Line, expectedStream.Labels)
    66  			}
    67  		}
    68  	}
    69  
    70  	return nil
    71  }