promtool: Show more human readable got/exp output (#8064)

Avoid using %#v, nothing needs to parse this, so escaping " and so on
leads to hard to read output.

Add new lines, number and indentation to each alert series output.

Signed-off-by: David Leadbeater <dgl@dgl.cx>
This commit is contained in:
David Leadbeater 2021-10-28 22:17:18 +11:00 committed by GitHub
parent 69e309d202
commit c91c2bbea5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -47,6 +47,7 @@ func RulesUnitTest(queryOpts promql.LazyLoaderOpts, files ...string) int {
fmt.Fprintln(os.Stderr, " FAILED:") fmt.Fprintln(os.Stderr, " FAILED:")
for _, e := range errs { for _, e := range errs {
fmt.Fprintln(os.Stderr, e.Error()) fmt.Fprintln(os.Stderr, e.Error())
fmt.Println()
} }
failed = true failed = true
} else { } else {
@ -313,30 +314,18 @@ func (tg *testGroup) test(evalInterval time.Duration, groupOrderMap map[string]i
}) })
} }
var sb strings.Builder
if gotAlerts.Len() != expAlerts.Len() {
if tg.TestGroupName != "" {
fmt.Fprintf(&sb, " name: %s,\n", tg.TestGroupName)
}
fmt.Fprintf(&sb, " alertname:%s, time:%s, \n", testcase.Alertname, testcase.EvalTime.String())
fmt.Fprintf(&sb, " exp:%#v, \n", expAlerts.String())
fmt.Fprintf(&sb, " got:%#v", gotAlerts.String())
errs = append(errs, errors.New(sb.String()))
} else {
sort.Sort(gotAlerts) sort.Sort(gotAlerts)
sort.Sort(expAlerts) sort.Sort(expAlerts)
if !reflect.DeepEqual(expAlerts, gotAlerts) { if !reflect.DeepEqual(expAlerts, gotAlerts) {
var testName string
if tg.TestGroupName != "" { if tg.TestGroupName != "" {
fmt.Fprintf(&sb, " name: %s,\n", tg.TestGroupName) testName = fmt.Sprintf(" name: %s,\n", tg.TestGroupName)
}
fmt.Fprintf(&sb, " alertname:%s, time:%s, \n", testcase.Alertname, testcase.EvalTime.String())
fmt.Fprintf(&sb, " exp:%#v, \n", expAlerts.String())
fmt.Fprintf(&sb, " got:%#v", gotAlerts.String())
errs = append(errs, errors.New(sb.String()))
} }
expString := indentLines(expAlerts.String(), " ")
gotString := indentLines(gotAlerts.String(), " ")
errs = append(errs, errors.Errorf("%s alertname: %s, time: %s, \n exp:%v, \n got:%v",
testName, testcase.Alertname, testcase.EvalTime.String(), expString, gotString))
} }
} }
@ -385,7 +374,7 @@ Outer:
return labels.Compare(gotSamples[i].Labels, gotSamples[j].Labels) <= 0 return labels.Compare(gotSamples[i].Labels, gotSamples[j].Labels) <= 0
}) })
if !reflect.DeepEqual(expSamples, gotSamples) { if !reflect.DeepEqual(expSamples, gotSamples) {
errs = append(errs, errors.Errorf(" expr: %q, time: %s,\n exp:%#v\n got:%#v", testCase.Expr, errs = append(errs, errors.Errorf(" expr: %q, time: %s,\n exp: %v\n got: %v", testCase.Expr,
testCase.EvalTime.String(), parsedSamplesString(expSamples), parsedSamplesString(gotSamples))) testCase.EvalTime.String(), parsedSamplesString(expSamples), parsedSamplesString(gotSamples)))
} }
} }
@ -468,6 +457,23 @@ func query(ctx context.Context, qs string, t time.Time, engine *promql.Engine, q
} }
} }
// indentLines prefixes each line in the supplied string with the given "indent"
// string.
func indentLines(lines, indent string) string {
sb := strings.Builder{}
n := strings.Split(lines, "\n")
for i, l := range n {
if i > 0 {
sb.WriteString(indent)
}
sb.WriteString(l)
if i != len(n)-1 {
sb.WriteRune('\n')
}
}
return sb.String()
}
type labelsAndAnnotations []labelAndAnnotation type labelsAndAnnotations []labelAndAnnotation
func (la labelsAndAnnotations) Len() int { return len(la) } func (la labelsAndAnnotations) Len() int { return len(la) }
@ -484,11 +490,11 @@ func (la labelsAndAnnotations) String() string {
if len(la) == 0 { if len(la) == 0 {
return "[]" return "[]"
} }
s := "[" + la[0].String() s := "[\n0:" + indentLines("\n"+la[0].String(), " ")
for _, l := range la[1:] { for i, l := range la[1:] {
s += ", " + l.String() s += ",\n" + fmt.Sprintf("%d", i+1) + ":" + indentLines("\n"+l.String(), " ")
} }
s += "]" s += "\n]"
return s return s
} }
@ -499,7 +505,7 @@ type labelAndAnnotation struct {
} }
func (la *labelAndAnnotation) String() string { func (la *labelAndAnnotation) String() string {
return "Labels:" + la.Labels.String() + " Annotations:" + la.Annotations.String() return "Labels:" + la.Labels.String() + "\nAnnotations:" + la.Annotations.String()
} }
type series struct { type series struct {