From 3a64c2172560f646cc606531eb34e25d79890158 Mon Sep 17 00:00:00 2001 From: bwplotka Date: Mon, 11 Nov 2024 22:22:04 +0000 Subject: [PATCH] e2e test for telemetrygen -> Prometheus with UTF-8 support. Signed-off-by: bwplotka --- test/go.mod | 29 ++++++++++ test/go.sum | 58 +++++++++++++++++++ test/otel_test.go | 141 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 228 insertions(+) create mode 100644 test/go.mod create mode 100644 test/go.sum create mode 100644 test/otel_test.go diff --git a/test/go.mod b/test/go.mod new file mode 100644 index 0000000000..53828cd7a8 --- /dev/null +++ b/test/go.mod @@ -0,0 +1,29 @@ +module github.com/prometheus/prometheus/test + +go 1.22.6 + +require ( + github.com/efficientgo/core v1.0.0-rc.0 + github.com/efficientgo/e2e v0.14.0 + github.com/prometheus/client_golang v1.20.6-0.20241021131810-bffa92259bd6 +) + +require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/jpillora/backoff v1.0.0 // indirect + github.com/klauspost/compress v1.17.10 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.60.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + golang.org/x/net v0.29.0 // indirect + golang.org/x/oauth2 v0.23.0 // indirect + golang.org/x/sys v0.25.0 // indirect + golang.org/x/text v0.18.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect +) diff --git a/test/go.sum b/test/go.sum new file mode 100644 index 0000000000..27624cc20a --- /dev/null +++ b/test/go.sum @@ -0,0 +1,58 @@ +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/efficientgo/core v1.0.0-rc.0 h1:jJoA0N+C4/knWYVZ6GrdHOtDyrg8Y/TR4vFpTaqTsqs= +github.com/efficientgo/core v1.0.0-rc.0/go.mod h1:kQa0V74HNYMfuJH6jiPiwNdpWXl4xd/K4tzlrcvYDQI= +github.com/efficientgo/e2e v0.14.0 h1:Jxgeus4nq4COPhACC7nYRTKX1BTzSS86Z/Z2sW9W+kE= +github.com/efficientgo/e2e v0.14.0/go.mod h1:Hi+sz0REtlhVZ8zcdeTC3j6LUEEpJpPtNjOaOKuNcgI= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/klauspost/compress v1.17.10 h1:oXAz+Vh0PMUvJczoi+flxpnBEPxoER1IaAnU/NMPtT0= +github.com/klauspost/compress v1.17.10/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.20.6-0.20241021131810-bffa92259bd6 h1:OupJ9xL69cspgCKA6JnE2Gh09WtvjLmMrbAycLKF+sw= +github.com/prometheus/client_golang v1.20.6-0.20241021131810-bffa92259bd6/go.mod h1:SJYWANZZtDbfu6CSYeDvRDkzhGX71yepDKePKDTya3M= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= +golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/test/otel_test.go b/test/otel_test.go new file mode 100644 index 0000000000..8fc1794d7a --- /dev/null +++ b/test/otel_test.go @@ -0,0 +1,141 @@ +package test + +import ( + "fmt" + "os" + "path/filepath" + "strconv" + "testing" + + "github.com/efficientgo/core/testutil" + "github.com/efficientgo/e2e" + e2einteractive "github.com/efficientgo/e2e/interactive" + e2emon "github.com/efficientgo/e2e/monitoring" +) + +const ( + promImage = "quay.io/prometheus/prometheus:v3.0.0-rc.1" + otelGenImage = "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen:v0.113.0" +) + +func TestPrometheus_ReceivingOtel(t *testing.T) { + e, err := e2e.New() + t.Cleanup(e.Close) + testutil.Ok(t, err) + + // Create self-scraping Prometheus that also receives OTLP. + prom := newPrometheus(e, "prom-1", promImage, nil) + + // Create OpenTelemetry telemetrygen container. + // https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/cmd/telemetrygen + otelgen := newOtelGen(e, "otelgen-1", otelGenImage, prom.InternalEndpoint("http"), nil) + testutil.Ok(t, e2e.StartAndWaitReady(prom, otelgen)) + + //testutil.Ok(t, prom.WaitSumMetricsWithOptions( + // e2emon.Greater(expectSamples), []string{"prometheus_remote_storage_samples_total"}, + // e2emon.WithLabelMatchers(&matchers.Matcher{Name: "remote_name", Value: "v2-to-sink", Type: matchers.MatchEqual}), + // e2emon.WithWaitBackoff(&backoff.Config{Min: 1 * time.Second, Max: 1 * time.Second, MaxRetries: 300}), // Wait 5m max. + //)) + //testutil.Ok(t, prom.WaitSumMetricsWithOptions( + // e2emon.Greater(expectSamples), []string{"prometheus_remote_storage_samples_total"}, + // e2emon.WithLabelMatchers(&matchers.Matcher{Name: "remote_name", Value: "v1-to-sink", Type: matchers.MatchEqual}), + //)) + + testutil.Ok(t, e2einteractive.OpenInBrowser("http://"+prom.Endpoint("http"))) // Open Prometheus UI. + //testutil.Ok(t, e2einteractive.OpenInBrowser("http://"+otelgen.Endpoint("http")+"/metrics")) + testutil.Ok(t, e2einteractive.RunUntilEndpointHit()) +} + +func newOtelGen(e e2e.Environment, name, image string, otlpEndpoint string, flagOverride map[string]string) e2e.Runnable { + f := e.Runnable(name).Future() + args := map[string]string{ + // https://opentelemetry.io/docs/specs/semconv/http/http-metrics/#metric-httpclientactive_requests + "--metric-name": "http.client.active_requests", + "--rate": "0.2", + "--metrics": "10000", // ~13h + "--workers": "1", + "--otlp-insecure": "", + "--otlp-http": "", + "--otlp-endpoint": otlpEndpoint, + "--otlp-http-url-path": "/api/v1/otlp/v1/metrics", + "--otlp-attributes": "service.instance.id=\"my-laptop\"", + } + if flagOverride != nil { + args = e2e.MergeFlagsWithoutRemovingEmpty(args, flagOverride) + } + + return f.Init(e2e.StartOptions{ + Image: image, + Command: e2e.NewCommand("metrics", + append([]string{ + "--telemetry-attributes=server.address=\"top-secret🙈\"", + "--telemetry-attributes=server.⚠️=\"🔥\"", + }, e2e.BuildArgs(args)...)...), + User: strconv.Itoa(os.Getuid()), + //EnvVars: map[string]string{ + // "OTEL_EXPORTER_OTLP_PROTOCOL": "http/protobuf", + // "OTEL_EXPORTER_OTLP_METRICS_ENDPOINT": "http://" + otlpEndpoint + "/api/v1/otlp/v1/metrics", + // "OTEL_SERVICE_NAME": "otelgen", + // "OTEL_RESOURCE_ATTRIBUTES": "service.instance.id=my-laptop", + //}, + }) +} + +func newPrometheus(env e2e.Environment, name, image string, flagOverride map[string]string) *e2emon.Prometheus { + ports := map[string]int{"http": 9090} + + f := env.Runnable(name).WithPorts(ports).Future() + config := fmt.Sprintf(` +global: + external_labels: + prometheus: %v + metric_name_validation_scheme: utf8 +otlp: + promote_resource_attributes: + - service.instance.id + translation_strategy: "NoUTF8EscapingWithSuffixes" +scrape_configs: +- job_name: 'self' + scrape_interval: 5s + scrape_timeout: 5s + static_configs: + - targets: ['localhost:%v'] + +`, name, ports["http"]) + if err := os.WriteFile(filepath.Join(f.Dir(), "prometheus.yml"), []byte(config), 0o600); err != nil { + return &e2emon.Prometheus{Runnable: e2e.NewFailedRunnable(name, fmt.Errorf("create prometheus config failed: %w", err))} + } + + args := map[string]string{ + "--web.listen-address": fmt.Sprintf(":%d", ports["http"]), + "--web.enable-otlp-receiver": "", + "--config.file": filepath.Join(f.Dir(), "prometheus.yml"), + "--storage.tsdb.path": f.Dir(), + "--enable-feature=exemplar-storage": "", + "--enable-feature=native-histograms": "", + "--enable-feature=metadata-wal-records": "", + "--storage.tsdb.no-lockfile": "", + "--storage.tsdb.retention.time": "1d", + "--storage.tsdb.wal-compression": "", + "--storage.tsdb.min-block-duration": "2h", + "--storage.tsdb.max-block-duration": "2h", + "--web.enable-lifecycle": "", + "--log.format": "json", + "--log.level": "info", + } + if flagOverride != nil { + args = e2e.MergeFlagsWithoutRemovingEmpty(args, flagOverride) + } + + p := e2emon.AsInstrumented(f.Init(e2e.StartOptions{ + Image: image, + Command: e2e.NewCommandWithoutEntrypoint("prometheus", e2e.BuildArgs(args)...), + Readiness: e2e.NewHTTPReadinessProbe("http", "/-/ready", 200, 200), + User: strconv.Itoa(os.Getuid()), + }), "http") + + return &e2emon.Prometheus{ + Runnable: p, + Instrumented: p, + } +}