From 3b08e3d07241283364c3bd33371e665383e63eda Mon Sep 17 00:00:00 2001 From: YANGDB Date: Sat, 15 Jul 2023 09:32:07 -0700 Subject: [PATCH] upstream updates Signed-off-by: YANGDB Signed-off-by: YANGDB --- .env | 10 +- .github/workflows/build-images.yml | 133 +++++ .github/workflows/checks.yml | 3 + .github/workflows/release.yml | 117 +--- CHANGELOG.md | 4 + Makefile | 31 + docker-compose.minimal.yml | 544 ++++++++++++++++++ docker-compose.yml | 210 ++++++- kubernetes/opentelemetry-demo.yaml | 6 +- .../src/main/java/oteldemo/AdService.java | 17 +- .../src/featureflags/FeatureFlagHelper.cs | 16 +- src/checkoutservice/main.go | 15 +- src/frontend/Dockerfile.cypress | 2 +- src/frontend/cypress/e2e/Home.cy.ts | 4 +- src/frontendproxy/envoy.tmpl.yaml | 22 +- src/otelcollector/otelcol-observability.yml | 21 + src/productcatalogservice/main.go | 4 +- .../recommendation_server.py | 16 +- test/test.js | 4 +- test/tracetesting/Dockerfile | 17 + test/tracetesting/ad-service/all.yaml | 10 + test/tracetesting/ad-service/get.yaml | 28 + .../cart-service/add-item-to-cart.yaml | 35 ++ test/tracetesting/cart-service/all.yaml | 14 + .../cart-service/check-if-cart-is-empty.yaml | 27 + .../check-if-cart-is-populated.yaml | 28 + .../tracetesting/cart-service/empty-cart.yaml | 27 + test/tracetesting/checkout-service/all.yaml | 10 + .../checkout-service/place-order.yaml | 46 ++ test/tracetesting/cli-config.yml | 6 + test/tracetesting/currency-service/all.yaml | 11 + .../currency-service/convert.yaml | 34 ++ .../currency-service/supported.yaml | 25 + test/tracetesting/email-service/all.yaml | 10 + .../email-service/confirmation.yaml | 62 ++ .../frontend-service/01-see-ads.yaml | 35 ++ .../02-get-product-recommendation.yaml | 36 ++ .../frontend-service/03-browse-product.yaml | 31 + .../04-add-product-to-cart.yaml | 38 ++ .../frontend-service/05-view-cart.yaml | 25 + .../06-checking-out-cart.yaml | 60 ++ test/tracetesting/frontend-service/all.yaml | 15 + test/tracetesting/payment-service/all.yaml | 13 + .../amex-credit-card-not-allowed.yaml | 37 ++ .../payment-service/expired-credit-card.yaml | 37 ++ .../payment-service/invalid-credit-card.yaml | 37 ++ .../payment-service/valid-credit-card.yaml | 38 ++ .../product-catalog-service/all.yaml | 12 + .../product-catalog-service/get.yaml | 32 ++ .../product-catalog-service/list.yaml | 26 + .../product-catalog-service/search.yaml | 28 + .../recommendation-service/all.yaml | 10 + .../recommendation-service/list.yaml | 25 + test/tracetesting/run.bash | 80 +++ test/tracetesting/shipping-service/all.yaml | 12 + .../shipping-service/empty-quote.yaml | 36 ++ test/tracetesting/shipping-service/order.yaml | 39 ++ test/tracetesting/shipping-service/quote.yaml | 41 ++ test/tracetesting/tracetest-config.yaml | 24 + test/tracetesting/tracetest-provision.yaml | 31 + 60 files changed, 2191 insertions(+), 176 deletions(-) create mode 100644 .github/workflows/build-images.yml create mode 100644 docker-compose.minimal.yml create mode 100644 src/otelcollector/otelcol-observability.yml create mode 100644 test/tracetesting/Dockerfile create mode 100644 test/tracetesting/ad-service/all.yaml create mode 100644 test/tracetesting/ad-service/get.yaml create mode 100644 test/tracetesting/cart-service/add-item-to-cart.yaml create mode 100644 test/tracetesting/cart-service/all.yaml create mode 100644 test/tracetesting/cart-service/check-if-cart-is-empty.yaml create mode 100644 test/tracetesting/cart-service/check-if-cart-is-populated.yaml create mode 100644 test/tracetesting/cart-service/empty-cart.yaml create mode 100644 test/tracetesting/checkout-service/all.yaml create mode 100644 test/tracetesting/checkout-service/place-order.yaml create mode 100755 test/tracetesting/cli-config.yml create mode 100644 test/tracetesting/currency-service/all.yaml create mode 100644 test/tracetesting/currency-service/convert.yaml create mode 100644 test/tracetesting/currency-service/supported.yaml create mode 100644 test/tracetesting/email-service/all.yaml create mode 100644 test/tracetesting/email-service/confirmation.yaml create mode 100644 test/tracetesting/frontend-service/01-see-ads.yaml create mode 100644 test/tracetesting/frontend-service/02-get-product-recommendation.yaml create mode 100644 test/tracetesting/frontend-service/03-browse-product.yaml create mode 100644 test/tracetesting/frontend-service/04-add-product-to-cart.yaml create mode 100644 test/tracetesting/frontend-service/05-view-cart.yaml create mode 100644 test/tracetesting/frontend-service/06-checking-out-cart.yaml create mode 100644 test/tracetesting/frontend-service/all.yaml create mode 100644 test/tracetesting/payment-service/all.yaml create mode 100644 test/tracetesting/payment-service/amex-credit-card-not-allowed.yaml create mode 100644 test/tracetesting/payment-service/expired-credit-card.yaml create mode 100644 test/tracetesting/payment-service/invalid-credit-card.yaml create mode 100644 test/tracetesting/payment-service/valid-credit-card.yaml create mode 100644 test/tracetesting/product-catalog-service/all.yaml create mode 100644 test/tracetesting/product-catalog-service/get.yaml create mode 100644 test/tracetesting/product-catalog-service/list.yaml create mode 100644 test/tracetesting/product-catalog-service/search.yaml create mode 100644 test/tracetesting/recommendation-service/all.yaml create mode 100644 test/tracetesting/recommendation-service/list.yaml create mode 100755 test/tracetesting/run.bash create mode 100644 test/tracetesting/shipping-service/all.yaml create mode 100644 test/tracetesting/shipping-service/empty-quote.yaml create mode 100644 test/tracetesting/shipping-service/order.yaml create mode 100644 test/tracetesting/shipping-service/quote.yaml create mode 100644 test/tracetesting/tracetest-config.yaml create mode 100644 test/tracetesting/tracetest-provision.yaml diff --git a/.env b/.env index cf29de5e38..b4e1045a97 100644 --- a/.env +++ b/.env @@ -8,10 +8,10 @@ ENV_PLATFORM=local # OpenTelemetry Collector OTEL_COLLECTOR_HOST=otelcol -OTEL_COLLECTOR_PORT=4317 -OTEL_COLLECTOR_HEALTH_CHECK_PORT=1313 -OTEL_EXPORTER_OTLP_ENDPOINT=http://${OTEL_COLLECTOR_HOST}:${OTEL_COLLECTOR_PORT} -PUBLIC_OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:4318/v1/traces +OTEL_COLLECTOR_PORT_GRPC=4317 +OTEL_COLLECTOR_PORT_HTTP=4318 +OTEL_EXPORTER_OTLP_ENDPOINT=http://${OTEL_COLLECTOR_HOST}:${OTEL_COLLECTOR_PORT_GRPC} +PUBLIC_OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:8080/oltp-http/v1/traces # OpenTelemetry Resource Definitions OTEL_RESOURCE_ATTRIBUTES="service.namespace=opentelemetry-demo" @@ -43,7 +43,7 @@ EMAIL_SERVICE_PORT=6060 EMAIL_SERVICE_ADDR=http://emailservice:${EMAIL_SERVICE_PORT} # Feature Flag Service -FEATURE_FLAG_SERVICE_PORT=8881 +FEATURE_FLAG_SERVICE_PORT=8081 FEATURE_FLAG_SERVICE_ADDR=featureflagservice:${FEATURE_FLAG_SERVICE_PORT} FEATURE_FLAG_SERVICE_HOST=feature-flag-service FEATURE_FLAG_GRPC_SERVICE_PORT=50053 diff --git a/.github/workflows/build-images.yml b/.github/workflows/build-images.yml new file mode 100644 index 0000000000..594f68e89f --- /dev/null +++ b/.github/workflows/build-images.yml @@ -0,0 +1,133 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 +on: + workflow_call: + inputs: + push: + description: Should the images be pushed + default: false + required: false + type: boolean + version: + description: The version used when tagging the image + default: dev + required: false + type: string + +jobs: + build_and_push_images: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + env: + RELEASE_VERSION: "${{ github.event.release.tag_name }}" + DOCKERHUB_REPO: "otel/demo" + GHCR_REPO: "ghcr.io/open-telemetry/demo" + + strategy: + fail-fast: false + matrix: + file_tag: + - file: ./src/adservice/Dockerfile + tag_suffix: adservice + context: ./ + - file: ./src/cartservice/src/Dockerfile + tag_suffix: cartservice + context: ./ + - file: ./src/checkoutservice/Dockerfile + tag_suffix: checkoutservice + context: ./ + - file: ./src/currencyservice/Dockerfile + tag_suffix: currencyservice + context: ./src/currencyservice + - file: ./src/emailservice/Dockerfile + tag_suffix: emailservice + context: ./src/emailservice + # TODO: https://github.com/open-telemetry/opentelemetry-demo/issues/956 + # - file: ./src/featureflagservice/Dockerfile + # tag_suffix: featureflagservice + # context: ./ + - file: ./src/frontend/Dockerfile + tag_suffix: frontend + context: ./ + - file: ./src/frontendproxy/Dockerfile + tag_suffix: frontendproxy + context: ./ + - file: ./src/loadgenerator/Dockerfile + tag_suffix: loadgenerator + context: ./ + - file: ./src/paymentservice/Dockerfile + tag_suffix: paymentservice + context: ./ + - file: ./src/productcatalogservice/Dockerfile + tag_suffix: productcatalogservice + context: ./ + - file: ./src/quoteservice/Dockerfile + tag_suffix: quoteservice + context: ./ + - file: ./src/shippingservice/Dockerfile + tag_suffix: shippingservice + context: ./ + - file: ./src/recommendationservice/Dockerfile + tag_suffix: recommendationservice + context: ./ + - file: ./src/kafka/Dockerfile + tag_suffix: kafka + context: ./ + - file: ./src/accountingservice/Dockerfile + tag_suffix: accountingservice + context: ./ + - file: ./src/frauddetectionservice/Dockerfile + tag_suffix: frauddetectionservice + context: ./ + - file: ./src/frontend/Dockerfile.cypress + tag_suffix: frontend-tests + context: ./ + - file: ./test/Dockerfile + tag_suffix: integrationTests + context: ./ + + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Log in to the Container registry + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + if: ${{ inputs.push }} + + - name: Log in to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + if: ${{ inputs.push }} + + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + with: + config-inline: | + [worker.oci] + max-parallelism = 2 + + - name: Matrix Build and push demo images + uses: docker/build-push-action@v3.3.0 + with: + context: ${{ matrix.file_tag.context }} + file: ${{ matrix.file_tag.file }} + platforms: linux/amd64,linux/arm64 + push: ${{ inputs.push }} + tags: | + ${{ env.DOCKERHUB_REPO }}:${{ inputs.version }}-${{matrix.file_tag.tag_suffix }} + ${{ env.GHCR_REPO }}:${{ inputs.version }}-${{ matrix.file_tag.tag_suffix }} + cache-from: type=gha + cache-to: type=gha diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 4fa249f22e..e116c776b6 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -7,6 +7,9 @@ on: branches: [ main ] jobs: + build_images: + uses: ./.github/workflows/build-images.yml + markdownlint: runs-on: ubuntu-latest steps: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3d2b4491b2..6045c5444b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -8,116 +8,7 @@ on: jobs: build_and_push_images: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - - env: - RELEASE_VERSION: "${{ github.event.release.tag_name }}" - DOCKERHUB_REPO: "otel/demo" - GHCR_REPO: "ghcr.io/open-telemetry/demo" - - strategy: - matrix: - file_tag: - - file: ./src/adservice/Dockerfile - tag_suffix: adservice - context: ./ - - file: ./src/cartservice/src/Dockerfile - tag_suffix: cartservice - context: ./ - - file: ./src/checkoutservice/Dockerfile - tag_suffix: checkoutservice - context: ./ - - file: ./src/currencyservice/Dockerfile - tag_suffix: currencyservice - context: ./src/currencyservice - - file: ./src/emailservice/Dockerfile - tag_suffix: emailservice - context: ./src/emailservice - - file: ./src/featureflagservice/Dockerfile - tag_suffix: featureflagservice - context: ./ - - file: ./src/frontend/Dockerfile - tag_suffix: frontend - context: ./ - - file: ./src/frontendproxy/Dockerfile - tag_suffix: frontendproxy - context: ./ - - file: ./src/loadgenerator/Dockerfile - tag_suffix: loadgenerator - context: ./ - - file: ./src/paymentservice/Dockerfile - tag_suffix: paymentservice - context: ./ - - file: ./src/productcatalogservice/Dockerfile - tag_suffix: productcatalogservice - context: ./ - - file: ./src/quoteservice/Dockerfile - tag_suffix: quoteservice - context: ./ - - file: ./src/shippingservice/Dockerfile - tag_suffix: shippingservice - context: ./ - - file: ./src/recommendationservice/Dockerfile - tag_suffix: recommendationservice - context: ./ - - file: ./src/kafka/Dockerfile - tag_suffix: kafka - context: ./ - - file: ./src/accountingservice/Dockerfile - tag_suffix: accountingservice - context: ./ - - file: ./src/frauddetectionservice/Dockerfile - tag_suffix: frauddetectionservice - context: ./ - - file: ./src/frontend/Dockerfile.cypress - tag_suffix: frontend-tests - context: ./ - - file: ./test/Dockerfile - tag_suffix: integrationTests - context: ./ - - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - - name: Log in to the Container registry - uses: docker/login-action@v2 - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - if: github.event_name != 'pull_request' - - - name: Log in to Docker Hub - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - if: github.event_name != 'pull_request' - - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - with: - config-inline: | - [worker.oci] - max-parallelism = 2 - - - name: Matrix Build and push demo images - uses: docker/build-push-action@v3.3.0 - with: - context: ${{ matrix.file_tag.context }} - file: ${{ matrix.file_tag.file }} - platforms: linux/amd64,linux/arm64 - push: ${{ github.event_name != 'pull_request' }} - tags: | - ${{ env.DOCKERHUB_REPO }}:${{ env.RELEASE_VERSION || 'pr' }}-${{matrix.file_tag.tag_suffix }} - ${{ env.GHCR_REPO }}:${{ env.RELEASE_VERSION || 'pr' }}-${{ matrix.file_tag.tag_suffix }} - cache-from: type=gha - cache-to: type=gha + uses: ./.github/workflows/build-images.yml + with: + push: true + version: ${{ github.event.release.tag_name }}" diff --git a/CHANGELOG.md b/CHANGELOG.md index e78d4b72e0..1fb98ba6d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,10 @@ release. ([#935](https://github.com/open-telemetry/opentelemetry-demo/pull/935)) * [cartservice] update service to .NET 7 ([#942](https://github.com/open-telemetry/opentelemetry-demo/pull/942)) +* Introduce minimal mode to run demo + ([#872](https://github.com/open-telemetry/opentelemetry-demo/pull/872)) +* [frontendproxy]Envoy expose a route for the collector to route frontend spans + ([#938](https://github.com/open-telemetry/opentelemetry-demo/pull/938)) ## 1.4.0 diff --git a/Makefile b/Makefile index 620b01b18c..ff657bffb0 100644 --- a/Makefile +++ b/Makefile @@ -94,6 +94,10 @@ build-env-file: run-tests: docker compose run frontendTests docker compose run integrationTests + docker compose run traceBasedTests + +run-tracetesting: + docker compose run traceBasedTests .PHONY: generate-protobuf generate-protobuf: @@ -107,3 +111,30 @@ generate-kubernetes-manifests: echo "# SPDX-License-Identifier: Apache-2.0" >> kubernetes/opentelemetry-demo.yaml echo "# This file is generated by 'make generate-kubernetes-manifests'" >> kubernetes/opentelemetry-demo.yaml helm template opentelemetry-demo open-telemetry/opentelemetry-demo --namespace otel-demo | sed '/helm.sh\/chart\:/d' | sed '/helm.sh\/hook/d' | sed '/managed-by\: Helm/d' >> kubernetes/opentelemetry-demo.yaml + +.PHONY: start +start: + docker compose up --force-recreate --remove-orphans --detach + @echo "" + @echo "OpenTelemetry Demo is running." + @echo "Go to http://localhost:8080 for the demo UI." + @echo "Go to http://localhost:8080/jaeger/ui for the Jaeger UI." + @echo "Go to http://localhost:8080/grafana/ for the Grafana UI." + @echo "Go to http://localhost:8080/loadgen/ for the Load Generator UI." + @echo "Go to http://localhost:8080/feature/ for the Feature Flag UI." + +.PHONY: start-minimal +start-minimal: + docker compose -f docker-compose.minimal.yml up --force-recreate --remove-orphans --detach + @echo "" + @echo "OpenTelemetry Demo in minimal mode is running." + @echo "Go to http://localhost:8080 for the demo UI." + @echo "Go to http://localhost:8080/jaeger/ui for the Jaeger UI." + @echo "Go to http://localhost:8080/grafana/ for the Grafana UI." + @echo "Go to http://localhost:8080/loadgen/ for the Load Generator UI." + +.PHONY: stop +stop: + docker compose down --remove-orphans --volumes + @echo "" + @echo "OpenTelemetry Demo is stopped." diff --git a/docker-compose.minimal.yml b/docker-compose.minimal.yml new file mode 100644 index 0000000000..af32b0d1c3 --- /dev/null +++ b/docker-compose.minimal.yml @@ -0,0 +1,544 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +version: '3.9' +x-default-logging: &logging + driver: "json-file" + options: + max-size: "5m" + max-file: "2" + +networks: + default: + name: opentelemetry-demo + driver: bridge + +services: + # ****************** + # Core Demo Services + # ****************** + + # AdService + adservice: + image: ${IMAGE_NAME}:${IMAGE_VERSION}-adservice + container_name: ad-service + build: + context: ./ + dockerfile: ./src/adservice/Dockerfile + cache_from: + - ${IMAGE_NAME}:${IMAGE_VERSION}-adservice + deploy: + resources: + limits: + memory: 300M + restart: unless-stopped + ports: + - "${AD_SERVICE_PORT}" + environment: + - AD_SERVICE_PORT + - OTEL_EXPORTER_OTLP_ENDPOINT + - OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE + - OTEL_RESOURCE_ATTRIBUTES + - OTEL_LOGS_EXPORTER=otlp + - OTEL_SERVICE_NAME=adservice + depends_on: + otelcol: + condition: service_started + logging: *logging + + # Cart service + cartservice: + image: ${IMAGE_NAME}:${IMAGE_VERSION}-cartservice + container_name: cart-service + build: + context: ./ + dockerfile: ./src/cartservice/src/Dockerfile + cache_from: + - ${IMAGE_NAME}:${IMAGE_VERSION}-cartservice + deploy: + resources: + limits: + memory: 160M + restart: unless-stopped + ports: + - "${CART_SERVICE_PORT}" + environment: + - CART_SERVICE_PORT + - REDIS_ADDR + - OTEL_EXPORTER_OTLP_ENDPOINT + - OTEL_RESOURCE_ATTRIBUTES + - OTEL_SERVICE_NAME=cartservice + - ASPNETCORE_URLS=http://*:${CART_SERVICE_PORT} + depends_on: + redis-cart: + condition: service_started + otelcol: + condition: service_started + logging: *logging + + # Checkout service + checkoutservice: + image: ${IMAGE_NAME}:${IMAGE_VERSION}-checkoutservice + container_name: checkout-service + build: + context: ./ + dockerfile: ./src/checkoutservice/Dockerfile + cache_from: + - ${IMAGE_NAME}:${IMAGE_VERSION}-checkoutservice + deploy: + resources: + limits: + memory: 20M + restart: unless-stopped + ports: + - "${CHECKOUT_SERVICE_PORT}" + environment: + - CHECKOUT_SERVICE_PORT + - CART_SERVICE_ADDR + - CURRENCY_SERVICE_ADDR + - EMAIL_SERVICE_ADDR + - PAYMENT_SERVICE_ADDR + - PRODUCT_CATALOG_SERVICE_ADDR + - SHIPPING_SERVICE_ADDR + - OTEL_EXPORTER_OTLP_ENDPOINT + - OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE + - OTEL_RESOURCE_ATTRIBUTES + - OTEL_SERVICE_NAME=checkoutservice + depends_on: + cartservice: + condition: service_started + currencyservice: + condition: service_started + emailservice: + condition: service_started + paymentservice: + condition: service_started + productcatalogservice: + condition: service_started + shippingservice: + condition: service_started + otelcol: + condition: service_started + logging: *logging + + # Currency service + currencyservice: + image: ${IMAGE_NAME}:${IMAGE_VERSION}-currencyservice + container_name: currency-service + build: + context: ./src/currencyservice + cache_from: + - ${IMAGE_NAME}:${IMAGE_VERSION}-currencyservice + args: + - GRPC_VERSION=1.46.0 + - OPENTELEMETRY_VERSION=1.5.0 + deploy: + resources: + limits: + memory: 20M + restart: unless-stopped + ports: + - "${CURRENCY_SERVICE_PORT}" + environment: + - CURRENCY_SERVICE_PORT + - OTEL_EXPORTER_OTLP_ENDPOINT + - OTEL_RESOURCE_ATTRIBUTES=${OTEL_RESOURCE_ATTRIBUTES},service.name=currencyservice # The C++ SDK does not support OTEL_SERVICE_NAME + depends_on: + otelcol: + condition: service_started + logging: *logging + + # Email service + emailservice: + image: ${IMAGE_NAME}:${IMAGE_VERSION}-emailservice + container_name: email-service + build: + context: ./src/emailservice + cache_from: + - ${IMAGE_NAME}:${IMAGE_VERSION}-emailservice + deploy: + resources: + limits: + memory: 100M + restart: unless-stopped + ports: + - "${EMAIL_SERVICE_PORT}" + environment: + - APP_ENV=production + - EMAIL_SERVICE_PORT + - OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://${OTEL_COLLECTOR_HOST}:4318/v1/traces + - OTEL_RESOURCE_ATTRIBUTES + - OTEL_SERVICE_NAME=emailservice + depends_on: + otelcol: + condition: service_started + logging: *logging + + # Frontend + frontend: + image: ${IMAGE_NAME}:${IMAGE_VERSION}-frontend + container_name: frontend + build: + context: ./ + dockerfile: ./src/frontend/Dockerfile + cache_from: + - ${IMAGE_NAME}:${IMAGE_VERSION}-frontend + deploy: + resources: + limits: + memory: 200M + restart: unless-stopped + ports: + - "${FRONTEND_PORT}" + environment: + - PORT=${FRONTEND_PORT} + - FRONTEND_ADDR + - AD_SERVICE_ADDR + - CART_SERVICE_ADDR + - CHECKOUT_SERVICE_ADDR + - CURRENCY_SERVICE_ADDR + - PRODUCT_CATALOG_SERVICE_ADDR + - RECOMMENDATION_SERVICE_ADDR + - SHIPPING_SERVICE_ADDR + - OTEL_EXPORTER_OTLP_ENDPOINT + - OTEL_RESOURCE_ATTRIBUTES=${OTEL_RESOURCE_ATTRIBUTES} + - ENV_PLATFORM + - OTEL_SERVICE_NAME=frontend + - PUBLIC_OTEL_EXPORTER_OTLP_TRACES_ENDPOINT + - OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE + - WEB_OTEL_SERVICE_NAME=frontend-web + depends_on: + adservice: + condition: service_started + cartservice: + condition: service_started + checkoutservice: + condition: service_started + currencyservice: + condition: service_started + productcatalogservice: + condition: service_started + quoteservice: + condition: service_started + recommendationservice: + condition: service_started + shippingservice: + condition: service_started + otelcol: + condition: service_started + logging: *logging + + # Frontend Proxy (Envoy) + frontendproxy: + image: ${IMAGE_NAME}:${IMAGE_VERSION}-frontendproxy + container_name: frontend-proxy + build: + context: ./ + dockerfile: src/frontendproxy/Dockerfile + deploy: + resources: + limits: + memory: 50M + ports: + - "${ENVOY_PORT}:${ENVOY_PORT}" + - 10000:10000 + environment: + - FRONTEND_PORT + - FRONTEND_HOST + - FEATURE_FLAG_SERVICE_PORT + - FEATURE_FLAG_SERVICE_HOST + - LOCUST_WEB_HOST + - LOCUST_WEB_PORT + - GRAFANA_SERVICE_PORT + - GRAFANA_SERVICE_HOST + - JAEGER_SERVICE_PORT + - JAEGER_SERVICE_HOST + - OTEL_COLLECTOR_HOST + - OTEL_COLLECTOR_PORT_GRPC + - ENVOY_PORT + depends_on: + frontend: + condition: service_started + loadgenerator: + condition: service_started + jaeger: + condition: service_started + grafana: + condition: service_started + + # Load Generator + loadgenerator: + image: ${IMAGE_NAME}:${IMAGE_VERSION}-loadgenerator + container_name: load-generator + build: + context: ./ + dockerfile: ./src/loadgenerator/Dockerfile + cache_from: + - ${IMAGE_NAME}:${IMAGE_VERSION}-loadgenerator + deploy: + resources: + limits: + memory: 120M + restart: unless-stopped + ports: + - "${LOCUST_WEB_PORT}" + environment: + - LOCUST_WEB_PORT + - LOCUST_USERS + - LOCUST_HOST + - LOCUST_HEADLESS + - LOCUST_AUTOSTART + - OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://${OTEL_COLLECTOR_HOST}:4318/v1/traces + - OTEL_RESOURCE_ATTRIBUTES + - OTEL_SERVICE_NAME=loadgenerator + - PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python + depends_on: + frontend: + condition: service_started + logging: *logging + + # Payment service + paymentservice: + image: ${IMAGE_NAME}:${IMAGE_VERSION}-paymentservice + container_name: payment-service + build: + context: ./ + dockerfile: ./src/paymentservice/Dockerfile + cache_from: + - ${IMAGE_NAME}:${IMAGE_VERSION}-paymentservice + deploy: + resources: + limits: + memory: 120M + restart: unless-stopped + ports: + - "${PAYMENT_SERVICE_PORT}" + environment: + - PAYMENT_SERVICE_PORT + - OTEL_EXPORTER_OTLP_ENDPOINT + - OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE + - OTEL_RESOURCE_ATTRIBUTES + - OTEL_SERVICE_NAME=paymentservice + depends_on: + otelcol: + condition: service_started + logging: *logging + + # Product Catalog service + productcatalogservice: + image: ${IMAGE_NAME}:${IMAGE_VERSION}-productcatalogservice + container_name: product-catalog-service + build: + context: ./ + dockerfile: ./src/productcatalogservice/Dockerfile + cache_from: + - ${IMAGE_NAME}:${IMAGE_VERSION}-productcatalogservice + deploy: + resources: + limits: + memory: 20M + restart: unless-stopped + ports: + - "${PRODUCT_CATALOG_SERVICE_PORT}" + environment: + - PRODUCT_CATALOG_SERVICE_PORT + - OTEL_EXPORTER_OTLP_ENDPOINT + - OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE + - OTEL_RESOURCE_ATTRIBUTES + - OTEL_SERVICE_NAME=productcatalogservice + depends_on: + otelcol: + condition: service_started + logging: *logging + + # Quote service + quoteservice: + image: ${IMAGE_NAME}:${IMAGE_VERSION}-quoteservice + container_name: quote-service + build: + context: ./ + dockerfile: ./src/quoteservice/Dockerfile + cache_from: + - ${IMAGE_NAME}:${IMAGE_VERSION}-quoteservice + deploy: + resources: + limits: + memory: 40M + restart: unless-stopped + ports: + - "${QUOTE_SERVICE_PORT}" + environment: + - OTEL_EXPORTER_OTLP_ENDPOINT=http://${OTEL_COLLECTOR_HOST}:4318 + - OTEL_PHP_AUTOLOAD_ENABLED=true + - QUOTE_SERVICE_PORT + - OTEL_RESOURCE_ATTRIBUTES + - OTEL_SERVICE_NAME=quoteservice + depends_on: + otelcol: + condition: service_started + logging: *logging + + # Recommendation service + recommendationservice: + image: ${IMAGE_NAME}:${IMAGE_VERSION}-recommendationservice + container_name: recommendation-service + build: + context: ./ + dockerfile: ./src/recommendationservice/Dockerfile + cache_from: + - ${IMAGE_NAME}:${IMAGE_VERSION}-recommendationservice + deploy: + resources: + limits: + memory: 50M + restart: unless-stopped + ports: + - "${RECOMMENDATION_SERVICE_PORT}" + environment: + - RECOMMENDATION_SERVICE_PORT + - PRODUCT_CATALOG_SERVICE_ADDR + - OTEL_PYTHON_LOG_CORRELATION=true + - OTEL_EXPORTER_OTLP_ENDPOINT + - OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE + - OTEL_RESOURCE_ATTRIBUTES + - OTEL_SERVICE_NAME=recommendationservice + - PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python + depends_on: + productcatalogservice: + condition: service_started + otelcol: + condition: service_started + logging: *logging + + # Shipping service + shippingservice: + image: ${IMAGE_NAME}:${IMAGE_VERSION}-shippingservice + container_name: shipping-service + build: + context: ./ + dockerfile: ./src/shippingservice/Dockerfile + cache_from: + - ${IMAGE_NAME}:${IMAGE_VERSION}-shippingservice + deploy: + resources: + limits: + memory: 20M + restart: unless-stopped + ports: + - "${SHIPPING_SERVICE_PORT}" + environment: + - SHIPPING_SERVICE_PORT + - QUOTE_SERVICE_ADDR + - OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://${OTEL_COLLECTOR_HOST}:4317/v1/traces + - OTEL_RESOURCE_ATTRIBUTES + - OTEL_SERVICE_NAME=shippingservice + depends_on: + otelcol: + condition: service_started + logging: *logging + + # ****************** + # Dependent Services + # ****************** + # Redis used by Cart service + redis-cart: + image: redis:alpine + container_name: redis-cart + user: redis + deploy: + resources: + limits: + memory: 20M + restart: unless-stopped + ports: + - "${REDIS_PORT}" + logging: *logging + + + # ******************** + # Telemetry Components + # ******************** + # Jaeger + jaeger: + image: jaegertracing/all-in-one + container_name: jaeger + command: + - "--memory.max-traces" + - "10000" + - "--query.base-path" + - "/jaeger/ui" + - "--prometheus.server-url" + - "http://${PROMETHEUS_ADDR}" + deploy: + resources: + limits: + memory: 300M + restart: unless-stopped + ports: + - "${JAEGER_SERVICE_PORT}" # Jaeger UI + - "4317" # OTLP gRPC default port + environment: + - COLLECTOR_OTLP_ENABLED=true + - METRICS_STORAGE_TYPE=prometheus + logging: *logging + + # Grafana + grafana: + image: grafana/grafana:9.4.7 + container_name: grafana + deploy: + resources: + limits: + memory: 100M + volumes: + - ./src/grafana/grafana.ini:/etc/grafana/grafana.ini + - ./src/grafana/provisioning/:/etc/grafana/provisioning/ + ports: + - "${GRAFANA_SERVICE_PORT}" + logging: *logging + + # OpenTelemetry Collector + otelcol: + image: otel/opentelemetry-collector-contrib:0.76.1 + container_name: otel-col + deploy: + resources: + limits: + memory: 125M + restart: unless-stopped + command: [ "--config=/etc/otelcol-config.yml", "--config=/etc/otelcol-observability.yml", "--config=/etc/otelcol-config-extras.yml" ] + volumes: + - ./src/otelcollector/otelcol-config.yml:/etc/otelcol-config.yml + - ./src/otelcollector/otelcol-observability.yml:/etc/otelcol-observability.yml + - ./src/otelcollector/otelcol-config-extras.yml:/etc/otelcol-config-extras.yml + ports: + - "4317" # OTLP over gRPC receiver + - "4318:4318" # OTLP over HTTP receiver + - "9464" # Prometheus exporter + - "8888" # metrics endpoint + depends_on: + - jaeger + logging: *logging + + # Prometheus + prometheus: + image: quay.io/prometheus/prometheus:v2.43.0 + container_name: prometheus + command: + - --web.console.templates=/etc/prometheus/consoles + - --web.console.libraries=/etc/prometheus/console_libraries + - --storage.tsdb.retention.time=1h + - --config.file=/etc/prometheus/prometheus-config.yaml + - --storage.tsdb.path=/prometheus + - --web.enable-lifecycle + - --web.route-prefix=/ + - --enable-feature=exemplar-storage + volumes: + - ./src/prometheus/prometheus-config.yaml:/etc/prometheus/prometheus-config.yaml + deploy: + resources: + limits: + memory: 300M + ports: + - "${PROMETHEUS_SERVICE_PORT}:${PROMETHEUS_SERVICE_PORT}" + logging: *logging diff --git a/docker-compose.yml b/docker-compose.yml index aab0e91930..8d013effb7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,6 @@ # Copyright The OpenTelemetry Authors # SPDX-License-Identifier: Apache-2.0 - version: '3.9' x-default-logging: &logging driver: "json-file" @@ -74,7 +73,8 @@ services: - OTEL_LOGS_EXPORTER=otlp - OTEL_SERVICE_NAME=adservice depends_on: - - otelcol + otelcol: + condition: service_started logging: *logging # Cart service @@ -95,15 +95,16 @@ services: - "${CART_SERVICE_PORT}" environment: - CART_SERVICE_PORT - - FEATURE_FLAG_GRPC_SERVICE_ADDR - REDIS_ADDR - OTEL_EXPORTER_OTLP_ENDPOINT - OTEL_RESOURCE_ATTRIBUTES - OTEL_SERVICE_NAME=cartservice - ASPNETCORE_URLS=http://*:${CART_SERVICE_PORT} depends_on: - - redis-cart - - otelcol + redis-cart: + condition: service_started + otelcol: + condition: service_started logging: *logging # Checkout service @@ -177,7 +178,8 @@ services: - OTEL_EXPORTER_OTLP_ENDPOINT - OTEL_RESOURCE_ATTRIBUTES=${OTEL_RESOURCE_ATTRIBUTES},service.name=currencyservice # The C++ SDK does not support OTEL_SERVICE_NAME depends_on: - - otelcol + otelcol: + condition: service_started logging: *logging # Email service @@ -202,7 +204,8 @@ services: - OTEL_RESOURCE_ATTRIBUTES - OTEL_SERVICE_NAME=emailservice depends_on: - - otelcol + otelcol: + condition: service_started logging: *logging # Feature Flag service @@ -297,17 +300,67 @@ services: - OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE - WEB_OTEL_SERVICE_NAME=frontend-web depends_on: - - adservice - - cartservice - - checkoutservice - - currencyservice - - otelcol - - productcatalogservice - - quoteservice - - recommendationservice - - shippingservice + adservice: + condition: service_started + cartservice: + condition: service_started + checkoutservice: + condition: service_started + currencyservice: + condition: service_started + productcatalogservice: + condition: service_started + quoteservice: + condition: service_started + recommendationservice: + condition: service_started + shippingservice: + condition: service_started + otelcol: + condition: service_started logging: *logging + # Frontend Proxy (Envoy) + frontendproxy: + image: ${IMAGE_NAME}:${IMAGE_VERSION}-frontendproxy + container_name: frontend-proxy + build: + context: ./ + dockerfile: src/frontendproxy/Dockerfile + deploy: + resources: + limits: + memory: 50M + ports: + - "${ENVOY_PORT}:${ENVOY_PORT}" + - 10000:10000 + environment: + - FRONTEND_PORT + - FRONTEND_HOST + - FEATURE_FLAG_SERVICE_PORT + - FEATURE_FLAG_SERVICE_HOST + - LOCUST_WEB_HOST + - LOCUST_WEB_PORT + - GRAFANA_SERVICE_PORT + - GRAFANA_SERVICE_HOST + - JAEGER_SERVICE_PORT + - JAEGER_SERVICE_HOST + - OTEL_COLLECTOR_HOST + - OTEL_COLLECTOR_PORT_GRPC + - OTEL_COLLECTOR_PORT_HTTP + - ENVOY_PORT + depends_on: + frontend: + condition: service_started + featureflagservice: + condition: service_started + loadgenerator: + condition: service_started + jaeger: + condition: service_started + grafana: + condition: service_started + # Load Generator loadgenerator: image: ${IMAGE_NAME}:${IMAGE_VERSION}-loadgenerator @@ -335,7 +388,8 @@ services: - OTEL_SERVICE_NAME=loadgenerator - PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python depends_on: - - frontend + frontend: + condition: service_started logging: *logging # Payment service @@ -361,7 +415,8 @@ services: - OTEL_RESOURCE_ATTRIBUTES - OTEL_SERVICE_NAME=paymentservice depends_on: - - otelcol + otelcol: + condition: service_started logging: *logging # Product Catalog service @@ -391,7 +446,8 @@ services: - OTEL_RESOURCE_ATTRIBUTES - OTEL_SERVICE_NAME=productcatalogservice depends_on: - - otelcol + otelcol: + condition: service_started logging: *logging # Quote service @@ -418,7 +474,8 @@ services: - OTEL_RESOURCE_ATTRIBUTES - OTEL_SERVICE_NAME=quoteservice depends_on: - - otelcol + otelcol: + condition: service_started logging: *logging # Recommendation service @@ -448,12 +505,15 @@ services: - OTEL_SERVICE_NAME=recommendationservice - PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python depends_on: - - productcatalogservice - - otelcol - - featureflagservice + featureflagservice: + condition: service_started + productcatalogservice: + condition: service_started + otelcol: + condition: service_started logging: *logging - # Frontend Proxy service + # Frontend Nginx Proxy service nginx: image: nginx:latest container_name: nginx @@ -509,7 +569,8 @@ services: - OTEL_RESOURCE_ATTRIBUTES - OTEL_SERVICE_NAME=shippingservice depends_on: - - otelcol + otelcol: + condition: service_started logging: *logging # ****************** @@ -672,9 +733,10 @@ services: limits: memory: 125M restart: unless-stopped - command: [ "--config=/etc/otelcol-config.yml", "--config=/etc/otelcol-config-extras.yml" ] + command: [ "--config=/etc/otelcol-config.yml", "--config=/etc/otelcol-observability.yml", "--config=/etc/otelcol-config-extras.yml" ] volumes: - ./src/otelcollector/otelcol-config.yml:/etc/otelcol-config.yml + - ./src/otelcollector/otelcol-observability.yml:/etc/otelcol-observability.yml - ./src/otelcollector/otelcol-config-extras.yml:/etc/otelcol-config-extras.yml ports: - "4317" # OTLP over gRPC receiver @@ -840,3 +902,99 @@ services: - recommendationservice - shippingservice - quoteservice + + # Tracebased Tests + traceBasedTests: + image: ${IMAGE_NAME}:${IMAGE_VERSION}-traceBasedTests + container_name: traceBasedTests + profiles: + - tests + build: + context: ./ + dockerfile: ./test/tracetesting/Dockerfile + environment: + - AD_SERVICE_ADDR + - CART_SERVICE_ADDR + - CHECKOUT_SERVICE_ADDR + - CURRENCY_SERVICE_ADDR + - EMAIL_SERVICE_ADDR + - FRONTEND_ADDR + - PAYMENT_SERVICE_ADDR + - PRODUCT_CATALOG_SERVICE_ADDR + - RECOMMENDATION_SERVICE_ADDR + - SHIPPING_SERVICE_ADDR + extra_hosts: + - "host.docker.internal:host-gateway" + depends_on: + tracetest-server: + condition: service_healthy + # adding demo services as dependencies + frontend: + condition: service_started + adservice: + condition: service_started + cartservice: + condition: service_started + checkoutservice: + condition: service_started + currencyservice: + condition: service_started + emailservice: + condition: service_started + paymentservice: + condition: service_started + productcatalogservice: + condition: service_started + recommendationservice: + condition: service_started + shippingservice: + condition: service_started + quoteservice: + condition: service_started + + tracetest-server: + image: kubeshop/tracetest:latest + platform: linux/amd64 + container_name: tracetest-server + profiles: + - tests + volumes: + - type: bind + source: ./test/tracetesting/tracetest-config.yaml + target: /app/tracetest.yaml + - type: bind + source: ./test/tracetesting/tracetest-provision.yaml + target: /app/provision.yaml + command: --provisioning-file /app/provision.yaml + ports: + - 11633:11633 + extra_hosts: + - "host.docker.internal:host-gateway" + depends_on: + tracetest-postgres: + condition: service_healthy + otelcol: + condition: service_started + healthcheck: + test: [ "CMD", "wget", "--spider", "localhost:11633" ] + interval: 1s + timeout: 3s + retries: 60 + environment: + TRACETEST_DEV: ${TRACETEST_DEV} + + tracetest-postgres: + image: postgres:14 + container_name: tracetest-postgres + profiles: + - tests + 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 diff --git a/kubernetes/opentelemetry-demo.yaml b/kubernetes/opentelemetry-demo.yaml index 34313a755c..8b03b7cc47 100644 --- a/kubernetes/opentelemetry-demo.yaml +++ b/kubernetes/opentelemetry-demo.yaml @@ -7761,7 +7761,7 @@ spec: - name: WEB_OTEL_SERVICE_NAME value: frontend-web - name: PUBLIC_OTEL_EXPORTER_OTLP_TRACES_ENDPOINT - value: http://localhost:4318/v1/traces + value: http://localhost:8080/oltp-http/v1/traces - name: OTEL_RESOURCE_ATTRIBUTES value: service.name=$(OTEL_SERVICE_NAME),service.instance.id=$(OTEL_K8S_POD_UID),service.namespace=opentelemetry-demo,k8s.namespace.name=$(OTEL_K8S_NAMESPACE),k8s.node.name=$(OTEL_K8S_NODE_NAME),k8s.pod.name=$(OTEL_K8S_POD_NAME) resources: @@ -7860,8 +7860,10 @@ spec: value: "16686" - name: JAEGER_SERVICE_HOST value: 'opentelemetry-demo-jaeger-query' - - name: OTEL_COLLECTOR_PORT + - name: OTEL_COLLECTOR_PORT_GRPC value: "4317" + - name: OTEL_COLLECTOR_PORT_HTTP + value: "4318" - name: OTEL_COLLECTOR_HOST value: $(OTEL_COLLECTOR_NAME) - name: OTEL_RESOURCE_ATTRIBUTES diff --git a/src/adservice/src/main/java/oteldemo/AdService.java b/src/adservice/src/main/java/oteldemo/AdService.java index baa4e9f2e8..549c84ffa6 100644 --- a/src/adservice/src/main/java/oteldemo/AdService.java +++ b/src/adservice/src/main/java/oteldemo/AdService.java @@ -74,13 +74,12 @@ private void start() throws IOException { String featureFlagServiceAddr = Optional.ofNullable(System.getenv("FEATURE_FLAG_GRPC_SERVICE_ADDR")) - .orElseThrow( - () -> - new IllegalStateException( - "environment vars: FEATURE_FLAG_GRPC_SERVICE_ADDR must not be null")); - FeatureFlagServiceBlockingStub featureFlagServiceStub = - oteldemo.FeatureFlagServiceGrpc.newBlockingStub( - ManagedChannelBuilder.forTarget(featureFlagServiceAddr).usePlaintext().build()); + .orElse(""); + FeatureFlagServiceBlockingStub featureFlagServiceStub = null; + if (!featureFlagServiceAddr.isEmpty()) { + featureFlagServiceStub = oteldemo.FeatureFlagServiceGrpc.newBlockingStub( + ManagedChannelBuilder.forTarget(featureFlagServiceAddr).usePlaintext().build()); + } server = ServerBuilder.forPort(port) @@ -195,6 +194,10 @@ public void getAds(AdRequest req, StreamObserver responseObserver) { } boolean checkAdFailure() { + if (featureFlagServiceStub == null) { + return false; + } + // Flip a coin and fail 1/10th of the time if feature flag is enabled if (random.nextInt(10) != 1) { return false; diff --git a/src/cartservice/src/featureflags/FeatureFlagHelper.cs b/src/cartservice/src/featureflags/FeatureFlagHelper.cs index af9cf3d291..7256d8dcb2 100644 --- a/src/cartservice/src/featureflags/FeatureFlagHelper.cs +++ b/src/cartservice/src/featureflags/FeatureFlagHelper.cs @@ -13,13 +13,23 @@ public class FeatureFlagHelper public FeatureFlagHelper() { - var featureFlagServiceUri = new Uri($"http://{Environment.GetEnvironmentVariable("FEATURE_FLAG_GRPC_SERVICE_ADDR")}"); - var channel = Grpc.Net.Client.GrpcChannel.ForAddress(featureFlagServiceUri); - _featureFlagServiceClient = new FeatureFlagService.FeatureFlagServiceClient(channel); + var featureFlagServiceAddress = Environment.GetEnvironmentVariable("FEATURE_FLAG_GRPC_SERVICE_ADDR"); + if (string.IsNullOrEmpty(featureFlagServiceAddress)) + { + _featureFlagServiceClient = null; + } else { + var featureFlagServiceUri = new Uri($"http://{Environment.GetEnvironmentVariable("FEATURE_FLAG_GRPC_SERVICE_ADDR")}"); + var channel = Grpc.Net.Client.GrpcChannel.ForAddress(featureFlagServiceUri); + _featureFlagServiceClient = new FeatureFlagService.FeatureFlagServiceClient(channel); + } } public async Task GenerateCartError() { + if (_featureFlagServiceClient == null) + { + return false; + } if (Random.Next(10) != 1) { return false; diff --git a/src/checkoutservice/main.go b/src/checkoutservice/main.go index 5f0ebe704d..af4953df73 100644 --- a/src/checkoutservice/main.go +++ b/src/checkoutservice/main.go @@ -159,11 +159,13 @@ func main() { mustMapEnv(&svc.currencySvcAddr, "CURRENCY_SERVICE_ADDR") mustMapEnv(&svc.emailSvcAddr, "EMAIL_SERVICE_ADDR") mustMapEnv(&svc.paymentSvcAddr, "PAYMENT_SERVICE_ADDR") - mustMapEnv(&svc.kafkaBrokerSvcAddr, "KAFKA_SERVICE_ADDR") + svc.kafkaBrokerSvcAddr = os.Getenv("KAFKA_SERVICE_ADDR") - svc.KafkaProducerClient, err = kafka.CreateKafkaProducer([]string{svc.kafkaBrokerSvcAddr}, log) - if err != nil { - log.Fatal(err) + if svc.kafkaBrokerSvcAddr != "" { + svc.KafkaProducerClient, err = kafka.CreateKafkaProducer([]string{svc.kafkaBrokerSvcAddr}, log) + if err != nil { + log.Fatal(err) + } } log.Infof("service config: %+v", svc) @@ -277,7 +279,10 @@ func (cs *checkoutService) PlaceOrder(ctx context.Context, req *pb.PlaceOrderReq log.Infof("order confirmation email sent to %q", req.Email) } - cs.sendToPostProcessor(ctx, orderResult) + // send to kafka only if kafka broker address is set + if cs.kafkaBrokerSvcAddr != "" { + cs.sendToPostProcessor(ctx, orderResult) + } resp := &pb.PlaceOrderResponse{Order: orderResult} return resp, nil diff --git a/src/frontend/Dockerfile.cypress b/src/frontend/Dockerfile.cypress index 560eb2ccda..c421f753eb 100644 --- a/src/frontend/Dockerfile.cypress +++ b/src/frontend/Dockerfile.cypress @@ -1,6 +1,6 @@ FROM cypress/included:10.3.1-typescript WORKDIR /app COPY ./src/frontend . -RUN npm ci +RUN npm clean-install ENTRYPOINT ["cypress", "run"] diff --git a/src/frontend/cypress/e2e/Home.cy.ts b/src/frontend/cypress/e2e/Home.cy.ts index 1e5526d9a4..300912f696 100644 --- a/src/frontend/cypress/e2e/Home.cy.ts +++ b/src/frontend/cypress/e2e/Home.cy.ts @@ -12,14 +12,14 @@ describe('Home Page', () => { it('should validate the home page', () => { getElementByField(CypressFields.HomePage).should('exist'); - getElementByField(CypressFields.ProductCard, getElementByField(CypressFields.ProductList)).should('have.length', 9); + getElementByField(CypressFields.ProductCard, getElementByField(CypressFields.ProductList)).should('have.length', 10); getElementByField(CypressFields.SessionId).should('contain', SessionGateway.getSession().userId); }); it('should change currency', () => { getElementByField(CypressFields.CurrencySwitcher).select('EUR'); - getElementByField(CypressFields.ProductCard, getElementByField(CypressFields.ProductList)).should('have.length', 9); + getElementByField(CypressFields.ProductCard, getElementByField(CypressFields.ProductList)).should('have.length', 10); getElementByField(CypressFields.CurrencySwitcher).should('have.value', 'EUR'); diff --git a/src/frontendproxy/envoy.tmpl.yaml b/src/frontendproxy/envoy.tmpl.yaml index 2eb11a5570..431f76a166 100644 --- a/src/frontendproxy/envoy.tmpl.yaml +++ b/src/frontendproxy/envoy.tmpl.yaml @@ -22,7 +22,7 @@ static_resources: "@type": type.googleapis.com/envoy.config.trace.v3.OpenTelemetryConfig grpc_service: envoy_grpc: - cluster_name: opentelemetry_collector + cluster_name: opentelemetry_collector_grpc timeout: 0.250s service_name: frontend-proxy route_config: @@ -36,6 +36,8 @@ static_resources: route: { cluster: featureflag, prefix_rewrite: "/" } - match: { prefix: "/loadgen" } route: { cluster: loadgen, prefix_rewrite: "/" } + - match: { prefix: "/oltp-http/" } + route: { cluster: opentelemetry_collector_http, prefix_rewrite: "/" } - match: { prefix: "/jaeger" } route: { cluster: jaeger } - match: { prefix: "/grafana" } @@ -48,7 +50,7 @@ static_resources: "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router clusters: - - name: opentelemetry_collector + - name: opentelemetry_collector_grpc type: STRICT_DNS lb_policy: ROUND_ROBIN typed_extension_protocol_options: @@ -57,14 +59,26 @@ static_resources: explicit_http_config: http2_protocol_options: {} load_assignment: - cluster_name: opentelemetry_collector + cluster_name: opentelemetry_collector_grpc endpoints: - lb_endpoints: - endpoint: address: socket_address: address: ${OTEL_COLLECTOR_HOST} - port_value: ${OTEL_COLLECTOR_PORT} + port_value: ${OTEL_COLLECTOR_PORT_GRPC} + - name: opentelemetry_collector_http + type: STRICT_DNS + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: opentelemetry_collector_http + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: ${OTEL_COLLECTOR_HOST} + port_value: ${OTEL_COLLECTOR_PORT_HTTP} - name: frontend type: STRICT_DNS lb_policy: ROUND_ROBIN diff --git a/src/otelcollector/otelcol-observability.yml b/src/otelcollector/otelcol-observability.yml new file mode 100644 index 0000000000..9b7ebd7e2f --- /dev/null +++ b/src/otelcollector/otelcol-observability.yml @@ -0,0 +1,21 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + + +exporters: + otlp: + endpoint: "jaeger:4317" + tls: + insecure: true + prometheus: + endpoint: "otelcol:9464" + resource_to_telemetry_conversion: + enabled: true + enable_open_metrics: true + +service: + pipelines: + traces: + exporters: [otlp, logging, spanmetrics] + metrics: + exporters: [prometheus, logging] diff --git a/src/productcatalogservice/main.go b/src/productcatalogservice/main.go index 51bd43420c..c372772011 100644 --- a/src/productcatalogservice/main.go +++ b/src/productcatalogservice/main.go @@ -126,7 +126,7 @@ func main() { svc := &productCatalog{} var port string mustMapEnv(&port, "PRODUCT_CATALOG_SERVICE_PORT") - mustMapEnv(&svc.featureFlagSvcAddr, "FEATURE_FLAG_GRPC_SERVICE_ADDR") + svc.featureFlagSvcAddr = os.Getenv("FEATURE_FLAG_GRPC_SERVICE_ADDR") log.Infof("ProductCatalogService gRPC server started on port: %s", port) @@ -245,7 +245,7 @@ func (p *productCatalog) SearchProducts(ctx context.Context, req *pb.SearchProdu } func (p *productCatalog) checkProductFailure(ctx context.Context, id string) bool { - if id != "OLJCESPC7Z" { + if id != "OLJCESPC7Z" || p.featureFlagSvcAddr == "" { return false } diff --git a/src/recommendationservice/recommendation_server.py b/src/recommendationservice/recommendation_server.py index e996193bf0..88f03f368c 100644 --- a/src/recommendationservice/recommendation_server.py +++ b/src/recommendationservice/recommendation_server.py @@ -1,4 +1,3 @@ -#!/usr/bin/python # Copyright The OpenTelemetry Authors # SPDX-License-Identifier: Apache-2.0 #!/usr/bin/python @@ -34,6 +33,7 @@ cached_ids = [] first_run = True + class RecommendationService(demo_pb2_grpc.RecommendationServiceServicer): def ListRecommendations(self, request, context): prod_list = get_product_list(request.product_ids) @@ -107,16 +107,21 @@ def get_product_list(request_product_ids): return prod_list + def must_map_env(key: str): value = os.environ.get(key) if value is None: raise Exception(f'{key} environment variable must be set') return value + def check_feature_flag(flag_name: str): + if feature_flag_stub is None: + return False flag = feature_flag_stub.GetFlag(demo_pb2.GetFlagRequest(name=flag_name)).flag return flag.enabled + if __name__ == "__main__": service_name = must_map_env('OTEL_SERVICE_NAME') @@ -143,11 +148,14 @@ def check_feature_flag(flag_name: str): logger.addHandler(handler) catalog_addr = must_map_env('PRODUCT_CATALOG_SERVICE_ADDR') - ff_addr = must_map_env('FEATURE_FLAG_GRPC_SERVICE_ADDR') pc_channel = grpc.insecure_channel(catalog_addr) - ff_channel = grpc.insecure_channel(ff_addr) product_catalog_stub = demo_pb2_grpc.ProductCatalogServiceStub(pc_channel) - feature_flag_stub = demo_pb2_grpc.FeatureFlagServiceStub(ff_channel) + + ff_addr = os.environ.get('FEATURE_FLAG_GRPC_SERVICE_ADDR') + feature_flag_stub = None + if ff_addr is not None: + ff_channel = grpc.insecure_channel(ff_addr) + feature_flag_stub = demo_pb2_grpc.FeatureFlagServiceStub(ff_channel) # Create gRPC server server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) diff --git a/test/test.js b/test/test.js index 0d6071a6cc..0fd07167f0 100644 --- a/test/test.js +++ b/test/test.js @@ -254,7 +254,7 @@ test("payment: expired credit card", (t) => { test("product: list", async (t) => { const res = await productList({}); - t.is(res.products.length, 9); + t.is(res.products.length, 10); }); test("product: get", async (t) => { @@ -283,7 +283,7 @@ test("recommendation: list products", async (t) => { const req = deepCopy(data.recommend); const res = await recommend(req); - t.is(res.productIds.length, 4); + t.is(res.productIds.length, 5); t.is(arrayIntersection(res.productIds, req.productIds).length, 0); }); diff --git a/test/tracetesting/Dockerfile b/test/tracetesting/Dockerfile new file mode 100644 index 0000000000..0cec0abd95 --- /dev/null +++ b/test/tracetesting/Dockerfile @@ -0,0 +1,17 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + + +FROM alpine + +WORKDIR /app + +RUN apk --update add bash jq curl +RUN curl -L https://raw.githubusercontent.com/kubeshop/tracetest/main/install-cli.sh | bash + +COPY ./test/tracetesting ./test/tracetesting +COPY ./pb ./pb + +WORKDIR /app/test/tracetesting + +CMD ["/bin/sh", "/app/test/tracetesting/run.bash"] diff --git a/test/tracetesting/ad-service/all.yaml b/test/tracetesting/ad-service/all.yaml new file mode 100644 index 0000000000..70bdbcca31 --- /dev/null +++ b/test/tracetesting/ad-service/all.yaml @@ -0,0 +1,10 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Transaction +spec: + id: ad-service-all + name: 'Ad Service' + description: Run all Ad Service tests enabled in sequence + steps: + - ./get.yaml diff --git a/test/tracetesting/ad-service/get.yaml b/test/tracetesting/ad-service/get.yaml new file mode 100644 index 0000000000..58c18f8888 --- /dev/null +++ b/test/tracetesting/ad-service/get.yaml @@ -0,0 +1,28 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Test +spec: + id: ad-get-ads + name: 'Ad: get' + description: Get Ads from API + trigger: + type: grpc + grpc: + protobufFile: ../../../pb/demo.proto + address: ${env:AD_SERVICE_ADDR} + method: oteldemo.AdService.GetAds + request: |- + { + "contextKeys": [ "galaxy", "telescope" ] + } + specs: + - name: It returns two ads + selector: span[tracetest.span.type="rpc" name="oteldemo.AdService/GetAds" rpc.system="grpc" rpc.method="GetAds" rpc.service="oteldemo.AdService"] + assertions: + - attr:app.ads.count = 2 + - name: It returns a valid redirectUrl for each ads + selector: span[tracetest.span.type="general" name="Tracetest trigger"] + assertions: + - attr:tracetest.response.body | json_path '$.ads[0].redirectUrl' contains "/product/" + - attr:tracetest.response.body | json_path '$.ads[1].redirectUrl' contains "/product/" diff --git a/test/tracetesting/cart-service/add-item-to-cart.yaml b/test/tracetesting/cart-service/add-item-to-cart.yaml new file mode 100644 index 0000000000..a63ad7c632 --- /dev/null +++ b/test/tracetesting/cart-service/add-item-to-cart.yaml @@ -0,0 +1,35 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Test +spec: + id: cart-add-item-to-cart + name: 'Cart: add item to cart' + description: Add one item to the shopping cart + trigger: + type: grpc + grpc: + protobufFile: ../../../pb/demo.proto + address: ${env:CART_SERVICE_ADDR} + method: oteldemo.CartService.AddItem + request: |- + { + "userId": "1234", + "item": { + "productId": "OLJCESPC7Z", + "quantity": 1 + } + } + specs: + - name: It added an item correctly into the shopping cart + selector: span[name="oteldemo.CartService/AddItem"] + assertions: + - attr:rpc.grpc.status_code = 0 + - name: It set the cart item correctly on the database + selector: span[tracetest.span.type="database" name="HMSET" db.system="redis" db.redis.database_index="0"] + assertions: + - attr:db.statement = "HMSET 1234" + - name: It returned an empty cart + selector: span[tracetest.span.type="general" name="Tracetest trigger"] + assertions: + - "attr:tracetest.response.body = '{\n \n}'" diff --git a/test/tracetesting/cart-service/all.yaml b/test/tracetesting/cart-service/all.yaml new file mode 100644 index 0000000000..89a5457344 --- /dev/null +++ b/test/tracetesting/cart-service/all.yaml @@ -0,0 +1,14 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Transaction +spec: + id: cart-all + name: 'Cart Service' + description: Run all Cart tests enabled in sequence + steps: + - ./empty-cart.yaml + - ./add-item-to-cart.yaml + - ./check-if-cart-is-populated.yaml + - ./empty-cart.yaml + - ./check-if-cart-is-empty.yaml diff --git a/test/tracetesting/cart-service/check-if-cart-is-empty.yaml b/test/tracetesting/cart-service/check-if-cart-is-empty.yaml new file mode 100644 index 0000000000..53292b2d9b --- /dev/null +++ b/test/tracetesting/cart-service/check-if-cart-is-empty.yaml @@ -0,0 +1,27 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Test +spec: + id: cart-check-if-cart-is-empty + name: 'Cart: check if cart is empty' + description: Check if the shopping cart has no items + trigger: + type: grpc + grpc: + protobufFile: ../../../pb/demo.proto + address: ${env:CART_SERVICE_ADDR} + method: oteldemo.CartService.GetCart + request: |- + { + "userId": "1234" + } + specs: + - name: It retrieved the cart items correctly + selector: span[name="oteldemo.CartService/GetCart"] + assertions: + - attr:rpc.grpc.status_code = 0 + - name: It returned no items + selector: span[tracetest.span.type="general" name="Tracetest trigger"] + assertions: + - attr:tracetest.response.body | json_path '$.items' = "[]" diff --git a/test/tracetesting/cart-service/check-if-cart-is-populated.yaml b/test/tracetesting/cart-service/check-if-cart-is-populated.yaml new file mode 100644 index 0000000000..25e5d8a1a7 --- /dev/null +++ b/test/tracetesting/cart-service/check-if-cart-is-populated.yaml @@ -0,0 +1,28 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Test +spec: + id: cart-check-if-cart-is-populated + name: 'Cart: check if cart is populated' + description: Check if the shopping cart has one item + trigger: + type: grpc + grpc: + protobufFile: ../../../pb/demo.proto + address: ${env:CART_SERVICE_ADDR} + method: oteldemo.CartService.GetCart + request: |- + { + "userId": "1234" + } + specs: + - name: It retrieved the cart items correctly + selector: span[name="oteldemo.CartService/GetCart"] + assertions: + - attr:rpc.grpc.status_code = 0 + - name: It returned the first item with correct attributes + selector: span[tracetest.span.type="general" name="Tracetest trigger"] + assertions: + - attr:tracetest.response.body | json_path '$.items[0].quantity' = 1 + - attr:tracetest.response.body | json_path '$.items[0].productId' = "OLJCESPC7Z" diff --git a/test/tracetesting/cart-service/empty-cart.yaml b/test/tracetesting/cart-service/empty-cart.yaml new file mode 100644 index 0000000000..7fdf4f6f20 --- /dev/null +++ b/test/tracetesting/cart-service/empty-cart.yaml @@ -0,0 +1,27 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Test +spec: + id: cart-empty-cart + name: 'Cart: empty cart' + description: Clean shopping cart + trigger: + type: grpc + grpc: + protobufFile: ../../../pb/demo.proto + address: ${env:CART_SERVICE_ADDR} + method: oteldemo.CartService.EmptyCart + request: |- + { + "userId": "1234" + } + specs: + - name: It emptied the shopping cart with success + selector: span[name="oteldemo.CartService/EmptyCart"] + assertions: + - attr:rpc.grpc.status_code = 0 + - name: It sent cleaning message to the database + selector: span[tracetest.span.type="database" name="EXPIRE" db.system="redis" db.redis.database_index="0"] + assertions: + - attr:db.statement = "EXPIRE 1234" diff --git a/test/tracetesting/checkout-service/all.yaml b/test/tracetesting/checkout-service/all.yaml new file mode 100644 index 0000000000..031e478414 --- /dev/null +++ b/test/tracetesting/checkout-service/all.yaml @@ -0,0 +1,10 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Transaction +spec: + id: checkout-service-all + name: 'Checkout Service' + description: Run all Checkout Service tests enabled in sequence + steps: + - ./place-order.yaml diff --git a/test/tracetesting/checkout-service/place-order.yaml b/test/tracetesting/checkout-service/place-order.yaml new file mode 100644 index 0000000000..14e88ef119 --- /dev/null +++ b/test/tracetesting/checkout-service/place-order.yaml @@ -0,0 +1,46 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Test +spec: + id: checkout-place-order + name: 'Checkout: place order' + description: Place one order on the system + trigger: + type: grpc + grpc: + protobufFile: ../../../pb/demo.proto + address: ${env:CHECKOUT_SERVICE_ADDR} + method: oteldemo.CheckoutService.PlaceOrder + request: |- + { + "userId": "1997", + "userCurrency": "USD", + "address": { + "streetAddress": "410 Terry Ave. North", + "city": "Seattle", + "state": "Washington", + "country": "United States", + "zipCode": "98109" + }, + "email": "amazon@example.com", + "creditCard": { + "creditCardNumber": "4117-7059-6121-5486", + "creditCardCvv": 346, + "creditCardExpirationYear": 2025, + "creditCardExpirationMonth": 3 + } + } + specs: + - name: It returns a valid order + selector: span[tracetest.span.type="general" name="Tracetest trigger"] + assertions: + - attr:tracetest.response.body | json_path '$.order.orderId' != "" + - attr:tracetest.response.body | json_path '$.order.shippingTrackingId' != "" + - attr:tracetest.response.body | json_path '$.order.shippingAddress' != "{}" + - attr:tracetest.response.body | json_path '$.order.shippingCost.currencyCode' = "USD" + - name: It calls the PlaceOrder method successfuly + selector: span[tracetest.span.type="rpc" name="oteldemo.CheckoutService/PlaceOrder" + rpc.system="grpc" rpc.method="PlaceOrder" rpc.service="oteldemo.CheckoutService"] + assertions: + - attr:rpc.grpc.status_code = 0 diff --git a/test/tracetesting/cli-config.yml b/test/tracetesting/cli-config.yml new file mode 100755 index 0000000000..9cd26732c7 --- /dev/null +++ b/test/tracetesting/cli-config.yml @@ -0,0 +1,6 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +scheme: http +endpoint: tracetest-server:11633 +analyticsEnabled: false diff --git a/test/tracetesting/currency-service/all.yaml b/test/tracetesting/currency-service/all.yaml new file mode 100644 index 0000000000..ee1bdc4965 --- /dev/null +++ b/test/tracetesting/currency-service/all.yaml @@ -0,0 +1,11 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Transaction +spec: + id: currency-service-all + name: 'Currency Service' + description: Run all Currency Service tests enabled in sequence + steps: + - ./convert.yaml + - ./supported.yaml diff --git a/test/tracetesting/currency-service/convert.yaml b/test/tracetesting/currency-service/convert.yaml new file mode 100644 index 0000000000..f0c6ead817 --- /dev/null +++ b/test/tracetesting/currency-service/convert.yaml @@ -0,0 +1,34 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Test +spec: + id: currency-convert + name: 'Currency: Convert' + description: Convert a currency + trigger: + type: grpc + grpc: + protobufFile: ../../../pb/demo.proto + address: ${env:CURRENCY_SERVICE_ADDR} + method: oteldemo.CurrencyService.Convert + request: |- + { + "from": { + "currencyCode": "USD", + "units": 330, + "nanos": 750000000 + }, + "toCode": "CAD" + } + specs: + - name: It converts from USD to CAD + selector: span[tracetest.span.type="rpc" name="CurrencyService/Convert" rpc.system="grpc" + rpc.method="Convert" rpc.service="CurrencyService"] + assertions: + - attr:app.currency.conversion.from = "USD" + - attr:app.currency.conversion.to = "CAD" + - name: It has more nanos than expected + selector: span[tracetest.span.type="general" name="Tracetest trigger"] + assertions: + - attr:tracetest.response.body| json_path '$.nanos' >= 599380800 diff --git a/test/tracetesting/currency-service/supported.yaml b/test/tracetesting/currency-service/supported.yaml new file mode 100644 index 0000000000..491dd03cc8 --- /dev/null +++ b/test/tracetesting/currency-service/supported.yaml @@ -0,0 +1,25 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Test +spec: + id: currency-supported + name: 'Currency: Supported' + description: Get all supported currencies + trigger: + type: grpc + grpc: + protobufFile: ../../../pb/demo.proto + address: ${env:CURRENCY_SERVICE_ADDR} + method: oteldemo.CurrencyService.GetSupportedCurrencies + specs: + - name: It has a span called "CurrencyService/GetSupportedCurrencies" + selector: span[tracetest.span.type="rpc" name="CurrencyService/GetSupportedCurrencies" + rpc.system="grpc" rpc.method="GetSupportedCurrencies" rpc.service="CurrencyService"] + assertions: + - attr:name = "CurrencyService/GetSupportedCurrencies" + - name: It returns the expected currency codes + selector: span[tracetest.span.type="general" name="Tracetest trigger"] + assertions: + - attr:tracetest.response.body | json_path '$.currencyCodes[0]' = "ZAR" + - attr:tracetest.response.body | json_path '$.currencyCodes[32]' = "MYR" diff --git a/test/tracetesting/email-service/all.yaml b/test/tracetesting/email-service/all.yaml new file mode 100644 index 0000000000..3fde9a62e4 --- /dev/null +++ b/test/tracetesting/email-service/all.yaml @@ -0,0 +1,10 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Transaction +spec: + id: email-service-all + name: 'Email Service' + description: Run all Email Service tests enabled in sequence + steps: + - ./confirmation.yaml diff --git a/test/tracetesting/email-service/confirmation.yaml b/test/tracetesting/email-service/confirmation.yaml new file mode 100644 index 0000000000..e586f6d3bc --- /dev/null +++ b/test/tracetesting/email-service/confirmation.yaml @@ -0,0 +1,62 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Test +spec: + id: email-confirmation + name: 'Email: Confirmation' + description: Send an order confirmation email + trigger: + type: http + httpRequest: + url: ${env:EMAIL_SERVICE_ADDR}/send_order_confirmation + method: POST + headers: + - key: Content-Type + value: application/json + body: | + { + "email": "google@example.com", + "order": { + "order_id": "505", + "shipping_tracking_id": "dead-beef", + "shipping_cost": { + "currency_code": "USD", + "units": 17, + "nanos": 980000000 + }, + "shipping_address": { + "street_address_1": "1600 Amphitheatre Parkway", + "city": "Mountain View", + "state": "California", + "country": "United States", + "zip_code": "94043" + }, + "items": [ + { + "item": { + "product_id": "1YMWWN1N4O", + "quantity": 5 + }, + "cost": { + "currency_code": "USD", + "units": 100, + "nanos": 0 + } + } + ] + } + } + specs: + - name: It should be called successfully + selector: span[tracetest.span.type="http" name="POST /send_order_confirmation" http.method="POST"] + assertions: + - attr:http.status_code = 200 + - name: It should render a email to send + selector: span[tracetest.span.type="general" name="sinatra.render_template"] + assertions: + - attr:name = "sinatra.render_template" + - name: It should send an email + selector: span[tracetest.span.type="general" name="send_email"] + assertions: + - attr:name = "send_email" diff --git a/test/tracetesting/frontend-service/01-see-ads.yaml b/test/tracetesting/frontend-service/01-see-ads.yaml new file mode 100644 index 0000000000..0e9e7fd6d9 --- /dev/null +++ b/test/tracetesting/frontend-service/01-see-ads.yaml @@ -0,0 +1,35 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Test +spec: + id: frontend-see-adds + name: 'Frontend: See Ads' + description: Simulate the user seeing a ads on Astronomy Shop + trigger: + type: http + httpRequest: + url: http://${env:FRONTEND_ADDR}/api/data + method: GET + headers: + - key: Content-Type + value: application/json + body: | + { + "contextKeys": [ + "binoculars", + "telescopes", + "accessories" + ] + } + specs: + - name: It called the frontend with success and got a valid redirectUrl for each ads + selector: span[tracetest.span.type="general" name="Tracetest trigger"] + assertions: + - attr:tracetest.response.status = 200 + - attr:tracetest.response.body | json_path '$[0].redirectUrl' contains "/product/" + - attr:tracetest.response.body | json_path '$[1].redirectUrl' contains "/product/" + - name: It returns two ads + selector: span[tracetest.span.type="rpc" name="oteldemo.AdService/GetAds" rpc.system="grpc" rpc.method="GetAds" rpc.service="oteldemo.AdService"] + assertions: + - attr:app.ads.count = 2 diff --git a/test/tracetesting/frontend-service/02-get-product-recommendation.yaml b/test/tracetesting/frontend-service/02-get-product-recommendation.yaml new file mode 100644 index 0000000000..bc0bb2a87c --- /dev/null +++ b/test/tracetesting/frontend-service/02-get-product-recommendation.yaml @@ -0,0 +1,36 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Test +spec: + id: frontend-get-recommendation + name: 'Frontend: Get recommendations' + description: Simulate the user seeing recomendations on Astronomy Shop + trigger: + type: http + httpRequest: + url: http://${env:FRONTEND_ADDR}/api/recommendations + method: GET + headers: + - key: Content-Type + value: application/json + body: | + { + "productIds":[ + "0PUK6V6EV0", + "1YMWWN1N4O", + "2ZYFJ3GM2N", + "66VCHSJNUP", + "6E92ZMYYFZ" + ] + } + specs: + - name: It called the frontend with success + selector: span[tracetest.span.type="general" name="Tracetest trigger"] + assertions: + - attr:tracetest.response.status = 200 + - name: It called ListRecommendations correctly and got 5 products + selector: span[tracetest.span.type="rpc" name="/oteldemo.RecommendationService/ListRecommendations" rpc.system="grpc" rpc.method="ListRecommendations" rpc.service="oteldemo.RecommendationService"] + assertions: + - attr:rpc.grpc.status_code = 0 + - attr:app.products_recommended.count = 5 diff --git a/test/tracetesting/frontend-service/03-browse-product.yaml b/test/tracetesting/frontend-service/03-browse-product.yaml new file mode 100644 index 0000000000..041a0c582f --- /dev/null +++ b/test/tracetesting/frontend-service/03-browse-product.yaml @@ -0,0 +1,31 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Test +spec: + id: frontend-browse-product + name: 'Frontend: Browse products' + description: Simulate the user browsing products on Astronomy Shop + trigger: + type: http + httpRequest: + url: http://${env:FRONTEND_ADDR}/api/products/0PUK6V6EV0 + method: GET + headers: + - key: Content-Type + value: application/json + specs: + - name: It called the frontend with success and got a product with valid attributes + selector: span[tracetest.span.type="general" name="Tracetest trigger"] + assertions: + - attr:tracetest.response.status = 200 + - attr:tracetest.response.body | json_path '$.id' = "0PUK6V6EV0" + - attr:tracetest.response.body | json_path '$.description' != "" + - attr:tracetest.response.body | json_path '$.picture' != "" + - attr:tracetest.response.body | json_path '$.priceUsd' != "{}" + - attr:tracetest.response.body | json_path '$.categories' != "[]" + - name: It queried the product catalog correctly for a specific product + selector: span[tracetest.span.type="rpc" name="oteldemo.ProductCatalogService/GetProduct" rpc.system="grpc" rpc.method="GetProduct" rpc.service="oteldemo.ProductCatalogService"] + assertions: + - attr:rpc.grpc.status_code = 0 + - attr:app.product.id = "0PUK6V6EV0" diff --git a/test/tracetesting/frontend-service/04-add-product-to-cart.yaml b/test/tracetesting/frontend-service/04-add-product-to-cart.yaml new file mode 100644 index 0000000000..5c838c6685 --- /dev/null +++ b/test/tracetesting/frontend-service/04-add-product-to-cart.yaml @@ -0,0 +1,38 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Test +spec: + id: frontend-add-product + name: 'Frontend: Add product to the cart' + description: Simulate a user adding a selected product to the shopping cart + trigger: + type: http + httpRequest: + url: http://${env:FRONTEND_ADDR}/api/cart + method: POST + headers: + - key: Content-Type + value: application/json + body: | + { + "item": { + "productId": "0PUK6V6EV0", + "quantity": 2 + }, + "userId": "2491f868-88f1-4345-8836-d5d8511a9f83" + } + specs: + - name: It called the frontend with success + selector: span[tracetest.span.type="general" name="Tracetest trigger"] + assertions: + - attr:tracetest.response.status = 200 + - name: It added an item correctly into the shopping cart + selector: span[name="oteldemo.CartService/AddItem"] + assertions: + - attr:rpc.grpc.status_code = 0 + - attr:app.product.id = "0PUK6V6EV0" + - name: It set the cart item correctly on the database + selector: span[tracetest.span.type="database" name="HMSET" db.system="redis" db.redis.database_index="0"] + assertions: + - attr:db.statement = "HMSET 2491f868-88f1-4345-8836-d5d8511a9f83" diff --git a/test/tracetesting/frontend-service/05-view-cart.yaml b/test/tracetesting/frontend-service/05-view-cart.yaml new file mode 100644 index 0000000000..f029ceadb9 --- /dev/null +++ b/test/tracetesting/frontend-service/05-view-cart.yaml @@ -0,0 +1,25 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Test +spec: + id: frontend-view-cart + name: 'Frontend: View cart' + description: Simulate a user viewing the shopping cart + trigger: + type: http + httpRequest: + url: http://${env:FRONTEND_ADDR}/api/cart?userId=2491f868-88f1-4345-8836-d5d8511a9f83 + method: GET + headers: + - key: Content-Type + value: application/json + specs: + - name: It called the frontend with success + selector: span[tracetest.span.type="general" name="Tracetest trigger"] + assertions: + - attr:tracetest.response.status = 200 + - name: It retrieved the cart items correctly + selector: span[name="oteldemo.CartService/GetCart"] + assertions: + - attr:rpc.grpc.status_code = 0 diff --git a/test/tracetesting/frontend-service/06-checking-out-cart.yaml b/test/tracetesting/frontend-service/06-checking-out-cart.yaml new file mode 100644 index 0000000000..3c9be1579b --- /dev/null +++ b/test/tracetesting/frontend-service/06-checking-out-cart.yaml @@ -0,0 +1,60 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Test +spec: + id: frontend-checkout-shopping-cart + name: 'Frontend: Checking out shopping cart' + description: Simulate user checking out shopping cart + trigger: + type: http + httpRequest: + url: http://${env:FRONTEND_ADDR}/api/checkout + method: POST + headers: + - key: Content-Type + value: application/json + body: | + { + "userId": "2491f868-88f1-4345-8836-d5d8511a9f83", + "email": "someone@example.com", + "address": { + "streetAddress": "1600 Amphitheatre Parkway", + "state": "CA", + "country": "United States", + "city": "Mountain View", + "zipCode": "94043" + }, + "userCurrency": "USD", + "creditCard": { + "creditCardCvv": 672, + "creditCardExpirationMonth": 1, + "creditCardExpirationYear": 2030, + "creditCardNumber": "4432-8015-6152-0454" + } + } + specs: + - name: It called the frontend with success + selector: span[tracetest.span.type="general" name="Tracetest trigger"] + assertions: + - attr:tracetest.response.status = 200 + - selector: span[tracetest.span.type="rpc" name="oteldemo.CheckoutService/PlaceOrder" rpc.system="grpc" rpc.method="PlaceOrder" rpc.service="oteldemo.CheckoutService"] + name: "The order was placed" + assertions: + - attr:app.user.id = "2491f868-88f1-4345-8836-d5d8511a9f83" + - attr:app.order.items.count = 1 + - selector: span[tracetest.span.type="rpc" name="oteldemo.PaymentService/Charge" rpc.system="grpc" rpc.method="Charge" rpc.service="oteldemo.PaymentService"] + name: "The user was charged" + assertions: + - attr:rpc.grpc.status_code = 0 + - attr:tracetest.selected_spans.count >= 1 + - selector: span[tracetest.span.type="rpc" name="oteldemo.ShippingService/ShipOrder" rpc.system="grpc" rpc.method="ShipOrder" rpc.service="oteldemo.ShippingService"] + name: "The product was shipped" + assertions: + - attr:rpc.grpc.status_code = 0 + - attr:tracetest.selected_spans.count >= 1 + - selector: span[tracetest.span.type="rpc" name="oteldemo.CartService/EmptyCart" rpc.system="grpc" rpc.method="EmptyCart" rpc.service="oteldemo.CartService"] + name: "The cart was emptied" + assertions: + - attr:rpc.grpc.status_code = 0 + - attr:tracetest.selected_spans.count >= 1 diff --git a/test/tracetesting/frontend-service/all.yaml b/test/tracetesting/frontend-service/all.yaml new file mode 100644 index 0000000000..f3b8635d3b --- /dev/null +++ b/test/tracetesting/frontend-service/all.yaml @@ -0,0 +1,15 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Transaction +spec: + id: frontend-all + name: 'Frontend Service' + description: Run all Frontend tests enabled in sequence, simulating a process of a user purchasing products on Astronomy store + steps: + - ./01-see-ads.yaml + - ./02-get-product-recommendation.yaml + - ./03-browse-product.yaml + - ./04-add-product-to-cart.yaml + - ./05-view-cart.yaml + - ./06-checking-out-cart.yaml diff --git a/test/tracetesting/payment-service/all.yaml b/test/tracetesting/payment-service/all.yaml new file mode 100644 index 0000000000..d27c985755 --- /dev/null +++ b/test/tracetesting/payment-service/all.yaml @@ -0,0 +1,13 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Transaction +spec: + id: payment-service-all + name: 'Payment Service' + description: Run all Payment Service tests enabled in sequence + steps: + - ./valid-credit-card.yaml + - ./invalid-credit-card.yaml + - ./amex-credit-card-not-allowed.yaml + - ./expired-credit-card.yaml diff --git a/test/tracetesting/payment-service/amex-credit-card-not-allowed.yaml b/test/tracetesting/payment-service/amex-credit-card-not-allowed.yaml new file mode 100644 index 0000000000..0f04a39232 --- /dev/null +++ b/test/tracetesting/payment-service/amex-credit-card-not-allowed.yaml @@ -0,0 +1,37 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Test +spec: + id: payment-amex-credit-card-not-allowed + name: 'Payment: Amex credit card not allowed' + description: Charge customer with an Amex credit card + trigger: + type: grpc + grpc: + protobufFile: ../../../pb/demo.proto + address: ${env:PAYMENT_SERVICE_ADDR} + method: oteldemo.PaymentService.Charge + request: |- + { + "amount": { + "currencyCode": "USD", + "units": 43, + "nanos": 130000000 + }, + "creditCard": { + "creditCardNumber": "3714 496353 98431", + "creditCardCvv": 672, + "creditCardExpirationYear": 2039, + "creditCardExpirationMonth": 1 + } + } + specs: + - name: It should call Charge method and receive a gRPC error + selector: span[tracetest.span.type="rpc" name="grpc.oteldemo.PaymentService/Charge" rpc.system="grpc" rpc.method="Charge" rpc.service="oteldemo.PaymentService"] + assertions: + - attr:grpc.error_message = "Sorry, we cannot process amex credit cards. Only VISA or MasterCard is accepted." + - name: It should return a return an gRPC error code to the caller + selector: span[tracetest.span.type="general" name="Tracetest trigger"] + assertions: + - attr:tracetest.response.status = 2 diff --git a/test/tracetesting/payment-service/expired-credit-card.yaml b/test/tracetesting/payment-service/expired-credit-card.yaml new file mode 100644 index 0000000000..fbc8272d98 --- /dev/null +++ b/test/tracetesting/payment-service/expired-credit-card.yaml @@ -0,0 +1,37 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Test +spec: + id: payment-expired-credit-card + name: 'Payment: expired credit card' + description: Charge customer with an expired credit card + trigger: + type: grpc + grpc: + protobufFile: ../../../pb/demo.proto + address: ${env:PAYMENT_SERVICE_ADDR} + method: oteldemo.PaymentService.Charge + request: |- + { + "amount": { + "currencyCode": "USD", + "units": 43, + "nanos": 130000000 + }, + "creditCard": { + "creditCardNumber": "4432-8015-6152-0454", + "creditCardCvv": 672, + "creditCardExpirationYear": 2021, + "creditCardExpirationMonth": 1 + } + } + specs: + - name: It should call Charge method and receive a gRPC error + selector: span[tracetest.span.type="rpc" name="grpc.oteldemo.PaymentService/Charge" rpc.system="grpc" rpc.method="Charge" rpc.service="oteldemo.PaymentService"] + assertions: + - attr:grpc.error_message = "The credit card (ending 0454) expired on 1/2021." + - name: It should return a return an gRPC error code to the caller + selector: span[tracetest.span.type="general" name="Tracetest trigger"] + assertions: + - attr:tracetest.response.status = 2 diff --git a/test/tracetesting/payment-service/invalid-credit-card.yaml b/test/tracetesting/payment-service/invalid-credit-card.yaml new file mode 100644 index 0000000000..4bc67fda2a --- /dev/null +++ b/test/tracetesting/payment-service/invalid-credit-card.yaml @@ -0,0 +1,37 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Test +spec: + id: payment-invalid-credit-card + name: 'Payment: invalid credit card' + description: Charge customer with an invalid credit card + trigger: + type: grpc + grpc: + protobufFile: ../../../pb/demo.proto + address: ${env:PAYMENT_SERVICE_ADDR} + method: oteldemo.PaymentService.Charge + request: |- + { + "amount": { + "currencyCode": "USD", + "units": 43, + "nanos": 130000000 + }, + "creditCard": { + "creditCardNumber": "0000-0000-0000-0000", + "creditCardCvv": 672, + "creditCardExpirationYear": 2039, + "creditCardExpirationMonth": 1 + } + } + specs: + - name: It should call Charge method and receive a gRPC error + selector: span[tracetest.span.type="rpc" name="grpc.oteldemo.PaymentService/Charge" rpc.system="grpc" rpc.method="Charge" rpc.service="oteldemo.PaymentService"] + assertions: + - attr:grpc.error_message = "Credit card info is invalid." + - name: It should return a return an gRPC error code to the caller + selector: span[tracetest.span.type="general" name="Tracetest trigger"] + assertions: + - attr:tracetest.response.status = 2 diff --git a/test/tracetesting/payment-service/valid-credit-card.yaml b/test/tracetesting/payment-service/valid-credit-card.yaml new file mode 100644 index 0000000000..2a3d41941b --- /dev/null +++ b/test/tracetesting/payment-service/valid-credit-card.yaml @@ -0,0 +1,38 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Test +spec: + id: payment-valid-credit-card + name: 'Payment: valid credit card' + description: Charge customer with a valid credit card + trigger: + type: grpc + grpc: + protobufFile: ../../../pb/demo.proto + address: ${env:PAYMENT_SERVICE_ADDR} + method: oteldemo.PaymentService.Charge + request: |- + { + "amount": { + "currencyCode": "USD", + "units": 43, + "nanos": 130000000 + }, + "creditCard": { + "creditCardNumber": "4432-8015-6152-0454", + "creditCardCvv": 672, + "creditCardExpirationYear": 2039, + "creditCardExpirationMonth": 1 + } + } + specs: + - name: It should call Charge method successfully + selector: span[tracetest.span.type="rpc" name="grpc.oteldemo.PaymentService/Charge" rpc.system="grpc" rpc.method="Charge" rpc.service="oteldemo.PaymentService"] + # instead of returning status_code 0, this service returns 1, but it works as intended + assertions: + - attr:rpc.grpc.status_code = 1 + - name: It should return a transaction ID + selector: span[tracetest.span.type="general" name="Tracetest trigger"] + assertions: + - attr:tracetest.response.body | json_path '$.transactionId' != "" diff --git a/test/tracetesting/product-catalog-service/all.yaml b/test/tracetesting/product-catalog-service/all.yaml new file mode 100644 index 0000000000..5d0a5c6ef6 --- /dev/null +++ b/test/tracetesting/product-catalog-service/all.yaml @@ -0,0 +1,12 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Transaction +spec: + id: product-catalog-service-all + name: 'Product Catalog Service' + description: Run all Product Catalog Service tests enabled in sequence + steps: + - ./list.yaml + - ./get.yaml + - ./search.yaml diff --git a/test/tracetesting/product-catalog-service/get.yaml b/test/tracetesting/product-catalog-service/get.yaml new file mode 100644 index 0000000000..b46679a000 --- /dev/null +++ b/test/tracetesting/product-catalog-service/get.yaml @@ -0,0 +1,32 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Test +spec: + id: product-get + name: 'Product: Get' + description: Get a single product available on product catalog + trigger: + type: grpc + grpc: + protobufFile: ../../../pb/demo.proto + address: ${env:PRODUCT_CATALOG_SERVICE_ADDR} + method: oteldemo.ProductCatalogService.GetProduct + request: |- + { + "id": "OLJCESPC7Z" + } + specs: + - name: It queried the product catalog correctly for a specific product + selector: span[tracetest.span.type="rpc" name="oteldemo.ProductCatalogService/GetProduct" rpc.system="grpc" rpc.method="GetProduct" rpc.service="oteldemo.ProductCatalogService"] + assertions: + - attr:rpc.grpc.status_code = 0 + - attr:app.product.id = "OLJCESPC7Z" + - name: It returned a product with valid attributes + selector: span[tracetest.span.type="general" name="Tracetest trigger"] + assertions: + - attr:tracetest.response.body | json_path '$.id' = "OLJCESPC7Z" + - attr:tracetest.response.body | json_path '$.description' != "" + - attr:tracetest.response.body | json_path '$.picture' != "" + - attr:tracetest.response.body | json_path '$.priceUsd' != "{}" + - attr:tracetest.response.body | json_path '$.categories' != "[]" diff --git a/test/tracetesting/product-catalog-service/list.yaml b/test/tracetesting/product-catalog-service/list.yaml new file mode 100644 index 0000000000..0ad5d56cfa --- /dev/null +++ b/test/tracetesting/product-catalog-service/list.yaml @@ -0,0 +1,26 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Test +spec: + id: product-list + name: 'Product: List' + description: List all products available on product catalog + trigger: + type: grpc + grpc: + protobufFile: ../../../pb/demo.proto + address: ${env:PRODUCT_CATALOG_SERVICE_ADDR} + method: oteldemo.ProductCatalogService.ListProducts + request: "" + specs: + - name: It queried the product catalog correctly + selector: span[tracetest.span.type="rpc" name="oteldemo.ProductCatalogService/ListProducts" + rpc.system="grpc" rpc.method="ListProducts" rpc.service="oteldemo.ProductCatalogService"] + assertions: + - attr:rpc.grpc.status_code = 0 + - attr:app.products.count = 10 + - name: It returned products with IDs + selector: span[tracetest.span.type="general" name="Tracetest trigger"] + assertions: + - attr:tracetest.response.body | json_path '$.products[*].id' != "" diff --git a/test/tracetesting/product-catalog-service/search.yaml b/test/tracetesting/product-catalog-service/search.yaml new file mode 100644 index 0000000000..2c3f1e3e9d --- /dev/null +++ b/test/tracetesting/product-catalog-service/search.yaml @@ -0,0 +1,28 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Test +spec: + id: product-search + name: 'Product: Search' + description: Search for products querying for their names + trigger: + type: grpc + grpc: + protobufFile: ../../../pb/demo.proto + address: ${env:PRODUCT_CATALOG_SERVICE_ADDR} + method: oteldemo.ProductCatalogService.SearchProducts + request: |- + { + "query": "Roof Binoculars" + } + specs: + - name: It called SearchProducts correctly and it returned 1 item + selector: span[tracetest.span.type="rpc" name="oteldemo.ProductCatalogService/SearchProducts" rpc.system="grpc" rpc.method="SearchProducts" rpc.service="oteldemo.ProductCatalogService"] + assertions: + - attr:app.products_search.count = 1 + - attr:rpc.grpc.status_code = 0 + - name: It returned the desired product + selector: span[tracetest.span.type="general" name="Tracetest trigger"] + assertions: + - attr:tracetest.response.body | json_path '$.results[0].name' = "Roof Binoculars" diff --git a/test/tracetesting/recommendation-service/all.yaml b/test/tracetesting/recommendation-service/all.yaml new file mode 100644 index 0000000000..b739a2e917 --- /dev/null +++ b/test/tracetesting/recommendation-service/all.yaml @@ -0,0 +1,10 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Transaction +spec: + id: recommendation-service-all + name: 'Recommendation Service' + description: Run all Recommendation Service tests enabled in sequence + steps: + - ./list.yaml diff --git a/test/tracetesting/recommendation-service/list.yaml b/test/tracetesting/recommendation-service/list.yaml new file mode 100644 index 0000000000..e6d5539696 --- /dev/null +++ b/test/tracetesting/recommendation-service/list.yaml @@ -0,0 +1,25 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Test +spec: + id: recommendation-list + name: 'Recommendation: List products' + description: List all products recommended to an user + trigger: + type: grpc + grpc: + protobufFile: ../../../pb/demo.proto + address: ${env:RECOMMENDATION_SERVICE_ADDR} + method: oteldemo.RecommendationService.ListRecommendations + request: |- + { + "userId": "1234", + "productIds": [ "OLJCESPC7Z", "66VCHSJNUP", "1YMWWN1N4O", "L9ECAV7KIM", "2ZYFJ3GM2N" ] + } + specs: + - name: It called ListRecommendations correctly and got 5 products + selector: span[tracetest.span.type="rpc" name="/oteldemo.RecommendationService/ListRecommendations" rpc.system="grpc" rpc.method="ListRecommendations" rpc.service="oteldemo.RecommendationService"] + assertions: + - attr:rpc.grpc.status_code = 0 + - attr:app.products_recommended.count = 5 diff --git a/test/tracetesting/run.bash b/test/tracetesting/run.bash new file mode 100755 index 0000000000..75ee37083a --- /dev/null +++ b/test/tracetesting/run.bash @@ -0,0 +1,80 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 +#/bin/bash + +# This script set up how to run Tracetest and which test files +# be executed + +set -e + +check_if_tracetest_is_installed() { + if ! command -v tracetest &> /dev/null + then + echo "tracetest CLI could not be found" + exit -1 + fi +} + +create_env_file() { + cat << EOF > tracetesting-env.yaml +type: Environment +spec: + id: tracetesting-env + name: tracetesting-env + values: + - key: AD_SERVICE_ADDR + value: $AD_SERVICE_ADDR + - key: CART_SERVICE_ADDR + value: $CART_SERVICE_ADDR + - key: CHECKOUT_SERVICE_ADDR + value: $CHECKOUT_SERVICE_ADDR + - key: CURRENCY_SERVICE_ADDR + value: $CURRENCY_SERVICE_ADDR + - key: EMAIL_SERVICE_ADDR + value: $EMAIL_SERVICE_ADDR + - key: FRONTEND_ADDR + value: $FRONTEND_ADDR + - key: PAYMENT_SERVICE_ADDR + value: $PAYMENT_SERVICE_ADDR + - key: PRODUCT_CATALOG_SERVICE_ADDR + value: $PRODUCT_CATALOG_SERVICE_ADDR + - key: RECOMMENDATION_SERVICE_ADDR + value: $RECOMMENDATION_SERVICE_ADDR + - key: SHIPPING_SERVICE_ADDR + value: $SHIPPING_SERVICE_ADDR +EOF +} + +run_tracetest() { + service_name=$1 + test_file=./$service_name/all.yaml + + tracetest --config ./cli-config.yml test run --definition $test_file --environment ./tracetesting-env.yaml --wait-for-result + return $? +} + +check_if_tracetest_is_installed +create_env_file + +echo "Starting tests..." + +EXIT_STATUS=0 + +echo "" +echo "Running trace-based tests..." + +run_tracetest ad-service || EXIT_STATUS=$? +run_tracetest cart-service || EXIT_STATUS=$? +run_tracetest currency-service || EXIT_STATUS=$? +run_tracetest checkout-service || EXIT_STATUS=$? +run_tracetest frontend-service || EXIT_STATUS=$? +run_tracetest email-service || EXIT_STATUS=$? +run_tracetest payment-service || EXIT_STATUS=$? +run_tracetest product-catalog-service || EXIT_STATUS=$? +run_tracetest recommendation-service || EXIT_STATUS=$? +run_tracetest shipping-service || EXIT_STATUS=$? + +echo "" +echo "Tests done! Exit code: $EXIT_STATUS" + +exit $EXIT_STATUS \ No newline at end of file diff --git a/test/tracetesting/shipping-service/all.yaml b/test/tracetesting/shipping-service/all.yaml new file mode 100644 index 0000000000..88cac40962 --- /dev/null +++ b/test/tracetesting/shipping-service/all.yaml @@ -0,0 +1,12 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Transaction +spec: + id: shipping-service-all + name: 'Shipping Service' + description: Run all Shipping Service tests enabled in sequence + steps: + - ./quote.yaml + - ./empty-quote.yaml + - ./order.yaml diff --git a/test/tracetesting/shipping-service/empty-quote.yaml b/test/tracetesting/shipping-service/empty-quote.yaml new file mode 100644 index 0000000000..df90da835f --- /dev/null +++ b/test/tracetesting/shipping-service/empty-quote.yaml @@ -0,0 +1,36 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Test +spec: + id: shipping-empty-quote + name: 'Shipping: Empty Quote' + description: Quote delivery for no items + trigger: + type: grpc + grpc: + protobufFile: ../../../pb/demo.proto + address: ${env:SHIPPING_SERVICE_ADDR} + method: oteldemo.ShippingService.GetQuote + request: |- + { + "address": { + "streetAddress": "One Microsoft Way", + "city": "Redmond", + "state": "Washington", + "country": "United States", + "zipCode": "98052" + }, + "items": [] + } + specs: + - name: It called GetQuote correctly + selector: span[tracetest.span.type="rpc" name="oteldemo.ShippingService/GetQuote" rpc.system="grpc"] + assertions: + - attr:rpc.grpc.status_code = 0 + - name: It returned a valid quote + selector: span[tracetest.span.type="general" name="Tracetest trigger"] + assertions: + - attr:tracetest.response.body | json_path '$.costUsd.currencyCode' = "USD" + - attr:tracetest.response.body | json_path '$.costUsd.units' = 0 + - attr:tracetest.response.body | json_path '$.costUsd.nanos' = 0 diff --git a/test/tracetesting/shipping-service/order.yaml b/test/tracetesting/shipping-service/order.yaml new file mode 100644 index 0000000000..27aaa37b8f --- /dev/null +++ b/test/tracetesting/shipping-service/order.yaml @@ -0,0 +1,39 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Test +spec: + id: shipping-order + name: 'Shipping: Order' + description: Create one delivery order + trigger: + type: grpc + grpc: + protobufFile: ../../../pb/demo.proto + address: ${env:SHIPPING_SERVICE_ADDR} + method: oteldemo.ShippingService.ShipOrder + request: |- + { + "address": { + "streetAddress": "One Microsoft Way", + "city": "Redmond", + "state": "Washington", + "country": "United States", + "zipCode": "98052" + }, + "items": [ + { + "productId": "66VCHSJNUP", + "quantity": 2 + } + ] + } + specs: + - name: It called GetQuote correctly + selector: span[tracetest.span.type="rpc" name="oteldemo.ShippingService/ShipOrder" rpc.system="grpc"] + assertions: + - attr:rpc.grpc.status_code = 0 + - name: It returned a trackingId + selector: span[tracetest.span.type="general" name="Tracetest trigger"] + assertions: + - attr:tracetest.response.body | json_path '$.trackingId' != "" diff --git a/test/tracetesting/shipping-service/quote.yaml b/test/tracetesting/shipping-service/quote.yaml new file mode 100644 index 0000000000..2cfd48bd7f --- /dev/null +++ b/test/tracetesting/shipping-service/quote.yaml @@ -0,0 +1,41 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +type: Test +spec: + id: shipping-quote + name: 'Shipping: Quote' + description: Quote delivery for one order + trigger: + type: grpc + grpc: + protobufFile: ../../../pb/demo.proto + address: ${env:SHIPPING_SERVICE_ADDR} + method: oteldemo.ShippingService.GetQuote + request: |- + { + "address": { + "streetAddress": "One Microsoft Way", + "city": "Redmond", + "state": "Washington", + "country": "United States", + "zipCode": "98052" + }, + "items": [ + { + "productId": "66VCHSJNUP", + "quantity": 2 + } + ] + } + specs: + - name: It called GetQuote correctly + selector: span[tracetest.span.type="rpc" name="oteldemo.ShippingService/GetQuote" rpc.system="grpc"] + assertions: + - attr:rpc.grpc.status_code = 0 + - name: It returned a valid quote + selector: span[tracetest.span.type="general" name="Tracetest trigger"] + assertions: + - attr:tracetest.response.body | json_path '$.costUsd.currencyCode' = "USD" + - attr:tracetest.response.body | json_path '$.costUsd.units' = 17 + - attr:tracetest.response.body | json_path '$.costUsd.nanos' = 800000000 diff --git a/test/tracetesting/tracetest-config.yaml b/test/tracetesting/tracetest-config.yaml new file mode 100644 index 0000000000..8cd23c94c4 --- /dev/null +++ b/test/tracetesting/tracetest-config.yaml @@ -0,0 +1,24 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +postgres: + host: tracetest-postgres + user: postgres + password: postgres + port: 5432 + dbname: postgres + params: sslmode=disable + +telemetry: + exporters: + collector: + serviceName: tracetest + sampling: 100 + exporter: + type: collector + collector: + endpoint: otelcol:4317 + +server: + telemetry: + exporter: collector diff --git a/test/tracetesting/tracetest-provision.yaml b/test/tracetesting/tracetest-provision.yaml new file mode 100644 index 0000000000..7abc02c260 --- /dev/null +++ b/test/tracetesting/tracetest-provision.yaml @@ -0,0 +1,31 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +--- +type: PollingProfile +spec: + name: Default + strategy: periodic + default: true + periodic: + retryDelay: 10s + timeout: 3m + +--- +type: Demo +spec: + name: "OpenTelemetry Shop" + enabled: true + type: otelstore + opentelemetryStore: + frontendEndpoint: http://frontend:8080 + +--- +type: DataStore +spec: + name: Jaeger + type: jaeger + jaeger: + endpoint: jaeger:16685 + tls: + insecure: true