github.com/muhammadn/cortex@v1.9.1-0.20220510110439-46bb7000d03d/tools/query-audit/auditor.go (about) 1 package main 2 3 import ( 4 "math" 5 6 "github.com/pkg/errors" 7 "github.com/prometheus/common/model" 8 ) 9 10 // Auditor is a struct for auditing prometheus queries 11 type Auditor struct{} 12 13 // Diff stores a difference between two queries 14 type Diff struct { 15 Series int 16 Diff float64 // avg proportional diff across all series & samples 17 sampleDiffs []float64 // proportional diffs as measured by x/control 18 } 19 20 // Audit audits two prometheus queries 21 func (a *Auditor) Audit(control, x model.Value) (Diff, error) { 22 if x.Type() == model.ValMatrix && control.Type() == model.ValMatrix { 23 return a.auditMatrix(x.(model.Matrix), control.(model.Matrix)) 24 } 25 26 if x.Type() == model.ValVector && control.Type() == model.ValVector { 27 return a.auditVector(x.(model.Vector), control.(model.Vector)) 28 } 29 30 return Diff{}, errors.Errorf("unsupported types for equality: got %s & %s", control.Type().String(), x.Type().String()) 31 } 32 33 func (a *Auditor) auditMatrix(x, y model.Matrix) (diff Diff, err error) { 34 // different # of returned series 35 if len(x) != len(y) { 36 return diff, errors.Errorf("different # of series: control=%d, other=%d", len(x), len(y)) 37 } 38 39 for i := 0; i < len(x); i++ { 40 xSeries, ySeries := x[i], y[i] 41 if !xSeries.Metric.Equal(ySeries.Metric) { 42 return diff, errors.Errorf("mismatched metrics: %v vs %v", xSeries.Metric, ySeries.Metric) 43 } 44 45 xVals, yVals := xSeries.Values, ySeries.Values 46 if len(xVals) != len(yVals) { 47 return diff, errors.Errorf( 48 "mismatched number of samples for series %v. control=%d, other=%d", 49 xSeries.Metric, 50 len(xVals), 51 len(yVals), 52 ) 53 } 54 55 for j := 0; j < len(xVals); j++ { 56 xSample, ySample := xVals[j], yVals[j] 57 58 if xSample.Timestamp != ySample.Timestamp { 59 return diff, errors.Errorf( 60 "mismatched timestamp for %d sample of series %v. control=%d, other=%d", 61 j, 62 xSeries.Metric, 63 xSample.Timestamp, 64 ySample.Timestamp, 65 ) 66 } 67 68 absDiff := math.Abs(float64(ySample.Value-xSample.Value)) / math.Abs(float64(xSample.Value)) 69 70 // 0/0 -> no diff 71 if math.IsNaN(absDiff) { 72 absDiff = 0 73 } 74 75 diff.sampleDiffs = append(diff.sampleDiffs, absDiff) 76 77 } 78 } 79 80 diff.Series = len(x) 81 var avgDiffProportion float64 82 for _, d := range diff.sampleDiffs { 83 avgDiffProportion += d 84 } 85 diff.Diff = avgDiffProportion / float64(len(diff.sampleDiffs)) 86 87 return diff, nil 88 } 89 90 func (a *Auditor) auditVector(x, y model.Vector) (Diff, error) { 91 return Diff{}, errors.New("unimplemented") 92 }