1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2025-02-03 13:11:53 +02:00

Rewrite Prometheus exporter tests (#4274)

* Remove TesInvalidInsrtrumentForPrometheusIsIgnored

* Reimplement ConcurrentSafe test

* Add TestIncompatibleMeterName
This commit is contained in:
Robert Pająk 2023-07-04 14:58:38 +02:00 committed by GitHub
parent 10c3445543
commit c404a30b96
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 40 additions and 145 deletions

View File

@ -17,19 +17,16 @@ package prometheus
import (
"context"
"os"
"strings"
"sync"
"testing"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/testutil"
dto "github.com/prometheus/client_model/go"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/otel/attribute"
otelmetric "go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/sdk/instrumentation"
"go.opentelemetry.io/otel/sdk/metric"
"go.opentelemetry.io/otel/sdk/metric/aggregation"
"go.opentelemetry.io/otel/sdk/resource"
@ -677,163 +674,58 @@ func TestDuplicateMetrics(t *testing.T) {
}
}
func TestCollectConcurrentSafe(t *testing.T) {
registry := prometheus.NewRegistry()
cfg := newConfig(WithRegisterer(registry))
reader := metric.NewManualReader(cfg.manualReaderOptions()...)
collector := &collector{
reader: reader,
disableTargetInfo: false,
withoutUnits: true,
disableScopeInfo: cfg.disableScopeInfo,
scopeInfos: make(map[instrumentation.Scope]prometheus.Metric),
metricFamilies: make(map[string]*dto.MetricFamily),
}
err := cfg.registerer.Register(collector)
require.NoError(t, err)
func TestCollectorConcurrentSafe(t *testing.T) {
// This tests makes sure that the implemented
// https://pkg.go.dev/github.com/prometheus/client_golang/prometheus#Collector
// is concurrent safe.
ctx := context.Background()
// initialize resource
res, err := resource.New(ctx,
resource.WithAttributes(semconv.ServiceName("prometheus_test")),
resource.WithAttributes(semconv.TelemetrySDKVersion("latest")),
)
registry := prometheus.NewRegistry()
exporter, err := New(WithRegisterer(registry))
require.NoError(t, err)
res, err = resource.Merge(resource.Default(), res)
provider := metric.NewMeterProvider(metric.WithReader(exporter))
meter := provider.Meter("testmeter")
cnt, err := meter.Int64Counter("foo")
require.NoError(t, err)
cnt.Add(ctx, 100)
exporter := &Exporter{Reader: reader}
// initialize provider
provider := metric.NewMeterProvider(
metric.WithReader(exporter),
metric.WithResource(res),
)
// initialize two meter a, b
meterA := provider.Meter("ma", otelmetric.WithInstrumentationVersion("v0.1.0"))
meterB := provider.Meter("mb", otelmetric.WithInstrumentationVersion("v0.1.0"))
fooA, err := meterA.Int64Counter("foo",
otelmetric.WithUnit("By"),
otelmetric.WithDescription("meter counter foo"))
assert.NoError(t, err)
opt := otelmetric.WithAttributes(
attribute.Key("A").String("B"),
)
fooA.Add(ctx, 100, opt)
fooB, err := meterB.Int64Counter("foo",
otelmetric.WithUnit("By"),
otelmetric.WithDescription("meter counter foo"))
assert.NoError(t, err)
fooB.Add(ctx, 100, opt)
concurrencyLevel := 100
ch := make(chan prometheus.Metric, concurrencyLevel)
var wg sync.WaitGroup
concurrencyLevel := 10
for i := 0; i < concurrencyLevel; i++ {
wg.Add(1)
go func() {
collector.Collect(ch)
defer wg.Done()
_, err := registry.Gather() // this calls collector.Collect
assert.NoError(t, err)
}()
}
for ; concurrencyLevel > 0; concurrencyLevel-- {
select {
case <-ch:
concurrencyLevel--
if concurrencyLevel == 0 {
return
}
case <-time.After(time.Second):
t.Fatal("timeout")
}
}
wg.Wait()
}
func TesInvalidInsrtrumentForPrometheusIsIgnored(t *testing.T) {
registry := prometheus.NewRegistry()
cfg := newConfig(WithRegisterer(registry))
func TestIncompatibleMeterName(t *testing.T) {
// This test checks that Prometheus exporter ignores
// when it encounters incompatible meter name.
reader := metric.NewManualReader(cfg.manualReaderOptions()...)
collector := &collector{
reader: reader,
disableTargetInfo: false,
withoutUnits: true,
disableScopeInfo: false,
scopeInfos: make(map[instrumentation.Scope]prometheus.Metric),
metricFamilies: make(map[string]*dto.MetricFamily),
}
err := cfg.registerer.Register(collector)
require.NoError(t, err)
// Invalid label or metric name leads to error returned from
// createScopeInfoMetric.
invalidName := string([]byte{0xff, 0xfe, 0xfd})
ctx := context.Background()
// initialize resource
res, err := resource.New(ctx,
resource.WithAttributes(semconv.ServiceName("prometheus_test")),
resource.WithAttributes(semconv.TelemetrySDKVersion("latest")),
)
registry := prometheus.NewRegistry()
exporter, err := New(WithRegisterer(registry))
require.NoError(t, err)
res, err = resource.Merge(resource.Default(), res)
require.NoError(t, err)
exporter := &Exporter{Reader: reader}
// initialize provider
provider := metric.NewMeterProvider(
metric.WithReader(exporter),
metric.WithResource(res),
)
metric.WithResource(resource.Empty()),
metric.WithReader(exporter))
meter := provider.Meter(invalidName)
cnt, err := meter.Int64Counter("foo")
require.NoError(t, err)
cnt.Add(ctx, 100)
// invalid label or metric name leads to error returned from
// createScopeInfoMetric
invalidName := string([]byte{0xff, 0xfe, 0xfd})
validName := "validName"
file, err := os.Open("testdata/TestIncompatibleMeterName.txt")
require.NoError(t, err)
t.Cleanup(func() { require.NoError(t, file.Close()) })
meterA := provider.Meter(invalidName, otelmetric.WithInstrumentationVersion("v0.1.0"))
counterA, err := meterA.Int64Counter("with-invalid-description",
otelmetric.WithUnit("By"),
otelmetric.WithDescription(invalidName))
assert.NoError(t, err)
counterA.Add(ctx, 100, otelmetric.WithAttributes(
attribute.Key(invalidName).String(invalidName),
))
meterB := provider.Meter(validName, otelmetric.WithInstrumentationVersion("v0.1.0"))
counterB, err := meterB.Int64Counter(validName,
otelmetric.WithUnit("By"),
otelmetric.WithDescription(validName))
assert.NoError(t, err)
counterB.Add(ctx, 100, otelmetric.WithAttributes(
attribute.Key(validName).String(validName),
))
ch := make(chan prometheus.Metric)
go collector.Collect(ch)
for {
select {
case m := <-ch:
require.NotNil(t, m)
if strings.Contains(m.Desc().String(), validName) {
return
}
case <-time.After(time.Second):
t.Fatalf("timeout")
}
}
err = testutil.GatherAndCompare(registry, file)
require.NoError(t, err)
}

View File

@ -0,0 +1,3 @@
# HELP target_info Target metadata
# TYPE target_info gauge
target_info 1