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:
parent
10c3445543
commit
c404a30b96
@ -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")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
3
exporters/prometheus/testdata/TestIncompatibleMeterName.txt
vendored
Executable file
3
exporters/prometheus/testdata/TestIncompatibleMeterName.txt
vendored
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
# HELP target_info Target metadata
|
||||||
|
# TYPE target_info gauge
|
||||||
|
target_info 1
|
Loading…
x
Reference in New Issue
Block a user