From ab498e0d02f88508809e12c83fa5119c8489bda3 Mon Sep 17 00:00:00 2001 From: Antoine Toulme Date: Mon, 13 Jan 2025 09:52:25 -0800 Subject: [PATCH] reenable redis discovery by running the redis server in a dedicated test (#5782) * reenable redis discovery by running the redis server in a bridge network * update discovery * fix docker host * run the test in its own test run * simplify by running the test in isolation --- .github/workflows/integration-test.yml | 2 +- Makefile | 5 +- docker/docker-compose.yml | 1 + tests/receivers/redis/bundled_test.go | 101 ++++-- tests/receivers/redis/testdata/expected.yaml | 290 ++++++++++++++++++ .../resource_metrics/all_server_bundled.yaml | 68 ---- 6 files changed, 365 insertions(+), 102 deletions(-) create mode 100644 tests/receivers/redis/testdata/expected.yaml delete mode 100644 tests/receivers/redis/testdata/resource_metrics/all_server_bundled.yaml diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml index 0303c6a4ea..bcc516fa90 100644 --- a/.github/workflows/integration-test.yml +++ b/.github/workflows/integration-test.yml @@ -338,7 +338,7 @@ jobs: id: get-matrix run: | includes="" - for service in "apache" "jmx/cassandra" "kafkametrics" "mongodb" "nginx" "envoy" "oracledb" "mysql"; do + for service in "apache" "jmx/cassandra" "kafkametrics" "mongodb" "nginx" "envoy" "oracledb" "mysql" "redis"; do for arch in "amd64" "arm64"; do if [ "$service" = "mongodb" ]; then # tests for mongo "6.0" and "7.0" are flaky, skipping for now diff --git a/Makefile b/Makefile index ff16101f74..53bcf36138 100644 --- a/Makefile +++ b/Makefile @@ -115,11 +115,14 @@ integration-test-envoy-discovery: integration-test-nginx-discovery: @set -e; cd tests && $(GOTEST_SERIAL) $(BUILD_INFO_TESTS) --tags=discovery_integration_nginx -v -timeout 5m -count 1 ./... +.PHONY: integration-test-redis-discovery +integration-test-redis-discovery: + @set -e; cd tests && $(GOTEST_SERIAL) $(BUILD_INFO_TESTS) --tags=discovery_integration_redis -v -timeout 5m -count 1 ./... + .PHONY: integration-test-oracledb-discovery integration-test-oracledb-discovery: @set -e; cd tests && $(GOTEST_SERIAL) $(BUILD_INFO_TESTS) --tags=discovery_integration_oracledb -v -timeout 5m -count 1 ./... - .PHONY: smartagent-integration-test smartagent-integration-test: @set -e; cd tests && $(GOTEST_SERIAL) $(BUILD_INFO_TESTS) --tags=smartagent_integration -v -timeout 5m -count 1 ./... diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index fa70347b29..4d9e1c84fa 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -281,6 +281,7 @@ services: image: quay.io/splunko11ytest/redis_server:latest profiles: - integration + - integration-test-redis-discovery build: ./redis_server ports: - "6379:6379" diff --git a/tests/receivers/redis/bundled_test.go b/tests/receivers/redis/bundled_test.go index f8e62e48cf..0d344253c2 100644 --- a/tests/receivers/redis/bundled_test.go +++ b/tests/receivers/redis/bundled_test.go @@ -12,48 +12,85 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build integration +//go:build discovery_integration_redis package tests import ( "fmt" - "runtime" + "path/filepath" "testing" + "time" + + "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/golden" + "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest/pmetrictest" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/signalfx/splunk-otel-collector/tests/testutils" ) func TestRedisDockerObserver(t *testing.T) { - t.Skip("Discovery mode picks up other Docker containers running, making the test fail.") testutils.SkipIfNotContainerTest(t) - if runtime.GOOS == "darwin" { - t.Skip("unable to share sockets between mac and d4m vm: https://github.com/docker/for-mac/issues/483#issuecomment-758836836") - } - - testutils.AssertAllMetricsReceived(t, "all_server_bundled.yaml", "otlp_exporter.yaml", - nil, []testutils.CollectorBuilder{ - func(c testutils.Collector) testutils.Collector { - cc := c.(*testutils.CollectorContainer) - cc.Container = cc.Container.WithBinds("/var/run/docker.sock:/var/run/docker.sock:ro") - cc.Container = cc.Container.WillWaitForLogs("Discovering for next") - cc.Container = cc.Container.WithUser(fmt.Sprintf("999:%d", testutils.GetDockerGID(t))) - return cc - }, - func(collector testutils.Collector) testutils.Collector { - return collector.WithEnv(map[string]string{ - "REDIS_PASSWORD": "securepassword", - "REDIS_USERNAME": "otel", - // confirm that debug logging doesn't affect runtime - "SPLUNK_DISCOVERY_LOG_LEVEL": "debug", - }).WithArgs( - "--discovery", - "--set", "splunk.discovery.receivers.redis.config.password=${REDIS_PASSWORD}", - "--set", "splunk.discovery.receivers.redis.config.username=${REDIS_USERNAME}", - "--set", `splunk.discovery.extensions.k8s_observer.enabled=false`, - "--set", `splunk.discovery.extensions.host_observer.enabled=false`, - ) - }, - }, - ) + dockerSocket := testutils.CreateDockerSocketProxy(t) + require.NoError(t, dockerSocket.Start()) + t.Cleanup(func() { + dockerSocket.Stop() + }) + + tc := testutils.NewTestcase(t) + defer tc.PrintLogsOnFailure() + defer tc.ShutdownOTLPReceiverSink() + + _, shutdown := tc.SplunkOtelCollectorContainer("otlp_exporter.yaml", func(c testutils.Collector) testutils.Collector { + cc := c.(*testutils.CollectorContainer) + cc.Container = cc.Container.WillWaitForLogs("Discovering for next") + return cc + }, + func(collector testutils.Collector) testutils.Collector { + return collector.WithEnv(map[string]string{ + "REDIS_PASSWORD": "securepassword", + "REDIS_USERNAME": "otel", + // confirm that debug logging doesn't affect runtime + "SPLUNK_DISCOVERY_LOG_LEVEL": "debug", + "SPLUNK_DISCOVERY_DURATION": "20s", + }).WithArgs( + "--discovery", + "--set", "splunk.discovery.receivers.redis.config.password=${REDIS_PASSWORD}", + "--set", "splunk.discovery.receivers.redis.config.username=${REDIS_USERNAME}", + "--set", `splunk.discovery.extensions.k8s_observer.enabled=false`, + "--set", `splunk.discovery.extensions.host_observer.enabled=false`, + "--set", fmt.Sprintf("splunk.discovery.extensions.docker_observer.config.endpoint=tcp://%s", dockerSocket.ContainerEndpoint), + ) + }) + defer shutdown() + expected, err := golden.ReadMetrics(filepath.Join("testdata", "expected.yaml")) + require.NoError(t, err) + require.EventuallyWithT(t, func(tt *assert.CollectT) { + if len(tc.OTLPReceiverSink.AllMetrics()) == 0 { + assert.Fail(tt, "No metrics collected") + return + } + err := pmetrictest.CompareMetrics(expected, tc.OTLPReceiverSink.AllMetrics()[len(tc.OTLPReceiverSink.AllMetrics())-1], + pmetrictest.IgnoreResourceAttributeValue("service.instance.id"), + pmetrictest.IgnoreResourceAttributeValue("net.host.port"), + pmetrictest.IgnoreResourceAttributeValue("net.host.name"), + pmetrictest.IgnoreResourceAttributeValue("server.address"), + pmetrictest.IgnoreResourceAttributeValue("container.name"), + pmetrictest.IgnoreResourceAttributeValue("server.port"), + pmetrictest.IgnoreResourceAttributeValue("service.name"), + pmetrictest.IgnoreResourceAttributeValue("service_instance_id"), + pmetrictest.IgnoreResourceAttributeValue("service_version"), + pmetrictest.IgnoreMetricAttributeValue("service_version"), + pmetrictest.IgnoreMetricAttributeValue("service_instance_id"), + pmetrictest.IgnoreTimestamp(), + pmetrictest.IgnoreStartTimestamp(), + pmetrictest.IgnoreMetricDataPointsOrder(), + pmetrictest.IgnoreScopeMetricsOrder(), + pmetrictest.IgnoreScopeVersion(), + pmetrictest.IgnoreResourceMetricsOrder(), + pmetrictest.IgnoreMetricValues(), + ) + assert.NoError(tt, err) + }, 60*time.Second, 1*time.Second) } diff --git a/tests/receivers/redis/testdata/expected.yaml b/tests/receivers/redis/testdata/expected.yaml new file mode 100644 index 0000000000..4eaace0f51 --- /dev/null +++ b/tests/receivers/redis/testdata/expected.yaml @@ -0,0 +1,290 @@ +resourceMetrics: + - resource: + attributes: + - key: container.image.name + value: + stringValue: quay.io/splunko11ytest/redis_server + - key: container.name + value: + stringValue: docker-redis_server-1 + - key: redis.version + value: + stringValue: 7.4.2 + scopeMetrics: + - metrics: + - description: Number of clients pending on a blocking call + name: redis.clients.blocked + sum: + aggregationTemporality: 2 + dataPoints: + - asInt: "0" + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + unit: '{client}' + - description: Number of client connections (excluding connections from replicas) + name: redis.clients.connected + sum: + aggregationTemporality: 2 + dataPoints: + - asInt: "1" + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + unit: '{client}' + - description: Biggest input buffer among current client connections + gauge: + dataPoints: + - asInt: "8" + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: redis.clients.max_input_buffer + unit: By + - description: Longest output list among current client connections + gauge: + dataPoints: + - asInt: "0" + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: redis.clients.max_output_buffer + unit: By + - description: Number of commands processed per second + gauge: + dataPoints: + - asInt: "0" + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: redis.commands + unit: '{ops}/s' + - description: Total number of commands processed by the server + name: redis.commands.processed + sum: + aggregationTemporality: 2 + dataPoints: + - asInt: "16" + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + isMonotonic: true + unit: '{command}' + - description: Total number of connections accepted by the server + name: redis.connections.received + sum: + aggregationTemporality: 2 + dataPoints: + - asInt: "4" + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + isMonotonic: true + unit: '{connection}' + - description: Number of connections rejected because of maxclients limit + name: redis.connections.rejected + sum: + aggregationTemporality: 2 + dataPoints: + - asInt: "0" + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + isMonotonic: true + unit: '{connection}' + - description: System CPU consumed by the Redis server in seconds since server start + name: redis.cpu.time + sum: + aggregationTemporality: 2 + dataPoints: + - asDouble: 0.518125 + attributes: + - key: state + value: + stringValue: sys + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asDouble: 0 + attributes: + - key: state + value: + stringValue: sys_children + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asDouble: 0.516068 + attributes: + - key: state + value: + stringValue: sys_main_thread + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asDouble: 2.504274 + attributes: + - key: state + value: + stringValue: user + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asDouble: 0.002564 + attributes: + - key: state + value: + stringValue: user_children + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asDouble: 2.504765 + attributes: + - key: state + value: + stringValue: user_main_thread + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + isMonotonic: true + unit: s + - description: Number of evicted keys due to maxmemory limit + name: redis.keys.evicted + sum: + aggregationTemporality: 2 + dataPoints: + - asInt: "0" + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + isMonotonic: true + unit: '{key}' + - description: Total number of key expiration events + name: redis.keys.expired + sum: + aggregationTemporality: 2 + dataPoints: + - asInt: "0" + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + isMonotonic: true + unit: '{event}' + - description: Number of successful lookup of keys in the main dictionary + name: redis.keyspace.hits + sum: + aggregationTemporality: 2 + dataPoints: + - asInt: "0" + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + isMonotonic: true + unit: '{hit}' + - description: Number of failed lookup of keys in the main dictionary + name: redis.keyspace.misses + sum: + aggregationTemporality: 2 + dataPoints: + - asInt: "0" + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + isMonotonic: true + unit: '{miss}' + - description: Duration of the latest fork operation in microseconds + gauge: + dataPoints: + - asInt: "0" + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: redis.latest_fork + unit: us + - description: Ratio between used_memory_rss and used_memory + gauge: + dataPoints: + - asDouble: 15.2 + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: redis.memory.fragmentation_ratio + unit: "1" + - description: Number of bytes used by the Lua engine + gauge: + dataPoints: + - asInt: "31744" + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: redis.memory.lua + unit: By + - description: Peak memory consumed by Redis (in bytes) + gauge: + dataPoints: + - asInt: "1097400" + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: redis.memory.peak + unit: By + - description: Number of bytes that Redis allocated as seen by the operating system + gauge: + dataPoints: + - asInt: "16023552" + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: redis.memory.rss + unit: By + - description: Total number of bytes allocated by Redis using its allocator + gauge: + dataPoints: + - asInt: "1094136" + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: redis.memory.used + unit: By + - description: The total number of bytes read from the network + name: redis.net.input + sum: + aggregationTemporality: 2 + dataPoints: + - asInt: "859" + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + isMonotonic: true + unit: By + - description: The total number of bytes written to the network + name: redis.net.output + sum: + aggregationTemporality: 2 + dataPoints: + - asInt: "24660" + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + isMonotonic: true + unit: By + - description: Number of changes since the last dump + name: redis.rdb.changes_since_last_save + sum: + aggregationTemporality: 2 + dataPoints: + - asInt: "0" + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + unit: '{change}' + - description: The master offset of the replication backlog buffer + gauge: + dataPoints: + - asInt: "0" + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: redis.replication.backlog_first_byte_offset + unit: By + - description: The server's current replication offset + gauge: + dataPoints: + - asInt: "0" + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: redis.replication.offset + unit: By + - description: Number of connected replicas + name: redis.slaves.connected + sum: + aggregationTemporality: 2 + dataPoints: + - asInt: "0" + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + unit: '{replica}' + - description: Number of seconds since Redis server start + name: redis.uptime + sum: + aggregationTemporality: 2 + dataPoints: + - asInt: "354" + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + isMonotonic: true + unit: s + scope: + name: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/redisreceiver + version: v0.116.0-11-g739c4d44 diff --git a/tests/receivers/redis/testdata/resource_metrics/all_server_bundled.yaml b/tests/receivers/redis/testdata/resource_metrics/all_server_bundled.yaml deleted file mode 100644 index 2f416463b7..0000000000 --- a/tests/receivers/redis/testdata/resource_metrics/all_server_bundled.yaml +++ /dev/null @@ -1,68 +0,0 @@ -resource_metrics: - - attributes: - redis.version: - container.image.name: - container.name: redis-server - scope_metrics: - - instrumentation_scope: - name: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/redisreceiver - version: - metrics: - - name: redis.uptime - type: IntMonotonicCumulativeSum - - name: redis.cpu.time - type: DoubleMonotonicCumulativeSum - - name: redis.clients.connected - type: IntNonmonotonicCumulativeSum - - name: redis.clients.max_input_buffer - type: IntGauge - - name: redis.clients.max_output_buffer - type: IntGauge - - name: redis.clients.blocked - type: IntNonmonotonicCumulativeSum - - name: redis.keys.expired - type: IntMonotonicCumulativeSum - - name: redis.keys.evicted - type: IntMonotonicCumulativeSum - - name: redis.connections.rejected - type: IntMonotonicCumulativeSum - - name: redis.memory.used - type: IntGauge - - name: redis.memory.rss - type: IntGauge - - name: redis.memory.peak - type: IntGauge - - name: redis.memory.lua - type: IntGauge - - name: redis.memory.fragmentation_ratio - type: DoubleGauge - - name: redis.rdb.changes_since_last_save - type: IntNonmonotonicCumulativeSum - - name: redis.commands - type: IntGauge - - name: redis.connections.received - type: IntMonotonicCumulativeSum - - name: redis.commands.processed - type: IntMonotonicCumulativeSum - - name: redis.net.input - type: IntMonotonicCumulativeSum - - name: redis.net.output - type: IntMonotonicCumulativeSum - - name: redis.keyspace.hits - type: IntMonotonicCumulativeSum - - name: redis.keyspace.misses - type: IntMonotonicCumulativeSum - - name: redis.latest_fork - type: IntGauge - - name: redis.slaves.connected - type: IntNonmonotonicCumulativeSum - - name: redis.replication.backlog_first_byte_offset - type: IntGauge - - name: redis.replication.offset - type: IntGauge - - name: redis.db.avg_ttl - type: IntGauge - - name: redis.db.expires - type: IntGauge - - name: redis.db.keys - type: IntGauge