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

chore: Tracetest Cloud x K6 example #3452

Merged
merged 3 commits into from
Dec 18, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/tracetest-cloud-k6/.env.template
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TRACETEST_API_KEY=
2 changes: 2 additions & 0 deletions examples/tracetest-cloud-k6/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.env
k6
61 changes: 61 additions & 0 deletions examples/tracetest-cloud-k6/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Tracetest Cloud + K6

This example objective is to show how you can run load tests enhanced with trace-based testing using Tracetest Cloud and k6 against an instrumented service (Pokeshop API).
xoscar marked this conversation as resolved.
Show resolved Hide resolved

For more detailed information about the K6 Tracetest Binary take a look a the [docs](https://docs.tracetest.io/tools-and-integrations/integrations/k6).

## Prerequisites

1. Signing up to [app.tracetest.io](https://app.tracetest.io)
xoscar marked this conversation as resolved.
Show resolved Hide resolved
2. Creating an [environment](https://docs.tracetest.io/concepts/environments)
xoscar marked this conversation as resolved.
Show resolved Hide resolved
3. Having access to the environment's [agent token](https://docs.tracetest.io/configuration/agent)
xoscar marked this conversation as resolved.
Show resolved Hide resolved

## Steps

1. [Install the Tracetest CLI](https://docs.tracetest.io/installing/)
xoscar marked this conversation as resolved.
Show resolved Hide resolved
2. Copy the `.env.template` file into `.env` and add the `TRACETEST_API_KEY`. This is the Agent API token from your environment.
3. Create a [token from your environment](https://docs.tracetest.io/concepts/environment-tokens).
4. Run `tracetest configure` on a terminal and select the environment in use
xoscar marked this conversation as resolved.
Show resolved Hide resolved
5. Run the project by using docker-compose: `docker-compose up -d` (Linux) or `docker compose up -d` (Mac)
xoscar marked this conversation as resolved.
Show resolved Hide resolved
6. Test if it works by running: `tracetest run test -f tests/test.yaml`. This will create and run a test with trace id as trigger
xoscar marked this conversation as resolved.
Show resolved Hide resolved
7. Build the k6 binary with the extension by using `xk6 build v0.42.0 --with github.com/kubeshop/xk6-tracetest`
xoscar marked this conversation as resolved.
Show resolved Hide resolved
8. Now you are ready to run your load test, you can achieve this by running the following command: `XK6_TRACETEST_API_TOKEN=<your-environment-token> ./k6 run ./import-pokemon.js -o xk6-tracetest`
xoscar marked this conversation as resolved.
Show resolved Hide resolved
9. After the load test finishes you should be able to see an output like the following:

```bash
./k6 run ./import-pokemon.js -o xk6-tracetest
context menu


/\ |‾‾| /‾‾/ /‾‾/
/\ / \ | |/ / / /
/ \/ \ | ( / ‾‾\
/ \ | |\ \ | (‾) |
/ __________ \ |__| \__\ \_____/ .io

execution: local
script: ./import-pokemon.js
output: xk6-tracetest-output (TestRunID: 38055)

scenarios: (100.00%) 1 scenario, 1 max VUs, 35s max duration (incl. graceful stop):
* default: 1 looping VUs for 5s (gracefulStop: 30s)

[TotalRuns=6, SuccessfulRus=1, FailedRuns=5]
[FAILED]
[Request=GET - http://localhost:8081/pokemon/import, TraceID=dc0718bcecceeec731b343235eb9c15a, RunState=FINISHED FailingSpecs=true, TracetestURL= https://app.tracetest.io/organizations/ttorg_ced62e34638d965e/environments/ttenv_807d0129a10be776/test/kc_MgKoVR/run/11]
[Request=POST - http://localhost:8081/pokemon/import, TraceID=dc0718fe83cfeec7315daf10d212d351, RunState=FINISHED FailingSpecs=true, TracetestURL= https://app.tracetest.io/organizations/ttorg_ced62e34638d965e/environments/ttenv_807d0129a10be776/test/kc_MgKoVR/run/4]
[Request=POST - http://localhost:8081/pokemon/import, TraceID=dc0718a8f4ceeec731e47f13762e61b8, RunState=FINISHED FailingSpecs=true, TracetestURL= https://app.tracetest.io/organizations/ttorg_ced62e34638d965e/environments/ttenv_807d0129a10be776/test/kc_MgKoVR/run/8]
[Request=POST - http://localhost:8081/pokemon/import, TraceID=dc0718bcecceeec731b343235eb9c15a, RunState=FINISHED FailingSpecs=true, TracetestURL= https://app.tracetest.io/organizations/ttorg_ced62e34638d965e/environments/ttenv_807d0129a10be776/test/kc_MgKoVR/run/9]
[Request=POST - http://localhost:8081/pokemon/import, TraceID=dc071893fcceeec731148270c6671a1e, RunState=FINISHED FailingSpecs=true, TracetestURL= https://app.tracetest.io/organizations/ttorg_ced62e34638d965e/environments/ttenv_807d0129a10be776/test/kc_MgKoVR/run/6]
[SUCCESSFUL]
[Request=POST - http://localhost:8081/pokemon/import, TraceID=dc0718cee4ceeec731f3f414bf3a2a16, RunState=FINISHED FailingSpecs=false, TracetestURL= https://app.tracetest.io/organizations/ttorg_ced62e34638d965e/environments/ttenv_807d0129a10be776/test/kc_MgKoVR/run/3]

running (05.0s), 0/1 VUs, 5 complete and 0 interrupted iterations
default ✓ [======================================] 1 VUs 5s
```

## What's Next?

After running the initial set of tests, you can click the run link for any of them, update the assertions and run the scripts once more. This flow enables complete a trace-based TDD flow.

![assertions](assets/assertions.gif)
Binary file added examples/tracetest-cloud-k6/assets/assertions.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 22 additions & 0 deletions examples/tracetest-cloud-k6/collector.config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
receivers:
otlp:
protocols:
grpc:
http:

processors:
batch:
timeout: 100ms

exporters:
jaeger:
endpoint: jaeger:14250
tls:
insecure: true

service:
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [jaeger]
125 changes: 125 additions & 0 deletions examples/tracetest-cloud-k6/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
version: "3"

services:
tracetest-agent:
image: kubeshop/tracetest-agent:latest
environment:
TRACETEST_DEV: ${TRACETEST_DEV}
TRACETEST_API_KEY: ${TRACETEST_API_KEY}

postgres:
image: postgres:14
environment:
POSTGRES_PASSWORD: postgres
POSTGRES_USER: postgres
healthcheck:
test: pg_isready -U "$$POSTGRES_USER" -d "$$POSTGRES_DB"
interval: 1s
timeout: 5s
retries: 60

otel-collector:
image: otel/opentelemetry-collector:0.54.0
command:
- "--config"
- "/otel-local-config.yaml"
volumes:
- ./collector.config.yaml:/otel-local-config.yaml
depends_on:
- jaeger

jaeger:
image: jaegertracing/all-in-one:latest
restart: unless-stopped
healthcheck:
test: ["CMD", "wget", "--spider", "localhost:16686"]
interval: 1s
timeout: 3s
retries: 60

cache:
image: redis:6
restart: unless-stopped
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 1s
timeout: 3s
retries: 60

queue:
image: rabbitmq:3.8-management
restart: unless-stopped
healthcheck:
test: rabbitmq-diagnostics -q check_running
interval: 1s
timeout: 5s
retries: 60

demo-api:
image: kubeshop/demo-pokemon-api:latest
restart: unless-stopped
pull_policy: always
environment:
REDIS_URL: cache
DATABASE_URL: postgresql://postgres:postgres@postgres:5432/postgres?schema=public
RABBITMQ_HOST: queue
POKE_API_BASE_URL: https://pokeapi.co/api/v2
COLLECTOR_ENDPOINT: http://otel-collector:4317
NPM_RUN_COMMAND: api
healthcheck:
test: ["CMD", "wget", "--spider", "localhost:8081"]
interval: 1s
timeout: 3s
retries: 60
ports:
- 8081:8081
depends_on:
postgres:
condition: service_healthy
cache:
condition: service_healthy
queue:
condition: service_healthy

demo-worker:
image: kubeshop/demo-pokemon-api:latest
restart: unless-stopped
pull_policy: always
environment:
REDIS_URL: cache
DATABASE_URL: postgresql://postgres:postgres@postgres:5432/postgres?schema=public
RABBITMQ_HOST: queue
POKE_API_BASE_URL: https://pokeapi.co/api/v2
COLLECTOR_ENDPOINT: http://otel-collector:4317
NPM_RUN_COMMAND: worker
depends_on:
postgres:
condition: service_healthy
cache:
condition: service_healthy
queue:
condition: service_healthy

demo-rpc:
image: kubeshop/demo-pokemon-api:latest
restart: unless-stopped
pull_policy: always
environment:
REDIS_URL: cache
DATABASE_URL: postgresql://postgres:postgres@postgres:5432/postgres?schema=public
RABBITMQ_HOST: queue
POKE_API_BASE_URL: https://pokeapi.co/api/v2
COLLECTOR_ENDPOINT: http://otel-collector:4317
NPM_RUN_COMMAND: rpc
healthcheck:
test: ["CMD", "lsof", "-i", "8082"]
interval: 1s
timeout: 3s
retries: 60
depends_on:
postgres:
condition: service_healthy
cache:
condition: service_healthy
queue:
condition: service_healthy
56 changes: 56 additions & 0 deletions examples/tracetest-cloud-k6/import-pokemon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { Http, Tracetest } from "k6/x/tracetest";
import { sleep } from "k6";

export const options = {
vus: 1,
duration: "5s",
};

const http = new Http();
const testId = "kc_MgKoVR";
const tracetest = Tracetest();

let pokemonId = 6;

export default function () {
const url = "http://localhost:8081/pokemon/import";
const payload = JSON.stringify({
id: pokemonId++,
});
const params = {
headers: {
"Content-Type": "application/json",
},
tracetest: {
testId,
},
};

const response = http.post(url, payload, params);

tracetest.runTest(
response.trace_id,
{
test_id: testId,
variable_name: "TRACE_ID",
should_wait: true,
},
{
id: "123",
url,
method: "GET",
}
);

sleep(1);
}

export function handleSummary() {
return {
stdout: tracetest.summary(),
};
}

export function teardown() {
tracetest.validateResult();
}
23 changes: 23 additions & 0 deletions examples/tracetest-cloud-k6/tests/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
type: Test
spec:
id: kc_MgKoVR
name: K6
description: K6
trigger:
type: traceid
traceid:
id: ${env:TRACE_ID}
specs:
- selector: span[tracetest.span.type="general" name="import pokemon"]
name: Should have imported the pokemon
assertions:
- attr:tracetest.selected_spans.count = 1
- selector: |-
span[tracetest.span.type="http" net.peer.name="pokeapi.co" http.method="GET"]
name: Should trigger a request to the POKEAPI
assertions:
- attr:http.url = "https://pokeapi.co/api/v2/pokemon/6"
- selector: span[tracetest.span.type="database" name="create postgres.pokemon"]
name: Should insert the pokemon to the DB
assertions:
- attr:db.result | json_path '.name' = "charizard"
7 changes: 7 additions & 0 deletions examples/tracetest-cloud-k6/tracetest-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
postgres:
host: postgres
user: postgres
password: postgres
port: 5432
dbname: postgres
params: sslmode=disable
19 changes: 19 additions & 0 deletions examples/tracetest-cloud-k6/tracetest-provision.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
type: PollingProfile
spec:
name: Default
strategy: periodic
default: true
periodic:
retryDelay: 5s
timeout: 10m

---
type: DataStore
spec:
name: jaeger
type: jaeger
jaeger:
endpoint: jaeger:16685
tls:
insecure: true