diff --git a/examples/tracetest-grafana-tempo-pokeshop/.gitignore b/examples/tracetest-grafana-tempo-pokeshop/.gitignore new file mode 100644 index 0000000000..319a7df331 --- /dev/null +++ b/examples/tracetest-grafana-tempo-pokeshop/.gitignore @@ -0,0 +1,3 @@ +node_modules +.DS_Store +tempo-data \ No newline at end of file diff --git a/examples/tracetest-grafana-tempo-pokeshop/README.md b/examples/tracetest-grafana-tempo-pokeshop/README.md new file mode 100644 index 0000000000..2de80b0821 --- /dev/null +++ b/examples/tracetest-grafana-tempo-pokeshop/README.md @@ -0,0 +1,20 @@ +# Tracetest + Grafana Tempo + Pokeshop + + + +This examples' objective is to show how you can: + +1. Configure your Tracetest instance to connect to Grafana Tempo and use it as a trace data store. +2. Configure Grafana to query traces from Tempo + +## Steps + +1. [Install the tracetest CLI](https://docs.tracetest.io/installing/) +2. Run `tracetest configure --endpoint http://localhost:11633` on a terminal +3. Run the project by using docker-compose: `docker-compose up -d` (Linux) or `docker compose up -d` (Mac) +4. Test if it works by running: `tracetest test run -d tests/test.yaml`. This would trigger a test that will send and retrieve spans from the Grafana Tempo instance that is running on your machine. View the test on `http://localhost:11633`. +5. View traces in Grafana on `http://localhost:3000`. Use this TraceQL query: + + ```yaml + { name="POST /pokemon/import" } + ``` diff --git a/examples/tracetest-grafana-tempo-pokeshop/collector.config.yaml b/examples/tracetest-grafana-tempo-pokeshop/collector.config.yaml new file mode 100644 index 0000000000..94338fd811 --- /dev/null +++ b/examples/tracetest-grafana-tempo-pokeshop/collector.config.yaml @@ -0,0 +1,24 @@ +receivers: + otlp: + protocols: + grpc: + http: + +processors: + batch: + timeout: 100ms + +exporters: + logging: + loglevel: debug + otlp/tempo: + endpoint: tempo:4317 + tls: + insecure: true + +service: + pipelines: + traces: + receivers: [otlp] + processors: [batch] + exporters: [otlp/tempo] diff --git a/examples/tracetest-grafana-tempo-pokeshop/docker-compose.yml b/examples/tracetest-grafana-tempo-pokeshop/docker-compose.yml new file mode 100644 index 0000000000..e2e6f05769 --- /dev/null +++ b/examples/tracetest-grafana-tempo-pokeshop/docker-compose.yml @@ -0,0 +1,169 @@ +version: "3" +services: + + # Tracetest + tracetest: + image: kubeshop/tracetest:${TAG:-latest} + platform: linux/amd64 + volumes: + - type: bind + source: ./tracetest.config.yaml + target: /app/tracetest.yaml + - type: bind + source: ./tracetest.provision.yaml + target: /app/provisioning.yaml + ports: + - 11633:11633 + command: --provisioning-file /app/provisioning.yaml + extra_hosts: + - "host.docker.internal:host-gateway" + depends_on: + postgres: + condition: service_healthy + otel-collector: + condition: service_started + healthcheck: + test: ["CMD", "wget", "--spider", "localhost:11633"] + interval: 1s + timeout: 3s + retries: 60 + environment: + TRACETEST_DEV: ${TRACETEST_DEV} + # Tracetest End + + # Grafana + otel-collector: + image: otel/opentelemetry-collector-contrib:0.59.0 + command: + - "--config" + - "/otel-local-config.yaml" + volumes: + - ./collector.config.yaml:/otel-local-config.yaml + depends_on: + - tempo + tempo: + image: grafana/tempo:latest + command: [ "-config.file=/etc/tempo.yaml" ] + volumes: + - ./tempo.config.yaml:/etc/tempo.yaml + - ./tempo-data:/tmp/tempo + ports: + - "3200" # tempo + - "4317" # otlp grpc + - "4318" # otlp http + grafana: + image: grafana/grafana:9.4.3 + volumes: + - ./grafana.config.yaml:/etc/grafana/provisioning/datasources/datasources.yaml + environment: + - GF_AUTH_ANONYMOUS_ENABLED=true + - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin + - GF_AUTH_DISABLE_LOGIN_FORM=true + - GF_FEATURE_TOGGLES_ENABLE=traceqlEditor + ports: + - "3000:3000" + # Grafana End + + # Demo + 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 + ports: + - 5432:5432 + + demo-cache: + image: redis:6 + restart: unless-stopped + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 1s + timeout: 3s + retries: 60 + + demo-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: demo-cache + DATABASE_URL: postgresql://postgres:postgres@postgres:5432/postgres?schema=public + RABBITMQ_HOST: demo-queue + POKE_API_BASE_URL: https://pokeapi.co/api/v2 + COLLECTOR_ENDPOINT: http://otel-collector:4317 + NPM_RUN_COMMAND: api + ports: + - "8081:8081" + healthcheck: + test: ["CMD", "wget", "--spider", "localhost:8081"] + interval: 1s + timeout: 3s + retries: 60 + depends_on: + postgres: + condition: service_healthy + demo-cache: + condition: service_healthy + demo-queue: + condition: service_healthy + + demo-worker: + image: kubeshop/demo-pokemon-api:latest + restart: unless-stopped + pull_policy: always + environment: + REDIS_URL: demo-cache + DATABASE_URL: postgresql://postgres:postgres@postgres:5432/postgres?schema=public + RABBITMQ_HOST: demo-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 + demo-cache: + condition: service_healthy + demo-queue: + condition: service_healthy + + demo-rpc: + image: kubeshop/demo-pokemon-api:latest + restart: unless-stopped + pull_policy: always + environment: + REDIS_URL: demo-cache + DATABASE_URL: postgresql://postgres:postgres@postgres:5432/postgres?schema=public + RABBITMQ_HOST: demo-queue + POKE_API_BASE_URL: https://pokeapi.co/api/v2 + COLLECTOR_ENDPOINT: http://otel-collector:4317 + NPM_RUN_COMMAND: rpc + ports: + - 8082:8082 + healthcheck: + test: ["CMD", "lsof", "-i", "8082"] + interval: 1s + timeout: 3s + retries: 60 + depends_on: + postgres: + condition: service_healthy + demo-cache: + condition: service_healthy + demo-queue: + condition: service_healthy + # Demo End diff --git a/examples/tracetest-grafana-tempo-pokeshop/grafana.config.yaml b/examples/tracetest-grafana-tempo-pokeshop/grafana.config.yaml new file mode 100644 index 0000000000..25ce873388 --- /dev/null +++ b/examples/tracetest-grafana-tempo-pokeshop/grafana.config.yaml @@ -0,0 +1,14 @@ +apiVersion: 1 + +datasources: +- name: Tempo + type: tempo + access: proxy + orgId: 1 + url: http://tempo:3200 + basicAuth: false + isDefault: true + version: 1 + editable: false + apiVersion: 1 + uid: tempo diff --git a/examples/tracetest-grafana-tempo-pokeshop/tempo.config.yaml b/examples/tracetest-grafana-tempo-pokeshop/tempo.config.yaml new file mode 100644 index 0000000000..4ff4935c13 --- /dev/null +++ b/examples/tracetest-grafana-tempo-pokeshop/tempo.config.yaml @@ -0,0 +1,35 @@ +auth_enabled: false + +server: + http_listen_port: 3200 + grpc_listen_port: 9095 + +distributor: + receivers: + otlp: + protocols: + http: + grpc: + +ingester: + trace_idle_period: 10s + max_block_bytes: 1_000_000 + max_block_duration: 5m + +compactor: + compaction: + compaction_window: 1h + max_compaction_objects: 1000000 + block_retention: 1h + compacted_block_retention: 10m + +storage: + trace: + backend: local + wal: + path: /tmp/tempo/wal + local: + path: /tmp/tempo/blocks + pool: + max_workers: 100 + queue_depth: 10000 diff --git a/examples/tracetest-grafana-tempo-pokeshop/tests/curl_post.sh b/examples/tracetest-grafana-tempo-pokeshop/tests/curl_post.sh new file mode 100644 index 0000000000..4377e282cd --- /dev/null +++ b/examples/tracetest-grafana-tempo-pokeshop/tests/curl_post.sh @@ -0,0 +1 @@ +curl -d '{"id":"6"}' -H "Content-Type: application/json" -X POST http://localhost:8081/pokemon/import \ No newline at end of file diff --git a/examples/tracetest-grafana-tempo-pokeshop/tests/test.yaml b/examples/tracetest-grafana-tempo-pokeshop/tests/test.yaml new file mode 100644 index 0000000000..766796948c --- /dev/null +++ b/examples/tracetest-grafana-tempo-pokeshop/tests/test.yaml @@ -0,0 +1,33 @@ +type: Test +spec: + id: -ao9stJVg + name: Pokeshop - Import + description: Import a Pokemon + trigger: + type: http + httpRequest: + url: http://demo-api:8081/pokemon/import + method: POST + headers: + - key: Content-Type + value: application/json + body: '{"id":6}' + specs: + - name: Import Pokemon Span Exists + selector: span[tracetest.span.type="general" name="import pokemon"] + assertions: + - attr:tracetest.selected_spans.count = 1 + - name: Matching db result with the Pokemon Name + selector: span[tracetest.span.type="database" name="create postgres.pokemon" db.system="postgres" + db.name="postgres" db.user="postgres" db.operation="create" db.sql.table="pokemon"] + assertions: + - attr:db.result contains "charizard" + - name: Uses correct Pokemon ID + selector: span[tracetest.span.type="database" name="get pokemon_6" db.system="redis" + db.operation="get" db.redis.database_index="0"] + assertions: + - attr:db.payload = '{"key":"pokemon_6"}' + - name: 'All HTTP Spans: Status code is 200' + selector: span[tracetest.span.type="http"] + assertions: + - attr:http.status_code = 200 diff --git a/examples/tracetest-grafana-tempo-pokeshop/tracetest.config.yaml b/examples/tracetest-grafana-tempo-pokeshop/tracetest.config.yaml new file mode 100644 index 0000000000..fe32b236be --- /dev/null +++ b/examples/tracetest-grafana-tempo-pokeshop/tracetest.config.yaml @@ -0,0 +1,8 @@ +--- +postgres: + host: postgres + user: postgres + password: postgres + port: 5432 + dbname: postgres + params: sslmode=disable diff --git a/examples/tracetest-grafana-tempo-pokeshop/tracetest.provision.yaml b/examples/tracetest-grafana-tempo-pokeshop/tracetest.provision.yaml new file mode 100644 index 0000000000..a41ed54827 --- /dev/null +++ b/examples/tracetest-grafana-tempo-pokeshop/tracetest.provision.yaml @@ -0,0 +1,32 @@ +--- +type: PollingProfile +spec: + name: Default + strategy: periodic + default: true + periodic: + retryDelay: 5s + timeout: 10m + +--- +type: DataStore +spec: + name: Tempo + type: tempo + tempo: + type: grpc + grpc: + endpoint: tempo:9095 + tls: + insecure: true + +--- +type: Demo +spec: + type: pokeshop + enabled: true + name: pokeshop + opentelemetryStore: {} + pokeshop: + httpEndpoint: http://demo-api:8081 + grpcEndpoint: demo-rpc:8082 \ No newline at end of file