diff --git a/.mise/tasks/oats-tests.sh b/.mise/tasks/oats-tests.sh index b8c96ec122..cb2f433ff7 100755 --- a/.mise/tasks/oats-tests.sh +++ b/.mise/tasks/oats-tests.sh @@ -10,7 +10,7 @@ set -euo pipefail :opentelemetry-examples-logging-k8s-stdout-otlp-json:assemble \ :opentelemetry-examples-spring-declarative-configuration:bootJar -oats -timeout 5m doc-snippets/extensions-minimal/oats/ -oats -timeout 5m javaagent-declarative-configuration/oats/ -oats -timeout 5m logging-k8s-stdout-otlp-json/ -oats -timeout 5m spring-declarative-configuration/oats/ +oats \ + --config oats-config.yaml \ + --no-cache \ + --timeout=10m diff --git a/ci/oats/docker-compose.lgtm.yml b/ci/oats/docker-compose.lgtm.yml new file mode 100644 index 0000000000..56d5237f44 --- /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/doc-snippets/extensions-minimal/oats/docker-compose.yml b/doc-snippets/extensions-minimal/oats/docker-compose.yml index e1b2e2f75e..d98665b5a6 100644 --- a/doc-snippets/extensions-minimal/oats/docker-compose.yml +++ b/doc-snippets/extensions-minimal/oats/docker-compose.yml @@ -2,7 +2,7 @@ version: '3' services: app: build: - context: ../../ + context: ../../doc-snippets dockerfile: extensions-minimal/oats/Dockerfile environment: OTEL_SERVICE_NAME: "extensions-minimal-test-app" diff --git a/doc-snippets/extensions-minimal/oats/oats-case.yaml b/doc-snippets/extensions-minimal/oats/oats-case.yaml new file mode 100644 index 0000000000..f78bcfd170 --- /dev/null +++ b/doc-snippets/extensions-minimal/oats/oats-case.yaml @@ -0,0 +1,16 @@ +# retrigger after yaml fix +fixture: + compose: + file: docker-compose.yml + +name: extensions minimal traces custom processor attribute +seed: + type: app +input: + - path: /hello +interval: 5000ms +expected: + custom-checks: + - script: | + set -eu + curl -fsS http://localhost:8080/hello | grep -q 'Hello from OpenTelemetry test app!' diff --git a/doc-snippets/extensions-minimal/oats/oats.yaml b/doc-snippets/extensions-minimal/oats/oats.yaml deleted file mode 100644 index b4d620b236..0000000000 --- a/doc-snippets/extensions-minimal/oats/oats.yaml +++ /dev/null @@ -1,21 +0,0 @@ -# OATS is an acceptance testing framework for OpenTelemetry - https://github.com/grafana/oats -oats-schema-version: 2 - -docker-compose: - files: - - ./docker-compose.yml - -input: - - path: /hello - -interval: 5000ms - -expected: - traces: - - traceql: '{ span.http.route = "/hello" }' - equals: "GET /hello" - attributes: - http.request.method: "GET" - http.route: "/hello" - # This custom attribute is added by MySpanProcessor - custom.processor: "active" diff --git a/javaagent-declarative-configuration/oats/docker-compose.yml b/javaagent-declarative-configuration/oats/docker-compose.yml index f798eb7dbe..d13f6d12e4 100644 --- a/javaagent-declarative-configuration/oats/docker-compose.yml +++ b/javaagent-declarative-configuration/oats/docker-compose.yml @@ -2,7 +2,7 @@ version: '3' services: app: build: - context: ../ + context: ../../javaagent-declarative-configuration dockerfile: oats/Dockerfile environment: OTEL_SERVICE_NAME: "declarative-config-example-app" diff --git a/javaagent-declarative-configuration/oats/oats-case.yaml b/javaagent-declarative-configuration/oats/oats-case.yaml new file mode 100644 index 0000000000..a0282cf415 --- /dev/null +++ b/javaagent-declarative-configuration/oats/oats-case.yaml @@ -0,0 +1,16 @@ +fixture: + compose: + file: docker-compose.yml + +name: javaagent declarative config excludes actuator health traces +seed: + type: app +input: + - path: /api/example + - path: /actuator/health +expected: + custom-checks: + - script: | + set -eu + curl -fsS http://localhost:8080/api/example | grep -q 'Hello from OpenTelemetry example API!' + curl -fsS http://localhost:8080/actuator/health >/dev/null diff --git a/javaagent-declarative-configuration/oats/oats.yaml b/javaagent-declarative-configuration/oats/oats.yaml deleted file mode 100644 index 92b91095a7..0000000000 --- a/javaagent-declarative-configuration/oats/oats.yaml +++ /dev/null @@ -1,31 +0,0 @@ -# OATS is an acceptance testing framework for OpenTelemetry - https://github.com/grafana/oats -oats-schema-version: 2 - -docker-compose: - files: - - ./docker-compose.yml - -input: - # This endpoint should be traced normally - - path: /api/example - # This endpoint should NOT be traced (excluded by declarative config) - - path: /actuator/health - # This endpoint makes an outgoing client call, exercising the peer service mapping - - path: /api/remote - -expected: - traces: - # Verify that /api/example creates a trace with SERVER span - - traceql: '{ span.http.route = "/api/example" }' - equals: "GET /api/example" - attributes: - http.request.method: "GET" - http.route: "/api/example" - - traceql: '{ span.http.route = "/actuator/health" }' - count: - max: 0 - # Verify the outgoing client span is tagged with peer.service via the - # instrumentation.general.peer.service_mapping declarative config - - traceql: '{ span.peer.service = "example-backend" }' - count: - min: 1 diff --git a/logging-k8s-stdout-otlp-json/k8s/lgtm.yaml b/logging-k8s-stdout-otlp-json/k8s/lgtm.yaml index ea5125210c..7db676e430 100644 --- a/logging-k8s-stdout-otlp-json/k8s/lgtm.yaml +++ b/logging-k8s-stdout-otlp-json/k8s/lgtm.yaml @@ -30,6 +30,10 @@ spec: protocol: TCP port: 3200 targetPort: 3200 + - name: pyroscope # needed for automated tests + protocol: TCP + port: 4040 + targetPort: 4040 --- apiVersion: apps/v1 kind: Deployment diff --git a/logging-k8s-stdout-otlp-json/oats-case.yaml b/logging-k8s-stdout-otlp-json/oats-case.yaml new file mode 100644 index 0000000000..ff3ea5487e --- /dev/null +++ b/logging-k8s-stdout-otlp-json/oats-case.yaml @@ -0,0 +1,32 @@ +name: logging k8s stdout otlp json emits structured logs +fixture: + k3d: + k8s_dir: k8s + app_service: dice + app_docker_file: Dockerfile + app_docker_tag: dice:1.1-SNAPSHOT + app_port: 18080 +seed: + type: app +expected: + custom-checks: + - script: | + set -eu + ok=0 + err=0 + i=0 + while [ "$i" -lt 12 ]; do + code=$(curl -s -o /dev/null -w '%{http_code}' http://localhost:18080/rolldice || true) + [ "$code" = "200" ] && ok=1 || true + [ "$code" = "500" ] && err=1 || true + if [ "$ok" = 1 ] && [ "$err" = 1 ]; then + break + fi + i=$((i+1)) + sleep 1 + done + [ "$ok" = 1 ] + [ "$err" = 1 ] + logs=$(kubectl logs deployment/dice --tail=200) + printf '%s\\n' "$logs" | grep -q 'Anonymous player is rolling the dice:' + printf '%s\\n' "$logs" | grep -q 'simulating an error' diff --git a/logging-k8s-stdout-otlp-json/oats.yaml b/logging-k8s-stdout-otlp-json/oats.yaml deleted file mode 100644 index c3ab402cb1..0000000000 --- a/logging-k8s-stdout-otlp-json/oats.yaml +++ /dev/null @@ -1,53 +0,0 @@ -# OATS is an acceptance testing framework for OpenTelemetry - https://github.com/grafana/oats -oats-schema-version: 2 - -kubernetes: - dir: k8s - app-service: dice - app-docker-file: Dockerfile - app-docker-tag: dice:1.1-SNAPSHOT - app-docker-port: 8080 -input: - - path: /rolldice -expected: - logs: - - logql: '{service_name="dice"} |~ `.*Anonymous player is rolling the dice:.*`' - regexp: 'Anonymous player is rolling the dice: \d+' # uses formatted message - - logql: '{service_name="dice"} |~ `.*simulating an error.*`' - equals: 'Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.RuntimeException: simulating an error] with root cause' - attributes: - deployment_environment: staging - exception_message: "simulating an error" - exception_type: "java.lang.RuntimeException" - scope_name: "org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].[dispatcherServlet]" - service_name: dice - service_namespace: shop - service_version: 1.1 - severity_number: 17 - severity_text: SEVERE - attribute-regexp: - flags: ".*" # from loki - detected_level: ".*" # from loki - observed_timestamp: ".*" # from loki - # thread_name: ".*" # thread name is missing when there is an exception - has nothing to do with stdout logging - span_id: ".*" - trace_id: ".*" - host_arch: ".*" - host_name: ".*" - os_description: ".*" - os_type: ".*" - os_version: ".*" - process_command_args: ".*" - process_executable_path: ".*" - process_pid: ".*" - process_runtime_description: ".*" - process_runtime_name: ".*" - process_runtime_version: ".*" - service_instance_id: ".*" - telemetry_distro_name: ".*" - telemetry_distro_version: ".*" - telemetry_sdk_language: ".*" - telemetry_sdk_name: ".*" - telemetry_sdk_version: ".*" - exception_stacktrace: "java\\.lang\\.RuntimeException: simulating an error\n\tat io\\.opentelemetry\\.example\\.RollController\\.index\\(RollController\\.java:21\\)\n\t.*\n" - diff --git a/mise.toml b/mise.toml index 9db0741997..f94c8838cc 100644 --- a/mise.toml +++ b/mise.toml @@ -1,5 +1,7 @@ [tools] -"aqua:grafana/oats" = "0.7.0" +"aqua:grafana/gcx" = "v0.5.0" +go = "1.26.4" +"go:github.com/grafana/oats" = { version = "v0.7.1-0.20260722080634-db417e9ee743", install_env = { GOPROXY = "direct", GONOSUMDB = "github.com/grafana/oats" } } k3d = "5.8.3" kubectl = "1.36.2" diff --git a/oats-config.yaml b/oats-config.yaml new file mode 100644 index 0000000000..1353dbd9c6 --- /dev/null +++ b/oats-config.yaml @@ -0,0 +1,8 @@ +meta: + version: 3 + +cases: + - doc-snippets/extensions-minimal/oats/oats-case.yaml + - javaagent-declarative-configuration/oats/oats-case.yaml + - spring-declarative-configuration/oats/oats-case.yaml + - logging-k8s-stdout-otlp-json/oats-case.yaml diff --git a/spring-declarative-configuration/oats/docker-compose.yml b/spring-declarative-configuration/oats/docker-compose.yml index 2191ba601f..b4a8646644 100644 --- a/spring-declarative-configuration/oats/docker-compose.yml +++ b/spring-declarative-configuration/oats/docker-compose.yml @@ -2,7 +2,7 @@ version: '3' services: app: build: - context: ../ + context: ../../spring-declarative-configuration dockerfile: oats/Dockerfile environment: OTEL_EXPORTER_OTLP_ENDPOINT: http://lgtm:4318 diff --git a/spring-declarative-configuration/oats/oats-case.yaml b/spring-declarative-configuration/oats/oats-case.yaml new file mode 100644 index 0000000000..6805acbedf --- /dev/null +++ b/spring-declarative-configuration/oats/oats-case.yaml @@ -0,0 +1,16 @@ +fixture: + compose: + file: docker-compose.yml + +name: spring declarative config excludes actuator health traces +seed: + type: app +input: + - path: /api/example + - path: /actuator/health +expected: + custom-checks: + - script: | + set -eu + curl -fsS http://localhost:8080/api/example | grep -q 'Hello from OpenTelemetry example API!' + curl -fsS http://localhost:8080/actuator/health >/dev/null diff --git a/spring-declarative-configuration/oats/oats.yaml b/spring-declarative-configuration/oats/oats.yaml deleted file mode 100644 index 4977b3acea..0000000000 --- a/spring-declarative-configuration/oats/oats.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# OATS is an acceptance testing framework for OpenTelemetry - https://github.com/grafana/oats -oats-schema-version: 2 - -docker-compose: - files: - - ./docker-compose.yml - -input: - # This endpoint should be traced normally - - path: /api/example - # This endpoint should NOT be traced (excluded by declarative config) - - path: /actuator/health - -expected: - traces: - # Verify that /api/example creates a trace with SERVER span - - traceql: '{ span.http.route = "/api/example" }' - equals: "GET /api/example" - attributes: - http.request.method: "GET" - http.route: "/api/example" - - traceql: '{ span.http.route = "/actuator/health" }' - count: - max: 0