Skip to content

Commit a217a55

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 a217a55

11 files changed

+1108
-626
lines changed

receiver/prometheusreceiver/metrics_receiver_helper_test.go

Lines changed: 128 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)
426439
})
427440
}
428441

@@ -437,75 +450,152 @@ 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) {
454+
metricExpectations = append(metricExpectations, []metricExpectation{
455+
{
456+
"scrape_duration_seconds",
457+
pmetric.MetricTypeGauge,
458+
"s",
459+
nil,
460+
nil,
461+
},
462+
{
463+
"scrape_samples_post_metric_relabeling",
464+
pmetric.MetricTypeGauge,
465+
"",
466+
nil,
467+
nil,
468+
},
469+
{
470+
"scrape_samples_scraped",
471+
pmetric.MetricTypeGauge,
472+
"",
473+
nil,
474+
nil,
475+
},
476+
{
477+
"scrape_series_added",
478+
pmetric.MetricTypeGauge,
479+
"",
480+
nil,
481+
nil,
482+
},
483+
{
484+
"up",
485+
pmetric.MetricTypeGauge,
486+
"",
487+
nil,
488+
nil,
489+
},
490+
}...)
491+
492+
allMetrics := getMetrics(got)
493+
for _, me := range metricExpectations {
494+
id := fmt.Sprintf("name '%s' type '%s' unit '%s'", me.name, me.mtype.String(), me.munit)
495+
pos := -1
496+
for k, m := range allMetrics {
497+
if me.name != m.Name() || me.mtype != m.Type() || me.munit != m.Unit() {
446498
continue
447499
}
448500

449-
present = true
450-
metricTypeExpectations(t, m)
451-
metricUnitExpectations(t, m)
452-
for i, de := range dataPointExpectations {
501+
require.Equal(t, -1, pos, "metric %s is not unique", id)
502+
pos = k
503+
504+
for i, de := range me.dataPointExpectations {
453505
switch m.Type() {
454506
case pmetric.MetricTypeGauge:
455507
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)
508+
require.Len(t, me.dataPointExpectations, m.Gauge().DataPoints().Len(), "Expected number of data-points in Gauge metric '%s' does not match to testdata", id)
457509
npc(t, m.Gauge().DataPoints().At(i))
458510
}
459511
case pmetric.MetricTypeSum:
460512
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)
513+
require.Len(t, me.dataPointExpectations, m.Sum().DataPoints().Len(), "Expected number of data-points in Sum metric '%s' does not match to testdata", id)
462514
npc(t, m.Sum().DataPoints().At(i))
463515
}
464516
case pmetric.MetricTypeHistogram:
465517
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)
518+
require.Len(t, me.dataPointExpectations, m.Histogram().DataPoints().Len(), "Expected number of data-points in Histogram metric '%s' does not match to testdata", id)
467519
hpc(t, m.Histogram().DataPoints().At(i))
468520
}
469521
case pmetric.MetricTypeSummary:
470522
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)
523+
require.Len(t, me.dataPointExpectations, m.Summary().DataPoints().Len(), "Expected number of data-points in Summary metric '%s' does not match to testdata", id)
472524
spc(t, m.Summary().DataPoints().At(i))
473525
}
474526
case pmetric.MetricTypeExponentialHistogram:
475527
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)
528+
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)
477529
ehc(t, m.ExponentialHistogram().DataPoints().At(i))
478530
}
479531
case pmetric.MetricTypeEmpty:
480532
}
481533
}
534+
535+
if me.extraExpectation != nil {
536+
me.extraExpectation(t, m)
537+
}
482538
}
483-
require.True(t, present, "expected metric '%s' is not present", name)
539+
require.GreaterOrEqual(t, pos, 0, "expected metric %s is not present", id)
540+
allMetrics = append(allMetrics[:pos], allMetrics[pos+1:]...)
541+
}
542+
543+
remainingMetrics := []string{}
544+
for _, m := range allMetrics {
545+
remainingMetrics = append(remainingMetrics, fmt.Sprintf("%s(%s,%s)", m.Name(), m.Type().String(), m.Unit()))
484546
}
547+
548+
require.Len(t, allMetrics, 0, "not all metrics were validated: %v", strings.Join(remainingMetrics, ", "))
485549
}
486550

487-
func assertMetricAbsent(name string) testExpectation {
551+
func assertMetricPresent(name string, mtype pmetric.MetricType, munit string, dataPointExpectations []dataPointExpectation) testExpectation {
488552
return func(t *testing.T, rm pmetric.ResourceMetrics) {
553+
id := fmt.Sprintf("name '%s' type '%s' unit '%s'", name, mtype.String(), munit)
554+
489555
allMetrics := getMetrics(rm)
556+
var present bool
490557
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-
}
558+
if name != m.Name() || mtype != m.Type() || munit != m.Unit() {
559+
continue
560+
}
501561

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")
562+
present = true
563+
for i, de := range dataPointExpectations {
564+
switch m.Type() {
565+
case pmetric.MetricTypeGauge:
566+
for _, npc := range de.numberPointComparator {
567+
require.Len(t, dataPointExpectations, m.Gauge().DataPoints().Len(), "Expected number of data-points in Gauge metric '%s' does not match to testdata", id)
568+
npc(t, m.Gauge().DataPoints().At(i))
569+
}
570+
case pmetric.MetricTypeSum:
571+
for _, npc := range de.numberPointComparator {
572+
require.Len(t, dataPointExpectations, m.Sum().DataPoints().Len(), "Expected number of data-points in Sum metric '%s' does not match to testdata", id)
573+
npc(t, m.Sum().DataPoints().At(i))
574+
}
575+
case pmetric.MetricTypeHistogram:
576+
for _, hpc := range de.histogramPointComparator {
577+
require.Len(t, dataPointExpectations, m.Histogram().DataPoints().Len(), "Expected number of data-points in Histogram metric '%s' does not match to testdata", id)
578+
hpc(t, m.Histogram().DataPoints().At(i))
579+
}
580+
case pmetric.MetricTypeSummary:
581+
for _, spc := range de.summaryPointComparator {
582+
require.Len(t, dataPointExpectations, m.Summary().DataPoints().Len(), "Expected number of data-points in Summary metric '%s' does not match to testdata", id)
583+
spc(t, m.Summary().DataPoints().At(i))
584+
}
585+
case pmetric.MetricTypeExponentialHistogram:
586+
for _, ehc := range de.exponentialHistogramComparator {
587+
require.Len(t, dataPointExpectations, m.ExponentialHistogram().DataPoints().Len(), "Expected number of data-points in Exponential Histogram metric '%s' does not match to testdata", id)
588+
ehc(t, m.ExponentialHistogram().DataPoints().At(i))
589+
}
590+
case pmetric.MetricTypeEmpty:
591+
}
592+
}
593+
}
594+
require.True(t, present, "expected metric %s is not present", id)
505595
}
506596
}
507597

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

0 commit comments

Comments
 (0)