Skip to content

Commit d751e3e

Browse files
committed
[chore](prometheusreceiver): use type and unit as identifier in tests
I'd like to fix a technical dept from #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 that were not expected - excluding the 5 scrape metrics. This means that assertMetricAbsent is not needed anymore. Signed-off-by: György Krajcsovits <[email protected]>
1 parent e5d5741 commit d751e3e

11 files changed

+1138
-644
lines changed

receiver/prometheusreceiver/metrics_receiver_helper_test.go

Lines changed: 132 additions & 40 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 metricChecker
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, false)
426439
})
427440
}
428441

@@ -437,75 +450,154 @@ 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, existsOnly bool) {
454+
var defaultExpectations []metricExpectation
455+
switch {
456+
case existsOnly:
457+
case normalizedNames:
458+
defaultExpectations = []metricExpectation{
459+
{
460+
"scrape_duration",
461+
pmetric.MetricTypeGauge,
462+
"s",
463+
nil,
464+
nil,
465+
},
466+
{
467+
"scrape_samples_post_metric_relabeling",
468+
pmetric.MetricTypeGauge,
469+
"",
470+
nil,
471+
nil,
472+
},
473+
{
474+
"scrape_samples_scraped",
475+
pmetric.MetricTypeGauge,
476+
"",
477+
nil,
478+
nil,
479+
},
480+
{
481+
"scrape_series_added",
482+
pmetric.MetricTypeGauge,
483+
"",
484+
nil,
485+
nil,
486+
},
487+
{
488+
"up",
489+
pmetric.MetricTypeGauge,
490+
"",
491+
nil,
492+
nil,
493+
},
494+
}
495+
case !normalizedNames:
496+
defaultExpectations = []metricExpectation{
497+
{
498+
"scrape_duration_seconds",
499+
pmetric.MetricTypeGauge,
500+
"s",
501+
nil,
502+
nil,
503+
},
504+
{
505+
"scrape_samples_post_metric_relabeling",
506+
pmetric.MetricTypeGauge,
507+
"",
508+
nil,
509+
nil,
510+
},
511+
{
512+
"scrape_samples_scraped",
513+
pmetric.MetricTypeGauge,
514+
"",
515+
nil,
516+
nil,
517+
},
518+
{
519+
"scrape_series_added",
520+
pmetric.MetricTypeGauge,
521+
"",
522+
nil,
523+
nil,
524+
},
525+
{
526+
"up",
527+
pmetric.MetricTypeGauge,
528+
"",
529+
nil,
530+
nil,
531+
},
532+
}
533+
}
534+
535+
metricExpectations = append(defaultExpectations, metricExpectations...)
536+
537+
allMetrics := getMetrics(got)
538+
for _, me := range metricExpectations {
539+
id := fmt.Sprintf("name '%s' type '%s' unit '%s'", me.name, me.mtype.String(), me.munit)
540+
pos := -1
541+
for k, m := range allMetrics {
542+
if me.name != m.Name() || me.mtype != m.Type() || me.munit != m.Unit() {
446543
continue
447544
}
448545

449-
present = true
450-
metricTypeExpectations(t, m)
451-
metricUnitExpectations(t, m)
452-
for i, de := range dataPointExpectations {
546+
require.Equal(t, -1, pos, "metric %s is not unique", id)
547+
pos = k
548+
549+
for i, de := range me.dataPointExpectations {
453550
switch m.Type() {
454551
case pmetric.MetricTypeGauge:
455552
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)
553+
require.Len(t, me.dataPointExpectations, m.Gauge().DataPoints().Len(), "Expected number of data-points in Gauge metric '%s' does not match to testdata", id)
457554
npc(t, m.Gauge().DataPoints().At(i))
458555
}
459556
case pmetric.MetricTypeSum:
460557
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)
558+
require.Len(t, me.dataPointExpectations, m.Sum().DataPoints().Len(), "Expected number of data-points in Sum metric '%s' does not match to testdata", id)
462559
npc(t, m.Sum().DataPoints().At(i))
463560
}
464561
case pmetric.MetricTypeHistogram:
465562
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)
563+
require.Len(t, me.dataPointExpectations, m.Histogram().DataPoints().Len(), "Expected number of data-points in Histogram metric '%s' does not match to testdata", id)
467564
hpc(t, m.Histogram().DataPoints().At(i))
468565
}
469566
case pmetric.MetricTypeSummary:
470567
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)
568+
require.Len(t, me.dataPointExpectations, m.Summary().DataPoints().Len(), "Expected number of data-points in Summary metric '%s' does not match to testdata", id)
472569
spc(t, m.Summary().DataPoints().At(i))
473570
}
474571
case pmetric.MetricTypeExponentialHistogram:
475572
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)
573+
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)
477574
ehc(t, m.ExponentialHistogram().DataPoints().At(i))
478575
}
479576
case pmetric.MetricTypeEmpty:
480577
}
481578
}
482-
}
483-
require.True(t, present, "expected metric '%s' is not present", name)
484-
}
485-
}
486579

487-
func assertMetricAbsent(name string) testExpectation {
488-
return func(t *testing.T, rm pmetric.ResourceMetrics) {
489-
allMetrics := getMetrics(rm)
490-
for _, m := range allMetrics {
491-
assert.NotEqual(t, name, m.Name(), "Metric is present, but was expected absent")
580+
if me.extraExpectation != nil {
581+
me.extraExpectation(t, m)
582+
}
492583
}
584+
require.GreaterOrEqual(t, pos, 0, "expected metric %s is not present", id)
585+
allMetrics = append(allMetrics[:pos], allMetrics[pos+1:]...)
493586
}
494-
}
495587

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")
588+
if existsOnly {
589+
return
499590
}
500-
}
501591

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")
592+
remainingMetrics := []string{}
593+
for _, m := range allMetrics {
594+
remainingMetrics = append(remainingMetrics, fmt.Sprintf("%s(%s,%s)", m.Name(), m.Type().String(), m.Unit()))
505595
}
596+
597+
require.Empty(t, allMetrics, "not all metrics were validated: %v", strings.Join(remainingMetrics, ", "))
506598
}
507599

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

0 commit comments

Comments
 (0)