diff --git a/.github/renovate-tracked-deps.json b/.github/renovate-tracked-deps.json index eebbdf0d6..fba9d60bd 100644 --- a/.github/renovate-tracked-deps.json +++ b/.github/renovate-tracked-deps.json @@ -103,6 +103,11 @@ "maven" ] }, + "ci/oats/docker-compose.lgtm.yml": { + "docker-compose": [ + "docker.io/grafana/otel-lgtm" + ] + }, "examples/example-custom-buckets/docker-compose.yaml": { "docker-compose": [ "eclipse-temurin", @@ -169,6 +174,7 @@ "zizmor" ], "regex": [ + "gcx", "grafana/docker-otel-lgtm", "micrometer-metrics/micrometer", "prometheus/jmx_exporter" diff --git a/ci/oats/docker-compose.lgtm.yml b/ci/oats/docker-compose.lgtm.yml new file mode 100644 index 000000000..56d5237f4 --- /dev/null +++ b/ci/oats/docker-compose.lgtm.yml @@ -0,0 +1,10 @@ +services: + lgtm: + image: ${LGTM_IMAGE:-docker.io/grafana/otel-lgtm:latest} + ports: + - "3000:3000" + - "4317:4317" + - "4318:4318" + - "3200:3200" + - "4040:4040" + - "9090:9090" diff --git a/ci/oats/gcx-wrapper.sh b/ci/oats/gcx-wrapper.sh new file mode 100755 index 000000000..65c8adc57 --- /dev/null +++ b/ci/oats/gcx-wrapper.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +set -euo pipefail + +real_gcx="${REAL_GCX_BIN:-gcx}" +args=() +skip_next=false +for arg in "$@"; do + if [ "$skip_next" = true ]; then + skip_next=false + continue + fi + if [ "$arg" = "--context" ]; then + skip_next=true + continue + fi + args+=("$arg") +done + +for _ in $(seq 1 120); do + token="$(docker exec lgtm cat /tmp/grafana-sa-token 2>/dev/null || true)" + if [ -n "$token" ]; then + export GRAFANA_SERVER="${GRAFANA_SERVER:-http://localhost:3000}" + export GRAFANA_TOKEN="$token" + exec "$real_gcx" "${args[@]}" + fi + sleep 1 +done + +printf 'gcx-wrapper: timed out waiting for grafana service-account token\n' >&2 +exit 1 diff --git a/examples/example-exporter-opentelemetry/oats-tests/agent/check_uptime_metric.py b/examples/example-exporter-opentelemetry/oats-tests/agent/check_uptime_metric.py new file mode 100755 index 000000000..a04d66b0e --- /dev/null +++ b/examples/example-exporter-opentelemetry/oats-tests/agent/check_uptime_metric.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 +import json +from urllib.request import urlopen + + +def get_json(url): + with urlopen(url) as response: + return json.loads(response.read().decode("utf-8")) + + +res = get_json("http://localhost:9090/api/v1/query?query=uptime_seconds_total") +results = res["data"]["result"] +assert results, "Expected uptime_seconds_total to be present" diff --git a/examples/example-exporter-opentelemetry/oats-tests/agent/docker-compose.yml b/examples/example-exporter-opentelemetry/oats-tests/agent/docker-compose.yml index 2b820bdea..46a541f54 100644 --- a/examples/example-exporter-opentelemetry/oats-tests/agent/docker-compose.yml +++ b/examples/example-exporter-opentelemetry/oats-tests/agent/docker-compose.yml @@ -4,7 +4,7 @@ version: "3.4" services: java: build: - context: ../.. + context: ../../examples/example-exporter-opentelemetry dockerfile: oats-tests/agent/Dockerfile environment: OTEL_SERVICE_NAME: "rolldice" diff --git a/examples/example-exporter-opentelemetry/oats-tests/agent/oats.yaml b/examples/example-exporter-opentelemetry/oats-tests/agent/oats.yaml index 899d1cd5d..1084b162c 100644 --- a/examples/example-exporter-opentelemetry/oats-tests/agent/oats.yaml +++ b/examples/example-exporter-opentelemetry/oats-tests/agent/oats.yaml @@ -1,12 +1,8 @@ -# OATS is an acceptance testing framework for OpenTelemetry - -# https://github.com/grafana/oats/tree/main/yaml -oats-schema-version: 2 -docker-compose: - files: - - ./docker-compose.yml +oats: 2 +name: java agent exporter preserves target_info identity +seed: + type: app expected: custom-checks: + - script: ./check_uptime_metric.py - script: ./service_instance_id_check.py - metrics: - - promql: "uptime_seconds_total{}" - value: ">= 0" diff --git a/examples/example-exporter-opentelemetry/oats-tests/http/check_uptime_metric.py b/examples/example-exporter-opentelemetry/oats-tests/http/check_uptime_metric.py new file mode 100755 index 000000000..a04d66b0e --- /dev/null +++ b/examples/example-exporter-opentelemetry/oats-tests/http/check_uptime_metric.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 +import json +from urllib.request import urlopen + + +def get_json(url): + with urlopen(url) as response: + return json.loads(response.read().decode("utf-8")) + + +res = get_json("http://localhost:9090/api/v1/query?query=uptime_seconds_total") +results = res["data"]["result"] +assert results, "Expected uptime_seconds_total to be present" diff --git a/examples/example-exporter-opentelemetry/oats-tests/http/docker-compose.yml b/examples/example-exporter-opentelemetry/oats-tests/http/docker-compose.yml index 889278010..2743dfef7 100644 --- a/examples/example-exporter-opentelemetry/oats-tests/http/docker-compose.yml +++ b/examples/example-exporter-opentelemetry/oats-tests/http/docker-compose.yml @@ -4,7 +4,7 @@ version: "3.4" services: java: build: - context: ../.. + context: ../../examples/example-exporter-opentelemetry dockerfile: oats-tests/http/Dockerfile environment: OTEL_SERVICE_NAME: "rolldice" diff --git a/examples/example-exporter-opentelemetry/oats-tests/http/oats.yaml b/examples/example-exporter-opentelemetry/oats-tests/http/oats.yaml index dbcfcf84f..443471de4 100644 --- a/examples/example-exporter-opentelemetry/oats-tests/http/oats.yaml +++ b/examples/example-exporter-opentelemetry/oats-tests/http/oats.yaml @@ -1,10 +1,7 @@ -# OATS is an acceptance testing framework for OpenTelemetry - -# https://github.com/grafana/oats/tree/main/yaml -oats-schema-version: 2 -docker-compose: - files: - - ./docker-compose.yml +oats: 2 +name: http protobuf exporter emits uptime metric +seed: + type: app expected: - metrics: - - promql: "uptime_seconds_total{}" - value: ">= 0" + custom-checks: + - script: ./check_uptime_metric.py diff --git a/mise.toml b/mise.toml index 3e1a4b62c..538da7f54 100644 --- a/mise.toml +++ b/mise.toml @@ -1,6 +1,6 @@ [tools] "go:github.com/grafana/oats" = "0.7.0" -hugo = "0.163.0" +hugo = "0.163.2" java = "temurin-25.0.3+9.0.LTS" node = "24.16.0" protoc = "35" @@ -9,14 +9,14 @@ protoc = "35" actionlint = "1.7.12" "aqua:grafana/flint" = "0.22.5" "aqua:jonwiggins/xmloxide" = "v0.4.3" -"aqua:owenlamont/ryl" = "0.14.0" -biome = "2.4.16" +"aqua:owenlamont/ryl" = "0.18.1" +biome = "2.5.0" editorconfig-checker = "3.7.0" google-java-format = "1.35.0" lychee = "0.24.2" -"npm:renovate" = "43.212.4" -ruff = "0.15.16" -rumdl = "0.2.9" +"npm:renovate" = "43.220.0" +ruff = "0.15.17" +rumdl = "v0.2.17" shellcheck = "v0.11.0" shfmt = "3.13.1" taplo = "0.10.0" @@ -93,7 +93,39 @@ run = "flint run --fix" [tasks.acceptance-test] description = "Run OATs acceptance tests" depends = "build" -run = "oats -lgtm-version $LGTM_VERSION -timeout 5m examples/" +run = """ +# renovate: datasource=github-releases depName=gcx packageName=grafana/gcx +export GCX_VERSION=v0.4.0 +gotmp="" + +if ! command -v go >/dev/null 2>&1; then + goversion="1.25.4" + arch="$(uname -m)" + case "$arch" in + x86_64|amd64) goarch="amd64" ;; + aarch64|arm64) goarch="arm64" ;; + *) echo "unsupported architecture: $arch" >&2; exit 1 ;; + esac + gotmp="$(mktemp -d)" + curl -fsSL "https://go.dev/dl/go${goversion}.linux-${goarch}.tar.gz" -o "$gotmp/go.tgz" + tar -C "$gotmp" -xzf "$gotmp/go.tgz" + export PATH="$gotmp/go/bin:$PATH" +fi + +go install "github.com/grafana/gcx/cmd/gcx@${GCX_VERSION}" + +workdir="$(mktemp -d)" +trap 'rm -rf "$workdir" ${gotmp:+"$gotmp"}' EXIT +git clone --depth 1 --branch v2 https://github.com/grafana/oats "$workdir/oats-src" +GOWORK=off go -C "$workdir/oats-src" build -o "$workdir/oats" ./cmd/v2 + +REAL_GCX_BIN="$(go env GOPATH)/bin/gcx" \ + "$workdir/oats" \ + --config oats.toml \ + --gcx ./ci/oats/gcx-wrapper.sh \ + --no-cache \ + --timeout=5m +""" [tasks.javadoc] description = "Generate Javadoc" diff --git a/oats.toml b/oats.toml new file mode 100644 index 000000000..e02512ffb --- /dev/null +++ b/oats.toml @@ -0,0 +1,28 @@ +[meta] +version = 2 + +[[suite]] +name = "example-exporter-http" +cases = ["examples/example-exporter-opentelemetry/oats-tests/http/oats.yaml"] +fixture = "example-exporter-http" +tags = ["metrics", "http-protobuf"] + +[[suite]] +name = "example-exporter-agent" +cases = ["examples/example-exporter-opentelemetry/oats-tests/agent/oats.yaml"] +fixture = "example-exporter-agent" +tags = ["metrics", "custom-check", "javaagent"] + +[fixture.example-exporter-http] +type = "compose" +compose_files = [ + "ci/oats/docker-compose.lgtm.yml", + "examples/example-exporter-opentelemetry/oats-tests/http/docker-compose.yml", +] + +[fixture.example-exporter-agent] +type = "compose" +compose_files = [ + "ci/oats/docker-compose.lgtm.yml", + "examples/example-exporter-opentelemetry/oats-tests/agent/docker-compose.yml", +]