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 ( import (
"context" "context"
"os" "os"
"strings" "sync"
"testing" "testing"
"time"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/testutil" "github.com/prometheus/client_golang/prometheus/testutil"
dto "github.com/prometheus/client_model/go"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/attribute"
otelmetric "go.opentelemetry.io/otel/metric" otelmetric "go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/sdk/instrumentation"
"go.opentelemetry.io/otel/sdk/metric" "go.opentelemetry.io/otel/sdk/metric"
"go.opentelemetry.io/otel/sdk/metric/aggregation" "go.opentelemetry.io/otel/sdk/metric/aggregation"
"go.opentelemetry.io/otel/sdk/resource" "go.opentelemetry.io/otel/sdk/resource"
@ -677,163 +674,58 @@ func TestDuplicateMetrics(t *testing.T) {
} }
} }
func TestCollectConcurrentSafe(t *testing.T) { func TestCollectorConcurrentSafe(t *testing.T) {
registry := prometheus.NewRegistry() // This tests makes sure that the implemented
cfg := newConfig(WithRegisterer(registry)) // https://pkg.go.dev/github.com/prometheus/client_golang/prometheus#Collector
// is concurrent safe.
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)
ctx := context.Background() ctx := context.Background()
registry := prometheus.NewRegistry()
// initialize resource exporter, err := New(WithRegisterer(registry))
res, err := resource.New(ctx,
resource.WithAttributes(semconv.ServiceName("prometheus_test")),
resource.WithAttributes(semconv.TelemetrySDKVersion("latest")),
)
require.NoError(t, err) 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) require.NoError(t, err)
cnt.Add(ctx, 100)
exporter := &Exporter{Reader: reader} var wg sync.WaitGroup
concurrencyLevel := 10
// 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)
for i := 0; i < concurrencyLevel; i++ { for i := 0; i < concurrencyLevel; i++ {
wg.Add(1)
go func() { go func() {
collector.Collect(ch) defer wg.Done()
_, err := registry.Gather() // this calls collector.Collect
assert.NoError(t, err)
}() }()
} }
for ; concurrencyLevel > 0; concurrencyLevel-- { wg.Wait()
select {
case <-ch:
concurrencyLevel--
if concurrencyLevel == 0 {
return
}
case <-time.After(time.Second):
t.Fatal("timeout")
}
}
} }
func TesInvalidInsrtrumentForPrometheusIsIgnored(t *testing.T) { func TestIncompatibleMeterName(t *testing.T) {
registry := prometheus.NewRegistry() // This test checks that Prometheus exporter ignores
cfg := newConfig(WithRegisterer(registry)) // when it encounters incompatible meter name.
reader := metric.NewManualReader(cfg.manualReaderOptions()...) // Invalid label or metric name leads to error returned from
// createScopeInfoMetric.
collector := &collector{ invalidName := string([]byte{0xff, 0xfe, 0xfd})
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)
ctx := context.Background() ctx := context.Background()
registry := prometheus.NewRegistry()
// initialize resource exporter, err := New(WithRegisterer(registry))
res, err := resource.New(ctx,
resource.WithAttributes(semconv.ServiceName("prometheus_test")),
resource.WithAttributes(semconv.TelemetrySDKVersion("latest")),
)
require.NoError(t, err) require.NoError(t, err)
res, err = resource.Merge(resource.Default(), res)
require.NoError(t, err)
exporter := &Exporter{Reader: reader}
// initialize provider
provider := metric.NewMeterProvider( provider := metric.NewMeterProvider(
metric.WithReader(exporter), metric.WithResource(resource.Empty()),
metric.WithResource(res), 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 file, err := os.Open("testdata/TestIncompatibleMeterName.txt")
// createScopeInfoMetric require.NoError(t, err)
invalidName := string([]byte{0xff, 0xfe, 0xfd}) t.Cleanup(func() { require.NoError(t, file.Close()) })
validName := "validName"
meterA := provider.Meter(invalidName, otelmetric.WithInstrumentationVersion("v0.1.0")) err = testutil.GatherAndCompare(registry, file)
require.NoError(t, err)
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")
}
}
} }

View File

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