Skip to content

Commit 09cbd64

Browse files
committed
refactor(receiver/prometheusreceiver): use type and unit as identifier in test
I'd like to fix a technical dept from open-telemetry#28663 where the Promtheus reveiver didn't allow receiving both classic and native histogram for the same metric name. To test the implementation, the assertions must not assume that the metric name alone is identifying in OpenTelemetry. No new tests added, I just refactored to make name+type+unit the identifier. Also I made it implicit that doCompare fails on metrics not expected - excluding the 5 scrape metrics. Signed-off-by: György Krajcsovits <[email protected]>
1 parent c232180 commit 09cbd64

11 files changed

+1151
-626
lines changed

receiver/prometheusreceiver/metrics_receiver_helper_test.go

Lines changed: 171 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"net/http"
1414
"net/http/httptest"
1515
"net/url"
16+
"strings"
1617
"sync"
1718
"sync/atomic"
1819
"testing"
@@ -396,7 +397,6 @@ func isExtraScrapeMetrics(m pmetric.Metric) bool {
396397
}
397398

398399
type (
399-
metricTypeComparator func(*testing.T, pmetric.Metric)
400400
numberPointComparator func(*testing.T, pmetric.NumberDataPoint)
401401
histogramPointComparator func(*testing.T, pmetric.HistogramDataPoint)
402402
summaryPointComparator func(*testing.T, pmetric.SummaryDataPoint)
@@ -410,19 +410,32 @@ type dataPointExpectation struct {
410410
exponentialHistogramComparator []exponentialHistogramComparator
411411
}
412412

413+
type metricChecker func(*testing.T, pmetric.Metric)
414+
415+
type metricExpectation struct {
416+
name string
417+
mtype pmetric.MetricType
418+
munit string
419+
dataPointExpectations []dataPointExpectation
420+
extraExpectation func(*testing.T, pmetric.Metric)
421+
}
422+
413423
type testExpectation func(*testing.T, pmetric.ResourceMetrics)
414424

415-
func doCompare(t *testing.T, name string, want pcommon.Map, got pmetric.ResourceMetrics, expectations []testExpectation) {
416-
doCompareNormalized(t, name, want, got, expectations, false)
425+
// doCompare is a helper function to compare the expected metrics with the actual metrics
426+
// name is the test name
427+
// want is the map of expected attributes
428+
// got is the actual metrics
429+
// metricExpections is the list of expected metrics, exluding the internal scrape metrics
430+
func doCompare(t *testing.T, name string, want pcommon.Map, got pmetric.ResourceMetrics, metricExpectations []metricExpectation) {
431+
doCompareNormalized(t, name, want, got, metricExpectations, false)
417432
}
418433

419-
func doCompareNormalized(t *testing.T, name string, want pcommon.Map, got pmetric.ResourceMetrics, expectations []testExpectation, normalizedNames bool) {
434+
func doCompareNormalized(t *testing.T, name string, want pcommon.Map, got pmetric.ResourceMetrics, metricExpectations []metricExpectation, normalizedNames bool) {
420435
t.Run(name, func(t *testing.T) {
421436
assert.Equal(t, expectedScrapeMetricCount, countScrapeMetricsRM(got, normalizedNames))
422437
assertExpectedAttributes(t, want, got)
423-
for _, e := range expectations {
424-
e(t, got)
425-
}
438+
assertExpectedMetrics(t, metricExpectations, got, normalizedNames)
426439
})
427440
}
428441

@@ -437,75 +450,195 @@ func assertExpectedAttributes(t *testing.T, want pcommon.Map, got pmetric.Resour
437450
}
438451
}
439452

440-
func assertMetricPresent(name string, metricTypeExpectations metricTypeComparator, metricUnitExpectations metricTypeComparator, dataPointExpectations []dataPointExpectation) testExpectation {
441-
return func(t *testing.T, rm pmetric.ResourceMetrics) {
442-
allMetrics := getMetrics(rm)
443-
var present bool
444-
for _, m := range allMetrics {
445-
if name != m.Name() {
453+
func assertExpectedMetrics(t *testing.T, metricExpectations []metricExpectation, got pmetric.ResourceMetrics, normalizedNames bool) {
454+
var defaultExpectations []metricExpectation
455+
if normalizedNames {
456+
defaultExpectations = []metricExpectation{
457+
{
458+
"scrape_duration",
459+
pmetric.MetricTypeGauge,
460+
"s",
461+
nil,
462+
nil,
463+
},
464+
{
465+
"scrape_samples_post_metric_relabeling",
466+
pmetric.MetricTypeGauge,
467+
"",
468+
nil,
469+
nil,
470+
},
471+
{
472+
"scrape_samples_scraped",
473+
pmetric.MetricTypeGauge,
474+
"",
475+
nil,
476+
nil,
477+
},
478+
{
479+
"scrape_series_added",
480+
pmetric.MetricTypeGauge,
481+
"",
482+
nil,
483+
nil,
484+
},
485+
{
486+
"up",
487+
pmetric.MetricTypeGauge,
488+
"",
489+
nil,
490+
nil,
491+
},
492+
}
493+
} else {
494+
defaultExpectations = []metricExpectation{
495+
{
496+
"scrape_duration_seconds",
497+
pmetric.MetricTypeGauge,
498+
"s",
499+
nil,
500+
nil,
501+
},
502+
{
503+
"scrape_samples_post_metric_relabeling",
504+
pmetric.MetricTypeGauge,
505+
"",
506+
nil,
507+
nil,
508+
},
509+
{
510+
"scrape_samples_scraped",
511+
pmetric.MetricTypeGauge,
512+
"",
513+
nil,
514+
nil,
515+
},
516+
{
517+
"scrape_series_added",
518+
pmetric.MetricTypeGauge,
519+
"",
520+
nil,
521+
nil,
522+
},
523+
{
524+
"up",
525+
pmetric.MetricTypeGauge,
526+
"",
527+
nil,
528+
nil,
529+
},
530+
}
531+
}
532+
533+
metricExpectations = append(defaultExpectations, metricExpectations...)
534+
535+
allMetrics := getMetrics(got)
536+
for _, me := range metricExpectations {
537+
id := fmt.Sprintf("name '%s' type '%s' unit '%s'", me.name, me.mtype.String(), me.munit)
538+
pos := -1
539+
for k, m := range allMetrics {
540+
if me.name != m.Name() || me.mtype != m.Type() || me.munit != m.Unit() {
446541
continue
447542
}
448543

449-
present = true
450-
metricTypeExpectations(t, m)
451-
metricUnitExpectations(t, m)
452-
for i, de := range dataPointExpectations {
544+
require.Equal(t, -1, pos, "metric %s is not unique", id)
545+
pos = k
546+
547+
for i, de := range me.dataPointExpectations {
453548
switch m.Type() {
454549
case pmetric.MetricTypeGauge:
455550
for _, npc := range de.numberPointComparator {
456-
require.Len(t, dataPointExpectations, m.Gauge().DataPoints().Len(), "Expected number of data-points in Gauge metric '%s' does not match to testdata", name)
551+
require.Len(t, me.dataPointExpectations, m.Gauge().DataPoints().Len(), "Expected number of data-points in Gauge metric '%s' does not match to testdata", id)
457552
npc(t, m.Gauge().DataPoints().At(i))
458553
}
459554
case pmetric.MetricTypeSum:
460555
for _, npc := range de.numberPointComparator {
461-
require.Len(t, dataPointExpectations, m.Sum().DataPoints().Len(), "Expected number of data-points in Sum metric '%s' does not match to testdata", name)
556+
require.Len(t, me.dataPointExpectations, m.Sum().DataPoints().Len(), "Expected number of data-points in Sum metric '%s' does not match to testdata", id)
462557
npc(t, m.Sum().DataPoints().At(i))
463558
}
464559
case pmetric.MetricTypeHistogram:
465560
for _, hpc := range de.histogramPointComparator {
466-
require.Len(t, dataPointExpectations, m.Histogram().DataPoints().Len(), "Expected number of data-points in Histogram metric '%s' does not match to testdata", name)
561+
require.Len(t, me.dataPointExpectations, m.Histogram().DataPoints().Len(), "Expected number of data-points in Histogram metric '%s' does not match to testdata", id)
467562
hpc(t, m.Histogram().DataPoints().At(i))
468563
}
469564
case pmetric.MetricTypeSummary:
470565
for _, spc := range de.summaryPointComparator {
471-
require.Len(t, dataPointExpectations, m.Summary().DataPoints().Len(), "Expected number of data-points in Summary metric '%s' does not match to testdata", name)
566+
require.Len(t, me.dataPointExpectations, m.Summary().DataPoints().Len(), "Expected number of data-points in Summary metric '%s' does not match to testdata", id)
472567
spc(t, m.Summary().DataPoints().At(i))
473568
}
474569
case pmetric.MetricTypeExponentialHistogram:
475570
for _, ehc := range de.exponentialHistogramComparator {
476-
require.Len(t, dataPointExpectations, m.ExponentialHistogram().DataPoints().Len(), "Expected number of data-points in Exponential Histogram metric '%s' does not match to testdata", name)
571+
require.Len(t, me.dataPointExpectations, m.ExponentialHistogram().DataPoints().Len(), "Expected number of data-points in Exponential Histogram metric '%s' does not match to testdata", id)
477572
ehc(t, m.ExponentialHistogram().DataPoints().At(i))
478573
}
479574
case pmetric.MetricTypeEmpty:
480575
}
481576
}
577+
578+
if me.extraExpectation != nil {
579+
me.extraExpectation(t, m)
580+
}
482581
}
483-
require.True(t, present, "expected metric '%s' is not present", name)
582+
require.GreaterOrEqual(t, pos, 0, "expected metric %s is not present", id)
583+
allMetrics = append(allMetrics[:pos], allMetrics[pos+1:]...)
584+
}
585+
586+
remainingMetrics := []string{}
587+
for _, m := range allMetrics {
588+
remainingMetrics = append(remainingMetrics, fmt.Sprintf("%s(%s,%s)", m.Name(), m.Type().String(), m.Unit()))
484589
}
590+
591+
require.Empty(t, allMetrics, "not all metrics were validated: %v", strings.Join(remainingMetrics, ", "))
485592
}
486593

487-
func assertMetricAbsent(name string) testExpectation {
594+
func assertMetricPresent(name string, mtype pmetric.MetricType, munit string, dataPointExpectations []dataPointExpectation) testExpectation {
488595
return func(t *testing.T, rm pmetric.ResourceMetrics) {
596+
id := fmt.Sprintf("name '%s' type '%s' unit '%s'", name, mtype.String(), munit)
597+
489598
allMetrics := getMetrics(rm)
599+
var present bool
490600
for _, m := range allMetrics {
491-
assert.NotEqual(t, name, m.Name(), "Metric is present, but was expected absent")
492-
}
493-
}
494-
}
495-
496-
func compareMetricType(typ pmetric.MetricType) metricTypeComparator {
497-
return func(t *testing.T, metric pmetric.Metric) {
498-
assert.Equal(t, typ.String(), metric.Type().String(), "Metric type does not match")
499-
}
500-
}
601+
if name != m.Name() || mtype != m.Type() || munit != m.Unit() {
602+
continue
603+
}
501604

502-
func compareMetricUnit(unit string) metricTypeComparator {
503-
return func(t *testing.T, metric pmetric.Metric) {
504-
assert.Equal(t, unit, metric.Unit(), "Metric unit does not match")
605+
present = true
606+
for i, de := range dataPointExpectations {
607+
switch m.Type() {
608+
case pmetric.MetricTypeGauge:
609+
for _, npc := range de.numberPointComparator {
610+
require.Len(t, dataPointExpectations, m.Gauge().DataPoints().Len(), "Expected number of data-points in Gauge metric '%s' does not match to testdata", id)
611+
npc(t, m.Gauge().DataPoints().At(i))
612+
}
613+
case pmetric.MetricTypeSum:
614+
for _, npc := range de.numberPointComparator {
615+
require.Len(t, dataPointExpectations, m.Sum().DataPoints().Len(), "Expected number of data-points in Sum metric '%s' does not match to testdata", id)
616+
npc(t, m.Sum().DataPoints().At(i))
617+
}
618+
case pmetric.MetricTypeHistogram:
619+
for _, hpc := range de.histogramPointComparator {
620+
require.Len(t, dataPointExpectations, m.Histogram().DataPoints().Len(), "Expected number of data-points in Histogram metric '%s' does not match to testdata", id)
621+
hpc(t, m.Histogram().DataPoints().At(i))
622+
}
623+
case pmetric.MetricTypeSummary:
624+
for _, spc := range de.summaryPointComparator {
625+
require.Len(t, dataPointExpectations, m.Summary().DataPoints().Len(), "Expected number of data-points in Summary metric '%s' does not match to testdata", id)
626+
spc(t, m.Summary().DataPoints().At(i))
627+
}
628+
case pmetric.MetricTypeExponentialHistogram:
629+
for _, ehc := range de.exponentialHistogramComparator {
630+
require.Len(t, dataPointExpectations, m.ExponentialHistogram().DataPoints().Len(), "Expected number of data-points in Exponential Histogram metric '%s' does not match to testdata", id)
631+
ehc(t, m.ExponentialHistogram().DataPoints().At(i))
632+
}
633+
case pmetric.MetricTypeEmpty:
634+
}
635+
}
636+
}
637+
require.True(t, present, "expected metric %s is not present", id)
505638
}
506639
}
507640

508-
func compareMetricIsMonotonic(isMonotonic bool) metricTypeComparator {
641+
func compareMetricIsMonotonic(isMonotonic bool) metricChecker {
509642
return func(t *testing.T, metric pmetric.Metric) {
510643
assert.Equal(t, pmetric.MetricTypeSum.String(), metric.Type().String(), "IsMonotonic only exists for sums")
511644
assert.Equal(t, isMonotonic, metric.Sum().IsMonotonic(), "IsMonotonic does not match")

0 commit comments

Comments
 (0)