Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add elixir based integration test #938

Merged
merged 1 commit into from
Jun 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions test/integration/configs/instrumenter-config-elixir.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
routes:
patterns:
- /test/:test_id
unmatched: path
otel_metrics_export:
endpoint: http://otelcol:4318
81 changes: 81 additions & 0 deletions test/integration/docker-compose-elixir.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
version: '3.8'

services:
testserver:
build:
context: ../..
dockerfile: test/integration/components/elixir/Dockerfile
image: hatest-testserver-elixir
ports:
- "4000:4000"
depends_on:
otelcol:
condition: service_started

autoinstrumenter:
build:
context: ../..
dockerfile: ./test/integration/components/beyla/Dockerfile
command:
- --config=/configs/instrumenter-config-elixir.yml
volumes:
- ./configs/:/configs
- ./system/sys/kernel/security:/sys/kernel/security
- ../../testoutput:/coverage
- ../../testoutput/run:/var/run/beyla
image: hatest-autoinstrumenter
privileged: true # in some environments (not GH Pull Requests) you can set it to false and then cap_add: [ SYS_ADMIN ]
network_mode: "service:testserver"
pid: "service:testserver"
environment:
GOCOVERDIR: "/coverage"
BEYLA_PRINT_TRACES: "true"
BEYLA_OPEN_PORT: "4000"
BEYLA_DISCOVERY_POLL_INTERVAL: 500ms
BEYLA_SERVICE_NAMESPACE: "integration-test"
BEYLA_METRICS_INTERVAL: "10ms"
BEYLA_BPF_BATCH_TIMEOUT: "10ms"
BEYLA_LOG_LEVEL: "DEBUG"
BEYLA_BPF_DEBUG: "TRUE"
BEYLA_METRICS_REPORT_TARGET: "true"
BEYLA_METRICS_REPORT_PEER: "true"
BEYLA_HOSTNAME: "beyla"
depends_on:
testserver:
condition: service_started

# OpenTelemetry Collector
otelcol:
image: otel/opentelemetry-collector-contrib:0.85.0
container_name: otel-col
deploy:
resources:
limits:
memory: 125M
restart: unless-stopped
command: [ "--config=/etc/otelcol-config/otelcol-config.yml" ]
volumes:
- ./configs/:/etc/otelcol-config
ports:
- "4317" # OTLP over gRPC receiver
- "4318:4318" # OTLP over HTTP receiver
- "9464" # Prometheus exporter
- "8888" # metrics endpoint
depends_on:
prometheus:
condition: service_started

# Prometheus
prometheus:
image: quay.io/prometheus/prometheus:v2.46.0
container_name: prometheus
command:
- --storage.tsdb.retention.time=1m
- --config.file=/etc/prometheus/prometheus-config.yml
- --storage.tsdb.path=/prometheus
- --web.enable-lifecycle
- --web.route-prefix=/
volumes:
- ./configs/:/etc/prometheus
ports:
- "9090:9090"
65 changes: 65 additions & 0 deletions test/integration/red_test_elixir.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//go:build integration

package integration

import (
"fmt"
"testing"

"github.com/mariomac/guara/pkg/test"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/grafana/beyla/test/integration/components/prom"
)

// does a smoke test to verify that all the components that started
// asynchronously for the Elixir test are up and communicating properly
func waitForElixirTestComponents(t *testing.T, url string) {
waitForTestComponentsSub(t, url, "/smoke")
}

func testREDMetricsForElixirHTTPLibrary(t *testing.T, url string, comm string) {
path := "/test"

pq := prom.Client{HostPort: prometheusHostPort}
var results []prom.Result

// Call 4 times the instrumented service, forcing it to:
// - process multiple calls in a row with, one more than we might need
// - returning a 200 code
for i := 0; i < 4; i++ {
doHTTPGet(t, fmt.Sprintf("%s%s/%d", url, path, i), 200)
}

// Eventually, Prometheus would make this query visible
test.Eventually(t, testTimeout, func(t require.TestingT) {
var err error
results, err = pq.Query(`http_server_request_duration_seconds_count{` +
`http_request_method="GET",` +
`http_response_status_code="200",` +
`service_namespace="integration-test",` +
`service_name="` + comm + `",` +
`http_route="/test/:test_id"}`)
require.NoError(t, err)
enoughPromResults(t, results)
val := totalPromCount(t, results)
assert.LessOrEqual(t, 3, val)
if len(results) > 0 {
res := results[0]
addr := res.Metric["client_address"]
assert.NotNil(t, addr)
}
})
}

func testREDMetricsElixirHTTP(t *testing.T) {
for _, testCaseURL := range []string{
"http://localhost:4000",
} {
t.Run(testCaseURL, func(t *testing.T) {
waitForElixirTestComponents(t, testCaseURL)
testREDMetricsForElixirHTTPLibrary(t, testCaseURL, "beam.smp")
})
}
}
10 changes: 10 additions & 0 deletions test/integration/suites_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,16 @@ func TestSuiteNoRoutes(t *testing.T) {
t.Run("BPF pinning folder unmounted", testBPFPinningUnmounted)
}

func TestSuite_Elixir(t *testing.T) {
compose, err := docker.ComposeSuite("docker-compose-elixir.yml", path.Join(pathOutput, "test-suite-elixir.log"))
require.NoError(t, err)
require.NoError(t, compose.Up())
t.Run("Elixir RED metrics", testREDMetricsElixirHTTP)
t.Run("BPF pinning folder mounted", testBPFPinningMounted)
require.NoError(t, compose.Close())
t.Run("BPF pinning folder unmounted", testBPFPinningUnmounted)
}

// Helpers

var lockdownPath = "/sys/kernel/security/lockdown"
Expand Down
Loading