From 07cda90df5a0e4f9d2a0b8640071f2d341236c52 Mon Sep 17 00:00:00 2001 From: Zhonghao Zhao Date: Fri, 6 Sep 2024 09:50:35 -0700 Subject: [PATCH 01/13] add ECS e2e. --- .github/workflows/java-ecs-canary.yml | 30 ++ .github/workflows/java-ecs-e2e-test.yml | 270 +++++++++++++++++ .github/workflows/java-ecs-retry.yml | 61 ++++ .github/workflows/java-ecs-test.yml | 281 +++++++++++++++++ .github/workflows/python-ecs-canary.yml | 30 ++ .github/workflows/python-ecs-retry.yml | 61 ++++ .github/workflows/python-ecs-test.yml | 283 ++++++++++++++++++ policys.txt | 80 +++++ terraform/java/ecs/main.tf | 94 ++++++ terraform/java/ecs/output.tf | 18 ++ .../java/ecs/resources/main-service.json.tpl | 125 ++++++++ terraform/java/ecs/variables.tf | 49 +++ terraform/python/ecs/main.tf | 94 ++++++ terraform/python/ecs/output.tf | 18 ++ .../ecs/resources/main-service.json.tpl | 152 ++++++++++ terraform/python/ecs/variables.tf | 49 +++ .../PredefinedExpectedTemplate.java | 10 + .../com/amazon/aoc/services/XRayService.java | 6 +- .../amazon/aoc/validators/TraceValidator.java | 17 +- .../java/ecs/hc-log.mustache | 13 + .../java/ecs/hc-metric.mustache | 74 +++++ .../java/ecs/hc-trace.mustache | 33 ++ .../python/ecs/hc-log.mustache | 13 + .../python/ecs/hc-metric.mustache | 74 +++++ .../python/ecs/hc-trace.mustache | 33 ++ .../validations/java/ecs/log-validation.yml | 4 + .../java/ecs/metric-validation.yml | 4 + .../validations/java/ecs/trace-validation.yml | 6 + .../validations/python/ecs/log-validation.yml | 4 + .../python/ecs/metric-validation.yml | 4 + .../python/ecs/trace-validation.yml | 6 + 31 files changed, 1989 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/java-ecs-canary.yml create mode 100644 .github/workflows/java-ecs-e2e-test.yml create mode 100644 .github/workflows/java-ecs-retry.yml create mode 100644 .github/workflows/java-ecs-test.yml create mode 100644 .github/workflows/python-ecs-canary.yml create mode 100644 .github/workflows/python-ecs-retry.yml create mode 100644 .github/workflows/python-ecs-test.yml create mode 100644 policys.txt create mode 100644 terraform/java/ecs/main.tf create mode 100644 terraform/java/ecs/output.tf create mode 100644 terraform/java/ecs/resources/main-service.json.tpl create mode 100644 terraform/java/ecs/variables.tf create mode 100644 terraform/python/ecs/main.tf create mode 100644 terraform/python/ecs/output.tf create mode 100644 terraform/python/ecs/resources/main-service.json.tpl create mode 100644 terraform/python/ecs/variables.tf create mode 100644 validator/src/main/resources/expected-data-template/java/ecs/hc-log.mustache create mode 100644 validator/src/main/resources/expected-data-template/java/ecs/hc-metric.mustache create mode 100644 validator/src/main/resources/expected-data-template/java/ecs/hc-trace.mustache create mode 100644 validator/src/main/resources/expected-data-template/python/ecs/hc-log.mustache create mode 100644 validator/src/main/resources/expected-data-template/python/ecs/hc-metric.mustache create mode 100644 validator/src/main/resources/expected-data-template/python/ecs/hc-trace.mustache create mode 100644 validator/src/main/resources/validations/java/ecs/log-validation.yml create mode 100644 validator/src/main/resources/validations/java/ecs/metric-validation.yml create mode 100644 validator/src/main/resources/validations/java/ecs/trace-validation.yml create mode 100644 validator/src/main/resources/validations/python/ecs/log-validation.yml create mode 100644 validator/src/main/resources/validations/python/ecs/metric-validation.yml create mode 100644 validator/src/main/resources/validations/python/ecs/trace-validation.yml diff --git a/.github/workflows/java-ecs-canary.yml b/.github/workflows/java-ecs-canary.yml new file mode 100644 index 000000000..6fff9a15d --- /dev/null +++ b/.github/workflows/java-ecs-canary.yml @@ -0,0 +1,30 @@ +## Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +## SPDX-License-Identifier: Apache-2.0 + +## This workflow aims to run the Application Signals Java end-to-end tests as a canary to +## test the artifacts for Application Signals enablement. It will deploy a sample app onto an ECS cluster, +## call the APIs, and validate the generated telemetry, including logs, metrics, and traces. +name: Java ECS Enablement Canary Testing +on: + schedule: + - cron: '*/15 * * * *' # run the workflow every 15 minutes + workflow_dispatch: # be able to run the workflow on demand + push: + branches: + - ecs-no-call-zzhlogin + +permissions: + id-token: write + contents: read + +jobs: + ecs: + strategy: + fail-fast: false + matrix: + aws-region: ['us-east-1'] + uses: ./.github/workflows/java-ecs-retry.yml + secrets: inherit + with: + aws-region: ${{ matrix.aws-region }} + caller-workflow-name: 'appsignals-e2e-java-ecs-canary-test' \ No newline at end of file diff --git a/.github/workflows/java-ecs-e2e-test.yml b/.github/workflows/java-ecs-e2e-test.yml new file mode 100644 index 000000000..1fdf9c3e4 --- /dev/null +++ b/.github/workflows/java-ecs-e2e-test.yml @@ -0,0 +1,270 @@ +## Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +## SPDX-License-Identifier: Apache-2.0 + +# This is a reusable workflow for running the E2E test for App Signals. +# It is meant to be called from another workflow. +# Read more about reusable workflows: https://docs.github.com/en/actions/using-workflows/reusing-workflows#overview +name: Java ECS Use Case +on: + workflow_call: + inputs: + aws-region: + required: true + type: string + caller-workflow-name: + required: true + type: string + adot-image-name: + required: false + type: string + cwagent-image-name: + required: false + type: string + +concurrency: + group: '${{ github.workflow }} @ ${{ inputs.aws-region }}' + cancel-in-progress: false + +permissions: + id-token: write + contents: read + +env: + E2E_TEST_AWS_REGION: ${{ inputs.aws-region }} + CALLER_WORKFLOW_NAME: ${{ inputs.caller-workflow-name }} + ADOT_IMAGE_NAME: ${{ inputs.adot-image-name }} + CLUSTER_NAME: e2e-test-java + SAMPLE_APP_NAME: main-service-java + METRIC_NAMESPACE: ApplicationSignals + LOG_GROUP_NAME: /aws/application-signals/data + TEST_RESOURCES_FOLDER: ${GITHUB_WORKSPACE} + E2E_TEST_ACCOUNT_ID: ${{ secrets.APPLICATION_SIGNALS_E2E_TEST_ACCOUNT_ID }} + E2E_TEST_ROLE_NAME: ${{ secrets.APPLICATION_SIGNALS_E2E_TEST_ROLE_NAME }} + ACCOUNT_ID: '007003802740' + CWAGENT_IMAGE_URI: 'public.ecr.aws/y8s3a7r9/cloudwatch-agent:latest' + +jobs: + java-ecs: + runs-on: ubuntu-latest + container: + image: public.ecr.aws/h6o3z5z9/aws-application-signals-test-framework-workflow-container:latest + steps: + - name: Generate testing id and sample app namespace + run: | + echo TESTING_ID="${{ github.job }}-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" >> $GITHUB_ENV + + - uses: actions/checkout@v4 + with: + repository: 'aws-observability/aws-application-signals-test-framework' + ref: ${{ env.CALLER_WORKFLOW_NAME == 'main-build' && 'main' || github.ref }} + fetch-depth: 0 + + # We initialize Gradlew Daemon early on during the workflow because sometimes initialization + # fails due to transient issues. If it fails here, then we will try again later before the validators + - name: Initiate Gradlew Daemon + id: initiate-gradlew + uses: ./.github/workflows/actions/execute_and_retry + continue-on-error: true + with: + command: "./gradlew :validator:build" + cleanup: "./gradlew clean" + max_retry: 3 + sleep_time: 60 + + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: arn:aws:iam::${{ env.E2E_TEST_ACCOUNT_ID }}:role/${{ env.E2E_TEST_ROLE_NAME }} + aws-region: us-east-1 + + # ACCOUNT_ID, region-account/${{ env.E2E_TEST_AWS_REGION }} + - name: Retrieve account + uses: aws-actions/aws-secretsmanager-get-secrets@v1 + with: + secret-ids: | + JAVA_MAIN_SAMPLE_APP_IMAGE, e2e-test/java-main-sample-app-image + JAVA_REMOTE_SAMPLE_APP_IMAGE, e2e-test/java-remote-sample-app-image + + # If the workflow is running as a canary, then we want to log in to the aws account in the appropriate region + - name: Configure AWS Credentials + if: ${{ github.event.repository.name == 'aws-application-signals-test-framework' }} + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: arn:aws:iam::${{ env.ACCOUNT_ID }}:role/${{ env.E2E_TEST_ROLE_NAME }} + aws-region: ${{ env.E2E_TEST_AWS_REGION }} + + - name: Initiate Terraform + uses: ./.github/workflows/actions/execute_and_retry + with: + command: "cd ${{ env.TEST_RESOURCES_FOLDER }}/terraform/java/ecs && terraform init && terraform validate" + cleanup: "rm -rf .terraform && rm -rf .terraform.lock.hcl" + max_retry: 6 + sleep_time: 60 + + - name: Set Sample App Image + run: | + echo MAIN_SAMPLE_APP_IMAGE_URI="${{ env.ACCOUNT_ID }}.dkr.ecr.${{ env.E2E_TEST_AWS_REGION }}.amazonaws.com/${{ env.JAVA_MAIN_SAMPLE_APP_IMAGE }}" >> $GITHUB_ENV + echo REMOTE_SAMPLE_APP_IMAGE_URI="${{ env.ACCOUNT_ID }}.dkr.ecr.${{ env.E2E_TEST_AWS_REGION }}.amazonaws.com/${{ env.JAVA_REMOTE_SAMPLE_APP_IMAGE }}" >> $GITHUB_ENV + + - name: Set Get ADOT Wheel command environment variable + run: | + if [ "${{ github.event.repository.name }}" = "aws-otel-java-instrumentation" ]; then + # Reusing the adot-main-build-staging-jar bucket to store the java wheel file + echo ADOT_INSTRUMENTATION_IMAGE_URI="${{ env.ADOT_IMAGE_NAME }}" >> $GITHUB_ENV + else + ADOT_INSTRUMENTATION_IMAGE_TAG=$(curl -s -I -L 'https://github.com/aws-observability/aws-otel-java-instrumentation/releases/latest' | grep -i Location | awk -F'/tag/' '{print $2}' | tr -d '\r') + echo ADOT_INSTRUMENTATION_IMAGE_URI="public.ecr.aws/aws-observability/adot-autoinstrumentation-java:$ADOT_INSTRUMENTATION_IMAGE_TAG" >> $GITHUB_ENV + fi +# +# - name: Set Get CW Agent command environment variable +# run: | +# if [ "${{ github.event.repository.name }}" = "amazon-cloudwatch-agent" ]; then +# echo CWAGENT_IMAGE_URI="${{ secrets.AWS_ECR_PRIVATE_REGISTRY }}/cwagent-integration-test:${{ github.sha }}" >> $GITHUB_ENV +# else +# echo CWAGENT_IMAGE_URI="public.ecr.aws/cloudwatch-agent/cloudwatch-agent:latest" >> $GITHUB_ENV +# fi + + - name: Deploy sample app via terraform and wait for the endpoint to come online + id: deploy-sample-app + working-directory: terraform/java/ecs + run: | + # Attempt to deploy the sample app on an EKS instance and wait for its endpoint to come online. + # There may be occasional failures due to transitivity issues, so try up to 2 times. + # deployment_failed of 0 indicates that both the terraform deployment and the endpoint are running, while 1 indicates + # that it failed at some point + retry_counter=0 + max_retry=2 + while [ $retry_counter -lt $max_retry ]; do + echo "Attempt $retry_counter" + deployment_failed=0 + terraform apply -auto-approve \ + -var="test_id=${{ env.TESTING_ID }}" \ + -var="aws_region=${{ env.E2E_TEST_AWS_REGION }}" \ + -var="ecs_cluster_name=${{ env.CLUSTER_NAME }}" \ + -var="sample_app_name=${{ env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }}" \ + -var="sample_app_image=${{ env.MAIN_SAMPLE_APP_IMAGE_URI }}" \ + -var="sample_remote_app_image=${{ env.REMOTE_SAMPLE_APP_IMAGE_URI }}" \ + -var="adot_instrumentation_image=${{ env.ADOT_INSTRUMENTATION_IMAGE_URI }}" \ + -var="cwagent_image=${{ env.CWAGENT_IMAGE_URI }}" \ + || deployment_failed=$? + + if [ $deployment_failed -ne 0 ]; then + echo "Terraform deployment was unsuccessful. Will attempt to retry deployment." + fi + + # If the deployment_failed is 1 then either the terraform deployment or the endpoint connection failed, so first destroy the + # resources created from terraform and try again. + if [ $deployment_failed -eq 1 ]; then + echo "Destroying terraform" + terraform destroy -auto-approve \ + -var="test_id=${{ env.TESTING_ID }}" \ + -var="aws_region=${{ env.E2E_TEST_AWS_REGION }}" \ + -var="ecs_cluster_name=${{ env.CLUSTER_NAME }}" \ + -var="sample_app_name=${{ env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }}" \ + -var="sample_app_image=${{ env.MAIN_SAMPLE_APP_IMAGE_URI }}" \ + -var="sample_remote_app_image=${{ env.REMOTE_SAMPLE_APP_IMAGE_URI }}" \ + -var="adot_instrumentation_image=${{ env.ADOT_INSTRUMENTATION_IMAGE_URI }}" \ + -var="cwagent_image=${{ env.CWAGENT_IMAGE_URI }}" + + retry_counter=$(($retry_counter+1)) + else + # If deployment succeeded, then exit the loop + break + fi + + if [ $retry_counter -ge $max_retry ]; then + echo "Max retry reached, failed to deploy terraform and connect to the endpoint. Exiting code" + exit 1 + fi + done + + - name: Sleep to Wait for Canary Generated and Log Artifact Versions + run: | + sleep 120 + echo "ADOT Image: ${{ env.ADOT_INSTRUMENTATION_IMAGE_URI }}"; + echo "CW Agent Image: ${{ env.CWAGENT_IMAGE_URI }}"; + + - name: Initiate Gradlew Daemon + if: steps.initiate-gradlew == 'failure' + uses: ./.github/workflows/actions/execute_and_retry + continue-on-error: true + with: + command: "./gradlew :validator:build" + cleanup: "./gradlew clean" + max_retry: 3 + sleep_time: 60 + + # Validation for app signals telemetry data + - name: Call endpoint and validate generated EMF logs + id: log-validation + if: steps.deploy-sample-app.outcome == 'success' && !cancelled() + run: ./gradlew validator:run --args='-c java/ecs/log-validation.yml + --testing-id ${{ env.TESTING_ID }} + --region ${{ env.E2E_TEST_AWS_REGION }} + --account-id ${{ env.ACCOUNT_ID }} + --metric-namespace ${{ env.METRIC_NAMESPACE }} + --log-group ${{ env.LOG_GROUP_NAME }} + --platform-info ${{ env.CLUSTER_NAME }} + --service-name ${{env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }} + --rollup' + + - name: Call endpoints and validate generated metrics + id: metric-validation + if: (steps.deploy-sample-app.outcome == 'success' || steps.log-validation.outcome == 'failure') && !cancelled() + run: ./gradlew validator:run --args='-c java/ecs/metric-validation.yml + --testing-id ${{ env.TESTING_ID }} + --region ${{ env.E2E_TEST_AWS_REGION }} + --account-id ${{ env.ACCOUNT_ID }} + --metric-namespace ${{ env.METRIC_NAMESPACE }} + --log-group ${{ env.LOG_GROUP_NAME }} + --platform-info ${{ env.CLUSTER_NAME }} + --service-name ${{env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }} + --rollup' + + - name: Call endpoints and validate generated traces + id: trace-validation + if: (steps.deploy-sample-app.outcome == 'success' || steps.log-validation.outcome == 'failure' || steps.metric-validation.outcome == 'failure') && !cancelled() + run: ./gradlew validator:run --args='-c java/ecs/trace-validation.yml + --testing-id ${{ env.TESTING_ID }} + --region ${{ env.E2E_TEST_AWS_REGION }} + --account-id ${{ env.ACCOUNT_ID }} + --metric-namespace ${{ env.METRIC_NAMESPACE }} + --log-group ${{ env.LOG_GROUP_NAME }} + --platform-info ${{ env.CLUSTER_NAME }} + --service-name ${{env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }} + --rollup' + + - name: Publish metric on test result + if: always() + run: | + if [ "${{ steps.log-validation.outcome }}" = "success" ] && [ "${{ steps.metric-validation.outcome }}" = "success" ] && [ "${{ steps.trace-validation.outcome }}" = "success" ]; then + aws cloudwatch put-metric-data --namespace 'ADOT/GitHubActions' \ + --metric-name Failure \ + --dimensions repository=${{ github.repository }},branch=${{ github.ref_name }},workflow=${{ env.CALLER_WORKFLOW_NAME }} \ + --value 0.0 \ + --region ${{ env.E2E_TEST_AWS_REGION }} + else + aws cloudwatch put-metric-data --namespace 'ADOT/GitHubActions' \ + --metric-name Failure \ + --dimensions repository=${{ github.repository }},branch=${{ github.ref_name }},workflow=${{ env.CALLER_WORKFLOW_NAME }} \ + --value 1.0 \ + --region ${{ env.E2E_TEST_AWS_REGION }} + fi + + # Clean up Procedures + + - name: Terraform destroy + if: always() + continue-on-error: true + timeout-minutes: 5 + working-directory: terraform/java/ecs + run: | + terraform destroy -auto-approve \ + -var="test_id=${{ env.TESTING_ID }}" \ + -var="aws_region=${{ env.E2E_TEST_AWS_REGION }}" \ + -var="ecs_cluster_name=${{ env.CLUSTER_NAME }}" \ + -var="sample_app_name=${{ env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }}" \ + -var="sample_app_image=${{ env.MAIN_SAMPLE_APP_IMAGE_URI }}" \ + -var="sample_remote_app_image=${{ env.REMOTE_SAMPLE_APP_IMAGE_URI }}" \ + -var="adot_instrumentation_image=${{ env.ADOT_INSTRUMENTATION_IMAGE_URI }}" \ + -var="cwagent_image=${{ env.CWAGENT_IMAGE_URI }}" \ No newline at end of file diff --git a/.github/workflows/java-ecs-retry.yml b/.github/workflows/java-ecs-retry.yml new file mode 100644 index 000000000..9fe09f760 --- /dev/null +++ b/.github/workflows/java-ecs-retry.yml @@ -0,0 +1,61 @@ +## Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +## SPDX-License-Identifier: Apache-2.0 + +# This is a reusable workflow for running the Enablement test for App Signals. +# It is meant to be called from another workflow. +# Read more about reusable workflows: https://docs.github.com/en/actions/using-workflows/reusing-workflows#overview +name: Java ECS Retry +on: + workflow_call: + inputs: + aws-region: + required: true + type: string + caller-workflow-name: + required: true + type: string + +concurrency: + group: 'java-ecs-${{ inputs.aws-region }}-${{ github.ref_name }}' + cancel-in-progress: false + +permissions: + id-token: write + contents: read + +jobs: + java-ecs-attempt-1: + uses: ./.github/workflows/java-ecs-test.yml + secrets: inherit + with: + aws-region: ${{ inputs.aws-region }} + caller-workflow-name: ${{ inputs.caller-workflow-name }} + + java-ecs-attempt-2: + needs: [ java-ecs-attempt-1 ] + if: ${{ needs.java-ecs-attempt-1.outputs.job-started != 'true' }} + uses: ./.github/workflows/java-ecs-test.yml + secrets: inherit + with: + aws-region: ${{ inputs.aws-region }} + caller-workflow-name: ${{ inputs.caller-workflow-name }} + + publish-metric-attempt-1: + needs: [ java-ecs-attempt-1, java-ecs-attempt-2 ] + if: always() + uses: ./.github/workflows/enablement-test-publish-result.yml + secrets: inherit + with: + aws-region: ${{ inputs.aws-region }} + caller-workflow-name: ${{ inputs.caller-workflow-name }} + validation-result: ${{ needs.java-ecs-attempt-1.outputs.validation-result || needs.java-ecs-attempt-2.outputs.validation-result }} + + publish-metric-attempt-2: + needs: [ java-ecs-attempt-1, java-ecs-attempt-2, publish-metric-attempt-1 ] + if: ${{ always() && needs.publish-metric-attempt-1.outputs.job-started != 'true' }} + uses: ./.github/workflows/enablement-test-publish-result.yml + secrets: inherit + with: + aws-region: ${{ inputs.aws-region }} + caller-workflow-name: ${{ inputs.caller-workflow-name }} + validation-result: ${{ needs.java-ecs-attempt-1.outputs.validation-result || needs.java-ecs-attempt-2.outputs.validation-result }} \ No newline at end of file diff --git a/.github/workflows/java-ecs-test.yml b/.github/workflows/java-ecs-test.yml new file mode 100644 index 000000000..63688b04c --- /dev/null +++ b/.github/workflows/java-ecs-test.yml @@ -0,0 +1,281 @@ +## Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +## SPDX-License-Identifier: Apache-2.0 + +# This is a reusable workflow for running the E2E test for App Signals. +# It is meant to be called from another workflow. +# Read more about reusable workflows: https://docs.github.com/en/actions/using-workflows/reusing-workflows#overview +name: Java ECS Use Case +on: + workflow_call: + inputs: + aws-region: + required: true + type: string + caller-workflow-name: + required: true + type: string + adot-image-name: + required: false + type: string + cwagent-image-name: + required: false + type: string + outputs: + job-started: + value: ${{ jobs.java-ecs.outputs.job-started }} + validation-result: + value: ${{ jobs.java-ecs.outputs.validation-result }} + +concurrency: + group: '${{ github.workflow }} @ ${{ inputs.aws-region }}' + cancel-in-progress: false + +permissions: + id-token: write + contents: read + +env: + E2E_TEST_AWS_REGION: ${{ inputs.aws-region }} + CALLER_WORKFLOW_NAME: ${{ inputs.caller-workflow-name }} + ADOT_IMAGE_NAME: ${{ inputs.adot-image-name }} + CLUSTER_NAME: e2e-test-java + SAMPLE_APP_NAME: main-service-java + METRIC_NAMESPACE: ApplicationSignals + LOG_GROUP_NAME: /aws/application-signals/data + TEST_RESOURCES_FOLDER: ${GITHUB_WORKSPACE} + E2E_TEST_ACCOUNT_ID: ${{ secrets.APPLICATION_SIGNALS_E2E_TEST_ACCOUNT_ID }} + E2E_TEST_ROLE_NAME: ${{ secrets.APPLICATION_SIGNALS_E2E_TEST_ROLE_NAME }} + +jobs: + java-ecs: + runs-on: ubuntu-latest + outputs: + job-started: ${{ steps.job-started.outputs.job-started }} + validation-result: ${{ steps.validation-result.outputs.validation-result }} + steps: + - name: Check if the job started + id: job-started + run: echo "job-started=true" >> $GITHUB_OUTPUT + + - name: Generate testing id and sample app namespace + run: | + echo TESTING_ID="${{ github.job }}-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" >> $GITHUB_ENV + + - uses: actions/checkout@v4 + with: + repository: 'aws-observability/aws-application-signals-test-framework' + ref: ${{ env.CALLER_WORKFLOW_NAME == 'main-build' && 'main' || github.ref }} + fetch-depth: 0 + + # We initialize Gradlew Daemon early on during the workflow because sometimes initialization + # fails due to transient issues. If it fails here, then we will try again later before the validators + - name: Initiate Gradlew Daemon + id: initiate-gradlew + uses: ./.github/workflows/actions/execute_and_retry + continue-on-error: true + with: + command: "./gradlew :validator:build" + cleanup: "./gradlew clean" + max_retry: 3 + sleep_time: 60 + + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: arn:aws:iam::${{ env.E2E_TEST_ACCOUNT_ID }}:role/${{ env.E2E_TEST_ROLE_NAME }} + aws-region: us-east-1 + + # ACCOUNT_ID, region-account/${{ env.E2E_TEST_AWS_REGION }} + - name: Retrieve account + uses: aws-actions/aws-secretsmanager-get-secrets@v1 + with: + secret-ids: | + ACCOUNT_ID, region-account/${{ env.E2E_TEST_AWS_REGION }} + JAVA_MAIN_SAMPLE_APP_IMAGE, e2e-test/java-main-sample-app-image + JAVA_REMOTE_SAMPLE_APP_IMAGE, e2e-test/java-remote-sample-app-image + + # If the workflow is running as a canary, then we want to log in to the aws account in the appropriate region + - name: Configure AWS Credentials + if: ${{ github.event.repository.name == 'aws-application-signals-test-framework' }} + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: arn:aws:iam::${{ env.ACCOUNT_ID }}:role/${{ env.E2E_TEST_ROLE_NAME }} + aws-region: ${{ env.E2E_TEST_AWS_REGION }} + + - name: Initiate Terraform + uses: ./.github/workflows/actions/execute_and_retry + with: + command: "cd ${{ env.TEST_RESOURCES_FOLDER }}/terraform/java/ecs && terraform init && terraform validate" + cleanup: "rm -rf .terraform && rm -rf .terraform.lock.hcl" + max_retry: 6 + sleep_time: 60 + + - name: Set Sample App Image + run: | + echo MAIN_SAMPLE_APP_IMAGE_URI="${{ env.ACCOUNT_ID }}.dkr.ecr.${{ env.E2E_TEST_AWS_REGION }}.amazonaws.com/${{ env.JAVA_MAIN_SAMPLE_APP_IMAGE }}" >> $GITHUB_ENV + echo REMOTE_SAMPLE_APP_IMAGE_URI="${{ env.ACCOUNT_ID }}.dkr.ecr.${{ env.E2E_TEST_AWS_REGION }}.amazonaws.com/${{ env.JAVA_REMOTE_SAMPLE_APP_IMAGE }}" >> $GITHUB_ENV + + - name: Set Get ADOT Wheel command environment variable + run: | + if [ "${{ github.event.repository.name }}" = "aws-otel-java-instrumentation" ]; then + # Reusing the adot-main-build-staging-jar bucket to store the java wheel file + echo ADOT_INSTRUMENTATION_IMAGE_URI="${{ env.ADOT_IMAGE_NAME }}" >> $GITHUB_ENV + else + ADOT_INSTRUMENTATION_IMAGE_TAG=$(curl -s -I -L 'https://github.com/aws-observability/aws-otel-java-instrumentation/releases/latest' | grep -i Location | awk -F'/tag/' '{print $2}' | tr -d '\r') + echo ADOT_INSTRUMENTATION_IMAGE_URI="public.ecr.aws/aws-observability/adot-autoinstrumentation-java:$ADOT_INSTRUMENTATION_IMAGE_TAG" >> $GITHUB_ENV + fi + + # Switch to use the public image for CW Agent + - name: Set Get CW Agent command environment variable + run: | + if [ "${{ github.event.repository.name }}" = "amazon-cloudwatch-agent" ]; then + echo CWAGENT_IMAGE_URI="${{ secrets.AWS_ECR_PRIVATE_REGISTRY }}/cwagent-integration-test:${{ github.sha }}" >> $GITHUB_ENV + else + # echo CWAGENT_IMAGE_URI="public.ecr.aws/cloudwatch-agent/cloudwatch-agent:latest" >> $GITHUB_ENV + echo CWAGENT_IMAGE_URI="public.ecr.aws/y8s3a7r9/cloudwatch-agent:latest" >> $GITHUB_ENV + fi + + - name: Deploy sample app via terraform and wait for the endpoint to come online + id: deploy-sample-app + working-directory: terraform/java/ecs + run: | + # Attempt to deploy the sample app on an EKS instance and wait for its endpoint to come online. + # There may be occasional failures due to transitivity issues, so try up to 2 times. + # deployment_failed of 0 indicates that both the terraform deployment and the endpoint are running, while 1 indicates + # that it failed at some point + retry_counter=0 + max_retry=2 + while [ $retry_counter -lt $max_retry ]; do + echo "Attempt $retry_counter" + deployment_failed=0 + terraform apply -auto-approve \ + -var="test_id=${{ env.TESTING_ID }}" \ + -var="aws_region=${{ env.E2E_TEST_AWS_REGION }}" \ + -var="ecs_cluster_name=${{ env.CLUSTER_NAME }}" \ + -var="sample_app_name=${{ env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }}" \ + -var="sample_app_image=${{ env.MAIN_SAMPLE_APP_IMAGE_URI }}" \ + -var="sample_remote_app_image=${{ env.REMOTE_SAMPLE_APP_IMAGE_URI }}" \ + -var="adot_instrumentation_image=${{ env.ADOT_INSTRUMENTATION_IMAGE_URI }}" \ + -var="cwagent_image=${{ env.CWAGENT_IMAGE_URI }}" \ + || deployment_failed=$? + + if [ $deployment_failed -ne 0 ]; then + echo "Terraform deployment was unsuccessful. Will attempt to retry deployment." + fi + + # If the deployment_failed is 1 then either the terraform deployment or the endpoint connection failed, so first destroy the + # resources created from terraform and try again. + if [ $deployment_failed -eq 1 ]; then + echo "Destroying terraform" + terraform destroy -auto-approve \ + -var="test_id=${{ env.TESTING_ID }}" \ + -var="aws_region=${{ env.E2E_TEST_AWS_REGION }}" \ + -var="ecs_cluster_name=${{ env.CLUSTER_NAME }}" \ + -var="sample_app_name=${{ env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }}" \ + -var="sample_app_image=${{ env.MAIN_SAMPLE_APP_IMAGE_URI }}" \ + -var="sample_remote_app_image=${{ env.REMOTE_SAMPLE_APP_IMAGE_URI }}" \ + -var="adot_instrumentation_image=${{ env.ADOT_INSTRUMENTATION_IMAGE_URI }}" \ + -var="cwagent_image=${{ env.CWAGENT_IMAGE_URI }}" + + retry_counter=$(($retry_counter+1)) + else + # If deployment succeeded, then exit the loop + break + fi + + if [ $retry_counter -ge $max_retry ]; then + echo "Max retry reached, failed to deploy terraform and connect to the endpoint. Exiting code" + exit 1 + fi + done + + - name: Sleep to Wait for Canary Generated and Log Artifact Versions + run: | + sleep 120 + echo "ADOT Image: ${{ env.ADOT_INSTRUMENTATION_IMAGE_URI }}"; + echo "CW Agent Image: ${{ env.CWAGENT_IMAGE_URI }}"; + + - name: Initiate Gradlew Daemon + if: steps.initiate-gradlew == 'failure' + uses: ./.github/workflows/actions/execute_and_retry + continue-on-error: true + with: + command: "./gradlew :validator:build" + cleanup: "./gradlew clean" + max_retry: 3 + sleep_time: 60 + + # Validation for app signals telemetry data + - name: Call endpoint and validate generated EMF logs + id: log-validation + if: steps.deploy-sample-app.outcome == 'success' && !cancelled() + run: ./gradlew validator:run --args='-c java/ecs/log-validation.yml + --testing-id ${{ env.TESTING_ID }} + --region ${{ env.E2E_TEST_AWS_REGION }} + --account-id ${{ env.ACCOUNT_ID }} + --metric-namespace ${{ env.METRIC_NAMESPACE }} + --log-group ${{ env.LOG_GROUP_NAME }} + --platform-info ${{ env.CLUSTER_NAME }} + --service-name ${{env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }} + --rollup' + + - name: Call endpoints and validate generated metrics + id: metric-validation + if: (steps.deploy-sample-app.outcome == 'success' || steps.log-validation.outcome == 'failure') && !cancelled() + run: ./gradlew validator:run --args='-c java/ecs/metric-validation.yml + --testing-id ${{ env.TESTING_ID }} + --region ${{ env.E2E_TEST_AWS_REGION }} + --account-id ${{ env.ACCOUNT_ID }} + --metric-namespace ${{ env.METRIC_NAMESPACE }} + --log-group ${{ env.LOG_GROUP_NAME }} + --platform-info ${{ env.CLUSTER_NAME }} + --service-name ${{env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }} + --rollup' + + - name: Call endpoints and validate generated traces + id: trace-validation + if: (steps.deploy-sample-app.outcome == 'success' || steps.log-validation.outcome == 'failure' || steps.metric-validation.outcome == 'failure') && !cancelled() + run: ./gradlew validator:run --args='-c java/ecs/trace-validation.yml + --testing-id ${{ env.TESTING_ID }} + --region ${{ env.E2E_TEST_AWS_REGION }} + --account-id ${{ env.ACCOUNT_ID }} + --metric-namespace ${{ env.METRIC_NAMESPACE }} + --log-group ${{ env.LOG_GROUP_NAME }} + --platform-info ${{ env.CLUSTER_NAME }} + --service-name ${{env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }} + --rollup' + + - name: Refresh AWS Credentials + if: ${{ github.event.repository.name == 'aws-application-signals-test-framework' }} + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: arn:aws:iam::${{ env.ACCOUNT_ID }}:role/${{ env.E2E_TEST_ROLE_NAME }} + aws-region: ${{ env.E2E_TEST_AWS_REGION }} + + - name: Save test results + if: always() + id: validation-result + run: | + if [ "${{ steps.log-validation.outcome }}" = "success" ] && [ "${{ steps.metric-validation.outcome }}" = "success" ] && [ "${{ steps.trace-validation.outcome }}" = "success" ]; then + echo "validation-result=success" >> $GITHUB_OUTPUT + else + echo "validation-result=failure" >> $GITHUB_OUTPUT + fi + + # Clean up Procedures + + - name: Terraform destroy + if: always() + continue-on-error: true + timeout-minutes: 5 + working-directory: terraform/java/ecs + run: | + terraform destroy -auto-approve \ + -var="test_id=${{ env.TESTING_ID }}" \ + -var="aws_region=${{ env.E2E_TEST_AWS_REGION }}" \ + -var="ecs_cluster_name=${{ env.CLUSTER_NAME }}" \ + -var="sample_app_name=${{ env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }}" \ + -var="sample_app_image=${{ env.MAIN_SAMPLE_APP_IMAGE_URI }}" \ + -var="sample_remote_app_image=${{ env.REMOTE_SAMPLE_APP_IMAGE_URI }}" \ + -var="adot_instrumentation_image=${{ env.ADOT_INSTRUMENTATION_IMAGE_URI }}" \ + -var="cwagent_image=${{ env.CWAGENT_IMAGE_URI }}" \ No newline at end of file diff --git a/.github/workflows/python-ecs-canary.yml b/.github/workflows/python-ecs-canary.yml new file mode 100644 index 000000000..e43f23d6d --- /dev/null +++ b/.github/workflows/python-ecs-canary.yml @@ -0,0 +1,30 @@ +## Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +## SPDX-License-Identifier: Apache-2.0 + +## This workflow aims to run the Application Signals Python end-to-end tests as a canary to +## test the artifacts for Application Signals enablement. It will deploy a sample app onto an ECS cluster, +## call the APIs, and validate the generated telemetry, including logs, metrics, and traces. +name: Python ECS Enablement Canary Testing +on: + schedule: + - cron: '*/15 * * * *' # run the workflow every 15 minutes + workflow_dispatch: # be able to run the workflow on demand + push: + branches: + - ecs-no-call-zzhlogin + +permissions: + id-token: write + contents: read + +jobs: + ecs: + strategy: + fail-fast: false + matrix: + aws-region: ['us-east-1'] + uses: ./.github/workflows/python-ecs-retry.yml + secrets: inherit + with: + aws-region: ${{ matrix.aws-region }} + caller-workflow-name: 'appsignals-e2e-python-ecs-canary-test' \ No newline at end of file diff --git a/.github/workflows/python-ecs-retry.yml b/.github/workflows/python-ecs-retry.yml new file mode 100644 index 000000000..f23ba7071 --- /dev/null +++ b/.github/workflows/python-ecs-retry.yml @@ -0,0 +1,61 @@ +## Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +## SPDX-License-Identifier: Apache-2.0 + +# This is a reusable workflow for running the Enablement test for App Signals. +# It is meant to be called from another workflow. +# Read more about reusable workflows: https://docs.github.com/en/actions/using-workflows/reusing-workflows#overview +name: Python ECS Retry +on: + workflow_call: + inputs: + aws-region: + required: true + type: string + caller-workflow-name: + required: true + type: string + +concurrency: + group: 'python-ecs-${{ inputs.aws-region }}-${{ github.ref_name }}' + cancel-in-progress: false + +permissions: + id-token: write + contents: read + +jobs: + python-ecs-attempt-1: + uses: ./.github/workflows/python-ecs-test.yml + secrets: inherit + with: + aws-region: ${{ inputs.aws-region }} + caller-workflow-name: ${{ inputs.caller-workflow-name }} + + python-ecs-attempt-2: + needs: [ python-ecs-attempt-1 ] + if: ${{ needs.python-ecs-attempt-1.outputs.job-started != 'true' }} + uses: ./.github/workflows/python-ecs-test.yml + secrets: inherit + with: + aws-region: ${{ inputs.aws-region }} + caller-workflow-name: ${{ inputs.caller-workflow-name }} + + publish-metric-attempt-1: + needs: [ python-ecs-attempt-1, python-ecs-attempt-2 ] + if: always() + uses: ./.github/workflows/enablement-test-publish-result.yml + secrets: inherit + with: + aws-region: ${{ inputs.aws-region }} + caller-workflow-name: ${{ inputs.caller-workflow-name }} + validation-result: ${{ needs.python-ecs-attempt-1.outputs.validation-result || needs.python-ecs-attempt-2.outputs.validation-result }} + + publish-metric-attempt-2: + needs: [ python-ecs-attempt-1, python-ecs-attempt-2, publish-metric-attempt-1 ] + if: ${{ always() && needs.publish-metric-attempt-1.outputs.job-started != 'true' }} + uses: ./.github/workflows/enablement-test-publish-result.yml + secrets: inherit + with: + aws-region: ${{ inputs.aws-region }} + caller-workflow-name: ${{ inputs.caller-workflow-name }} + validation-result: ${{ needs.python-ecs-attempt-1.outputs.validation-result || needs.python-ecs-attempt-2.outputs.validation-result }} \ No newline at end of file diff --git a/.github/workflows/python-ecs-test.yml b/.github/workflows/python-ecs-test.yml new file mode 100644 index 000000000..3759e8d60 --- /dev/null +++ b/.github/workflows/python-ecs-test.yml @@ -0,0 +1,283 @@ +## Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +## SPDX-License-Identifier: Apache-2.0 + +# This is a reusable workflow for running the E2E test for App Signals. +# It is meant to be called from another workflow. +# Read more about reusable workflows: https://docs.github.com/en/actions/using-workflows/reusing-workflows#overview +name: Python ECS Use Case +on: + workflow_call: + inputs: + aws-region: + required: true + type: string + caller-workflow-name: + required: true + type: string + adot-image-name: + required: false + type: string + cwagent-image-name: + required: false + type: string + outputs: + job-started: + value: ${{ jobs.python-ecs.outputs.job-started }} + validation-result: + value: ${{ jobs.python-ecs.outputs.validation-result }} + +concurrency: + group: '${{ github.workflow }} @ ${{ inputs.aws-region }}' + cancel-in-progress: false + +permissions: + id-token: write + contents: read + +env: + E2E_TEST_AWS_REGION: ${{ inputs.aws-region }} + CALLER_WORKFLOW_NAME: ${{ inputs.caller-workflow-name }} + ADOT_IMAGE_NAME: ${{ inputs.adot-image-name }} + CLUSTER_NAME: e2e-test-python + SAMPLE_APP_NAME: main-service-python + METRIC_NAMESPACE: ApplicationSignals + LOG_GROUP_NAME: /aws/application-signals/data + TEST_RESOURCES_FOLDER: ${GITHUB_WORKSPACE} + E2E_TEST_ACCOUNT_ID: ${{ secrets.APPLICATION_SIGNALS_E2E_TEST_ACCOUNT_ID }} + E2E_TEST_ROLE_NAME: ${{ secrets.APPLICATION_SIGNALS_E2E_TEST_ROLE_NAME }} + +jobs: + python-ecs: + runs-on: ubuntu-latest + outputs: + job-started: ${{ steps.job-started.outputs.job-started }} + validation-result: ${{ steps.validation-result.outputs.validation-result }} + steps: + - name: Check if the job started + id: job-started + run: echo "job-started=true" >> $GITHUB_OUTPUT + + - name: Generate testing id and sample app namespace + run: | + echo TESTING_ID="${{ github.job }}-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" >> $GITHUB_ENV + + - uses: actions/checkout@v4 + with: + repository: 'aws-observability/aws-application-signals-test-framework' + ref: ${{ env.CALLER_WORKFLOW_NAME == 'main-build' && 'main' || github.ref }} + fetch-depth: 0 + + # We initialize Gradlew Daemon early on during the workflow because sometimes initialization + # fails due to transient issues. If it fails here, then we will try again later before the validators + - name: Initiate Gradlew Daemon + id: initiate-gradlew + uses: ./.github/workflows/actions/execute_and_retry + continue-on-error: true + with: + command: "./gradlew :validator:build" + cleanup: "./gradlew clean" + max_retry: 3 + sleep_time: 60 + + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: arn:aws:iam::${{ env.E2E_TEST_ACCOUNT_ID }}:role/${{ env.E2E_TEST_ROLE_NAME }} + aws-region: us-east-1 + + # ACCOUNT_ID, region-account/${{ env.E2E_TEST_AWS_REGION }} + - name: Retrieve account + uses: aws-actions/aws-secretsmanager-get-secrets@v1 + with: + secret-ids: | + ACCOUNT_ID, region-account/${{ env.E2E_TEST_AWS_REGION }} + PYTHON_MAIN_SAMPLE_APP_IMAGE, e2e-test/python-main-sample-app-image + PYTHON_REMOTE_SAMPLE_APP_IMAGE, e2e-test/python-remote-sample-app-image + + # If the workflow is running as a canary, then we want to log in to the aws account in the appropriate region + - name: Configure AWS Credentials + if: ${{ github.event.repository.name == 'aws-application-signals-test-framework' }} + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: arn:aws:iam::${{ env.ACCOUNT_ID }}:role/${{ env.E2E_TEST_ROLE_NAME }} + aws-region: ${{ env.E2E_TEST_AWS_REGION }} + + - name: Initiate Terraform + uses: ./.github/workflows/actions/execute_and_retry + with: + command: "cd ${{ env.TEST_RESOURCES_FOLDER }}/terraform/python/ecs && terraform init && terraform validate" + cleanup: "rm -rf .terraform && rm -rf .terraform.lock.hcl" + max_retry: 6 + sleep_time: 60 + + - name: Set Sample App Image + run: | + echo MAIN_SAMPLE_APP_IMAGE_URI="${{ env.ACCOUNT_ID }}.dkr.ecr.${{ env.E2E_TEST_AWS_REGION }}.amazonaws.com/${{ env.PYTHON_MAIN_SAMPLE_APP_IMAGE }}" >> $GITHUB_ENV + echo REMOTE_SAMPLE_APP_IMAGE_URI="${{ env.ACCOUNT_ID }}.dkr.ecr.${{ env.E2E_TEST_AWS_REGION }}.amazonaws.com/${{ env.PYTHON_REMOTE_SAMPLE_APP_IMAGE }}" >> $GITHUB_ENV + + # Swich to use the public image for ADOT instrumentation + - name: Set Get ADOT Wheel command environment variable + run: | + if [ "${{ github.event.repository.name }}" = "aws-otel-python-instrumentation" ]; then + # Reusing the adot-main-build-staging-jar bucket to store the python wheel file + echo ADOT_INSTRUMENTATION_IMAGE_URI=="${{ env.ADOT_IMAGE_NAME }}" >> $GITHUB_ENV + else + # ADOT_INSTRUMENTATION_IMAGE_TAG=$(curl -s -I -L 'https://github.com/aws-observability/aws-otel-python-instrumentation/releases/latest' | grep -i Location | awk -F'/tag/' '{print $2}' | tr -d '\r') + # echo ADOT_INSTRUMENTATION_IMAGE_URI="public.ecr.aws/aws-observability/adot-autoinstrumentation-python:$ADOT_INSTRUMENTATION_IMAGE_TAG" >> $GITHUB_ENV + echo ADOT_INSTRUMENTATION_IMAGE_URI="${{ env.ACCOUNT_ID }}.dkr.ecr.us-east-1.amazonaws.com/adot-python-distro:latest" >> $GITHUB_ENV + fi + + # Switch to use the public image for CW Agent + - name: Set Get CW Agent command environment variable + run: | + if [ "${{ github.event.repository.name }}" = "amazon-cloudwatch-agent" ]; then + echo CWAGENT_IMAGE_URI="${{ secrets.AWS_ECR_PRIVATE_REGISTRY }}/cwagent-integration-test:${{ github.sha }}" >> $GITHUB_ENV + else + # echo CWAGENT_IMAGE_URI="public.ecr.aws/cloudwatch-agent/cloudwatch-agent:latest" >> $GITHUB_ENV + echo CWAGENT_IMAGE_URI="public.ecr.aws/y8s3a7r9/cloudwatch-agent:latest" >> $GITHUB_ENV + fi + + - name: Deploy sample app via terraform and wait for the endpoint to come online + id: deploy-sample-app + working-directory: terraform/python/ecs + run: | + # Attempt to deploy the sample app on an EKS instance and wait for its endpoint to come online. + # There may be occasional failures due to transitivity issues, so try up to 2 times. + # deployment_failed of 0 indicates that both the terraform deployment and the endpoint are running, while 1 indicates + # that it failed at some point + retry_counter=0 + max_retry=2 + while [ $retry_counter -lt $max_retry ]; do + echo "Attempt $retry_counter" + deployment_failed=0 + terraform apply -auto-approve \ + -var="test_id=${{ env.TESTING_ID }}" \ + -var="aws_region=${{ env.E2E_TEST_AWS_REGION }}" \ + -var="ecs_cluster_name=${{ env.CLUSTER_NAME }}" \ + -var="sample_app_name=${{ env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }}" \ + -var="sample_app_image=${{ env.MAIN_SAMPLE_APP_IMAGE_URI }}" \ + -var="sample_remote_app_image=${{ env.REMOTE_SAMPLE_APP_IMAGE_URI }}" \ + -var="adot_instrumentation_image=${{ env.ADOT_INSTRUMENTATION_IMAGE_URI }}" \ + -var="cwagent_image=${{ env.CWAGENT_IMAGE_URI }}" \ + || deployment_failed=$? + + if [ $deployment_failed -ne 0 ]; then + echo "Terraform deployment was unsuccessful. Will attempt to retry deployment." + fi + + # If the deployment_failed is 1 then either the terraform deployment or the endpoint connection failed, so first destroy the + # resources created from terraform and try again. + if [ $deployment_failed -eq 1 ]; then + echo "Destroying terraform" + terraform destroy -auto-approve \ + -var="test_id=${{ env.TESTING_ID }}" \ + -var="aws_region=${{ env.E2E_TEST_AWS_REGION }}" \ + -var="ecs_cluster_name=${{ env.CLUSTER_NAME }}" \ + -var="sample_app_name=${{ env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }}" \ + -var="sample_app_image=${{ env.MAIN_SAMPLE_APP_IMAGE_URI }}" \ + -var="sample_remote_app_image=${{ env.REMOTE_SAMPLE_APP_IMAGE_URI }}" \ + -var="adot_instrumentation_image=${{ env.ADOT_INSTRUMENTATION_IMAGE_URI }}" \ + -var="cwagent_image=${{ env.CWAGENT_IMAGE_URI }}" + + retry_counter=$(($retry_counter+1)) + else + # If deployment succeeded, then exit the loop + break + fi + + if [ $retry_counter -ge $max_retry ]; then + echo "Max retry reached, failed to deploy terraform and connect to the endpoint. Exiting code" + exit 1 + fi + done + + - name: Sleep to Wait for Canary Generated and Log Artifact Versions + run: | + sleep 120 + echo "ADOT Image: ${{ env.ADOT_INSTRUMENTATION_IMAGE_URI }}"; + echo "CW Agent Image: ${{ env.CWAGENT_IMAGE_URI }}"; + + - name: Initiate Gradlew Daemon + if: steps.initiate-gradlew == 'failure' + uses: ./.github/workflows/actions/execute_and_retry + continue-on-error: true + with: + command: "./gradlew :validator:build" + cleanup: "./gradlew clean" + max_retry: 3 + sleep_time: 60 + + # Validation for app signals telemetry data + - name: Call endpoint and validate generated EMF logs + id: log-validation + if: steps.deploy-sample-app.outcome == 'success' && !cancelled() + run: ./gradlew validator:run --args='-c python/ecs/log-validation.yml + --testing-id ${{ env.TESTING_ID }} + --region ${{ env.E2E_TEST_AWS_REGION }} + --account-id ${{ env.ACCOUNT_ID }} + --metric-namespace ${{ env.METRIC_NAMESPACE }} + --log-group ${{ env.LOG_GROUP_NAME }} + --platform-info ${{ env.CLUSTER_NAME }} + --service-name ${{env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }} + --rollup' + + - name: Call endpoints and validate generated metrics + id: metric-validation + if: (steps.deploy-sample-app.outcome == 'success' || steps.log-validation.outcome == 'failure') && !cancelled() + run: ./gradlew validator:run --args='-c python/ecs/metric-validation.yml + --testing-id ${{ env.TESTING_ID }} + --region ${{ env.E2E_TEST_AWS_REGION }} + --account-id ${{ env.ACCOUNT_ID }} + --metric-namespace ${{ env.METRIC_NAMESPACE }} + --log-group ${{ env.LOG_GROUP_NAME }} + --platform-info ${{ env.CLUSTER_NAME }} + --service-name ${{env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }} + --rollup' + + - name: Call endpoints and validate generated traces + id: trace-validation + if: (steps.deploy-sample-app.outcome == 'success' || steps.log-validation.outcome == 'failure' || steps.metric-validation.outcome == 'failure') && !cancelled() + run: ./gradlew validator:run --args='-c python/ecs/trace-validation.yml + --testing-id ${{ env.TESTING_ID }} + --region ${{ env.E2E_TEST_AWS_REGION }} + --account-id ${{ env.ACCOUNT_ID }} + --metric-namespace ${{ env.METRIC_NAMESPACE }} + --log-group ${{ env.LOG_GROUP_NAME }} + --platform-info ${{ env.CLUSTER_NAME }} + --service-name ${{env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }} + --rollup' + + - name: Refresh AWS Credentials + if: ${{ github.event.repository.name == 'aws-application-signals-test-framework' }} + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: arn:aws:iam::${{ env.ACCOUNT_ID }}:role/${{ env.E2E_TEST_ROLE_NAME }} + aws-region: ${{ env.E2E_TEST_AWS_REGION }} + + - name: Save test results + if: always() + id: validation-result + run: | + if [ "${{ steps.log-validation.outcome }}" = "success" ] && [ "${{ steps.metric-validation.outcome }}" = "success" ] && [ "${{ steps.trace-validation.outcome }}" = "success" ]; then + echo "validation-result=success" >> $GITHUB_OUTPUT + else + echo "validation-result=failure" >> $GITHUB_OUTPUT + fi + + # Clean up Procedures + + - name: Terraform destroy + if: always() + continue-on-error: true + timeout-minutes: 5 + working-directory: terraform/python/ecs + run: | + terraform destroy -auto-approve \ + -var="test_id=${{ env.TESTING_ID }}" \ + -var="aws_region=${{ env.E2E_TEST_AWS_REGION }}" \ + -var="ecs_cluster_name=${{ env.CLUSTER_NAME }}" \ + -var="sample_app_name=${{ env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }}" \ + -var="sample_app_image=${{ env.MAIN_SAMPLE_APP_IMAGE_URI }}" \ + -var="sample_remote_app_image=${{ env.REMOTE_SAMPLE_APP_IMAGE_URI }}" \ + -var="adot_instrumentation_image=${{ env.ADOT_INSTRUMENTATION_IMAGE_URI }}" \ + -var="cwagent_image=${{ env.CWAGENT_IMAGE_URI }}" \ No newline at end of file diff --git a/policys.txt b/policys.txt new file mode 100644 index 000000000..3e78d43af --- /dev/null +++ b/policys.txt @@ -0,0 +1,80 @@ +githubProviderRole +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Federated": "arn:aws:iam::654654176582:oidc-provider/token.actions.githubusercontent.com" + }, + "Action": "sts:AssumeRoleWithWebIdentity", + "Condition": { + "StringLike": { + "token.actions.githubusercontent.com:sub": [ + "repo:aws-observability/aws-application-signals-test-framework:ref:refs/heads/*", + "repo:aws-observability/aws-otel-python-instrumentation:ref:refs/heads/*", + "repo:aws-observability/aws-otel-dotnet-instrumentation:ref:refs/heads/*", + "repo:aws-observability/aws-otel-js-instrumentation:ref:refs/heads/*", + "repo:aws-observability/aws-otel-java-instrumentation:ref:refs/heads/*", + "repo:aws-observability/aws-otel-community:ref:refs/heads/*" + ] + } + } + }, + { + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam::654654176582:root" + }, + "Action": "sts:AssumeRole" + } + ] +} + + +MAIN_SAMPLE_APP_IMAGE_URI = 654654176582.dkr.ecr.us-east-1.amazonaws.com/appsignals-python-django-main-service +REMOTE_SAMPLE_APP_IMAGE_URI = 654654176582.dkr.ecr.us-east-1.amazonaws.com/appsignals-python-django-remote-service + + +Task Role: ecsE2ETestRole +AmazonEC2ContainerServiceRole +AmazonS3FullAccess +AmazonSSMReadOnlyAccess +AWSXrayWriteOnlyAccess +AWSXRayDaemonWriteAccess +CloudWatchAgentServerPolicy +ECSDataDog +ECSFargateAllowExecuteCommand + +Task Execution Role: ecsE2ETestExecutionRole +AmazonECSTaskExecutionRolePolicy +AmazonSSMReadOnlyAccess +CloudWatchAgentServerPolicy + + +export TF_LOG=DEBUG +terraform apply -auto-approve \ + -var="test_id=111111" \ + -var="aws_region=us-east-1" \ + -var="ecs_cluster_name=e2e-test-python" \ + -var="sample_app_name=main-service-python-zzhlocal" \ + -var="sample_app_image=007003802740.dkr.ecr.us-east-1.amazonaws.com/appsignals-python-django-main-service:latest" \ + -var="sample_remote_app_image=007003802740.dkr.ecr.us-east-1.amazonaws.com/appsignals-python-django-remote-service:latest" \ + -var="adot_instrumentation_image=007003802740.dkr.ecr.us-east-1.amazonaws.com/adot-python-distro:latest" \ + -var="cwagent_image=public.ecr.aws/y8s3a7r9/cloudwatch-agent:latest" + +terraform destroy -auto-approve \ + -var="test_id=111111" \ + -var="aws_region=us-east-1" \ + -var="ecs_cluster_name=e2e-test-python" \ + -var="sample_app_name=main-service-python-zzhlocal" \ + -var="sample_app_image=007003802740.dkr.ecr.us-east-1.amazonaws.com/appsignals-python-django-main-service:latest" \ + -var="sample_remote_app_image=007003802740.dkr.ecr.us-east-1.amazonaws.com/appsignals-python-django-remote-service:latest" \ + -var="adot_instrumentation_image=public.ecr.aws/aws-observability/adot-autoinstrumentation-python:v0.4.0" \ + -var="cwagent_image=public.ecr.aws/cloudwatch-agent/cloudwatch-agent:latest" + + + +{"Environment":"ecs:e2e-test-python","Operation":"GET /","PlatformType":"Generic","Service":"main-service-python-111111","Telemetry.Agent":"CWAgent/1.300045.1b823","Telemetry.SDK":"opentelemetry,0.4.0-aws,python,Auto","Telemetry.Source":"LocalRootSpan","Version":"1","_aws":{"CloudWatchMetrics":[{"Namespace":"ApplicationSignals","Dimensions":[["Environment","Operation","Service"],["Environment","Service"]],"Metrics":[{"Name":"Latency","Unit":"Milliseconds"},{"Name":"Error"},{"Name":"Fault"}]}],"Timestamp":1725560229171},"Error":{"Values":[0],"Counts":[2],"Max":0,"Min":0,"Count":2,"Sum":0},"Fault":{"Values":[0],"Counts":[2],"Max":0,"Min":0,"Count":2,"Sum":0},"Latency":{"Values":[0.6311079285541068,0.7586906445844908],"Counts":[1,1],"Max":0.75761,"Min":0.630616,"Count":2,"Sum":1.388226}} + +{"ECS.Cluster":"e2e-test-python","ECS.TaskDefinitionFamily":"main-service-python-python-ecs-10729837765-26-1","ECS.TaskDefinitionRevision":"1","ECS.TaskId":"a01227ec7a81451fa61c8bc2b62226d4","ECS.Workload":"","Environment":"ecs:e2e-test-python","Operation":"GET /","PlatformType":"AWS::ECS","Service":"main-service-python-python-ecs-10729837765-26-1","Telemetry.Agent":"CWAgent/Unknown","Telemetry.SDK":"opentelemetry,0.4.0.dev0-aws,python,Auto","Telemetry.Source":"LocalRootSpan","Version":"1","_aws":{"CloudWatchMetrics":[{"Namespace":"ApplicationSignals","Dimensions":[["Environment","Operation","Service"],["Environment","Service"]],"Metrics":[{"Name":"Fault"},{"Name":"Latency","Unit":"Milliseconds"},{"Name":"Error"}]}],"Timestamp":1725580280979},"aws.log.group.names":"[\"/ecs/service-e2e-test\"]","Error":{"Values":[0],"Counts":[2],"Max":0,"Min":0,"Count":2,"Sum":0},"Fault":{"Values":[0],"Counts":[2],"Max":0,"Min":0,"Count":2,"Sum":0},"Latency":{"Values":[0.530696394759346,0.5602270903010342],"Counts":[1,1],"Max":0.561569,"Min":0.532748,"Count":2,"Sum":1.094317}} \ No newline at end of file diff --git a/terraform/java/ecs/main.tf b/terraform/java/ecs/main.tf new file mode 100644 index 000000000..1cb98b58f --- /dev/null +++ b/terraform/java/ecs/main.tf @@ -0,0 +1,94 @@ +# ------------------------------------------------------------------------ +# Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). +# You may not use this file except in compliance with the License. +# A copy of the License is located at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# or in the "license" file accompanying this file. This file is distributed +# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +# express or implied. See the License for the specific language governing +# permissions and limitations under the License. +# ------------------------------------------------------------------------- + +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + } + } +} + +# Define the provider for AWS +provider "aws" {} + +resource "aws_default_vpc" "default" {} + +data "aws_subnets" "default_subnets" { + filter { + name = "vpc-id" + values = [aws_default_vpc.default.id] + } +} + +data "aws_iam_role" "e2e_test_task_role" { + # change + name = "ecsE2ETestRole" +} + +data "aws_iam_role" "e2e_test_task_execution_role" { + name = "ecsE2ETestExecutionRole" +} + +data "template_file" "main_service" { + template = file("./resources/main-service.json.tpl") + + vars = { + app_image = var.sample_app_image + app_service_name = "${var.sample_app_name}" + aws_region = var.aws_region + init_image = var.adot_instrumentation_image + cwagent_image = var.cwagent_image + } +} + +resource "aws_ecs_cluster" "e2e_test" { + name = var.ecs_cluster_name +} + +resource "aws_ecs_task_definition" "main_service" { + family = var.sample_app_name + network_mode = "awsvpc" + requires_compatibilities = ["FARGATE"] + execution_role_arn = data.aws_iam_role.e2e_test_task_execution_role.arn + task_role_arn = data.aws_iam_role.e2e_test_task_role.arn + cpu = 512 + memory = 1024 + runtime_platform { + operating_system_family = "LINUX" + cpu_architecture = "X86_64" + } + container_definitions = data.template_file.main_service.rendered + volume { + name = "opentelemetry-auto-instrumentation" + } +} + +resource "aws_ecs_service" "main_service" { + name = var.sample_app_name + cluster = aws_ecs_cluster.e2e_test.id + task_definition = aws_ecs_task_definition.main_service.arn + desired_count = 1 + enable_ecs_managed_tags = true + launch_type = "FARGATE" + + network_configuration { + security_groups = [aws_default_vpc.default.default_security_group_id] + subnets = data.aws_subnets.default_subnets.ids + assign_public_ip = true + } + + wait_for_steady_state = true +} \ No newline at end of file diff --git a/terraform/java/ecs/output.tf b/terraform/java/ecs/output.tf new file mode 100644 index 000000000..72e4af6b5 --- /dev/null +++ b/terraform/java/ecs/output.tf @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------------ +# Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). +# You may not use this file except in compliance with the License. +# A copy of the License is located at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# or in the "license" file accompanying this file. This file is distributed +# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +# express or implied. See the License for the specific language governing +# permissions and limitations under the License. +# ------------------------------------------------------------------------- + +output "sample_app_main_service_task_definition" { + value = aws_ecs_task_definition.main_service.arn +} \ No newline at end of file diff --git a/terraform/java/ecs/resources/main-service.json.tpl b/terraform/java/ecs/resources/main-service.json.tpl new file mode 100644 index 000000000..d09589bb0 --- /dev/null +++ b/terraform/java/ecs/resources/main-service.json.tpl @@ -0,0 +1,125 @@ +[ + { + "name": "app", + "image": "${app_image}", + "cpu": 0, + "portMappings": [ + { + "name": "app-8080-tcp", + "containerPort": 8080, + "hostPort": 8080, + "protocol": "tcp", + "appProtocol": "http" + } + ], + "essential": true, + "environment": [ + { + "name": "OTEL_EXPORTER_OTLP_PROTOCOL", + "value": "http/protobuf" + }, + { + "name": "OTEL_AWS_APPLICATION_SIGNALS_ENABLED", + "value": "true" + }, + { + "name": "OTEL_AWS_APPLICATION_SIGNALS_EXPORTER_ENDPOINT", + "value": "http://localhost:4316/v1/metrics" + }, + { + "name": "OTEL_RESOURCE_ATTRIBUTES", + "value": "service.name=${app_service_name}" + }, + { + "name": "OTEL_METRICS_EXPORTER", + "value": "none" + }, + { + "name": "JAVA_TOOL_OPTIONS", + "value": "-javaagent:/otel-auto-instrumentation/javaagent.jar" + }, + { + "name": "OTEL_LOGS_EXPORTER", + "value": "none" + }, + { + "name": "OTEL_TRACES_SAMPLER", + "value": "xray" + }, + { + "name": "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", + "value": "http://localhost:4316/v1/traces" + }, + { + "name": "OTEL_PROPAGATORS", + "value": "tracecontext,baggage,b3,xray" + } + ], + "mountPoints": [ + { + "sourceVolume": "opentelemetry-auto-instrumentation", + "containerPath": "/otel-auto-instrumentation", + "readOnly": false + } + ], + "logConfiguration": { + "logDriver": "awslogs", + "options": { + "awslogs-group": "/ecs/service-e2e-test", + "awslogs-create-group": "true", + "awslogs-region": "${aws_region}", + "awslogs-stream-prefix": "ecs" + } + } + }, + { + "name": "init", + "image": "${init_image}", + "cpu": 0, + "essential": false, + "command": [ + "cp", + "/javaagent.jar", + "/otel-auto-instrumentation/javaagent.jar" + ], + "mountPoints": [ + { + "sourceVolume": "opentelemetry-auto-instrumentation", + "containerPath": "/otel-auto-instrumentation", + "readOnly": false + } + ] + }, + { + "name": "ecs-cwagent", + "image": "${cwagent_image}", + "cpu": 0, + "essential": true, + "environment": [ + { + "name": "CW_CONFIG_CONTENT", + "value": "{\"agent\": {\"debug\": true}, \"traces\": {\"traces_collected\": {\"application_signals\": {\"enabled\": true}}}, \"logs\": {\"metrics_collected\": {\"application_signals\": {\"enabled\": true}}}}" + } + ], + "logConfiguration": { + "logDriver": "awslogs", + "options": { + "awslogs-group": "/ecs/ecs-cwagent", + "awslogs-create-group": "true", + "awslogs-region": "${aws_region}", + "awslogs-stream-prefix": "ecs" + } + } + }, + { + "name": "traffic-gen", + "image": "curlimages/curl:8.8.0", + "cpu": 0, + "essential": true, + "command": [ + "sh", + "-c", + "while true; do curl http://localhost:8080/; sleep 15; done" + ] + } +] \ No newline at end of file diff --git a/terraform/java/ecs/variables.tf b/terraform/java/ecs/variables.tf new file mode 100644 index 000000000..ddc3c2852 --- /dev/null +++ b/terraform/java/ecs/variables.tf @@ -0,0 +1,49 @@ +# ------------------------------------------------------------------------ +# Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). +# You may not use this file except in compliance with the License. +# A copy of the License is located at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# or in the "license" file accompanying this file. This file is distributed +# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +# express or implied. See the License for the specific language governing +# permissions and limitations under the License. +# ------------------------------------------------------------------------- + + +variable "test_id" { + default = "dummy-123" +} + +variable "aws_region" { + default = "us-west-2" +} + +variable "ecs_cluster_name" { + default = "e2e-test-java" +} + +variable "sample_app_name" { + default = "" +} + +variable "sample_app_image" { + // public.ecr.aws/m0o7p6d1/aws-apm-java-springboot-main-service:latest + default = "" +} + +variable "sample_remote_app_image" { + default = "" +} +variable "adot_instrumentation_image" { + // public.ecr.aws/aws-observability/adot-autoinstrumentation-java:v1.32.3 + default = "" +} + +variable "cwagent_image" { + // public.ecr.aws/y8s3a7r9/cloudwatch-agent:latest + default = "" +} \ No newline at end of file diff --git a/terraform/python/ecs/main.tf b/terraform/python/ecs/main.tf new file mode 100644 index 000000000..0f0eab8b3 --- /dev/null +++ b/terraform/python/ecs/main.tf @@ -0,0 +1,94 @@ +# ------------------------------------------------------------------------ +# Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). +# You may not use this file except in compliance with the License. +# A copy of the License is located at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# or in the "license" file accompanying this file. This file is distributed +# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +# express or implied. See the License for the specific language governing +# permissions and limitations under the License. +# ------------------------------------------------------------------------- + +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + } + } +} + +# Define the provider for AWS +provider "aws" {} + +resource "aws_default_vpc" "default" {} + +data "aws_subnets" "default_subnets" { + filter { + name = "vpc-id" + values = [aws_default_vpc.default.id] + } +} + +data "aws_iam_role" "e2e_test_task_role" { + # change + name = "ecsE2ETestRole" +} + +data "aws_iam_role" "e2e_test_task_execution_role" { + # change + name = "ecsE2ETestExecutionRole" +} + +data "template_file" "main_service" { + template = file("./resources/main-service.json.tpl") + + vars = { + app_image = var.sample_app_image + app_service_name = "${var.sample_app_name}" + aws_region = var.aws_region + init_image = var.adot_instrumentation_image + cwagent_image = var.cwagent_image + } +} + +resource "aws_ecs_cluster" "e2e_test" { + name = var.ecs_cluster_name +} +resource "aws_ecs_task_definition" "main_service" { + family = var.sample_app_name + network_mode = "awsvpc" + requires_compatibilities = ["FARGATE"] + execution_role_arn = data.aws_iam_role.e2e_test_task_execution_role.arn + task_role_arn = data.aws_iam_role.e2e_test_task_role.arn + cpu = 512 + memory = 1024 + runtime_platform { + operating_system_family = "LINUX" + cpu_architecture = "X86_64" + } + container_definitions = data.template_file.main_service.rendered + volume { + name = "opentelemetry-auto-instrumentation" + } +} + +resource "aws_ecs_service" "main_service" { + name = var.sample_app_name + cluster = aws_ecs_cluster.e2e_test.id + task_definition = aws_ecs_task_definition.main_service.arn + desired_count = 1 + enable_ecs_managed_tags = true + launch_type = "FARGATE" + + network_configuration { + security_groups = [aws_default_vpc.default.default_security_group_id] + subnets = data.aws_subnets.default_subnets.ids + assign_public_ip = true + } + + wait_for_steady_state = true +} \ No newline at end of file diff --git a/terraform/python/ecs/output.tf b/terraform/python/ecs/output.tf new file mode 100644 index 000000000..72e4af6b5 --- /dev/null +++ b/terraform/python/ecs/output.tf @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------------ +# Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). +# You may not use this file except in compliance with the License. +# A copy of the License is located at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# or in the "license" file accompanying this file. This file is distributed +# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +# express or implied. See the License for the specific language governing +# permissions and limitations under the License. +# ------------------------------------------------------------------------- + +output "sample_app_main_service_task_definition" { + value = aws_ecs_task_definition.main_service.arn +} \ No newline at end of file diff --git a/terraform/python/ecs/resources/main-service.json.tpl b/terraform/python/ecs/resources/main-service.json.tpl new file mode 100644 index 000000000..01f9a188b --- /dev/null +++ b/terraform/python/ecs/resources/main-service.json.tpl @@ -0,0 +1,152 @@ +[ + { + "name": "app", + "image": "${app_image}", + "cpu": 0, + "portMappings": [ + { + "name": "app-8080-tcp", + "containerPort": 8080, + "hostPort": 8080, + "protocol": "tcp", + "appProtocol": "http" + } + ], + "essential": true, + "command": [ + "sh", + "-c", + "python3 manage.py migrate --noinput && python3 manage.py collectstatic --noinput && python3 manage.py runserver 0.0.0.0:8080 --noreload" + ], + "environment": [ + { + "name": "PYTHONPATH", + "value": "/otel-auto-instrumentation-python/opentelemetry/instrumentation/auto_instrumentation:/django_frontend_app:/otel-auto-instrumentation-python" + }, + { + "name": "OTEL_EXPORTER_OTLP_PROTOCOL", + "value": "http/protobuf" + }, + { + "name": "OTEL_TRACES_SAMPLER_ARG", + "value": "endpoint=http://localhost:2000" + }, + { + "name": "OTEL_LOGS_EXPORTER", + "value": "none" + }, + { + "name": "OTEL_PYTHON_CONFIGURATOR", + "value": "aws_configurator" + }, + { + "name": "OTEL_TRACES_SAMPLER", + "value": "xray" + }, + { + "name": "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", + "value": "http://localhost:4316/v1/traces" + }, + { + "name": "DJANGO_SETTINGS_MODULE", + "value": "django_frontend_service.settings" + }, + { + "name": "OTEL_AWS_APPLICATION_SIGNALS_EXPORTER_ENDPOINT", + "value": "http://localhost:4316/v1/metrics" + }, + { + "name": "OTEL_AWS_APPLICATION_SIGNALS_ENABLED", + "value": "true" + }, + { + "name": "OTEL_RESOURCE_ATTRIBUTES", + "value": "service.name=${app_service_name}" + }, + { + "name": "OTEL_METRICS_EXPORTER", + "value": "none" + }, + { + "name": "OTEL_PYTHON_DISTRO", + "value": "aws_distro" + } + ], + "mountPoints": [ + { + "sourceVolume": "opentelemetry-auto-instrumentation", + "containerPath": "/otel-auto-instrumentation-python", + "readOnly": false + } + ], + "logConfiguration": { + "logDriver": "awslogs", + "options": { + "awslogs-group": "/ecs/service-e2e-test", + "awslogs-create-group": "true", + "awslogs-region": "${aws_region}", + "awslogs-stream-prefix": "ecs" + } + } + }, + { + "name": "init", + "image": "${init_image}", + "cpu": 0, + "essential": false, + "logConfiguration": { + "logDriver": "awslogs", + "options": { + "awslogs-group": "/ecs/ecs-cwagent", + "awslogs-create-group": "true", + "awslogs-region": "${aws_region}", + "awslogs-stream-prefix": "ecs" + } + }, + "command": [ + "cp", + "-a", + "/autoinstrumentation/.", + "/otel-auto-instrumentation-python" + ], + "mountPoints": [ + { + "sourceVolume": "opentelemetry-auto-instrumentation", + "containerPath": "/otel-auto-instrumentation-python", + "readOnly": false + } + ] + }, + { + "name": "ecs-cwagent", + "image": "${cwagent_image}", + "cpu": 0, + "essential": true, + "environment": [ + { + "name": "CW_CONFIG_CONTENT", + "value": "{\"agent\": {\"debug\": true}, \"traces\": {\"traces_collected\": {\"application_signals\": {\"enabled\": true}}}, \"logs\": {\"metrics_collected\": {\"application_signals\": {\"enabled\": true}}}}" + } + ], + "logConfiguration": { + "logDriver": "awslogs", + "options": { + "awslogs-group": "/ecs/ecs-cwagent", + "awslogs-create-group": "true", + "awslogs-region": "${aws_region}", + "awslogs-stream-prefix": "ecs" + } + } + }, + { + "name": "traffic-gen", + "image": "curlimages/curl:8.8.0", + "cpu": 0, + "essential": true, + "command": [ + "sh", + "-c", + "while true; do curl http://localhost:8080/; sleep 10; done" + ] + } +] \ No newline at end of file diff --git a/terraform/python/ecs/variables.tf b/terraform/python/ecs/variables.tf new file mode 100644 index 000000000..ddc3c2852 --- /dev/null +++ b/terraform/python/ecs/variables.tf @@ -0,0 +1,49 @@ +# ------------------------------------------------------------------------ +# Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). +# You may not use this file except in compliance with the License. +# A copy of the License is located at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# or in the "license" file accompanying this file. This file is distributed +# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +# express or implied. See the License for the specific language governing +# permissions and limitations under the License. +# ------------------------------------------------------------------------- + + +variable "test_id" { + default = "dummy-123" +} + +variable "aws_region" { + default = "us-west-2" +} + +variable "ecs_cluster_name" { + default = "e2e-test-java" +} + +variable "sample_app_name" { + default = "" +} + +variable "sample_app_image" { + // public.ecr.aws/m0o7p6d1/aws-apm-java-springboot-main-service:latest + default = "" +} + +variable "sample_remote_app_image" { + default = "" +} +variable "adot_instrumentation_image" { + // public.ecr.aws/aws-observability/adot-autoinstrumentation-java:v1.32.3 + default = "" +} + +variable "cwagent_image" { + // public.ecr.aws/y8s3a7r9/cloudwatch-agent:latest + default = "" +} \ No newline at end of file diff --git a/validator/src/main/java/com/amazon/aoc/fileconfigs/PredefinedExpectedTemplate.java b/validator/src/main/java/com/amazon/aoc/fileconfigs/PredefinedExpectedTemplate.java index 3b9c03d07..5cd3e4984 100644 --- a/validator/src/main/java/com/amazon/aoc/fileconfigs/PredefinedExpectedTemplate.java +++ b/validator/src/main/java/com/amazon/aoc/fileconfigs/PredefinedExpectedTemplate.java @@ -96,6 +96,11 @@ public enum PredefinedExpectedTemplate implements FileConfig { JAVA_K8S_CLIENT_CALL_METRIC("/expected-data-template/java/k8s/client-call-metric.mustache"), JAVA_K8S_CLIENT_CALL_TRACE("/expected-data-template/java/k8s/client-call-trace.mustache"), + /** Java ECS Test Case Validations */ + JAVA_ECS_HC_CALL_LOG("/expected-data-template/java/ecs/hc-log.mustache"), + JAVA_ECS_HC_CALL_METRIC("/expected-data-template/java/ecs/hc-metric.mustache"), + JAVA_ECS_HC_CALL_TRACE("/expected-data-template/java/ecs/hc-trace.mustache"), + /** Metric Limiter Test Case Validations */ JAVA_METRIC_LIMITER_METRIC("/expected-data-template/java/metric_limiter/metric-limiter-metric.mustache"), @@ -174,6 +179,11 @@ public enum PredefinedExpectedTemplate implements FileConfig { PYTHON_K8S_CLIENT_CALL_METRIC("/expected-data-template/python/k8s/client-call-metric.mustache"), PYTHON_K8S_CLIENT_CALL_TRACE("/expected-data-template/python/k8s/client-call-trace.mustache"), + /** Python ECS Test Case Validations */ + PYTHON_ECS_HC_CALL_LOG("/expected-data-template/python/ecs/hc-log.mustache"), + PYTHON_ECS_HC_CALL_METRIC("/expected-data-template/python/ecs/hc-metric.mustache"), + PYTHON_ECS_HC_CALL_TRACE("/expected-data-template/python/ecs/hc-trace.mustache"), + /** DotNet EC2 Default Test Case Validations */ DOTNET_EC2_DEFAULT_OUTGOING_HTTP_CALL_LOG( "/expected-data-template/dotnet/ec2/default/outgoing-http-call-log.mustache"), diff --git a/validator/src/main/java/com/amazon/aoc/services/XRayService.java b/validator/src/main/java/com/amazon/aoc/services/XRayService.java index a48978f77..040f4f149 100644 --- a/validator/src/main/java/com/amazon/aoc/services/XRayService.java +++ b/validator/src/main/java/com/amazon/aoc/services/XRayService.java @@ -26,10 +26,12 @@ import java.util.Date; import java.util.List; import org.joda.time.DateTime; +import lombok.extern.log4j.Log4j2; +@Log4j2 public class XRayService { private AWSXRay awsxRay; - private final int SEARCH_PERIOD = 60; + private final int SEARCH_PERIOD = 300; public static String DEFAULT_TRACE_ID = "1-00000000-000000000000000000000000"; public XRayService(String region) { @@ -53,6 +55,8 @@ public List listTraceByIds(List traceIdList) { public List searchTraces(String traceFilter) { Date currentDate = new Date(); Date pastDate = new DateTime(currentDate).minusSeconds(SEARCH_PERIOD).toDate(); + log.info("Searching for traces between {} and {}", pastDate, currentDate); + log.info("Filter expression: {}", traceFilter); GetTraceSummariesResult traceSummaryResult = awsxRay.getTraceSummaries( new GetTraceSummariesRequest() diff --git a/validator/src/main/java/com/amazon/aoc/validators/TraceValidator.java b/validator/src/main/java/com/amazon/aoc/validators/TraceValidator.java index 7033d645e..5e06f02b2 100644 --- a/validator/src/main/java/com/amazon/aoc/validators/TraceValidator.java +++ b/validator/src/main/java/com/amazon/aoc/validators/TraceValidator.java @@ -136,12 +136,17 @@ private Map getTrace() throws Exception { // Looking for trace generated by /client-call is different from the others because the API call is made by the sample app internally, // and not through external callers - if (validationConfig.getHttpPath().contains("client-call")) { - traceFilter += " AND (annotation.aws_local_service = \"local-root-client-call\" OR annotation.aws_local_service = \"local-root-client-call:80\")" ; - } else { - traceFilter += (String.format(" AND annotation.aws_local_operation = \"%s %s\"", - validationConfig.getHttpMethod().toUpperCase(), - validationConfig.getHttpPath())); + log.info("HTTP Path: {}", validationConfig.getHttpPath()); + log.info("traceFilter before: {}", traceFilter); + if (validationConfig.getHttpPath() != null) { + if (validationConfig.getHttpPath().contains("client-call")) { + traceFilter += " AND (annotation.aws_local_service = \"local-root-client-call\" OR annotation.aws_local_service = \"local-root-client-call:80\")" ; + } else { + log.info("HTTP Path is not null: {}", validationConfig.getHttpPath()); + traceFilter += (String.format(" AND annotation.aws_local_operation = \"%s %s\"", + validationConfig.getHttpMethod().toUpperCase(), + validationConfig.getHttpPath())); + } } log.info("Trace Filter: {}", traceFilter); List retrieveTraceLists = xrayService.searchTraces(traceFilter); diff --git a/validator/src/main/resources/expected-data-template/java/ecs/hc-log.mustache b/validator/src/main/resources/expected-data-template/java/ecs/hc-log.mustache new file mode 100644 index 000000000..5eab3c70c --- /dev/null +++ b/validator/src/main/resources/expected-data-template/java/ecs/hc-log.mustache @@ -0,0 +1,13 @@ +[{ + "ECS.Cluster": "^{{platformInfo}}$", + "ECS.TaskDefinitionFamily": "^{{serviceName}}$", + "ECS.TaskDefinitionRevision": "[0-9]*", + "ECS.TaskId": "[A-Za-z0-9]*", + "Environment": "^ecs:{{platformInfo}}$", + "Operation": "GET /", + "PlatformType": "^AWS::ECS$", + "Service": "^{{serviceName}}$", + "Telemetry.Agent": "^CWAgent\/([A-Za-z0-9.-]*)$", + "Telemetry.SDK": "^opentelemetry,([A-Za-z0-9-.]*),java,Auto$", + "Telemetry.Source": "^LocalRootSpan$" +}] \ No newline at end of file diff --git a/validator/src/main/resources/expected-data-template/java/ecs/hc-metric.mustache b/validator/src/main/resources/expected-data-template/java/ecs/hc-metric.mustache new file mode 100644 index 000000000..a35005faa --- /dev/null +++ b/validator/src/main/resources/expected-data-template/java/ecs/hc-metric.mustache @@ -0,0 +1,74 @@ +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: GET / + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ecs:{{platformInfo}} + +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ecs:{{platformInfo}} + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: GET / + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ecs:{{platformInfo}} + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ecs:{{platformInfo}} + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: GET / + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ecs:{{platformInfo}} + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ecs:{{platformInfo}} \ No newline at end of file diff --git a/validator/src/main/resources/expected-data-template/java/ecs/hc-trace.mustache b/validator/src/main/resources/expected-data-template/java/ecs/hc-trace.mustache new file mode 100644 index 000000000..c41e9fd61 --- /dev/null +++ b/validator/src/main/resources/expected-data-template/java/ecs/hc-trace.mustache @@ -0,0 +1,33 @@ +[ + { + "name": "^{{serviceName}}$", + "http": { + "request": { + "url": "^http://localhost:8080/$", + "method": "^GET$" + }, + "response": { + "status": "^200$" + } + }, + "aws": { + "account_id": "^{{accountId}}$" + }, + "annotations": { + "aws.local.service": "^{{serviceName}}$", + "aws.local.operation": "^GET /$", + "aws.local.environment": "^ecs:{{platformInfo}}$" + }, + "metadata": { + "default": { + "otel.resource.aws.ecs.launchtype": "^fargate$", + "otel.resource.aws.ecs.task.revision": "[0-9]*", + "otel.resource.cloud.platform": "^aws_ecs$", + "aws.ecs.cluster.name": "^{{platformInfo}}$", + "aws.ecs.task.id": "[A-Za-z0-9]*", + "PlatformType": "^AWS::ECS$", + "aws.span.kind": "^LOCAL_ROOT$" + } + } + } +] \ No newline at end of file diff --git a/validator/src/main/resources/expected-data-template/python/ecs/hc-log.mustache b/validator/src/main/resources/expected-data-template/python/ecs/hc-log.mustache new file mode 100644 index 000000000..e453f0310 --- /dev/null +++ b/validator/src/main/resources/expected-data-template/python/ecs/hc-log.mustache @@ -0,0 +1,13 @@ +[{ + "ECS.Cluster": "^{{platformInfo}}$", + "ECS.TaskDefinitionFamily": "^{{serviceName}}$", + "ECS.TaskDefinitionRevision": "[0-9]*", + "ECS.TaskId": "[A-Za-z0-9]*", + "Environment": "^ecs:{{platformInfo}}$", + "Operation": "GET /", + "PlatformType": "^AWS::ECS$", + "Service": "^{{serviceName}}$", + "Telemetry.Agent": "^CWAgent\/([A-Za-z0-9.-]*)$", + "Telemetry.SDK": "^opentelemetry,([A-Za-z0-9-.]*),python,Auto$", + "Telemetry.Source": "^LocalRootSpan$" +}] \ No newline at end of file diff --git a/validator/src/main/resources/expected-data-template/python/ecs/hc-metric.mustache b/validator/src/main/resources/expected-data-template/python/ecs/hc-metric.mustache new file mode 100644 index 000000000..a35005faa --- /dev/null +++ b/validator/src/main/resources/expected-data-template/python/ecs/hc-metric.mustache @@ -0,0 +1,74 @@ +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: GET / + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ecs:{{platformInfo}} + +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ecs:{{platformInfo}} + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: GET / + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ecs:{{platformInfo}} + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ecs:{{platformInfo}} + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: GET / + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ecs:{{platformInfo}} + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ecs:{{platformInfo}} \ No newline at end of file diff --git a/validator/src/main/resources/expected-data-template/python/ecs/hc-trace.mustache b/validator/src/main/resources/expected-data-template/python/ecs/hc-trace.mustache new file mode 100644 index 000000000..c41e9fd61 --- /dev/null +++ b/validator/src/main/resources/expected-data-template/python/ecs/hc-trace.mustache @@ -0,0 +1,33 @@ +[ + { + "name": "^{{serviceName}}$", + "http": { + "request": { + "url": "^http://localhost:8080/$", + "method": "^GET$" + }, + "response": { + "status": "^200$" + } + }, + "aws": { + "account_id": "^{{accountId}}$" + }, + "annotations": { + "aws.local.service": "^{{serviceName}}$", + "aws.local.operation": "^GET /$", + "aws.local.environment": "^ecs:{{platformInfo}}$" + }, + "metadata": { + "default": { + "otel.resource.aws.ecs.launchtype": "^fargate$", + "otel.resource.aws.ecs.task.revision": "[0-9]*", + "otel.resource.cloud.platform": "^aws_ecs$", + "aws.ecs.cluster.name": "^{{platformInfo}}$", + "aws.ecs.task.id": "[A-Za-z0-9]*", + "PlatformType": "^AWS::ECS$", + "aws.span.kind": "^LOCAL_ROOT$" + } + } + } +] \ No newline at end of file diff --git a/validator/src/main/resources/validations/java/ecs/log-validation.yml b/validator/src/main/resources/validations/java/ecs/log-validation.yml new file mode 100644 index 000000000..0302f1965 --- /dev/null +++ b/validator/src/main/resources/validations/java/ecs/log-validation.yml @@ -0,0 +1,4 @@ +- + validationType: "cw-log" + callingType: "none" + expectedLogStructureTemplate: "JAVA_ECS_HC_CALL_LOG" \ No newline at end of file diff --git a/validator/src/main/resources/validations/java/ecs/metric-validation.yml b/validator/src/main/resources/validations/java/ecs/metric-validation.yml new file mode 100644 index 000000000..c1cea45e4 --- /dev/null +++ b/validator/src/main/resources/validations/java/ecs/metric-validation.yml @@ -0,0 +1,4 @@ +- + validationType: "cw-metric" + callingType: "none" + expectedMetricTemplate: "JAVA_ECS_HC_CALL_METRIC" \ No newline at end of file diff --git a/validator/src/main/resources/validations/java/ecs/trace-validation.yml b/validator/src/main/resources/validations/java/ecs/trace-validation.yml new file mode 100644 index 000000000..322f35a35 --- /dev/null +++ b/validator/src/main/resources/validations/java/ecs/trace-validation.yml @@ -0,0 +1,6 @@ +- + validationType: "trace" + callingType: "none" + httpMethod: "get" + httpPath: "/" + expectedTraceTemplate: "JAVA_ECS_HC_CALL_TRACE" \ No newline at end of file diff --git a/validator/src/main/resources/validations/python/ecs/log-validation.yml b/validator/src/main/resources/validations/python/ecs/log-validation.yml new file mode 100644 index 000000000..473ffb2ee --- /dev/null +++ b/validator/src/main/resources/validations/python/ecs/log-validation.yml @@ -0,0 +1,4 @@ +- + validationType: "cw-log" + callingType: "none" + expectedLogStructureTemplate: "PYTHON_ECS_HC_CALL_LOG" \ No newline at end of file diff --git a/validator/src/main/resources/validations/python/ecs/metric-validation.yml b/validator/src/main/resources/validations/python/ecs/metric-validation.yml new file mode 100644 index 000000000..d1365d4bd --- /dev/null +++ b/validator/src/main/resources/validations/python/ecs/metric-validation.yml @@ -0,0 +1,4 @@ +- + validationType: "cw-metric" + callingType: "none" + expectedMetricTemplate: "PYTHON_ECS_HC_CALL_METRIC" \ No newline at end of file diff --git a/validator/src/main/resources/validations/python/ecs/trace-validation.yml b/validator/src/main/resources/validations/python/ecs/trace-validation.yml new file mode 100644 index 000000000..1ee776efa --- /dev/null +++ b/validator/src/main/resources/validations/python/ecs/trace-validation.yml @@ -0,0 +1,6 @@ +- + validationType: "trace" + callingType: "none" + httpMethod: "get" + httpPath: "/" + expectedTraceTemplate: "PYTHON_ECS_HC_CALL_TRACE" \ No newline at end of file From 6b054e1f16c3dfe0e48845edf831a6f2ed04f3c8 Mon Sep 17 00:00:00 2001 From: Zhonghao Zhao Date: Mon, 9 Sep 2024 13:31:16 -0700 Subject: [PATCH 02/13] Code Clean up. --- .github/workflows/java-ecs-canary.yml | 3 --- .github/workflows/python-ecs-canary.yml | 3 --- 2 files changed, 6 deletions(-) diff --git a/.github/workflows/java-ecs-canary.yml b/.github/workflows/java-ecs-canary.yml index 6fff9a15d..2bbf59b43 100644 --- a/.github/workflows/java-ecs-canary.yml +++ b/.github/workflows/java-ecs-canary.yml @@ -9,9 +9,6 @@ on: schedule: - cron: '*/15 * * * *' # run the workflow every 15 minutes workflow_dispatch: # be able to run the workflow on demand - push: - branches: - - ecs-no-call-zzhlogin permissions: id-token: write diff --git a/.github/workflows/python-ecs-canary.yml b/.github/workflows/python-ecs-canary.yml index e43f23d6d..d2c8ffb4f 100644 --- a/.github/workflows/python-ecs-canary.yml +++ b/.github/workflows/python-ecs-canary.yml @@ -9,9 +9,6 @@ on: schedule: - cron: '*/15 * * * *' # run the workflow every 15 minutes workflow_dispatch: # be able to run the workflow on demand - push: - branches: - - ecs-no-call-zzhlogin permissions: id-token: write From dddbd631b503f5f2b556f08499cd9be591fa5237 Mon Sep 17 00:00:00 2001 From: Zhonghao Zhao Date: Mon, 9 Sep 2024 13:50:12 -0700 Subject: [PATCH 03/13] Code clean up. --- .github/workflows/java-ecs-e2e-test.yml | 270 ------------------------ .github/workflows/java-ecs-test.yml | 1 - policys.txt | 80 ------- 3 files changed, 351 deletions(-) delete mode 100644 .github/workflows/java-ecs-e2e-test.yml delete mode 100644 policys.txt diff --git a/.github/workflows/java-ecs-e2e-test.yml b/.github/workflows/java-ecs-e2e-test.yml deleted file mode 100644 index 1fdf9c3e4..000000000 --- a/.github/workflows/java-ecs-e2e-test.yml +++ /dev/null @@ -1,270 +0,0 @@ -## Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -## SPDX-License-Identifier: Apache-2.0 - -# This is a reusable workflow for running the E2E test for App Signals. -# It is meant to be called from another workflow. -# Read more about reusable workflows: https://docs.github.com/en/actions/using-workflows/reusing-workflows#overview -name: Java ECS Use Case -on: - workflow_call: - inputs: - aws-region: - required: true - type: string - caller-workflow-name: - required: true - type: string - adot-image-name: - required: false - type: string - cwagent-image-name: - required: false - type: string - -concurrency: - group: '${{ github.workflow }} @ ${{ inputs.aws-region }}' - cancel-in-progress: false - -permissions: - id-token: write - contents: read - -env: - E2E_TEST_AWS_REGION: ${{ inputs.aws-region }} - CALLER_WORKFLOW_NAME: ${{ inputs.caller-workflow-name }} - ADOT_IMAGE_NAME: ${{ inputs.adot-image-name }} - CLUSTER_NAME: e2e-test-java - SAMPLE_APP_NAME: main-service-java - METRIC_NAMESPACE: ApplicationSignals - LOG_GROUP_NAME: /aws/application-signals/data - TEST_RESOURCES_FOLDER: ${GITHUB_WORKSPACE} - E2E_TEST_ACCOUNT_ID: ${{ secrets.APPLICATION_SIGNALS_E2E_TEST_ACCOUNT_ID }} - E2E_TEST_ROLE_NAME: ${{ secrets.APPLICATION_SIGNALS_E2E_TEST_ROLE_NAME }} - ACCOUNT_ID: '007003802740' - CWAGENT_IMAGE_URI: 'public.ecr.aws/y8s3a7r9/cloudwatch-agent:latest' - -jobs: - java-ecs: - runs-on: ubuntu-latest - container: - image: public.ecr.aws/h6o3z5z9/aws-application-signals-test-framework-workflow-container:latest - steps: - - name: Generate testing id and sample app namespace - run: | - echo TESTING_ID="${{ github.job }}-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" >> $GITHUB_ENV - - - uses: actions/checkout@v4 - with: - repository: 'aws-observability/aws-application-signals-test-framework' - ref: ${{ env.CALLER_WORKFLOW_NAME == 'main-build' && 'main' || github.ref }} - fetch-depth: 0 - - # We initialize Gradlew Daemon early on during the workflow because sometimes initialization - # fails due to transient issues. If it fails here, then we will try again later before the validators - - name: Initiate Gradlew Daemon - id: initiate-gradlew - uses: ./.github/workflows/actions/execute_and_retry - continue-on-error: true - with: - command: "./gradlew :validator:build" - cleanup: "./gradlew clean" - max_retry: 3 - sleep_time: 60 - - - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@v4 - with: - role-to-assume: arn:aws:iam::${{ env.E2E_TEST_ACCOUNT_ID }}:role/${{ env.E2E_TEST_ROLE_NAME }} - aws-region: us-east-1 - - # ACCOUNT_ID, region-account/${{ env.E2E_TEST_AWS_REGION }} - - name: Retrieve account - uses: aws-actions/aws-secretsmanager-get-secrets@v1 - with: - secret-ids: | - JAVA_MAIN_SAMPLE_APP_IMAGE, e2e-test/java-main-sample-app-image - JAVA_REMOTE_SAMPLE_APP_IMAGE, e2e-test/java-remote-sample-app-image - - # If the workflow is running as a canary, then we want to log in to the aws account in the appropriate region - - name: Configure AWS Credentials - if: ${{ github.event.repository.name == 'aws-application-signals-test-framework' }} - uses: aws-actions/configure-aws-credentials@v4 - with: - role-to-assume: arn:aws:iam::${{ env.ACCOUNT_ID }}:role/${{ env.E2E_TEST_ROLE_NAME }} - aws-region: ${{ env.E2E_TEST_AWS_REGION }} - - - name: Initiate Terraform - uses: ./.github/workflows/actions/execute_and_retry - with: - command: "cd ${{ env.TEST_RESOURCES_FOLDER }}/terraform/java/ecs && terraform init && terraform validate" - cleanup: "rm -rf .terraform && rm -rf .terraform.lock.hcl" - max_retry: 6 - sleep_time: 60 - - - name: Set Sample App Image - run: | - echo MAIN_SAMPLE_APP_IMAGE_URI="${{ env.ACCOUNT_ID }}.dkr.ecr.${{ env.E2E_TEST_AWS_REGION }}.amazonaws.com/${{ env.JAVA_MAIN_SAMPLE_APP_IMAGE }}" >> $GITHUB_ENV - echo REMOTE_SAMPLE_APP_IMAGE_URI="${{ env.ACCOUNT_ID }}.dkr.ecr.${{ env.E2E_TEST_AWS_REGION }}.amazonaws.com/${{ env.JAVA_REMOTE_SAMPLE_APP_IMAGE }}" >> $GITHUB_ENV - - - name: Set Get ADOT Wheel command environment variable - run: | - if [ "${{ github.event.repository.name }}" = "aws-otel-java-instrumentation" ]; then - # Reusing the adot-main-build-staging-jar bucket to store the java wheel file - echo ADOT_INSTRUMENTATION_IMAGE_URI="${{ env.ADOT_IMAGE_NAME }}" >> $GITHUB_ENV - else - ADOT_INSTRUMENTATION_IMAGE_TAG=$(curl -s -I -L 'https://github.com/aws-observability/aws-otel-java-instrumentation/releases/latest' | grep -i Location | awk -F'/tag/' '{print $2}' | tr -d '\r') - echo ADOT_INSTRUMENTATION_IMAGE_URI="public.ecr.aws/aws-observability/adot-autoinstrumentation-java:$ADOT_INSTRUMENTATION_IMAGE_TAG" >> $GITHUB_ENV - fi -# -# - name: Set Get CW Agent command environment variable -# run: | -# if [ "${{ github.event.repository.name }}" = "amazon-cloudwatch-agent" ]; then -# echo CWAGENT_IMAGE_URI="${{ secrets.AWS_ECR_PRIVATE_REGISTRY }}/cwagent-integration-test:${{ github.sha }}" >> $GITHUB_ENV -# else -# echo CWAGENT_IMAGE_URI="public.ecr.aws/cloudwatch-agent/cloudwatch-agent:latest" >> $GITHUB_ENV -# fi - - - name: Deploy sample app via terraform and wait for the endpoint to come online - id: deploy-sample-app - working-directory: terraform/java/ecs - run: | - # Attempt to deploy the sample app on an EKS instance and wait for its endpoint to come online. - # There may be occasional failures due to transitivity issues, so try up to 2 times. - # deployment_failed of 0 indicates that both the terraform deployment and the endpoint are running, while 1 indicates - # that it failed at some point - retry_counter=0 - max_retry=2 - while [ $retry_counter -lt $max_retry ]; do - echo "Attempt $retry_counter" - deployment_failed=0 - terraform apply -auto-approve \ - -var="test_id=${{ env.TESTING_ID }}" \ - -var="aws_region=${{ env.E2E_TEST_AWS_REGION }}" \ - -var="ecs_cluster_name=${{ env.CLUSTER_NAME }}" \ - -var="sample_app_name=${{ env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }}" \ - -var="sample_app_image=${{ env.MAIN_SAMPLE_APP_IMAGE_URI }}" \ - -var="sample_remote_app_image=${{ env.REMOTE_SAMPLE_APP_IMAGE_URI }}" \ - -var="adot_instrumentation_image=${{ env.ADOT_INSTRUMENTATION_IMAGE_URI }}" \ - -var="cwagent_image=${{ env.CWAGENT_IMAGE_URI }}" \ - || deployment_failed=$? - - if [ $deployment_failed -ne 0 ]; then - echo "Terraform deployment was unsuccessful. Will attempt to retry deployment." - fi - - # If the deployment_failed is 1 then either the terraform deployment or the endpoint connection failed, so first destroy the - # resources created from terraform and try again. - if [ $deployment_failed -eq 1 ]; then - echo "Destroying terraform" - terraform destroy -auto-approve \ - -var="test_id=${{ env.TESTING_ID }}" \ - -var="aws_region=${{ env.E2E_TEST_AWS_REGION }}" \ - -var="ecs_cluster_name=${{ env.CLUSTER_NAME }}" \ - -var="sample_app_name=${{ env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }}" \ - -var="sample_app_image=${{ env.MAIN_SAMPLE_APP_IMAGE_URI }}" \ - -var="sample_remote_app_image=${{ env.REMOTE_SAMPLE_APP_IMAGE_URI }}" \ - -var="adot_instrumentation_image=${{ env.ADOT_INSTRUMENTATION_IMAGE_URI }}" \ - -var="cwagent_image=${{ env.CWAGENT_IMAGE_URI }}" - - retry_counter=$(($retry_counter+1)) - else - # If deployment succeeded, then exit the loop - break - fi - - if [ $retry_counter -ge $max_retry ]; then - echo "Max retry reached, failed to deploy terraform and connect to the endpoint. Exiting code" - exit 1 - fi - done - - - name: Sleep to Wait for Canary Generated and Log Artifact Versions - run: | - sleep 120 - echo "ADOT Image: ${{ env.ADOT_INSTRUMENTATION_IMAGE_URI }}"; - echo "CW Agent Image: ${{ env.CWAGENT_IMAGE_URI }}"; - - - name: Initiate Gradlew Daemon - if: steps.initiate-gradlew == 'failure' - uses: ./.github/workflows/actions/execute_and_retry - continue-on-error: true - with: - command: "./gradlew :validator:build" - cleanup: "./gradlew clean" - max_retry: 3 - sleep_time: 60 - - # Validation for app signals telemetry data - - name: Call endpoint and validate generated EMF logs - id: log-validation - if: steps.deploy-sample-app.outcome == 'success' && !cancelled() - run: ./gradlew validator:run --args='-c java/ecs/log-validation.yml - --testing-id ${{ env.TESTING_ID }} - --region ${{ env.E2E_TEST_AWS_REGION }} - --account-id ${{ env.ACCOUNT_ID }} - --metric-namespace ${{ env.METRIC_NAMESPACE }} - --log-group ${{ env.LOG_GROUP_NAME }} - --platform-info ${{ env.CLUSTER_NAME }} - --service-name ${{env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }} - --rollup' - - - name: Call endpoints and validate generated metrics - id: metric-validation - if: (steps.deploy-sample-app.outcome == 'success' || steps.log-validation.outcome == 'failure') && !cancelled() - run: ./gradlew validator:run --args='-c java/ecs/metric-validation.yml - --testing-id ${{ env.TESTING_ID }} - --region ${{ env.E2E_TEST_AWS_REGION }} - --account-id ${{ env.ACCOUNT_ID }} - --metric-namespace ${{ env.METRIC_NAMESPACE }} - --log-group ${{ env.LOG_GROUP_NAME }} - --platform-info ${{ env.CLUSTER_NAME }} - --service-name ${{env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }} - --rollup' - - - name: Call endpoints and validate generated traces - id: trace-validation - if: (steps.deploy-sample-app.outcome == 'success' || steps.log-validation.outcome == 'failure' || steps.metric-validation.outcome == 'failure') && !cancelled() - run: ./gradlew validator:run --args='-c java/ecs/trace-validation.yml - --testing-id ${{ env.TESTING_ID }} - --region ${{ env.E2E_TEST_AWS_REGION }} - --account-id ${{ env.ACCOUNT_ID }} - --metric-namespace ${{ env.METRIC_NAMESPACE }} - --log-group ${{ env.LOG_GROUP_NAME }} - --platform-info ${{ env.CLUSTER_NAME }} - --service-name ${{env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }} - --rollup' - - - name: Publish metric on test result - if: always() - run: | - if [ "${{ steps.log-validation.outcome }}" = "success" ] && [ "${{ steps.metric-validation.outcome }}" = "success" ] && [ "${{ steps.trace-validation.outcome }}" = "success" ]; then - aws cloudwatch put-metric-data --namespace 'ADOT/GitHubActions' \ - --metric-name Failure \ - --dimensions repository=${{ github.repository }},branch=${{ github.ref_name }},workflow=${{ env.CALLER_WORKFLOW_NAME }} \ - --value 0.0 \ - --region ${{ env.E2E_TEST_AWS_REGION }} - else - aws cloudwatch put-metric-data --namespace 'ADOT/GitHubActions' \ - --metric-name Failure \ - --dimensions repository=${{ github.repository }},branch=${{ github.ref_name }},workflow=${{ env.CALLER_WORKFLOW_NAME }} \ - --value 1.0 \ - --region ${{ env.E2E_TEST_AWS_REGION }} - fi - - # Clean up Procedures - - - name: Terraform destroy - if: always() - continue-on-error: true - timeout-minutes: 5 - working-directory: terraform/java/ecs - run: | - terraform destroy -auto-approve \ - -var="test_id=${{ env.TESTING_ID }}" \ - -var="aws_region=${{ env.E2E_TEST_AWS_REGION }}" \ - -var="ecs_cluster_name=${{ env.CLUSTER_NAME }}" \ - -var="sample_app_name=${{ env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }}" \ - -var="sample_app_image=${{ env.MAIN_SAMPLE_APP_IMAGE_URI }}" \ - -var="sample_remote_app_image=${{ env.REMOTE_SAMPLE_APP_IMAGE_URI }}" \ - -var="adot_instrumentation_image=${{ env.ADOT_INSTRUMENTATION_IMAGE_URI }}" \ - -var="cwagent_image=${{ env.CWAGENT_IMAGE_URI }}" \ No newline at end of file diff --git a/.github/workflows/java-ecs-test.yml b/.github/workflows/java-ecs-test.yml index 63688b04c..2ff499a33 100644 --- a/.github/workflows/java-ecs-test.yml +++ b/.github/workflows/java-ecs-test.yml @@ -85,7 +85,6 @@ jobs: role-to-assume: arn:aws:iam::${{ env.E2E_TEST_ACCOUNT_ID }}:role/${{ env.E2E_TEST_ROLE_NAME }} aws-region: us-east-1 - # ACCOUNT_ID, region-account/${{ env.E2E_TEST_AWS_REGION }} - name: Retrieve account uses: aws-actions/aws-secretsmanager-get-secrets@v1 with: diff --git a/policys.txt b/policys.txt deleted file mode 100644 index 3e78d43af..000000000 --- a/policys.txt +++ /dev/null @@ -1,80 +0,0 @@ -githubProviderRole -{ - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Principal": { - "Federated": "arn:aws:iam::654654176582:oidc-provider/token.actions.githubusercontent.com" - }, - "Action": "sts:AssumeRoleWithWebIdentity", - "Condition": { - "StringLike": { - "token.actions.githubusercontent.com:sub": [ - "repo:aws-observability/aws-application-signals-test-framework:ref:refs/heads/*", - "repo:aws-observability/aws-otel-python-instrumentation:ref:refs/heads/*", - "repo:aws-observability/aws-otel-dotnet-instrumentation:ref:refs/heads/*", - "repo:aws-observability/aws-otel-js-instrumentation:ref:refs/heads/*", - "repo:aws-observability/aws-otel-java-instrumentation:ref:refs/heads/*", - "repo:aws-observability/aws-otel-community:ref:refs/heads/*" - ] - } - } - }, - { - "Effect": "Allow", - "Principal": { - "AWS": "arn:aws:iam::654654176582:root" - }, - "Action": "sts:AssumeRole" - } - ] -} - - -MAIN_SAMPLE_APP_IMAGE_URI = 654654176582.dkr.ecr.us-east-1.amazonaws.com/appsignals-python-django-main-service -REMOTE_SAMPLE_APP_IMAGE_URI = 654654176582.dkr.ecr.us-east-1.amazonaws.com/appsignals-python-django-remote-service - - -Task Role: ecsE2ETestRole -AmazonEC2ContainerServiceRole -AmazonS3FullAccess -AmazonSSMReadOnlyAccess -AWSXrayWriteOnlyAccess -AWSXRayDaemonWriteAccess -CloudWatchAgentServerPolicy -ECSDataDog -ECSFargateAllowExecuteCommand - -Task Execution Role: ecsE2ETestExecutionRole -AmazonECSTaskExecutionRolePolicy -AmazonSSMReadOnlyAccess -CloudWatchAgentServerPolicy - - -export TF_LOG=DEBUG -terraform apply -auto-approve \ - -var="test_id=111111" \ - -var="aws_region=us-east-1" \ - -var="ecs_cluster_name=e2e-test-python" \ - -var="sample_app_name=main-service-python-zzhlocal" \ - -var="sample_app_image=007003802740.dkr.ecr.us-east-1.amazonaws.com/appsignals-python-django-main-service:latest" \ - -var="sample_remote_app_image=007003802740.dkr.ecr.us-east-1.amazonaws.com/appsignals-python-django-remote-service:latest" \ - -var="adot_instrumentation_image=007003802740.dkr.ecr.us-east-1.amazonaws.com/adot-python-distro:latest" \ - -var="cwagent_image=public.ecr.aws/y8s3a7r9/cloudwatch-agent:latest" - -terraform destroy -auto-approve \ - -var="test_id=111111" \ - -var="aws_region=us-east-1" \ - -var="ecs_cluster_name=e2e-test-python" \ - -var="sample_app_name=main-service-python-zzhlocal" \ - -var="sample_app_image=007003802740.dkr.ecr.us-east-1.amazonaws.com/appsignals-python-django-main-service:latest" \ - -var="sample_remote_app_image=007003802740.dkr.ecr.us-east-1.amazonaws.com/appsignals-python-django-remote-service:latest" \ - -var="adot_instrumentation_image=public.ecr.aws/aws-observability/adot-autoinstrumentation-python:v0.4.0" \ - -var="cwagent_image=public.ecr.aws/cloudwatch-agent/cloudwatch-agent:latest" - - - -{"Environment":"ecs:e2e-test-python","Operation":"GET /","PlatformType":"Generic","Service":"main-service-python-111111","Telemetry.Agent":"CWAgent/1.300045.1b823","Telemetry.SDK":"opentelemetry,0.4.0-aws,python,Auto","Telemetry.Source":"LocalRootSpan","Version":"1","_aws":{"CloudWatchMetrics":[{"Namespace":"ApplicationSignals","Dimensions":[["Environment","Operation","Service"],["Environment","Service"]],"Metrics":[{"Name":"Latency","Unit":"Milliseconds"},{"Name":"Error"},{"Name":"Fault"}]}],"Timestamp":1725560229171},"Error":{"Values":[0],"Counts":[2],"Max":0,"Min":0,"Count":2,"Sum":0},"Fault":{"Values":[0],"Counts":[2],"Max":0,"Min":0,"Count":2,"Sum":0},"Latency":{"Values":[0.6311079285541068,0.7586906445844908],"Counts":[1,1],"Max":0.75761,"Min":0.630616,"Count":2,"Sum":1.388226}} - -{"ECS.Cluster":"e2e-test-python","ECS.TaskDefinitionFamily":"main-service-python-python-ecs-10729837765-26-1","ECS.TaskDefinitionRevision":"1","ECS.TaskId":"a01227ec7a81451fa61c8bc2b62226d4","ECS.Workload":"","Environment":"ecs:e2e-test-python","Operation":"GET /","PlatformType":"AWS::ECS","Service":"main-service-python-python-ecs-10729837765-26-1","Telemetry.Agent":"CWAgent/Unknown","Telemetry.SDK":"opentelemetry,0.4.0.dev0-aws,python,Auto","Telemetry.Source":"LocalRootSpan","Version":"1","_aws":{"CloudWatchMetrics":[{"Namespace":"ApplicationSignals","Dimensions":[["Environment","Operation","Service"],["Environment","Service"]],"Metrics":[{"Name":"Fault"},{"Name":"Latency","Unit":"Milliseconds"},{"Name":"Error"}]}],"Timestamp":1725580280979},"aws.log.group.names":"[\"/ecs/service-e2e-test\"]","Error":{"Values":[0],"Counts":[2],"Max":0,"Min":0,"Count":2,"Sum":0},"Fault":{"Values":[0],"Counts":[2],"Max":0,"Min":0,"Count":2,"Sum":0},"Latency":{"Values":[0.530696394759346,0.5602270903010342],"Counts":[1,1],"Max":0.561569,"Min":0.532748,"Count":2,"Sum":1.094317}} \ No newline at end of file From 35a4029a5cc524847f2b5510b2e01e85fd914111 Mon Sep 17 00:00:00 2001 From: Zhonghao Zhao Date: Mon, 9 Sep 2024 14:13:06 -0700 Subject: [PATCH 04/13] Test workflow run. --- .github/workflows/java-ecs-canary.yml | 3 +++ .github/workflows/python-ecs-canary.yml | 3 +++ .../com/amazon/aoc/services/XRayService.java | 2 +- .../amazon/aoc/validators/TraceValidator.java | 16 +++++----------- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/java-ecs-canary.yml b/.github/workflows/java-ecs-canary.yml index 2bbf59b43..6fff9a15d 100644 --- a/.github/workflows/java-ecs-canary.yml +++ b/.github/workflows/java-ecs-canary.yml @@ -9,6 +9,9 @@ on: schedule: - cron: '*/15 * * * *' # run the workflow every 15 minutes workflow_dispatch: # be able to run the workflow on demand + push: + branches: + - ecs-no-call-zzhlogin permissions: id-token: write diff --git a/.github/workflows/python-ecs-canary.yml b/.github/workflows/python-ecs-canary.yml index d2c8ffb4f..e43f23d6d 100644 --- a/.github/workflows/python-ecs-canary.yml +++ b/.github/workflows/python-ecs-canary.yml @@ -9,6 +9,9 @@ on: schedule: - cron: '*/15 * * * *' # run the workflow every 15 minutes workflow_dispatch: # be able to run the workflow on demand + push: + branches: + - ecs-no-call-zzhlogin permissions: id-token: write diff --git a/validator/src/main/java/com/amazon/aoc/services/XRayService.java b/validator/src/main/java/com/amazon/aoc/services/XRayService.java index 040f4f149..c26a9b5d2 100644 --- a/validator/src/main/java/com/amazon/aoc/services/XRayService.java +++ b/validator/src/main/java/com/amazon/aoc/services/XRayService.java @@ -31,7 +31,7 @@ @Log4j2 public class XRayService { private AWSXRay awsxRay; - private final int SEARCH_PERIOD = 300; + private final int SEARCH_PERIOD = 60; public static String DEFAULT_TRACE_ID = "1-00000000-000000000000000000000000"; public XRayService(String region) { diff --git a/validator/src/main/java/com/amazon/aoc/validators/TraceValidator.java b/validator/src/main/java/com/amazon/aoc/validators/TraceValidator.java index 5e06f02b2..1cd1ce6d2 100644 --- a/validator/src/main/java/com/amazon/aoc/validators/TraceValidator.java +++ b/validator/src/main/java/com/amazon/aoc/validators/TraceValidator.java @@ -136,17 +136,11 @@ private Map getTrace() throws Exception { // Looking for trace generated by /client-call is different from the others because the API call is made by the sample app internally, // and not through external callers - log.info("HTTP Path: {}", validationConfig.getHttpPath()); - log.info("traceFilter before: {}", traceFilter); - if (validationConfig.getHttpPath() != null) { - if (validationConfig.getHttpPath().contains("client-call")) { - traceFilter += " AND (annotation.aws_local_service = \"local-root-client-call\" OR annotation.aws_local_service = \"local-root-client-call:80\")" ; - } else { - log.info("HTTP Path is not null: {}", validationConfig.getHttpPath()); - traceFilter += (String.format(" AND annotation.aws_local_operation = \"%s %s\"", - validationConfig.getHttpMethod().toUpperCase(), - validationConfig.getHttpPath())); - } + if (validationConfig.getHttpPath().contains("client-call")) { + traceFilter += " AND (annotation.aws_local_service = \"local-root-client-call\" OR annotation.aws_local_service = \"local-root-client-call:80\")" ; + } else { + traceFilter += (String.format(" AND annotation.aws_local_operation = \"%s %s\"", + validationConfig.getHttpMethod().toUpperCase(), validationConfig.getHttpPath())); } log.info("Trace Filter: {}", traceFilter); List retrieveTraceLists = xrayService.searchTraces(traceFilter); From f645c816080128453783f3a306ccce11a8beb333 Mon Sep 17 00:00:00 2001 From: Zhonghao Zhao Date: Mon, 9 Sep 2024 14:25:26 -0700 Subject: [PATCH 05/13] Code clean up. --- .github/workflows/java-ecs-canary.yml | 3 --- .github/workflows/python-ecs-canary.yml | 3 --- 2 files changed, 6 deletions(-) diff --git a/.github/workflows/java-ecs-canary.yml b/.github/workflows/java-ecs-canary.yml index 6fff9a15d..2bbf59b43 100644 --- a/.github/workflows/java-ecs-canary.yml +++ b/.github/workflows/java-ecs-canary.yml @@ -9,9 +9,6 @@ on: schedule: - cron: '*/15 * * * *' # run the workflow every 15 minutes workflow_dispatch: # be able to run the workflow on demand - push: - branches: - - ecs-no-call-zzhlogin permissions: id-token: write diff --git a/.github/workflows/python-ecs-canary.yml b/.github/workflows/python-ecs-canary.yml index e43f23d6d..d2c8ffb4f 100644 --- a/.github/workflows/python-ecs-canary.yml +++ b/.github/workflows/python-ecs-canary.yml @@ -9,9 +9,6 @@ on: schedule: - cron: '*/15 * * * *' # run the workflow every 15 minutes workflow_dispatch: # be able to run the workflow on demand - push: - branches: - - ecs-no-call-zzhlogin permissions: id-token: write From ba84d865b98a2a0ff00656dbf81029befd1c37c2 Mon Sep 17 00:00:00 2001 From: Zhonghao Zhao Date: Mon, 9 Sep 2024 14:40:47 -0700 Subject: [PATCH 06/13] Remove unuseful comment. --- .github/workflows/python-ecs-test.yml | 1 - .../src/main/java/com/amazon/aoc/services/XRayService.java | 2 -- 2 files changed, 3 deletions(-) diff --git a/.github/workflows/python-ecs-test.yml b/.github/workflows/python-ecs-test.yml index 3759e8d60..fffc6763e 100644 --- a/.github/workflows/python-ecs-test.yml +++ b/.github/workflows/python-ecs-test.yml @@ -85,7 +85,6 @@ jobs: role-to-assume: arn:aws:iam::${{ env.E2E_TEST_ACCOUNT_ID }}:role/${{ env.E2E_TEST_ROLE_NAME }} aws-region: us-east-1 - # ACCOUNT_ID, region-account/${{ env.E2E_TEST_AWS_REGION }} - name: Retrieve account uses: aws-actions/aws-secretsmanager-get-secrets@v1 with: diff --git a/validator/src/main/java/com/amazon/aoc/services/XRayService.java b/validator/src/main/java/com/amazon/aoc/services/XRayService.java index c26a9b5d2..ee51da557 100644 --- a/validator/src/main/java/com/amazon/aoc/services/XRayService.java +++ b/validator/src/main/java/com/amazon/aoc/services/XRayService.java @@ -55,8 +55,6 @@ public List listTraceByIds(List traceIdList) { public List searchTraces(String traceFilter) { Date currentDate = new Date(); Date pastDate = new DateTime(currentDate).minusSeconds(SEARCH_PERIOD).toDate(); - log.info("Searching for traces between {} and {}", pastDate, currentDate); - log.info("Filter expression: {}", traceFilter); GetTraceSummariesResult traceSummaryResult = awsxRay.getTraceSummaries( new GetTraceSummariesRequest() From 70afa17ca54a39a4804f8012906ead99d3928502 Mon Sep 17 00:00:00 2001 From: Zhonghao Zhao Date: Thu, 12 Sep 2024 15:51:30 -0700 Subject: [PATCH 07/13] Address comments and use the latest ADOT python released image. --- .github/workflows/java-ecs-test.yml | 4 ++-- .github/workflows/python-ecs-test.yml | 10 ++++------ terraform/java/ecs/output.tf | 18 ------------------ .../java/ecs/resources/main-service.json.tpl | 4 ++-- terraform/java/ecs/variables.tf | 3 --- terraform/python/ecs/output.tf | 18 ------------------ .../python/ecs/resources/main-service.json.tpl | 4 ++-- terraform/python/ecs/variables.tf | 3 --- .../com/amazon/aoc/services/XRayService.java | 1 - .../amazon/aoc/validators/TraceValidator.java | 3 ++- 10 files changed, 12 insertions(+), 56 deletions(-) delete mode 100644 terraform/java/ecs/output.tf delete mode 100644 terraform/python/ecs/output.tf diff --git a/.github/workflows/java-ecs-test.yml b/.github/workflows/java-ecs-test.yml index 2ff499a33..2c4f236d6 100644 --- a/.github/workflows/java-ecs-test.yml +++ b/.github/workflows/java-ecs-test.yml @@ -114,10 +114,10 @@ jobs: echo MAIN_SAMPLE_APP_IMAGE_URI="${{ env.ACCOUNT_ID }}.dkr.ecr.${{ env.E2E_TEST_AWS_REGION }}.amazonaws.com/${{ env.JAVA_MAIN_SAMPLE_APP_IMAGE }}" >> $GITHUB_ENV echo REMOTE_SAMPLE_APP_IMAGE_URI="${{ env.ACCOUNT_ID }}.dkr.ecr.${{ env.E2E_TEST_AWS_REGION }}.amazonaws.com/${{ env.JAVA_REMOTE_SAMPLE_APP_IMAGE }}" >> $GITHUB_ENV - - name: Set Get ADOT Wheel command environment variable + - name: Set ADOT Java image environment variable run: | if [ "${{ github.event.repository.name }}" = "aws-otel-java-instrumentation" ]; then - # Reusing the adot-main-build-staging-jar bucket to store the java wheel file + # Use the staging image build by the ADOT Java repo echo ADOT_INSTRUMENTATION_IMAGE_URI="${{ env.ADOT_IMAGE_NAME }}" >> $GITHUB_ENV else ADOT_INSTRUMENTATION_IMAGE_TAG=$(curl -s -I -L 'https://github.com/aws-observability/aws-otel-java-instrumentation/releases/latest' | grep -i Location | awk -F'/tag/' '{print $2}' | tr -d '\r') diff --git a/.github/workflows/python-ecs-test.yml b/.github/workflows/python-ecs-test.yml index fffc6763e..436a82be6 100644 --- a/.github/workflows/python-ecs-test.yml +++ b/.github/workflows/python-ecs-test.yml @@ -114,16 +114,14 @@ jobs: echo MAIN_SAMPLE_APP_IMAGE_URI="${{ env.ACCOUNT_ID }}.dkr.ecr.${{ env.E2E_TEST_AWS_REGION }}.amazonaws.com/${{ env.PYTHON_MAIN_SAMPLE_APP_IMAGE }}" >> $GITHUB_ENV echo REMOTE_SAMPLE_APP_IMAGE_URI="${{ env.ACCOUNT_ID }}.dkr.ecr.${{ env.E2E_TEST_AWS_REGION }}.amazonaws.com/${{ env.PYTHON_REMOTE_SAMPLE_APP_IMAGE }}" >> $GITHUB_ENV - # Swich to use the public image for ADOT instrumentation - - name: Set Get ADOT Wheel command environment variable + - name: Set ADOT Python image environment variable run: | if [ "${{ github.event.repository.name }}" = "aws-otel-python-instrumentation" ]; then - # Reusing the adot-main-build-staging-jar bucket to store the python wheel file + # Use the staging image build by the ADOT Python repo echo ADOT_INSTRUMENTATION_IMAGE_URI=="${{ env.ADOT_IMAGE_NAME }}" >> $GITHUB_ENV else - # ADOT_INSTRUMENTATION_IMAGE_TAG=$(curl -s -I -L 'https://github.com/aws-observability/aws-otel-python-instrumentation/releases/latest' | grep -i Location | awk -F'/tag/' '{print $2}' | tr -d '\r') - # echo ADOT_INSTRUMENTATION_IMAGE_URI="public.ecr.aws/aws-observability/adot-autoinstrumentation-python:$ADOT_INSTRUMENTATION_IMAGE_TAG" >> $GITHUB_ENV - echo ADOT_INSTRUMENTATION_IMAGE_URI="${{ env.ACCOUNT_ID }}.dkr.ecr.us-east-1.amazonaws.com/adot-python-distro:latest" >> $GITHUB_ENV + ADOT_INSTRUMENTATION_IMAGE_TAG=$(curl -s -I -L 'https://github.com/aws-observability/aws-otel-python-instrumentation/releases/latest' | grep -i Location | awk -F'/tag/' '{print $2}' | tr -d '\r') + echo ADOT_INSTRUMENTATION_IMAGE_URI="public.ecr.aws/aws-observability/adot-autoinstrumentation-python:$ADOT_INSTRUMENTATION_IMAGE_TAG" >> $GITHUB_ENV fi # Switch to use the public image for CW Agent diff --git a/terraform/java/ecs/output.tf b/terraform/java/ecs/output.tf deleted file mode 100644 index 72e4af6b5..000000000 --- a/terraform/java/ecs/output.tf +++ /dev/null @@ -1,18 +0,0 @@ -# ------------------------------------------------------------------------ -# Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). -# You may not use this file except in compliance with the License. -# A copy of the License is located at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# or in the "license" file accompanying this file. This file is distributed -# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -# express or implied. See the License for the specific language governing -# permissions and limitations under the License. -# ------------------------------------------------------------------------- - -output "sample_app_main_service_task_definition" { - value = aws_ecs_task_definition.main_service.arn -} \ No newline at end of file diff --git a/terraform/java/ecs/resources/main-service.json.tpl b/terraform/java/ecs/resources/main-service.json.tpl index d09589bb0..4651a8f6b 100644 --- a/terraform/java/ecs/resources/main-service.json.tpl +++ b/terraform/java/ecs/resources/main-service.json.tpl @@ -113,13 +113,13 @@ }, { "name": "traffic-gen", - "image": "curlimages/curl:8.8.0", + "image": "amazonlinux:2", "cpu": 0, "essential": true, "command": [ "sh", "-c", - "while true; do curl http://localhost:8080/; sleep 15; done" + "while true; do wget -qO- http://localhost:8080/; sleep 10; done" ] } ] \ No newline at end of file diff --git a/terraform/java/ecs/variables.tf b/terraform/java/ecs/variables.tf index ddc3c2852..a47b95cdc 100644 --- a/terraform/java/ecs/variables.tf +++ b/terraform/java/ecs/variables.tf @@ -31,7 +31,6 @@ variable "sample_app_name" { } variable "sample_app_image" { - // public.ecr.aws/m0o7p6d1/aws-apm-java-springboot-main-service:latest default = "" } @@ -39,11 +38,9 @@ variable "sample_remote_app_image" { default = "" } variable "adot_instrumentation_image" { - // public.ecr.aws/aws-observability/adot-autoinstrumentation-java:v1.32.3 default = "" } variable "cwagent_image" { - // public.ecr.aws/y8s3a7r9/cloudwatch-agent:latest default = "" } \ No newline at end of file diff --git a/terraform/python/ecs/output.tf b/terraform/python/ecs/output.tf deleted file mode 100644 index 72e4af6b5..000000000 --- a/terraform/python/ecs/output.tf +++ /dev/null @@ -1,18 +0,0 @@ -# ------------------------------------------------------------------------ -# Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). -# You may not use this file except in compliance with the License. -# A copy of the License is located at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# or in the "license" file accompanying this file. This file is distributed -# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -# express or implied. See the License for the specific language governing -# permissions and limitations under the License. -# ------------------------------------------------------------------------- - -output "sample_app_main_service_task_definition" { - value = aws_ecs_task_definition.main_service.arn -} \ No newline at end of file diff --git a/terraform/python/ecs/resources/main-service.json.tpl b/terraform/python/ecs/resources/main-service.json.tpl index 01f9a188b..f7ba710ca 100644 --- a/terraform/python/ecs/resources/main-service.json.tpl +++ b/terraform/python/ecs/resources/main-service.json.tpl @@ -140,13 +140,13 @@ }, { "name": "traffic-gen", - "image": "curlimages/curl:8.8.0", + "image": "amazonlinux:2", "cpu": 0, "essential": true, "command": [ "sh", "-c", - "while true; do curl http://localhost:8080/; sleep 10; done" + "while true; do wget -qO- http://localhost:8080/; sleep 10; done" ] } ] \ No newline at end of file diff --git a/terraform/python/ecs/variables.tf b/terraform/python/ecs/variables.tf index ddc3c2852..a47b95cdc 100644 --- a/terraform/python/ecs/variables.tf +++ b/terraform/python/ecs/variables.tf @@ -31,7 +31,6 @@ variable "sample_app_name" { } variable "sample_app_image" { - // public.ecr.aws/m0o7p6d1/aws-apm-java-springboot-main-service:latest default = "" } @@ -39,11 +38,9 @@ variable "sample_remote_app_image" { default = "" } variable "adot_instrumentation_image" { - // public.ecr.aws/aws-observability/adot-autoinstrumentation-java:v1.32.3 default = "" } variable "cwagent_image" { - // public.ecr.aws/y8s3a7r9/cloudwatch-agent:latest default = "" } \ No newline at end of file diff --git a/validator/src/main/java/com/amazon/aoc/services/XRayService.java b/validator/src/main/java/com/amazon/aoc/services/XRayService.java index ee51da557..29a4daacb 100644 --- a/validator/src/main/java/com/amazon/aoc/services/XRayService.java +++ b/validator/src/main/java/com/amazon/aoc/services/XRayService.java @@ -28,7 +28,6 @@ import org.joda.time.DateTime; import lombok.extern.log4j.Log4j2; -@Log4j2 public class XRayService { private AWSXRay awsxRay; private final int SEARCH_PERIOD = 60; diff --git a/validator/src/main/java/com/amazon/aoc/validators/TraceValidator.java b/validator/src/main/java/com/amazon/aoc/validators/TraceValidator.java index 1cd1ce6d2..7033d645e 100644 --- a/validator/src/main/java/com/amazon/aoc/validators/TraceValidator.java +++ b/validator/src/main/java/com/amazon/aoc/validators/TraceValidator.java @@ -140,7 +140,8 @@ private Map getTrace() throws Exception { traceFilter += " AND (annotation.aws_local_service = \"local-root-client-call\" OR annotation.aws_local_service = \"local-root-client-call:80\")" ; } else { traceFilter += (String.format(" AND annotation.aws_local_operation = \"%s %s\"", - validationConfig.getHttpMethod().toUpperCase(), validationConfig.getHttpPath())); + validationConfig.getHttpMethod().toUpperCase(), + validationConfig.getHttpPath())); } log.info("Trace Filter: {}", traceFilter); List retrieveTraceLists = xrayService.searchTraces(traceFilter); From f7a54cca595d894b15e3b0367cb22168ff54c631 Mon Sep 17 00:00:00 2001 From: Zhonghao Zhao Date: Thu, 12 Sep 2024 15:54:43 -0700 Subject: [PATCH 08/13] Test workflow. --- .github/workflows/java-ecs-canary.yml | 3 +++ .github/workflows/python-ecs-canary.yml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/.github/workflows/java-ecs-canary.yml b/.github/workflows/java-ecs-canary.yml index 2bbf59b43..6fff9a15d 100644 --- a/.github/workflows/java-ecs-canary.yml +++ b/.github/workflows/java-ecs-canary.yml @@ -9,6 +9,9 @@ on: schedule: - cron: '*/15 * * * *' # run the workflow every 15 minutes workflow_dispatch: # be able to run the workflow on demand + push: + branches: + - ecs-no-call-zzhlogin permissions: id-token: write diff --git a/.github/workflows/python-ecs-canary.yml b/.github/workflows/python-ecs-canary.yml index d2c8ffb4f..e43f23d6d 100644 --- a/.github/workflows/python-ecs-canary.yml +++ b/.github/workflows/python-ecs-canary.yml @@ -9,6 +9,9 @@ on: schedule: - cron: '*/15 * * * *' # run the workflow every 15 minutes workflow_dispatch: # be able to run the workflow on demand + push: + branches: + - ecs-no-call-zzhlogin permissions: id-token: write From fe359ccceeaba4f4385d12799bf32fed2b334031 Mon Sep 17 00:00:00 2001 From: Zhonghao Zhao Date: Thu, 12 Sep 2024 18:31:06 -0700 Subject: [PATCH 09/13] Fix traffic gen.: --- terraform/java/ecs/resources/main-service.json.tpl | 2 +- terraform/python/ecs/resources/main-service.json.tpl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/terraform/java/ecs/resources/main-service.json.tpl b/terraform/java/ecs/resources/main-service.json.tpl index 4651a8f6b..4649b5b96 100644 --- a/terraform/java/ecs/resources/main-service.json.tpl +++ b/terraform/java/ecs/resources/main-service.json.tpl @@ -119,7 +119,7 @@ "command": [ "sh", "-c", - "while true; do wget -qO- http://localhost:8080/; sleep 10; done" + "while true; do curl http://localhost:8080/; sleep 10; done" ] } ] \ No newline at end of file diff --git a/terraform/python/ecs/resources/main-service.json.tpl b/terraform/python/ecs/resources/main-service.json.tpl index f7ba710ca..9f820fb6e 100644 --- a/terraform/python/ecs/resources/main-service.json.tpl +++ b/terraform/python/ecs/resources/main-service.json.tpl @@ -146,7 +146,7 @@ "command": [ "sh", "-c", - "while true; do wget -qO- http://localhost:8080/; sleep 10; done" + "while true; do curl http://localhost:8080/; sleep 10; done" ] } ] \ No newline at end of file From 77b249df2a7dc1a276f35a618b5ebeff10e34643 Mon Sep 17 00:00:00 2001 From: Zhonghao Zhao Date: Fri, 13 Sep 2024 09:31:58 -0700 Subject: [PATCH 10/13] Remove test condition. --- .github/workflows/java-ecs-canary.yml | 3 --- .github/workflows/python-ecs-canary.yml | 3 --- 2 files changed, 6 deletions(-) diff --git a/.github/workflows/java-ecs-canary.yml b/.github/workflows/java-ecs-canary.yml index 6fff9a15d..2bbf59b43 100644 --- a/.github/workflows/java-ecs-canary.yml +++ b/.github/workflows/java-ecs-canary.yml @@ -9,9 +9,6 @@ on: schedule: - cron: '*/15 * * * *' # run the workflow every 15 minutes workflow_dispatch: # be able to run the workflow on demand - push: - branches: - - ecs-no-call-zzhlogin permissions: id-token: write diff --git a/.github/workflows/python-ecs-canary.yml b/.github/workflows/python-ecs-canary.yml index e43f23d6d..d2c8ffb4f 100644 --- a/.github/workflows/python-ecs-canary.yml +++ b/.github/workflows/python-ecs-canary.yml @@ -9,9 +9,6 @@ on: schedule: - cron: '*/15 * * * *' # run the workflow every 15 minutes workflow_dispatch: # be able to run the workflow on demand - push: - branches: - - ecs-no-call-zzhlogin permissions: id-token: write From f2143fea2d054a591ae75a49939b501e80f47953 Mon Sep 17 00:00:00 2001 From: Zhonghao Zhao Date: Fri, 13 Sep 2024 11:22:26 -0700 Subject: [PATCH 11/13] Remove concurency. --- .github/workflows/java-ecs-test.yml | 4 ---- .github/workflows/python-ecs-test.yml | 4 ---- 2 files changed, 8 deletions(-) diff --git a/.github/workflows/java-ecs-test.yml b/.github/workflows/java-ecs-test.yml index 2c4f236d6..d514ced46 100644 --- a/.github/workflows/java-ecs-test.yml +++ b/.github/workflows/java-ecs-test.yml @@ -26,10 +26,6 @@ on: validation-result: value: ${{ jobs.java-ecs.outputs.validation-result }} -concurrency: - group: '${{ github.workflow }} @ ${{ inputs.aws-region }}' - cancel-in-progress: false - permissions: id-token: write contents: read diff --git a/.github/workflows/python-ecs-test.yml b/.github/workflows/python-ecs-test.yml index 436a82be6..9afa44fb8 100644 --- a/.github/workflows/python-ecs-test.yml +++ b/.github/workflows/python-ecs-test.yml @@ -26,10 +26,6 @@ on: validation-result: value: ${{ jobs.python-ecs.outputs.validation-result }} -concurrency: - group: '${{ github.workflow }} @ ${{ inputs.aws-region }}' - cancel-in-progress: false - permissions: id-token: write contents: read From 82b412cbb62f912494c0527f898df63ce9d0d3d2 Mon Sep 17 00:00:00 2001 From: Zhonghao Zhao Date: Fri, 13 Sep 2024 11:26:33 -0700 Subject: [PATCH 12/13] # This is a combination of 11 commits. # This is the 1st commit message: Test concurency. # The commit message #2 will be skipped: # Dummy commit # The commit message #3 will be skipped: # Dummy commit # The commit message #4 will be skipped: # Dummy commit # The commit message #5 will be skipped: # Dummy commit # The commit message #6 will be skipped: # add push. # The commit message #7 will be skipped: # Dummy commit # The commit message #8 will be skipped: # Dummy commit # The commit message #9 will be skipped: # Dummy commit # The commit message #10 will be skipped: # Add push condition. # The commit message #11 will be skipped: # Dummy commit --- .github/workflows/python-ecs-canary.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/python-ecs-canary.yml b/.github/workflows/python-ecs-canary.yml index d2c8ffb4f..e43f23d6d 100644 --- a/.github/workflows/python-ecs-canary.yml +++ b/.github/workflows/python-ecs-canary.yml @@ -9,6 +9,9 @@ on: schedule: - cron: '*/15 * * * *' # run the workflow every 15 minutes workflow_dispatch: # be able to run the workflow on demand + push: + branches: + - ecs-no-call-zzhlogin permissions: id-token: write From 2c6acd4f9ae937fd444f7a033fe7df5beef2aebd Mon Sep 17 00:00:00 2001 From: Zhonghao Zhao Date: Tue, 17 Sep 2024 10:31:06 -0700 Subject: [PATCH 13/13] # This is a combination of 11 commits. # This is the 1st commit message: Test concurency. # The commit message #2 will be skipped: # Dummy commit # The commit message #3 will be skipped: # Dummy commit # The commit message #4 will be skipped: # Dummy commit # The commit message #5 will be skipped: # Dummy commit # The commit message #6 will be skipped: # add push. # The commit message #7 will be skipped: # Dummy commit # The commit message #8 will be skipped: # Dummy commit # The commit message #9 will be skipped: # Dummy commit # The commit message #10 will be skipped: # Add push condition. # The commit message #11 will be skipped: # Dummy commit --- .github/workflows/dotnet-ec2-canary.yml | 15 + .../workflows/dotnet-ec2-windows-retry.yml | 57 +++ .github/workflows/dotnet-ec2-windows-test.yml | 339 ++++++++++++++++ .../workflows/dotnet-sample-app-s3-deploy.yml | 9 + .github/workflows/java-ecs-retry.yml | 4 - .github/workflows/java-ecs-test.yml | 12 +- .github/workflows/node-ec2-canary.yml | 9 +- .github/workflows/node-ec2-default-test.yml | 20 +- .github/workflows/node-k8s-canary.yml | 2 +- .github/workflows/python-ecs-canary.yml | 3 - .github/workflows/python-ecs-retry.yml | 4 - .github/workflows/python-ecs-test.yml | 12 +- .../dotnet/amazon-cloudwatch-agent.json | 16 + .../dotnet/dotnet-ec2-win-main-setup.ps1 | 117 ++++++ .../dotnet/dotnet-ec2-win-remote-setup.ps1 | 88 +++++ .../node/frontend-service/package-lock.json | 93 +++-- .../node/frontend-service/package.json | 2 +- .../node/remote-service/package-lock.json | 105 +++-- sample-apps/node/remote-service/package.json | 2 +- terraform/dotnet/ec2/windows/main.tf | 221 +++++++++++ terraform/dotnet/ec2/windows/output.tf | 38 ++ terraform/dotnet/ec2/windows/variables.tf | 38 ++ terraform/java/ecs/variables.tf | 2 +- terraform/python/ecs/variables.tf | 2 +- .../PredefinedExpectedTemplate.java | 21 + .../com/amazon/aoc/services/XRayService.java | 1 - .../ec2/windows/aws-sdk-call-log.mustache | 20 + .../ec2/windows/aws-sdk-call-metric.mustache | 374 ++++++++++++++++++ .../ec2/windows/aws-sdk-call-trace.mustache | 56 +++ .../ec2/windows/client-call-log.mustache | 20 + .../ec2/windows/client-call-metric.mustache | 227 +++++++++++ .../ec2/windows/client-call-trace.mustache | 56 +++ .../windows/outgoing-http-call-log.mustache | 20 + .../outgoing-http-call-metric.mustache | 227 +++++++++++ .../windows/outgoing-http-call-trace.mustache | 55 +++ .../ec2/windows/remote-service-log.mustache | 20 + .../windows/remote-service-metric.mustache | 312 +++++++++++++++ .../ec2/windows/remote-service-trace.mustache | 77 ++++ .../dotnet/k8s/aws-sdk-call-log.mustache | 2 +- .../dotnet/k8s/aws-sdk-call-metric.mustache | 6 +- .../dotnet/k8s/aws-sdk-call-trace.mustache | 2 +- .../dotnet/k8s/client-call-metric.mustache | 6 +- .../k8s/outgoing-http-call-log.mustache | 2 +- .../k8s/outgoing-http-call-metric.mustache | 6 +- .../k8s/outgoing-http-call-trace.mustache | 2 +- .../dotnet/k8s/remote-service-log.mustache | 2 +- .../dotnet/k8s/remote-service-metric.mustache | 12 +- .../dotnet/k8s/remote-service-trace.mustache | 4 +- .../java/ecs/hc-trace.mustache | 3 - .../python/ecs/hc-trace.mustache | 3 - .../dotnet/ec2/windows/log-validation.yml | 25 ++ .../dotnet/ec2/windows/metric-validation.yml | 25 ++ .../dotnet/ec2/windows/trace-validation.yml | 26 ++ .../validations/dotnet/k8s/log-validation.yml | 8 +- .../dotnet/k8s/metric-validation.yml | 8 +- .../dotnet/k8s/trace-validation.yml | 8 +- 56 files changed, 2691 insertions(+), 155 deletions(-) create mode 100644 .github/workflows/dotnet-ec2-windows-retry.yml create mode 100644 .github/workflows/dotnet-ec2-windows-test.yml create mode 100644 sample-apps/dotnet/amazon-cloudwatch-agent.json create mode 100644 sample-apps/dotnet/dotnet-ec2-win-main-setup.ps1 create mode 100644 sample-apps/dotnet/dotnet-ec2-win-remote-setup.ps1 create mode 100644 terraform/dotnet/ec2/windows/main.tf create mode 100644 terraform/dotnet/ec2/windows/output.tf create mode 100644 terraform/dotnet/ec2/windows/variables.tf create mode 100644 validator/src/main/resources/expected-data-template/dotnet/ec2/windows/aws-sdk-call-log.mustache create mode 100644 validator/src/main/resources/expected-data-template/dotnet/ec2/windows/aws-sdk-call-metric.mustache create mode 100644 validator/src/main/resources/expected-data-template/dotnet/ec2/windows/aws-sdk-call-trace.mustache create mode 100644 validator/src/main/resources/expected-data-template/dotnet/ec2/windows/client-call-log.mustache create mode 100644 validator/src/main/resources/expected-data-template/dotnet/ec2/windows/client-call-metric.mustache create mode 100644 validator/src/main/resources/expected-data-template/dotnet/ec2/windows/client-call-trace.mustache create mode 100644 validator/src/main/resources/expected-data-template/dotnet/ec2/windows/outgoing-http-call-log.mustache create mode 100644 validator/src/main/resources/expected-data-template/dotnet/ec2/windows/outgoing-http-call-metric.mustache create mode 100644 validator/src/main/resources/expected-data-template/dotnet/ec2/windows/outgoing-http-call-trace.mustache create mode 100644 validator/src/main/resources/expected-data-template/dotnet/ec2/windows/remote-service-log.mustache create mode 100644 validator/src/main/resources/expected-data-template/dotnet/ec2/windows/remote-service-metric.mustache create mode 100644 validator/src/main/resources/expected-data-template/dotnet/ec2/windows/remote-service-trace.mustache create mode 100644 validator/src/main/resources/validations/dotnet/ec2/windows/log-validation.yml create mode 100644 validator/src/main/resources/validations/dotnet/ec2/windows/metric-validation.yml create mode 100644 validator/src/main/resources/validations/dotnet/ec2/windows/trace-validation.yml diff --git a/.github/workflows/dotnet-ec2-canary.yml b/.github/workflows/dotnet-ec2-canary.yml index 1b3fb5bfa..a90c489a1 100644 --- a/.github/workflows/dotnet-ec2-canary.yml +++ b/.github/workflows/dotnet-ec2-canary.yml @@ -29,3 +29,18 @@ jobs: with: aws-region: ${{ matrix.aws-region }} caller-workflow-name: 'appsignals-dotnet-e2e-ec2-canary-test' + + + windows: + strategy: + fail-fast: false + matrix: + aws-region: [ 'af-south-1','ap-east-1','ap-northeast-1','ap-northeast-2','ap-northeast-3','ap-south-1','ap-south-2','ap-southeast-1', + 'ap-southeast-2','ap-southeast-3','ap-southeast-4','ca-central-1','eu-central-1','eu-central-2','eu-north-1', + 'eu-south-1','eu-south-2','eu-west-1','eu-west-2','eu-west-3','il-central-1','me-central-1','me-south-1', 'sa-east-1', + 'us-east-1','us-east-2', 'us-west-1', 'us-west-2' ] + uses: ./.github/workflows/dotnet-ec2-windows-retry.yml + secrets: inherit + with: + aws-region: ${{ matrix.aws-region }} + caller-workflow-name: 'appsignals-dotnet-e2e-ec2-windows-canary-test' \ No newline at end of file diff --git a/.github/workflows/dotnet-ec2-windows-retry.yml b/.github/workflows/dotnet-ec2-windows-retry.yml new file mode 100644 index 000000000..d2097b517 --- /dev/null +++ b/.github/workflows/dotnet-ec2-windows-retry.yml @@ -0,0 +1,57 @@ +## Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +## SPDX-License-Identifier: Apache-2.0 + +# This is a reusable workflow for running the Enablement test for App Signals. +# It is meant to be called from another workflow. +# Read more about reusable workflows: https://docs.github.com/en/actions/using-workflows/reusing-workflows#overview +name: Dotnet EC2 Windows Retry +on: + workflow_call: + inputs: + aws-region: + required: true + type: string + caller-workflow-name: + required: true + type: string + +permissions: + id-token: write + contents: read + +jobs: + dotnet-ec2-windows-attempt-1: + uses: ./.github/workflows/dotnet-ec2-windows-test.yml + secrets: inherit + with: + aws-region: ${{ inputs.aws-region }} + caller-workflow-name: ${{ inputs.caller-workflow-name }} + + dotnet-ec2-windows-attempt-2: + needs: [ dotnet-ec2-windows-attempt-1 ] + if: ${{ needs.dotnet-ec2-windows-attempt-1.outputs.job-started != 'true' }} + uses: ./.github/workflows/dotnet-ec2-windows-test.yml + secrets: inherit + with: + aws-region: ${{ inputs.aws-region }} + caller-workflow-name: ${{ inputs.caller-workflow-name }} + + publish-metric-attempt-1: + needs: [ dotnet-ec2-windows-attempt-1, dotnet-ec2-windows-attempt-2 ] + if: always() + uses: ./.github/workflows/enablement-test-publish-result.yml + secrets: inherit + with: + aws-region: ${{ inputs.aws-region }} + caller-workflow-name: ${{ inputs.caller-workflow-name }} + validation-result: ${{ needs.dotnet-ec2-windows-attempt-1.outputs.validation-result || needs.dotnet-ec2-windows-attempt-2.outputs.validation-result }} + + publish-metric-attempt-2: + needs: [ dotnet-ec2-windows-attempt-1, dotnet-ec2-windows-attempt-2, publish-metric-attempt-1 ] + if: ${{ always() && needs.publish-metric-attempt-1.outputs.job-started != 'true' }} + uses: ./.github/workflows/enablement-test-publish-result.yml + secrets: inherit + with: + aws-region: ${{ inputs.aws-region }} + caller-workflow-name: ${{ inputs.caller-workflow-name }} + validation-result: ${{ needs.dotnet-ec2-windows-attempt-1.outputs.validation-result || needs.dotnet-ec2-windows-attempt-2.outputs.validation-result }} \ No newline at end of file diff --git a/.github/workflows/dotnet-ec2-windows-test.yml b/.github/workflows/dotnet-ec2-windows-test.yml new file mode 100644 index 000000000..dc592e201 --- /dev/null +++ b/.github/workflows/dotnet-ec2-windows-test.yml @@ -0,0 +1,339 @@ +## Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +## SPDX-License-Identifier: Apache-2.0 + +# This is a reusable workflow for running the DotNet E2E Canary test for Application Signals. +# It is meant to be called from another workflow. +# Read more about reusable workflows: https://docs.github.com/en/actions/using-workflows/reusing-workflows#overview +name: DotNet EC2 Windows Use Case +on: + workflow_call: + inputs: + aws-region: + required: true + type: string + staging_distro_name: + required: false + default: 'aws-opentelemetry-distro' + type: string + caller-workflow-name: + required: true + type: string + outputs: + job-started: + value: ${{ jobs.dotnet-ec2-windows.outputs.job-started }} + validation-result: + value: ${{ jobs.dotnet-ec2-windows.outputs.validation-result }} + +permissions: + id-token: write + contents: read + +env: + E2E_TEST_AWS_REGION: ${{ inputs.aws-region }} + E2E_TEST_ACCOUNT_ID: ${{ secrets.APPLICATION_SIGNALS_E2E_TEST_ACCOUNT_ID }} + E2E_TEST_ROLE_NAME: ${{ secrets.APPLICATION_SIGNALS_E2E_TEST_ROLE_NAME }} + SAMPLE_APP_ZIP: "aws s3 cp s3://aws-appsignals-sample-app-prod-${{ inputs.aws-region }}/dotnet-sample-app.zip ./dotnet-sample-app.zip" + METRIC_NAMESPACE: ApplicationSignals + LOG_GROUP_NAME: /aws/application-signals/data + ADOT_DISTRO_NAME: ${{ inputs.staging_distro_name }} + TEST_RESOURCES_FOLDER: ${GITHUB_WORKSPACE} + +jobs: + dotnet-ec2-windows: + runs-on: ubuntu-latest + timeout-minutes: 30 + outputs: + job-started: ${{ steps.job-started.outputs.job-started }} + validation-result: ${{ steps.validation-result.outputs.validation-result }} + steps: + - name: Check if the job started + id: job-started + run: echo "job-started=true" >> $GITHUB_OUTPUT + + - uses: actions/checkout@v4 + with: + repository: 'aws-observability/aws-application-signals-test-framework' + ref: ${{ inputs.caller-workflow-name == 'main-build' && 'main' || github.ref }} + fetch-depth: 0 + + - name: Initiate Gradlew Daemon + id: initiate-gradlew + uses: ./.github/workflows/actions/execute_and_retry + continue-on-error: true + with: + command: "./gradlew :validator:build" + cleanup: "./gradlew clean" + max_retry: 3 + sleep_time: 60 + + - name: Generate testing id + run: echo TESTING_ID="${{ github.job }}-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" >> $GITHUB_ENV + + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: arn:aws:iam::${{ env.E2E_TEST_ACCOUNT_ID }}:role/${{ env.E2E_TEST_ROLE_NAME }} + aws-region: us-east-1 + + - name: Retrieve account + uses: aws-actions/aws-secretsmanager-get-secrets@v1 + with: + secret-ids: + ACCOUNT_ID, region-account/${{ env.E2E_TEST_AWS_REGION }} + + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: arn:aws:iam::${{ env.ACCOUNT_ID }}:role/${{ env.E2E_TEST_ROLE_NAME }} + aws-region: ${{ env.E2E_TEST_AWS_REGION }} + + - name: Set Get ADOT Distro command environment variable + run: | + if [ "${{ github.event.repository.name }}" = "aws-otel-dotnet-instrumentation" ]; then + # Get staging distro file from staging bucket + echo GET_ADOT_DISTRO_COMMAND="aws s3 cp s3://adot-autoinstrumentation-dotnet-staging/${{ env.ADOT_DISTRO_NAME }} ./${{ env.ADOT_DISTRO_NAME }}; Expand-Archive -Path /${{ env.ADOT_DISTRO_NAME }} -DestinationPath ./dotnet-distro" >> $GITHUB_ENV + else + # After Release will switch to latest tag instead of hard code version for canary purpose + echo GET_ADOT_DISTRO_COMMAND="wget -O ./aws-distro-opentelemetry-dotnet-instrumentation-windows.zip https://github.com/aws-observability/aws-otel-dotnet-instrumentation/releases/latest/download/aws-distro-opentelemetry-dotnet-instrumentation-windows.zip; Expand-Archive -Path ./aws-distro-opentelemetry-dotnet-instrumentation-windows.zip -DestinationPath ./dotnet-distro -Force" >> $GITHUB_ENV + fi + + - name: Set Get CW Agent command environment variable + run: | + if [ "${{ github.event.repository.name }}" = "amazon-cloudwatch-agent" ]; then + # Get cloudwatch agent staging file if triggered by cw-a repo + echo GET_CW_AGENT_MSI_COMMAND= "aws s3 cp s3://${{ secrets.S3_INTEGRATION_BUCKET }}/integration-test/binary/${{ github.sha }}/amazon-cloudwatch-agent.msi ./cw-agent.msi" >> $GITHUB_ENV + else + echo GET_CW_AGENT_MSI_COMMAND= "wget -O ./amazon-cloudwatch-agent.msi https://amazoncloudwatch-agent.s3.amazonaws.com/windows/amd64/latest/amazon-cloudwatch-agent.msi" >> $GITHUB_ENV + fi + + - name: Set up terraform + uses: ./.github/workflows/actions/execute_and_retry + with: + command: "wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg" + post-command: 'echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list + && sudo apt update && sudo apt install terraform' + sleep_time: 60 + + - name: Initiate Terraform + uses: ./.github/workflows/actions/execute_and_retry + with: + command: "cd ${{ env.TEST_RESOURCES_FOLDER }}/terraform/dotnet/ec2/windows && terraform init && terraform validate" + cleanup: "rm -rf .terraform && rm -rf .terraform.lock.hcl" + max_retry: 6 + sleep_time: 60 + + - name: Deploy sample app via terraform and wait for endpoint to come online + working-directory: terraform/dotnet/ec2/windows + run: | + # Attempt to deploy the sample app on an EC2 instance and wait for its endpoint to come online. + # There may be occasional failures due to transitivity issues, so try up to 2 times. + # deployment_failed of 0 indicates that both the terraform deployment and the endpoint are running, while 1 indicates + # that it failed at some point + retry_counter=0 + max_retry=2 + while [ $retry_counter -lt $max_retry ]; do + echo "Attempt $retry_counter" + deployment_failed=0 + terraform apply -auto-approve \ + -var="aws_region=${{ env.E2E_TEST_AWS_REGION }}" \ + -var="test_id=${{ env.TESTING_ID }}" \ + -var="sample_app_zip=${{ env.SAMPLE_APP_ZIP }}" \ + -var="get_cw_agent_msi_command=${{ env.GET_CW_AGENT_MSI_COMMAND }}" \ + -var="get_adot_distro_command=${{ env.GET_ADOT_DISTRO_COMMAND }}" \ + || deployment_failed=$? + + if [ $deployment_failed -eq 1 ]; then + echo "Terraform deployment was unsuccessful. Will attempt to retry deployment." + fi + + # If the success is 1 then either the terraform deployment or the endpoint connection failed, so first destroy the + # resources created from terraform and try again. + if [ $deployment_failed -eq 1 ]; then + echo "Destroying terraform" + terraform destroy -auto-approve \ + -var="test_id=${{ env.TESTING_ID }}" + + retry_counter=$(($retry_counter+1)) + else + # If deployment succeeded, then exit the loop + break + fi + + if [ $retry_counter -eq $max_retry ]; then + echo "Max retry reached, failed to deploy terraform and connect to the endpoint. Exiting code" + exit 1 + fi + done + + - name: Get the ec2 instance ami id + working-directory: terraform/dotnet/ec2/windows + run: | + echo "EC2_INSTANCE_AMI=$(terraform output ec2_instance_ami)" >> $GITHUB_ENV + + - name: Get SSM outputs + working-directory: terraform/dotnet/ec2/windows + run: | + echo "FRONTEND_SSM_ASSOCIATION_ID=$(terraform output frontend_script_association_id)" >> $GITHUB_ENV + echo "REMOTE_SSM_ASSOCIATION__ID=$(terraform output remote_script_association_id)" >> $GITHUB_ENV + + - name: Get the sample app endpoint + working-directory: terraform/dotnet/ec2/windows + run: | + echo "MAIN_SERVICE_ENDPOINT=localhost:8080" >> $GITHUB_ENV + echo "REMOTE_SERVICE_IP=$(terraform output sample_app_remote_service_private_ip)" >> $GITHUB_ENV + echo "MAIN_SERVICE_INSTANCE_ID=$(terraform output main_service_instance_id)" >> $GITHUB_ENV + echo "REMOTE_SERVICE_INSTANCE_ID=$(terraform output remote_service_instance_id)" >> $GITHUB_ENV + +# A standard Windows Deployment Script are Expect to run ~5min, plus waiting for SSM to be setup in EC2 instance ~2min +# 12 Min loose upper timeout bound is designed to allow for a rate situation: in a very small chance, +# It's possible for SSM document to take up to 8min to run and still produce expect setup outcome + - name: Monitor EC2 instances readiness and SSM execute status in Systems Manager + timeout-minutes: 12 + run: | + # Allow up to 5 min for EC2 instance connect to SSM + max_attempts=30 + attempt=0 + interval=10 + + check_instance_ready() { + local instance_id=$1 + while [[ $attempt -lt $max_attempts ]]; do + state=$(aws ssm describe-instance-information --filters Key=InstanceIds,Values=$instance_id --query "InstanceInformationList[0].PingStatus" --output text) + echo "Attempt $((attempt + 1))/$max_attempts: Current SSM state of instance $instance_id: $state" + + if [[ "$state" == "Online" ]]; then + echo "Instance $instance_id is 'Online' in Systems Manager and ready." + break + else + echo "Waiting for instance $instance_id to be 'Online' in Systems Manager..." + sleep $interval + attempt=$((attempt + 1)) + fi + done + + if [[ $attempt -ge $max_attempts ]]; then + echo "Timeout reached: Instance $instance_id did not become 'Online' in Systems Manager within expected time." + exit 1 + fi + } + + check_instance_ready ${{ env.MAIN_SERVICE_INSTANCE_ID }} + check_instance_ready ${{ env.REMOTE_SERVICE_INSTANCE_ID }} + + # Allow up to 10 min for SSM Document to run + max_attempts=60 + attempt=0 + + check_status() { + local association_id=$1 + + while [[ $attempt -lt $max_attempts ]]; do + aws ssm describe-association --association-id $association_id + local status=$(aws ssm describe-association --association-id $association_id --query "AssociationDescription.Overview.AssociationStatusAggregatedCount.Success" --output text) + echo "Attempt $((attempt + 1))/$max_attempts: Current status of SSM Association $association_id: $status" + if [[ "$status" == "1" ]]; then + echo "SSM Association $association_id succeeded." + break + else + echo "Waiting for SSM Association $association_id to succeed..." + sleep $interval + attempt=$((attempt + 1)) + fi + done + + if [[ $attempt -ge $max_attempts ]]; then + echo "Max attempts reached: SSM Association $association_id did not succeed after $max_attempts attempts." + exit 1 + fi + } + + check_status ${{ env.FRONTEND_SSM_ASSOCIATION_ID }} + check_status ${{ env.REMOTE_SSM_ASSOCIATION__ID }} + + - name: Initiate Gradlew Daemon + if: steps.initiate-gradlew == 'failure' + uses: ./.github/workflows/actions/execute_and_retry + continue-on-error: true + with: + command: "./gradlew" + cleanup: "./gradlew clean" + max_retry: 3 + sleep_time: 60 + + # Validation for pulse telemetry data + - name: Validate generated EMF logs + id: log-validation + run: ./gradlew validator:run --args='-c dotnet/ec2/windows/log-validation.yml + --testing-id ${{ env.TESTING_ID }} + --endpoint http://${{ env.MAIN_SERVICE_ENDPOINT }} + --remote-service-deployment-name ${{ env.REMOTE_SERVICE_IP }}:8081 + --region ${{ env.E2E_TEST_AWS_REGION }} + --metric-namespace ${{ env.METRIC_NAMESPACE }} + --log-group ${{ env.LOG_GROUP_NAME }} + --service-name dotnet-sample-application-${{ env.TESTING_ID }} + --remote-service-name dotnet-sample-remote-application-${{ env.TESTING_ID }} + --query-string ip=${{ env.REMOTE_SERVICE_IP }}&testingId=${{ env.TESTING_ID }} + --instance-ami ${{ env.EC2_INSTANCE_AMI }} + --instance-id ${{ env.MAIN_SERVICE_INSTANCE_ID }} + --rollup' + + - name: Validate generated metrics + id: metric-validation + if: (success() || steps.log-validation.outcome == 'failure') && !cancelled() + run: ./gradlew validator:run --args='-c dotnet/ec2/windows/metric-validation.yml + --testing-id ${{ env.TESTING_ID }} + --endpoint http://${{ env.MAIN_SERVICE_ENDPOINT }} + --remote-service-deployment-name ${{ env.REMOTE_SERVICE_IP }}:8081 + --region ${{ env.E2E_TEST_AWS_REGION }} + --metric-namespace ${{ env.METRIC_NAMESPACE }} + --log-group ${{ env.LOG_GROUP_NAME }} + --service-name dotnet-sample-application-${{ env.TESTING_ID }} + --remote-service-name dotnet-sample-remote-application-${{ env.TESTING_ID }} + --query-string ip=${{ env.REMOTE_SERVICE_IP }}&testingId=${{ env.TESTING_ID }} + --instance-ami ${{ env.EC2_INSTANCE_AMI }} + --instance-id ${{ env.MAIN_SERVICE_INSTANCE_ID }} + --rollup' + + - name: Validate generated traces + id: trace-validation + if: (success() || steps.log-validation.outcome == 'failure' || steps.metric-validation.outcome == 'failure') && !cancelled() + run: ./gradlew validator:run --args='-c dotnet/ec2/windows/trace-validation.yml + --testing-id ${{ env.TESTING_ID }} + --endpoint http://${{ env.MAIN_SERVICE_ENDPOINT }} + --remote-service-deployment-name ${{ env.REMOTE_SERVICE_IP }}:8081 + --region ${{ env.E2E_TEST_AWS_REGION }} + --account-id ${{ env.ACCOUNT_ID }} + --metric-namespace ${{ env.METRIC_NAMESPACE }} + --log-group ${{ env.LOG_GROUP_NAME }} + --service-name dotnet-sample-application-${{ env.TESTING_ID }} + --remote-service-name dotnet-sample-remote-application-${{ env.TESTING_ID }} + --query-string ip=${{ env.REMOTE_SERVICE_IP }}&testingId=${{ env.TESTING_ID }} + --instance-ami ${{ env.EC2_INSTANCE_AMI }} + --instance-id ${{ env.MAIN_SERVICE_INSTANCE_ID }} + --rollup' + + - name: Refresh AWS Credentials + if: ${{ github.event.repository.name == 'aws-application-signals-test-framework' }} + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: arn:aws:iam::${{ env.ACCOUNT_ID }}:role/${{ env.E2E_TEST_ROLE_NAME }} + aws-region: ${{ env.E2E_TEST_AWS_REGION }} + + - name: Save test results + if: always() + id: validation-result + run: | + if [ "${{ steps.log-validation.outcome }}" = "success" ] && [ "${{ steps.metric-validation.outcome }}" = "success" ] && [ "${{ steps.trace-validation.outcome }}" = "success" ]; then + echo "validation-result=success" >> $GITHUB_OUTPUT + else + echo "validation-result=failure" >> $GITHUB_OUTPUT + fi + + # Clean up Procedures + - name: Terraform destroy + if: always() + continue-on-error: true + working-directory: terraform/dotnet/ec2/windows + run: | + terraform destroy -auto-approve \ + -var="test_id=${{ env.TESTING_ID }}" \ No newline at end of file diff --git a/.github/workflows/dotnet-sample-app-s3-deploy.yml b/.github/workflows/dotnet-sample-app-s3-deploy.yml index 2047819ba..e24f2afb8 100644 --- a/.github/workflows/dotnet-sample-app-s3-deploy.yml +++ b/.github/workflows/dotnet-sample-app-s3-deploy.yml @@ -49,3 +49,12 @@ jobs: - name: Upload to S3 working-directory: sample-apps/dotnet run: aws s3api put-object --bucket aws-appsignals-sample-app-prod-${{ matrix.aws-region }} --body ./dotnet-sample-app.zip --key dotnet-sample-app.zip + + - name: Upload Windows Script to S3 + working-directory: sample-apps/dotnet + run: | + aws s3api put-object --bucket aws-appsignals-sample-app-prod-${{ matrix.aws-region }} --body ./dotnet-ec2-win-main-setup.ps1 --key dotnet-ec2-win-main-setup.ps1 + aws s3api put-object --bucket aws-appsignals-sample-app-prod-${{ matrix.aws-region }} --body ./dotnet-ec2-win-remote-setup.ps1 --key dotnet-ec2-win-remote-setup.ps1 + aws s3api put-object --bucket aws-appsignals-sample-app-prod-${{ matrix.aws-region }} --body ./amazon-cloudwatch-agent.json --key amazon-cloudwatch-agent.json + + diff --git a/.github/workflows/java-ecs-retry.yml b/.github/workflows/java-ecs-retry.yml index 9fe09f760..942f1bf17 100644 --- a/.github/workflows/java-ecs-retry.yml +++ b/.github/workflows/java-ecs-retry.yml @@ -15,10 +15,6 @@ on: required: true type: string -concurrency: - group: 'java-ecs-${{ inputs.aws-region }}-${{ github.ref_name }}' - cancel-in-progress: false - permissions: id-token: write contents: read diff --git a/.github/workflows/java-ecs-test.yml b/.github/workflows/java-ecs-test.yml index d514ced46..3a12dfa78 100644 --- a/.github/workflows/java-ecs-test.yml +++ b/.github/workflows/java-ecs-test.yml @@ -146,7 +146,7 @@ jobs: terraform apply -auto-approve \ -var="test_id=${{ env.TESTING_ID }}" \ -var="aws_region=${{ env.E2E_TEST_AWS_REGION }}" \ - -var="ecs_cluster_name=${{ env.CLUSTER_NAME }}" \ + -var="ecs_cluster_name=${{ env.CLUSTER_NAME }}-${{ env.TESTING_ID }}" \ -var="sample_app_name=${{ env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }}" \ -var="sample_app_image=${{ env.MAIN_SAMPLE_APP_IMAGE_URI }}" \ -var="sample_remote_app_image=${{ env.REMOTE_SAMPLE_APP_IMAGE_URI }}" \ @@ -165,7 +165,7 @@ jobs: terraform destroy -auto-approve \ -var="test_id=${{ env.TESTING_ID }}" \ -var="aws_region=${{ env.E2E_TEST_AWS_REGION }}" \ - -var="ecs_cluster_name=${{ env.CLUSTER_NAME }}" \ + -var="ecs_cluster_name=${{ env.CLUSTER_NAME }}-${{ env.TESTING_ID }}" \ -var="sample_app_name=${{ env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }}" \ -var="sample_app_image=${{ env.MAIN_SAMPLE_APP_IMAGE_URI }}" \ -var="sample_remote_app_image=${{ env.REMOTE_SAMPLE_APP_IMAGE_URI }}" \ @@ -210,7 +210,7 @@ jobs: --account-id ${{ env.ACCOUNT_ID }} --metric-namespace ${{ env.METRIC_NAMESPACE }} --log-group ${{ env.LOG_GROUP_NAME }} - --platform-info ${{ env.CLUSTER_NAME }} + --platform-info ${{ env.CLUSTER_NAME }}-${{ env.TESTING_ID }} --service-name ${{env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }} --rollup' @@ -223,7 +223,7 @@ jobs: --account-id ${{ env.ACCOUNT_ID }} --metric-namespace ${{ env.METRIC_NAMESPACE }} --log-group ${{ env.LOG_GROUP_NAME }} - --platform-info ${{ env.CLUSTER_NAME }} + --platform-info ${{ env.CLUSTER_NAME }}-${{ env.TESTING_ID }} --service-name ${{env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }} --rollup' @@ -236,7 +236,7 @@ jobs: --account-id ${{ env.ACCOUNT_ID }} --metric-namespace ${{ env.METRIC_NAMESPACE }} --log-group ${{ env.LOG_GROUP_NAME }} - --platform-info ${{ env.CLUSTER_NAME }} + --platform-info ${{ env.CLUSTER_NAME }}-${{ env.TESTING_ID }} --service-name ${{env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }} --rollup' @@ -268,7 +268,7 @@ jobs: terraform destroy -auto-approve \ -var="test_id=${{ env.TESTING_ID }}" \ -var="aws_region=${{ env.E2E_TEST_AWS_REGION }}" \ - -var="ecs_cluster_name=${{ env.CLUSTER_NAME }}" \ + -var="ecs_cluster_name=${{ env.CLUSTER_NAME }}-${{ env.TESTING_ID }}" \ -var="sample_app_name=${{ env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }}" \ -var="sample_app_image=${{ env.MAIN_SAMPLE_APP_IMAGE_URI }}" \ -var="sample_remote_app_image=${{ env.REMOTE_SAMPLE_APP_IMAGE_URI }}" \ diff --git a/.github/workflows/node-ec2-canary.yml b/.github/workflows/node-ec2-canary.yml index 584b4b226..8bacbc428 100644 --- a/.github/workflows/node-ec2-canary.yml +++ b/.github/workflows/node-ec2-canary.yml @@ -20,11 +20,10 @@ jobs: strategy: fail-fast: false matrix: - aws-region: [ 'us-east-1' ] - # aws-region: ['af-south-1','ap-east-1','ap-northeast-1','ap-northeast-2','ap-northeast-3','ap-south-1','ap-south-2','ap-southeast-1', - # 'ap-southeast-2','ap-southeast-3','ap-southeast-4','ca-central-1','eu-central-1','eu-central-2','eu-north-1', - # 'eu-south-1','eu-south-2','eu-west-1','eu-west-2','eu-west-3','il-central-1','me-central-1','me-south-1', 'sa-east-1', - # 'us-east-1','us-east-2', 'us-west-1', 'us-west-2'] + aws-region: ['af-south-1','ap-east-1','ap-northeast-1','ap-northeast-2','ap-northeast-3','ap-south-1','ap-south-2','ap-southeast-1', + 'ap-southeast-2','ap-southeast-3','ap-southeast-4','ca-central-1','eu-central-1','eu-central-2','eu-north-1', + 'eu-south-1','eu-south-2','eu-west-1','eu-west-2','eu-west-3','il-central-1','me-central-1','me-south-1', 'sa-east-1', + 'us-east-1','us-east-2', 'us-west-1', 'us-west-2'] uses: ./.github/workflows/node-ec2-default-retry.yml secrets: inherit with: diff --git a/.github/workflows/node-ec2-default-test.yml b/.github/workflows/node-ec2-default-test.yml index 2c7f0c985..56e4a7339 100644 --- a/.github/workflows/node-ec2-default-test.yml +++ b/.github/workflows/node-ec2-default-test.yml @@ -16,7 +16,7 @@ on: type: string staging-instrumentation-name: required: false - default: 'aws-aws-distro-opentelemetry-node-autoinstrumentation-0.0.1.tgz' + default: '@aws/aws-distro-opentelemetry-node-autoinstrumentation' type: string outputs: job-started: @@ -92,20 +92,13 @@ jobs: role-to-assume: arn:aws:iam::${{ env.ACCOUNT_ID }}:role/${{ env.E2E_TEST_ROLE_NAME }} aws-region: ${{ env.E2E_TEST_AWS_REGION }} - # TODO: Remove the following step once release testing is ready - - name: TEMPORARY TEST CONFIGS - run: | - echo ADOT_INSTRUMENTATION_NAME="aws-aws-distro-opentelemetry-node-autoinstrumentation-0.0.1.tgz" >> $GITHUB_ENV - - name: Set Get ADOT Instrumentation command environment variable run: | - echo GET_ADOT_INSTRUMENTATION_COMMAND="aws s3 cp s3://adot-autoinstrumentation-node-staging/${{ env.ADOT_INSTRUMENTATION_NAME }} ./${{ env.ADOT_INSTRUMENTATION_NAME }} && npm install ${{ env.ADOT_INSTRUMENTATION_NAME }}" >> $GITHUB_ENV - # TODO: Reintroduce release testing logic when artifacts are ready - # if [ "${{ github.event.repository.name }}" = "aws-otel-js-instrumentation" ]; then - # echo GET_ADOT_INSTRUMENTATION_COMMAND="aws s3 cp s3://adot-autoinstrumentation-node-staging/${{ env.ADOT_INSTRUMENTATION_NAME }} ./${{ env.ADOT_INSTRUMENTATION_NAME }} && npm install ${{ env.ADOT_INSTRUMENTATION_NAME }}" >> $GITHUB_ENV - # else - # echo GET_ADOT_INSTRUMENTATION_COMMAND="npm install ${{ env.ADOT_INSTRUMENTATION_NAME }}" >> $GITHUB_ENV - # fi + if [ "${{ github.event.repository.name }}" = "aws-otel-js-instrumentation" ]; then + echo GET_ADOT_INSTRUMENTATION_COMMAND="aws s3 cp s3://adot-autoinstrumentation-node-staging/${{ env.ADOT_INSTRUMENTATION_NAME }} ./${{ env.ADOT_INSTRUMENTATION_NAME }} && npm install ${{ env.ADOT_INSTRUMENTATION_NAME }}" >> $GITHUB_ENV + else + echo GET_ADOT_INSTRUMENTATION_COMMAND="npm install ${{ env.ADOT_INSTRUMENTATION_NAME }}" >> $GITHUB_ENV + fi - name: Set Get CW Agent command environment variable run: | @@ -273,6 +266,5 @@ jobs: continue-on-error: true working-directory: terraform/node/ec2/default run: | - sleep 180 && \ terraform destroy -auto-approve \ -var="test_id=${{ env.TESTING_ID }}" \ No newline at end of file diff --git a/.github/workflows/node-k8s-canary.yml b/.github/workflows/node-k8s-canary.yml index b36031d07..c6285ee03 100644 --- a/.github/workflows/node-k8s-canary.yml +++ b/.github/workflows/node-k8s-canary.yml @@ -23,4 +23,4 @@ jobs: with: # To run in more regions, a cluster must be provisioned manually on EC2 instances in that region aws-region: 'us-east-1' - caller-workflow-name: 'appsignals-e2e-node-k8s-canary-test' \ No newline at end of file + caller-workflow-name: 'appsignals-node-e2e-k8s-canary-test' diff --git a/.github/workflows/python-ecs-canary.yml b/.github/workflows/python-ecs-canary.yml index e43f23d6d..d2c8ffb4f 100644 --- a/.github/workflows/python-ecs-canary.yml +++ b/.github/workflows/python-ecs-canary.yml @@ -9,9 +9,6 @@ on: schedule: - cron: '*/15 * * * *' # run the workflow every 15 minutes workflow_dispatch: # be able to run the workflow on demand - push: - branches: - - ecs-no-call-zzhlogin permissions: id-token: write diff --git a/.github/workflows/python-ecs-retry.yml b/.github/workflows/python-ecs-retry.yml index f23ba7071..025572ac2 100644 --- a/.github/workflows/python-ecs-retry.yml +++ b/.github/workflows/python-ecs-retry.yml @@ -15,10 +15,6 @@ on: required: true type: string -concurrency: - group: 'python-ecs-${{ inputs.aws-region }}-${{ github.ref_name }}' - cancel-in-progress: false - permissions: id-token: write contents: read diff --git a/.github/workflows/python-ecs-test.yml b/.github/workflows/python-ecs-test.yml index 9afa44fb8..5f82714f8 100644 --- a/.github/workflows/python-ecs-test.yml +++ b/.github/workflows/python-ecs-test.yml @@ -146,7 +146,7 @@ jobs: terraform apply -auto-approve \ -var="test_id=${{ env.TESTING_ID }}" \ -var="aws_region=${{ env.E2E_TEST_AWS_REGION }}" \ - -var="ecs_cluster_name=${{ env.CLUSTER_NAME }}" \ + -var="ecs_cluster_name=${{ env.CLUSTER_NAME }}-${{ env.TESTING_ID }}" \ -var="sample_app_name=${{ env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }}" \ -var="sample_app_image=${{ env.MAIN_SAMPLE_APP_IMAGE_URI }}" \ -var="sample_remote_app_image=${{ env.REMOTE_SAMPLE_APP_IMAGE_URI }}" \ @@ -165,7 +165,7 @@ jobs: terraform destroy -auto-approve \ -var="test_id=${{ env.TESTING_ID }}" \ -var="aws_region=${{ env.E2E_TEST_AWS_REGION }}" \ - -var="ecs_cluster_name=${{ env.CLUSTER_NAME }}" \ + -var="ecs_cluster_name=${{ env.CLUSTER_NAME }}-${{ env.TESTING_ID }}" \ -var="sample_app_name=${{ env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }}" \ -var="sample_app_image=${{ env.MAIN_SAMPLE_APP_IMAGE_URI }}" \ -var="sample_remote_app_image=${{ env.REMOTE_SAMPLE_APP_IMAGE_URI }}" \ @@ -210,7 +210,7 @@ jobs: --account-id ${{ env.ACCOUNT_ID }} --metric-namespace ${{ env.METRIC_NAMESPACE }} --log-group ${{ env.LOG_GROUP_NAME }} - --platform-info ${{ env.CLUSTER_NAME }} + --platform-info ${{ env.CLUSTER_NAME }}-${{ env.TESTING_ID }} --service-name ${{env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }} --rollup' @@ -223,7 +223,7 @@ jobs: --account-id ${{ env.ACCOUNT_ID }} --metric-namespace ${{ env.METRIC_NAMESPACE }} --log-group ${{ env.LOG_GROUP_NAME }} - --platform-info ${{ env.CLUSTER_NAME }} + --platform-info ${{ env.CLUSTER_NAME }}-${{ env.TESTING_ID }} --service-name ${{env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }} --rollup' @@ -236,7 +236,7 @@ jobs: --account-id ${{ env.ACCOUNT_ID }} --metric-namespace ${{ env.METRIC_NAMESPACE }} --log-group ${{ env.LOG_GROUP_NAME }} - --platform-info ${{ env.CLUSTER_NAME }} + --platform-info ${{ env.CLUSTER_NAME }}-${{ env.TESTING_ID }} --service-name ${{env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }} --rollup' @@ -268,7 +268,7 @@ jobs: terraform destroy -auto-approve \ -var="test_id=${{ env.TESTING_ID }}" \ -var="aws_region=${{ env.E2E_TEST_AWS_REGION }}" \ - -var="ecs_cluster_name=${{ env.CLUSTER_NAME }}" \ + -var="ecs_cluster_name=${{ env.CLUSTER_NAME }}-${{ env.TESTING_ID }}" \ -var="sample_app_name=${{ env.SAMPLE_APP_NAME }}-${{ env.TESTING_ID }}" \ -var="sample_app_image=${{ env.MAIN_SAMPLE_APP_IMAGE_URI }}" \ -var="sample_remote_app_image=${{ env.REMOTE_SAMPLE_APP_IMAGE_URI }}" \ diff --git a/sample-apps/dotnet/amazon-cloudwatch-agent.json b/sample-apps/dotnet/amazon-cloudwatch-agent.json new file mode 100644 index 000000000..dd82b9e51 --- /dev/null +++ b/sample-apps/dotnet/amazon-cloudwatch-agent.json @@ -0,0 +1,16 @@ +{ + "agent": { + "debug": true, + "region": "REGION" + }, + "traces": { + "traces_collected": { + "application_signals": {} + } + }, + "logs": { + "metrics_collected": { + "application_signals": {} + } + } +} \ No newline at end of file diff --git a/sample-apps/dotnet/dotnet-ec2-win-main-setup.ps1 b/sample-apps/dotnet/dotnet-ec2-win-main-setup.ps1 new file mode 100644 index 000000000..c11513f68 --- /dev/null +++ b/sample-apps/dotnet/dotnet-ec2-win-main-setup.ps1 @@ -0,0 +1,117 @@ +param ( + [string]$GetCloudwatchAgentCommand, + [string]$GetAdotDistroCommand, + [string]$GetSampleAppCommand, + [string]$TestId, + [string]$RemoteServicePrivateEndpoint, + [string]$AWSRegion +) + +# This file is used to deploy and instrumentation main sample app for Dotnet E2E Canary test +# This is the most stable way to do that in automatically test workflow invloving EC2 and SSM + +# To avoid written UI for download and extract zip step, saving lots of time +$ProgressPreference = 'SilentlyContinue' + +# Install Dotnet +wget -O dotnet-install.ps1 https://dot.net/v1/dotnet-install.ps1 +.\dotnet-install.ps1 -Version 8.0.302 + +# Install and start Cloudwatch Agent +Invoke-Expression $GetCloudwatchAgentCommand + +Write-Host "Installing Cloudwatch Agent" +msiexec /i amazon-cloudwatch-agent.msi +$timeout = 30 +$interval = 5 +$call_cloudwatch = & "C:\Program Files\Amazon\AmazonCloudWatchAgent\amazon-cloudwatch-agent-ctl.ps1" +$elapsedTime = 0 + +while ($elapsedTime -lt $timeout) { + if ($call_cloudwatch) { + Start-Sleep -Seconds $interval + Write-Host "Install Finished" + break + } else { + Write-Host "Cloudwatch Agent not found: $filePath. Checking again in $interval seconds..." + Start-Sleep -Seconds $interval + $elapsedTime += $interval + } +} + +if ($elapsedTime -ge $timeout) { + Write-Host "CloudWatch not found after $timeout seconds." +} + +Write-Host "Install Finished" + +# Even after this step, it only expose 8080 to localhost and local (EC2) network on current config, so it's safe +# Leave it here for Debug purpose +New-NetFirewallRule -DisplayName "Allow TCP 8080" -Direction Inbound -Protocol TCP -LocalPort 8080 -Action Allow + +& "C:\Program Files\Amazon\AmazonCloudWatchAgent\amazon-cloudwatch-agent-ctl.ps1" -a fetch-config -m ec2 -s -c file:./amazon-cloudwatch-agent.json + +# Get Instrumentation Artifacts and Sample App +Invoke-Expression $GetAdotDistroCommand + +Invoke-Expression $GetSampleAppCommand + +Expand-Archive -Path .\dotnet-sample-app.zip -DestinationPath .\ -Force + +# Config Env variable for Windows EC2 + +$current_dir = Get-Location +Write-Host $current_dir + +Set-Location -Path "./asp_frontend_service" +$env:CORECLR_ENABLE_PROFILING = "1" +$env:CORECLR_PROFILER = "{918728DD-259F-4A6A-AC2B-B85E1B658318}" +$env:CORECLR_PROFILER_PATH = "$current_dir\dotnet-distro\win-x64\OpenTelemetry.AutoInstrumentation.Native.dll" +$env:DOTNET_ADDITIONAL_DEPS = "$current_dir\dotnet-distro\AdditionalDeps" +$env:DOTNET_SHARED_STORE = "$current_dir\dotnet-distro\store" +$env:DOTNET_STARTUP_HOOKS = "$current_dir\dotnet-distro\net\OpenTelemetry.AutoInstrumentation.StartupHook.dll" +$env:OTEL_DOTNET_AUTO_HOME = "$current_dir\dotnet-distro" +$env:OTEL_DOTNET_AUTO_PLUGINS = "AWS.Distro.OpenTelemetry.AutoInstrumentation.Plugin, AWS.Distro.OpenTelemetry.AutoInstrumentation" +$env:OTEL_EXPORTER_OTLP_PROTOCOL = "http/protobuf" +$env:OTEL_EXPORTER_OTLP_ENDPOINT = "http://127.0.0.1:4316" +$env:OTEL_AWS_APPLICATION_SIGNALS_EXPORTER_ENDPOINT = "http://127.0.0.1:4316/v1/metrics" +$env:OTEL_METRICS_EXPORTER = "none" +$env:OTEL_RESOURCE_ATTRIBUTES = "service.name=dotnet-sample-application-$TestId" +$env:OTEL_AWS_APPLICATION_SIGNALS_ENABLED = "true" +$env:OTEL_TRACES_SAMPLER = "always_on" +$env:ASPNETCORE_URLS = "http://0.0.0.0:8080" + + +dotnet build + + +Start-Process -FilePath "dotnet" -ArgumentList "bin/Debug/netcoreapp8.0/asp_frontend_service.dll" + +Write-Host "Start Sleep" +Start-Sleep -Seconds 10 + +# Deploy Traffic Generator + +# Install node and setup path for node +wget -O nodejs.zip https://nodejs.org/dist/v20.16.0/node-v20.16.0-win-x64.zip +Expand-Archive -Path .\nodejs.zip -DestinationPath .\nodejs -Force +$currentdir = Get-Location +Write-Host $currentdir +$env:Path += ";$currentdir" + "\nodejs\node-v20.16.0-win-x64" + +# Bring in the traffic generator files to EC2 Instance +aws s3 cp "s3://aws-appsignals-sample-app-prod-$AWSRegion/traffic-generator.zip" "./traffic-generator.zip" +Expand-Archive -Path "./traffic-generator.zip" -DestinationPath "./" -Force + +# Install the traffic generator dependencies +npm install + +# Start traffic generator +$env:MAIN_ENDPOINT = "localhost:8080" +$env:REMOTE_ENDPOINT = $RemoteServicePrivateEndpoint +$env:ID = $TestId + +Start-Process -FilePath "npm" -ArgumentList "start" + +Write-Host "Exiting" +exit \ No newline at end of file diff --git a/sample-apps/dotnet/dotnet-ec2-win-remote-setup.ps1 b/sample-apps/dotnet/dotnet-ec2-win-remote-setup.ps1 new file mode 100644 index 000000000..b4af24791 --- /dev/null +++ b/sample-apps/dotnet/dotnet-ec2-win-remote-setup.ps1 @@ -0,0 +1,88 @@ +param ( + [string]$GetCloudwatchAgentCommand, + [string]$GetAdotDistroCommand, + [string]$GetSampleAppCommand, + [string]$TestId +) + +# This file is used to deploy and instrumentation remote sample app for Dotnet E2E Canary test +# This is the most stable way to do that in automatically test workflow invloving EC2 and SSM + +# To avoid written UI for download and extract zip step, saving lots of time +$ProgressPreference = 'SilentlyContinue' + +# Install Dotnet +wget -O dotnet-install.ps1 https://dot.net/v1/dotnet-install.ps1 +.\dotnet-install.ps1 -Version 8.0.302 + +# Install and start Cloudwatch Agent +Invoke-Expression $GetCloudwatchAgentCommand + +Write-Host "Installing Cloudwatch Agent" +msiexec /i amazon-cloudwatch-agent.msi +$timeout = 30 +$interval = 5 +$call_cloudwatch = & "C:\Program Files\Amazon\AmazonCloudWatchAgent\amazon-cloudwatch-agent-ctl.ps1" +$elapsedTime = 0 + +while ($elapsedTime -lt $timeout) { + if ($call_cloudwatch) { + Start-Sleep -Seconds $interval + Write-Host "Install Finished" + break + } else { + Write-Host "Cloudwatch Agent not found: $filePath. Checking again in $interval seconds..." + Start-Sleep -Seconds $interval + $elapsedTime += $interval + } +} + +if ($elapsedTime -ge $timeout) { + Write-Host "CloudWatch not found after $timeout seconds." +} + +& "C:\Program Files\Amazon\AmazonCloudWatchAgent\amazon-cloudwatch-agent-ctl.ps1" -a fetch-config -m ec2 -s -c file:./amazon-cloudwatch-agent.json + +# Get Instrumentation Artifacts and Sample App +Invoke-Expression $GetAdotDistroCommand + +Invoke-Expression $GetSampleAppCommand + +Expand-Archive -Path .\dotnet-sample-app.zip -DestinationPath .\ -Force + +# Allow income traffic from main-service +New-NetFirewallRule -DisplayName "Allow TCP 8081" -Direction Inbound -Protocol TCP -LocalPort 8081 -Action Allow + +$current_dir = Get-Location +Write-Host $current_dir + +# Config Env variable for Windows EC2 +Set-Location -Path "./asp_remote_service" +$env:CORECLR_ENABLE_PROFILING = "1" +$env:CORECLR_PROFILER = "{918728DD-259F-4A6A-AC2B-B85E1B658318}" +$env:CORECLR_PROFILER_PATH = "$current_dir\dotnet-distro\win-x64\OpenTelemetry.AutoInstrumentation.Native.dll" +$env:DOTNET_ADDITIONAL_DEPS = "$current_dir\dotnet-distro\AdditionalDeps" +$env:DOTNET_SHARED_STORE = "$current_dir\dotnet-distro\store" +$env:DOTNET_STARTUP_HOOKS = "$current_dir\dotnet-distro\net\OpenTelemetry.AutoInstrumentation.StartupHook.dll" +$env:OTEL_DOTNET_AUTO_HOME = "$current_dir\dotnet-distro" +$env:OTEL_DOTNET_AUTO_PLUGINS = "AWS.Distro.OpenTelemetry.AutoInstrumentation.Plugin, AWS.Distro.OpenTelemetry.AutoInstrumentation" +$env:OTEL_EXPORTER_OTLP_PROTOCOL = "http/protobuf" +$env:OTEL_EXPORTER_OTLP_ENDPOINT = "http://127.0.0.1:4316" +$env:OTEL_AWS_APPLICATION_SIGNALS_EXPORTER_ENDPOINT = "http://127.0.0.1:4316/v1/metrics" +$env:OTEL_METRICS_EXPORTER = "none" +$env:OTEL_RESOURCE_ATTRIBUTES = "service.name=dotnet-sample-remote-application-$TestId" +$env:OTEL_AWS_APPLICATION_SIGNALS_ENABLED = "true" +$env:OTEL_TRACES_SAMPLER = "always_on" +$env:ASPNETCORE_URLS = "http://0.0.0.0:8081" + + +dotnet build + + +Start-Process -FilePath "dotnet" -ArgumentList "bin/Debug/netcoreapp8.0/asp_remote_service.dll" + + +Write-Host "Start Sleep" +Start-Sleep -Seconds 30 +Write-Host "Exiting" +exit \ No newline at end of file diff --git a/sample-apps/node/frontend-service/package-lock.json b/sample-apps/node/frontend-service/package-lock.json index 00178905e..496753ecd 100644 --- a/sample-apps/node/frontend-service/package-lock.json +++ b/sample-apps/node/frontend-service/package-lock.json @@ -12,7 +12,7 @@ "@aws-sdk/client-s3": "^3.621.0", "@types/express": "^4.17.21", "@types/node": "^20.14.6", - "express": "^4.19.2", + "express": "^4.21.0", "mysql2": "^3.11.0" } }, @@ -1618,9 +1618,9 @@ } }, "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -1630,7 +1630,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", + "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -1758,9 +1758,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "engines": { "node": ">= 0.8" } @@ -1798,36 +1798,36 @@ } }, "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", + "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.10", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -1860,12 +1860,12 @@ } }, "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -2047,9 +2047,12 @@ } }, "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/methods": { "version": "1.1.2", @@ -2182,9 +2185,9 @@ } }, "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" }, "node_modules/proxy-addr": { "version": "2.0.7", @@ -2199,11 +2202,11 @@ } }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -2259,9 +2262,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -2281,6 +2284,14 @@ "node": ">= 0.8.0" } }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -2292,14 +2303,14 @@ "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" diff --git a/sample-apps/node/frontend-service/package.json b/sample-apps/node/frontend-service/package.json index d43bd5161..2ca46bd30 100644 --- a/sample-apps/node/frontend-service/package.json +++ b/sample-apps/node/frontend-service/package.json @@ -13,7 +13,7 @@ "@aws-sdk/client-s3": "^3.621.0", "@types/express": "^4.17.21", "@types/node": "^20.14.6", - "express": "^4.19.2", + "express": "^4.21.0", "mysql2": "^3.11.0" } } diff --git a/sample-apps/node/remote-service/package-lock.json b/sample-apps/node/remote-service/package-lock.json index da347411d..ac3382b04 100644 --- a/sample-apps/node/remote-service/package-lock.json +++ b/sample-apps/node/remote-service/package-lock.json @@ -12,7 +12,7 @@ "@aws-sdk/client-s3": "^3.621.0", "@types/express": "^4.17.21", "@types/node": "^20.14.6", - "express": "^4.19.2", + "express": "^4.20.0", "mysql2": "^3.11.0", "nodemon": "^3.1.4" } @@ -1647,9 +1647,9 @@ } }, "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -1659,7 +1659,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", + "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -1669,6 +1669,20 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/body-parser/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/bowser": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", @@ -1875,36 +1889,36 @@ } }, "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/express/-/express-4.20.0.tgz", + "integrity": "sha512-pLdae7I6QqShF5PnNTCVn4hI91Dx0Grkn2+IAsMTgMIKuQVte2dN9PeGSSAME2FR8anOhVA62QDIUaWVfEXVLw==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "finalhandler": "1.2.0", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.10", "proxy-addr": "~2.0.7", "qs": "6.11.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.0", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -1915,6 +1929,14 @@ "node": ">= 0.10.0" } }, + "node_modules/express/node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/fast-xml-parser": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", @@ -2210,9 +2232,12 @@ } }, "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/methods": { "version": "1.1.2", @@ -2412,9 +2437,9 @@ } }, "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -2527,9 +2552,9 @@ } }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -2560,9 +2585,9 @@ "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.0.tgz", + "integrity": "sha512-pDLK8zwl2eKaYrs8mrPZBJua4hMplRWJ1tIFksVC3FtBEBnl8dxgeHtsaMS8DhS9i4fLObaon6ABoc4/hQGdPA==", "dependencies": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", @@ -2573,6 +2598,34 @@ "node": ">= 0.8.0" } }, + "node_modules/serve-static/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static/node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", diff --git a/sample-apps/node/remote-service/package.json b/sample-apps/node/remote-service/package.json index 4a60870e6..8fe6bb810 100644 --- a/sample-apps/node/remote-service/package.json +++ b/sample-apps/node/remote-service/package.json @@ -13,7 +13,7 @@ "@aws-sdk/client-s3": "^3.621.0", "@types/express": "^4.17.21", "@types/node": "^20.14.6", - "express": "^4.19.2", + "express": "^4.20.0", "mysql2": "^3.11.0", "nodemon": "^3.1.4" } diff --git a/terraform/dotnet/ec2/windows/main.tf b/terraform/dotnet/ec2/windows/main.tf new file mode 100644 index 000000000..7c45d0d25 --- /dev/null +++ b/terraform/dotnet/ec2/windows/main.tf @@ -0,0 +1,221 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + } + } +} + +provider "aws" {} + +resource "aws_default_vpc" "default" {} + +resource "tls_private_key" "ssh_key" { + algorithm = "RSA" + rsa_bits = 4096 +} + +resource "aws_key_pair" "aws_ssh_key" { + key_name = "instance_key-${var.test_id}" + public_key = tls_private_key.ssh_key.public_key_openssh +} + +data "aws_ami" "ami" { + owners = ["amazon"] + most_recent = true + filter { + name = "name" + values = ["Windows_Server-2022-English-Full-Base-*"] + } + filter { + name = "state" + values = ["available"] + } + filter { + name = "architecture" + values = ["x86_64"] + } + filter { + name = "image-type" + values = ["machine"] + } + + filter { + name = "root-device-name" + values = ["/dev/sda1"] + } + + filter { + name = "root-device-type" + values = ["ebs"] + } + + filter { + name = "virtualization-type" + values = ["hvm"] + } +} + +locals { + ssh_key_name = aws_key_pair.aws_ssh_key.key_name + private_key_content = tls_private_key.ssh_key.private_key_pem +} + +resource "aws_instance" "main_service_instance" { + ami = data.aws_ami.ami.id + instance_type = "t3.large" + key_name = local.ssh_key_name + iam_instance_profile = "APP_SIGNALS_EC2_TEST_ROLE" + vpc_security_group_ids = [aws_default_vpc.default.default_security_group_id] + associate_public_ip_address = true + instance_initiated_shutdown_behavior = "terminate" + metadata_options { + http_tokens = "required" + } + get_password_data = true + + tags = { + Name = "main-service-${var.test_id}" + } + + user_data = <<-EOF + + Write-Host "Block RDP" + Get-NetFirewallRule -DisplayName "Remote Desktop - User Mode (TCP-In)" | Set-NetFirewallRule -Enabled False + Get-Service -Name TermService | Select-Object -ExpandProperty DependentServices | ForEach-Object { Stop-Service -Name $_.Name -Force } + Stop-Service -Name TermService -Force + Set-Service -Name TermService -StartupType Disabled + msiexec.exe /i https://awscli.amazonaws.com/AWSCLIV2.msi /qn + $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") + $awsCliInstalled = Get-Command aws -ErrorAction SilentlyContinue + + while (-not $awsCliInstalled) { + Write-Host "Waiting for AWS CLI" + $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") + $awsCliInstalled = Get-Command aws -ErrorAction SilentlyContinue + Write-Host "Waiting" + Start-Sleep -Seconds 5 + } + Write-Host "AWS CLI Installed" + Write-Host "Finish execution" + + true + EOF +} + +resource "aws_instance" "remote_service_instance" { + ami = data.aws_ami.ami.id + instance_type = "t3.large" + key_name = local.ssh_key_name + iam_instance_profile = "APP_SIGNALS_EC2_TEST_ROLE" + vpc_security_group_ids = [aws_default_vpc.default.default_security_group_id] + associate_public_ip_address = true + instance_initiated_shutdown_behavior = "terminate" + metadata_options { + http_tokens = "required" + } + get_password_data = true + + tags = { + Name = "remote-service-${var.test_id}" + } + + user_data = <<-EOF + + Write-Host "Block RDP" + Get-NetFirewallRule -DisplayName "Remote Desktop - User Mode (TCP-In)" | Set-NetFirewallRule -Enabled False + Get-Service -Name TermService | Select-Object -ExpandProperty DependentServices | ForEach-Object { Stop-Service -Name $_.Name -Force } + Stop-Service -Name TermService -Force + Set-Service -Name TermService -StartupType Disabled + msiexec.exe /i https://awscli.amazonaws.com/AWSCLIV2.msi /qn + $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") + $awsCliInstalled = Get-Command aws -ErrorAction SilentlyContinue + + while (-not $awsCliInstalled) { + Write-Host "Waiting for AWS CLI" + $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") + $awsCliInstalled = Get-Command aws -ErrorAction SilentlyContinue + Write-Host "Waiting" + Start-Sleep -Seconds 5 + } + Write-Host "AWS CLI Installed" + Write-Host "Finish execution" + + true + EOF +} + +# Create SSM Document for main service setup +resource "aws_ssm_document" "main_service_setup" { + name = "main_service_setup_${var.test_id}" + document_type = "Command" + + content = <<-DOC + { + "schemaVersion": "2.2", + "description": "Setup main service instance", + "mainSteps": [ + { + "action": "aws:runPowerShellScript", + "name": "setupMainService", + "inputs": { + "runCommand": [ + "aws s3 cp s3://aws-appsignals-sample-app-prod-${var.aws_region}/amazon-cloudwatch-agent.json ./amazon-cloudwatch-agent.json", + "powershell -Command \"(Get-Content -Path 'amazon-cloudwatch-agent.json') -replace 'REGION', 'us-east-1' | Set-Content -Path 'amazon-cloudwatch-agent.json'\"", + "aws s3 cp s3://aws-appsignals-sample-app-prod-${var.aws_region}/dotnet-ec2-win-main-setup.ps1 ./dotnet-ec2-win-main-setup.ps1", + "powershell -ExecutionPolicy Bypass -File ./dotnet-ec2-win-main-setup.ps1 -GetCloudwatchAgentCommand \"${var.get_cw_agent_msi_command}\" -GetAdotDistroCommand \"${var.get_adot_distro_command}\" -GetSampleAppCommand \"${var.sample_app_zip}\" -TestId \"${var.test_id}\" -RemoteServicePrivateEndpoint \"${aws_instance.remote_service_instance.private_ip}\" -AWSRegion \"${var.aws_region}\"" + ] + } + } + ] + } + DOC +} + +# Create SSM Association for main service instance +resource "aws_ssm_association" "main_service_association" { + name = aws_ssm_document.main_service_setup.name + targets { + key = "InstanceIds" + values = [aws_instance.main_service_instance.id] + } + + depends_on = [aws_instance.main_service_instance] +} + +# Create SSM Document for remote service setup +resource "aws_ssm_document" "remote_service_setup" { + name = "remote_service_setup_${var.test_id}" + document_type = "Command" + + content = <<-DOC + { + "schemaVersion": "2.2", + "description": "Setup remote service instance", + "mainSteps": [ + { + "action": "aws:runPowerShellScript", + "name": "setupRemoteService", + "inputs": { + "runCommand": [ + "aws s3 cp s3://aws-appsignals-sample-app-prod-${var.aws_region}/amazon-cloudwatch-agent.json ./amazon-cloudwatch-agent.json", + "powershell -Command \"(Get-Content -Path 'amazon-cloudwatch-agent.json') -replace 'REGION', 'us-east-1' | Set-Content -Path 'amazon-cloudwatch-agent.json'\"", + "aws s3 cp s3://aws-appsignals-sample-app-prod-${var.aws_region}/dotnet-ec2-win-remote-setup.ps1 ./dotnet-ec2-win-remote-setup.ps1", + "powershell -ExecutionPolicy Bypass -File ./dotnet-ec2-win-remote-setup.ps1 -GetCloudwatchAgentCommand \"${var.get_cw_agent_msi_command}\" -GetAdotDistroCommand \"${var.get_adot_distro_command}\" -GetSampleAppCommand \"${var.sample_app_zip}\" -TestId \"${var.test_id}\"" + ] + } + } + ] + } + DOC +} + +# Create SSM Association for remote service instance +resource "aws_ssm_association" "remote_service_association" { + name = aws_ssm_document.remote_service_setup.name + targets { + key = "InstanceIds" + values = [aws_instance.remote_service_instance.id] + } + depends_on = [aws_instance.remote_service_instance] +} \ No newline at end of file diff --git a/terraform/dotnet/ec2/windows/output.tf b/terraform/dotnet/ec2/windows/output.tf new file mode 100644 index 000000000..5853d05ce --- /dev/null +++ b/terraform/dotnet/ec2/windows/output.tf @@ -0,0 +1,38 @@ +# ------------------------------------------------------------------------ +# Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). +# You may not use this file except in compliance with the License. +# A copy of the License is located at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# or in the "license" file accompanying this file. This file is distributed +# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +# express or implied. See the License for the specific language governing +# permissions and limitations under the License. +# ------------------------------------------------------------------------- + +output "sample_app_remote_service_private_ip" { + value = aws_instance.remote_service_instance.private_ip +} + +output "main_service_instance_id" { + value = aws_instance.main_service_instance.id +} + +output "remote_service_instance_id" { + value = aws_instance.remote_service_instance.id +} + +output "ec2_instance_ami" { + value = data.aws_ami.ami.id +} + +output "frontend_script_association_id" { + value = aws_ssm_association.main_service_association.id +} + +output "remote_script_association_id" { + value = aws_ssm_association.remote_service_association.id +} \ No newline at end of file diff --git a/terraform/dotnet/ec2/windows/variables.tf b/terraform/dotnet/ec2/windows/variables.tf new file mode 100644 index 000000000..10a6f5310 --- /dev/null +++ b/terraform/dotnet/ec2/windows/variables.tf @@ -0,0 +1,38 @@ +# ------------------------------------------------------------------------ +# Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). +# You may not use this file except in compliance with the License. +# A copy of the License is located at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# or in the "license" file accompanying this file. This file is distributed +# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +# express or implied. See the License for the specific language governing +# permissions and limitations under the License. +# ------------------------------------------------------------------------- + +variable "test_id" { + default = "windows-e2e-test-0" +} + +variable "aws_region" { + default = "" +} + +variable "user" { + default = "ec2-user" +} + +variable "sample_app_zip" { + default = "wget -O ./dotnet-sample-app.zip https://github.com/aws-observability/aws-application-signals-test-framework/raw/dotnetE2ETests/sample-apps/dotnet/dotnet-sample-app.zip" +} + +variable "get_adot_distro_command" { + default = "wget -O ./aws-distro-opentelemetry-dotnet-instrumentation-windows.zip https://github.com/aws-observability/aws-otel-dotnet-instrumentation/releases/download/v1.1.0/aws-distro-opentelemetry-dotnet-instrumentation-windows.zip; Expand-Archive -Path ./aws-distro-opentelemetry-dotnet-instrumentation-windows.zip -DestinationPath ./dotnet-distro -Force" +} + +variable "get_cw_agent_msi_command" { + default = "wget -O ./amazon-cloudwatch-agent.msi https://amazoncloudwatch-agent.s3.amazonaws.com/windows/amd64/latest/amazon-cloudwatch-agent.msi" +} \ No newline at end of file diff --git a/terraform/java/ecs/variables.tf b/terraform/java/ecs/variables.tf index a47b95cdc..d4aaee852 100644 --- a/terraform/java/ecs/variables.tf +++ b/terraform/java/ecs/variables.tf @@ -19,7 +19,7 @@ variable "test_id" { } variable "aws_region" { - default = "us-west-2" + default = "" } variable "ecs_cluster_name" { diff --git a/terraform/python/ecs/variables.tf b/terraform/python/ecs/variables.tf index a47b95cdc..d4aaee852 100644 --- a/terraform/python/ecs/variables.tf +++ b/terraform/python/ecs/variables.tf @@ -19,7 +19,7 @@ variable "test_id" { } variable "aws_region" { - default = "us-west-2" + default = "" } variable "ecs_cluster_name" { diff --git a/validator/src/main/java/com/amazon/aoc/fileconfigs/PredefinedExpectedTemplate.java b/validator/src/main/java/com/amazon/aoc/fileconfigs/PredefinedExpectedTemplate.java index b9862dae5..0421f7efb 100644 --- a/validator/src/main/java/com/amazon/aoc/fileconfigs/PredefinedExpectedTemplate.java +++ b/validator/src/main/java/com/amazon/aoc/fileconfigs/PredefinedExpectedTemplate.java @@ -204,6 +204,27 @@ public enum PredefinedExpectedTemplate implements FileConfig { DOTNET_EC2_DEFAULT_CLIENT_CALL_METRIC("/expected-data-template/dotnet/ec2/default/client-call-metric.mustache"), DOTNET_EC2_DEFAULT_CLIENT_CALL_TRACE("/expected-data-template/dotnet/ec2/default/client-call-trace.mustache"), + /** DotNet EC2 Windows Default Test Case Validations */ + DOTNET_EC2_WINDOWS_DEFAULT_OUTGOING_HTTP_CALL_LOG( + "/expected-data-template/dotnet/ec2/windows/outgoing-http-call-log.mustache"), + DOTNET_EC2_WINDOWS_DEFAULT_OUTGOING_HTTP_CALL_METRIC( + "/expected-data-template/dotnet/ec2/windows/outgoing-http-call-metric.mustache"), + DOTNET_EC2_WINDOWS_DEFAULT_OUTGOING_HTTP_CALL_TRACE( + "/expected-data-template/dotnet/ec2/windows/outgoing-http-call-trace.mustache"), + + DOTNET_EC2_WINDOWS_DEFAULT_AWS_SDK_CALL_LOG("/expected-data-template/dotnet/ec2/windows/aws-sdk-call-log.mustache"), + DOTNET_EC2_WINDOWS_DEFAULT_AWS_SDK_CALL_METRIC("/expected-data-template/dotnet/ec2/windows/aws-sdk-call-metric.mustache"), + DOTNET_EC2_WINDOWS_DEFAULT_AWS_SDK_CALL_TRACE("/expected-data-template/dotnet/ec2/windows/aws-sdk-call-trace.mustache"), + + DOTNET_EC2_WINDOWS_DEFAULT_REMOTE_SERVICE_LOG("/expected-data-template/dotnet/ec2/windows/remote-service-log.mustache"), + DOTNET_EC2_WINDOWS_DEFAULT_REMOTE_SERVICE_METRIC("/expected-data-template/dotnet/ec2/windows/remote-service-metric.mustache"), +// Because of a time sync issue, block the remote service trace check for now +// DOTNET_EC2_WINDOWS_DEFAULT_REMOTE_SERVICE_TRACE("/expected-data-template/dotnet/ec2/windows/remote-service-trace.mustache"), + + DOTNET_EC2_WINDOWS_DEFAULT_CLIENT_CALL_LOG("/expected-data-template/dotnet/ec2/windows/client-call-log.mustache"), + DOTNET_EC2_WINDOWS_DEFAULT_CLIENT_CALL_METRIC("/expected-data-template/dotnet/ec2/windows/client-call-metric.mustache"), + DOTNET_EC2_WINDOWS_DEFAULT_CLIENT_CALL_TRACE("/expected-data-template/dotnet/ec2/windows/client-call-trace.mustache"), + /** DotNet EC2 Asg Test Case Validations */ DOTNET_EC2_ASG_OUTGOING_HTTP_CALL_LOG("/expected-data-template/dotnet/ec2/asg/outgoing-http-call-log.mustache"), DOTNET_EC2_ASG_OUTGOING_HTTP_CALL_METRIC("/expected-data-template/dotnet/ec2/asg/outgoing-http-call-metric.mustache"), diff --git a/validator/src/main/java/com/amazon/aoc/services/XRayService.java b/validator/src/main/java/com/amazon/aoc/services/XRayService.java index 29a4daacb..a48978f77 100644 --- a/validator/src/main/java/com/amazon/aoc/services/XRayService.java +++ b/validator/src/main/java/com/amazon/aoc/services/XRayService.java @@ -26,7 +26,6 @@ import java.util.Date; import java.util.List; import org.joda.time.DateTime; -import lombok.extern.log4j.Log4j2; public class XRayService { private AWSXRay awsxRay; diff --git a/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/aws-sdk-call-log.mustache b/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/aws-sdk-call-log.mustache new file mode 100644 index 000000000..06f8fadda --- /dev/null +++ b/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/aws-sdk-call-log.mustache @@ -0,0 +1,20 @@ +[{ + "EC2.InstanceId": "^{{instanceId}}$", + "Environment": "^ec2:default$", + "PlatformType": "^AWS::EC2$", + "Operation": "GET /aws-sdk-call", + "Version": "^1$", + "Telemetry.Source": "^LocalRootSpan$", + "Host": "^ip(-[0-9]{1,3}){4}.*$" +}, +{ + "EC2.InstanceId": "^{{instanceId}}$", + "Environment": "^ec2:default$", + "PlatformType": "^AWS::EC2$", + "Operation": "GET /aws-sdk-call", + "Version": "^1$", + "RemoteService": "AWS::S3", + "RemoteOperation": "GetBucketLocation", + "Telemetry.Source": "^ClientSpan$", + "Host": "^ip(-[0-9]{1,3}){4}.*$" +}] \ No newline at end of file diff --git a/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/aws-sdk-call-metric.mustache b/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/aws-sdk-call-metric.mustache new file mode 100644 index 000000000..22d8da7a7 --- /dev/null +++ b/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/aws-sdk-call-metric.mustache @@ -0,0 +1,374 @@ +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: GET /aws-sdk-call + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: GET /aws-sdk-call + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteOperation + value: GetBucketLocation + - + name: RemoteService + value: AWS::S3 + +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteService + value: AWS::S3 + +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteOperation + value: GetBucketLocation + - + name: RemoteService + value: AWS::S3 + +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: GET /aws-sdk-call + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteOperation + value: GetBucketLocation + - + name: RemoteService + value: AWS::S3 + - + name: RemoteResourceIdentifier + value: {{testingId}} + - + name: RemoteResourceType + value: AWS::S3::Bucket + +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteOperation + value: GetBucketLocation + - + name: RemoteService + value: AWS::S3 + - + name: RemoteResourceIdentifier + value: {{testingId}} + - + name: RemoteResourceType + value: AWS::S3::Bucket + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: GET /aws-sdk-call + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: GET /aws-sdk-call + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteOperation + value: GetBucketLocation + - + name: RemoteService + value: AWS::S3 + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteService + value: AWS::S3 + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteOperation + value: GetBucketLocation + - + name: RemoteService + value: AWS::S3 + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: GET /aws-sdk-call + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteOperation + value: GetBucketLocation + - + name: RemoteService + value: AWS::S3 + - + name: RemoteResourceIdentifier + value: {{testingId}} + - + name: RemoteResourceType + value: AWS::S3::Bucket + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteOperation + value: GetBucketLocation + - + name: RemoteService + value: AWS::S3 + - + name: RemoteResourceIdentifier + value: {{testingId}} + - + name: RemoteResourceType + value: AWS::S3::Bucket + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: GET /aws-sdk-call + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: GET /aws-sdk-call + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteOperation + value: GetBucketLocation + - + name: RemoteService + value: AWS::S3 + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteService + value: AWS::S3 + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteOperation + value: GetBucketLocation + - + name: RemoteService + value: AWS::S3 + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: GET /aws-sdk-call + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteOperation + value: GetBucketLocation + - + name: RemoteService + value: AWS::S3 + - + name: RemoteResourceIdentifier + value: {{testingId}} + - + name: RemoteResourceType + value: AWS::S3::Bucket + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteOperation + value: GetBucketLocation + - + name: RemoteService + value: AWS::S3 + - + name: RemoteResourceIdentifier + value: {{testingId}} + - + name: RemoteResourceType + value: AWS::S3::Bucket \ No newline at end of file diff --git a/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/aws-sdk-call-trace.mustache b/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/aws-sdk-call-trace.mustache new file mode 100644 index 000000000..ef4a9759a --- /dev/null +++ b/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/aws-sdk-call-trace.mustache @@ -0,0 +1,56 @@ +[{ + "name": "^{{serviceName}}$", + "http": { + "request": { + "url": "^{{endpoint}}/aws-sdk-call$", + "method": "^GET$" + } + }, + "aws": { + "account_id": "^{{accountId}}$" + }, + "annotations": { + "aws.local.service": "^{{serviceName}}$", + "aws.local.operation": "^GET /aws-sdk-call$", + "aws.local.environment": "^ec2:default$" + }, + "metadata": { + "default": { + "EC2.InstanceId": "^{{instanceId}}$", + "PlatformType": "^AWS::EC2$", + "otel.resource.host.image.id": "^{{instanceAmi}}$", + "otel.resource.host.type": "^t3.large$", + "aws.span.kind": "^LOCAL_ROOT$" + } + }, + "subsegments": [ + { + "name": "^S3$", + "aws": { + "operation": "^GetBucketLocation$" + }, + "annotations": { + "aws.local.service": "^{{serviceName}}$", + "aws.local.operation": "^GET /aws-sdk-call$", + "aws.remote.service": "^AWS::S3$", + "aws.remote.operation": "^GetBucketLocation$", + "aws.local.environment": "^ec2:default$", + "aws.remote.resource.type": "AWS::S3::Bucket" + }, + "metadata": { + "default": { + "EC2.InstanceId": "^{{instanceId}}$", + "PlatformType": "^AWS::EC2$", + "aws.span.kind": "^CLIENT$" + } + }, + "namespace": "^aws$" + } + ] +}, +{ + "name": "^S3$", + "aws": { + "operation": "^GetBucketLocation$" + } +}] \ No newline at end of file diff --git a/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/client-call-log.mustache b/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/client-call-log.mustache new file mode 100644 index 000000000..85036f4da --- /dev/null +++ b/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/client-call-log.mustache @@ -0,0 +1,20 @@ +[{ + "EC2.InstanceId": "^{{instanceId}}$", + "Environment": "^ec2:default$", + "PlatformType": "^AWS::EC2$", + "Operation": "InternalOperation", + "Version": "^1$", + "Telemetry.Source": "^LocalRootSpan$", + "Host": "^ip(-[0-9]{1,3}){4}.*$" +}, +{ + "EC2.InstanceId": "^{{instanceId}}$", + "Environment": "^ec2:default$", + "PlatformType": "^AWS::EC2$", + "Operation": "InternalOperation", + "Version": "^1$", + "RemoteService": "local-root-client-call:80", + "RemoteOperation": "GET /", + "Telemetry.Source": "^ClientSpan$", + "Host": "^ip(-[0-9]{1,3}){4}.*$" +}] \ No newline at end of file diff --git a/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/client-call-metric.mustache b/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/client-call-metric.mustache new file mode 100644 index 000000000..85ed2565c --- /dev/null +++ b/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/client-call-metric.mustache @@ -0,0 +1,227 @@ +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Operation + value: InternalOperation + - + name: Environment + value: ec2:default + +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Operation + value: InternalOperation + - + name: Environment + value: ec2:default + - + name: RemoteService + value: local-root-client-call:80 + - + name: RemoteOperation + value: GET / + +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteService + value: local-root-client-call:80 + - + name: RemoteOperation + value: GET / + +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteService + value: local-root-client-call:80 + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Operation + value: InternalOperation + - + name: Environment + value: ec2:default + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Operation + value: InternalOperation + - + name: Environment + value: ec2:default + - + name: RemoteService + value: local-root-client-call:80 + - + name: RemoteOperation + value: GET / + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteService + value: local-root-client-call:80 + - + name: RemoteOperation + value: GET / + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteService + value: local-root-client-call:80 + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Operation + value: InternalOperation + - + name: Environment + value: ec2:default + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Operation + value: InternalOperation + - + name: Environment + value: ec2:default + - + name: RemoteService + value: local-root-client-call:80 + - + name: RemoteOperation + value: GET / + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteService + value: local-root-client-call:80 + - + name: RemoteOperation + value: GET / + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteService + value: local-root-client-call:80 \ No newline at end of file diff --git a/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/client-call-trace.mustache b/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/client-call-trace.mustache new file mode 100644 index 000000000..9ab62e784 --- /dev/null +++ b/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/client-call-trace.mustache @@ -0,0 +1,56 @@ +[{ + "name": "^{{serviceName}}$", + "annotations": { + "aws.local.service": "^{{serviceName}}$", + "aws.local.operation": "^InternalOperation$", + "aws.local.environment": "^ec2:default$" + }, + "metadata": { + "default": { + "otel.resource.host.image.id": "^{{instanceAmi}}$", + "otel.resource.host.type": "^t3.large$" + } + }, + "subsegments": [ + { + "name": "^local-root-client-call:80$", + "http": { + "request": { + "url": "^http://local-root-client-call/$", + "method": "^GET$" + } + }, + "annotations": { + "aws.local.service": "^{{serviceName}}$", + "aws.local.operation": "^InternalOperation$", + "aws.remote.service": "^local-root-client-call:80$", + "aws.remote.operation": "GET /", + "aws.local.environment": "^ec2:default$" + }, + "metadata": { + "default": { + "EC2.InstanceId": "^{{instanceId}}$", + "PlatformType": "^AWS::EC2$", + "aws.span.kind": "^LOCAL_ROOT$" + } + }, + "namespace": "^remote$" + } + ] +}, +{ + "name": "^local-root-client-call:80$", + "http": { + "request": { + "url": "^http://local-root-client-call/$", + "method": "^GET$" + }, + "response": { + "content_length": 0 + } + }, + "annotations": { + "aws.local.service": "^local-root-client-call:80$", + "aws.local.operation": "^GET /$" + } +}] \ No newline at end of file diff --git a/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/outgoing-http-call-log.mustache b/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/outgoing-http-call-log.mustache new file mode 100644 index 000000000..848e84902 --- /dev/null +++ b/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/outgoing-http-call-log.mustache @@ -0,0 +1,20 @@ +[{ + "EC2.InstanceId": "^{{instanceId}}$", + "Environment": "^ec2:default$", + "PlatformType": "^AWS::EC2$", + "Operation": "GET /outgoing-http-call", + "Version": "^1$", + "Telemetry.Source": "^LocalRootSpan$", + "Host": "^ip(-[0-9]{1,3}){4}.*$" +}, +{ + "EC2.InstanceId": "^{{instanceId}}$", + "Environment": "^ec2:default$", + "PlatformType": "^AWS::EC2$", + "Operation": "GET /outgoing-http-call", + "Version": "^1$", + "RemoteService": "aws.amazon.com:443", + "RemoteOperation": "GET /", + "Telemetry.Source": "^ClientSpan$", + "Host": "^ip(-[0-9]{1,3}){4}.*$" +}] \ No newline at end of file diff --git a/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/outgoing-http-call-metric.mustache b/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/outgoing-http-call-metric.mustache new file mode 100644 index 000000000..748e05178 --- /dev/null +++ b/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/outgoing-http-call-metric.mustache @@ -0,0 +1,227 @@ +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: GET /outgoing-http-call + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: GET /outgoing-http-call + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteOperation + value: GET / + - + name: RemoteService + value: aws.amazon.com:443 + +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteOperation + value: GET / + - + name: RemoteService + value: aws.amazon.com:443 + +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteService + value: aws.amazon.com:443 + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: GET /outgoing-http-call + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: GET /outgoing-http-call + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteOperation + value: GET / + - + name: RemoteService + value: aws.amazon.com:443 + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteOperation + value: GET / + - + name: RemoteService + value: aws.amazon.com:443 + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteService + value: aws.amazon.com:443 + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: GET /outgoing-http-call + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: GET /outgoing-http-call + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteOperation + value: GET / + - + name: RemoteService + value: aws.amazon.com:443 + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteOperation + value: GET / + - + name: RemoteService + value: aws.amazon.com:443 + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteService + value: aws.amazon.com:443 diff --git a/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/outgoing-http-call-trace.mustache b/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/outgoing-http-call-trace.mustache new file mode 100644 index 000000000..44a9c334b --- /dev/null +++ b/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/outgoing-http-call-trace.mustache @@ -0,0 +1,55 @@ +[{ + "name": "^{{serviceName}}$", + "http": { + "request": { + "url": "^{{endpoint}}/outgoing-http-call$", + "method": "^GET$" + } + }, + "aws": { + "account_id": "^{{accountId}}$" + }, + "annotations": { + "aws.local.service": "^{{serviceName}}$", + "aws.local.operation": "^GET /outgoing-http-call$", + "aws.local.environment": "^ec2:default$" + }, + "metadata": { + "default": { + "EC2.InstanceId": "^{{instanceId}}$", + "PlatformType": "^AWS::EC2$", + "otel.resource.host.image.id": "^{{instanceAmi}}$", + "otel.resource.host.type": "^t3.large$", + "aws.span.kind": "^LOCAL_ROOT$" + } + }, + "subsegments": [ + { + "name": "^aws.amazon.com:443$", + "http": { + "request": { + "url": "^https://aws.amazon.com/$", + "method": "^GET$" + } + }, + "annotations": { + "aws.local.service": "^{{serviceName}}$", + "aws.local.operation": "^GET /outgoing-http-call$", + "aws.remote.service": "^aws.amazon.com:443$", + "aws.remote.operation": "^GET /$", + "aws.local.environment": "^ec2:default$" + }, + "metadata": { + "default": { + "EC2.InstanceId": "^{{instanceId}}$", + "PlatformType": "^AWS::EC2$", + "aws.span.kind": "^CLIENT$" + } + }, + "namespace": "^remote$" + } + ] +}, +{ + "name": "^aws.amazon.com:443$" +}] diff --git a/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/remote-service-log.mustache b/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/remote-service-log.mustache new file mode 100644 index 000000000..cd457dc7b --- /dev/null +++ b/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/remote-service-log.mustache @@ -0,0 +1,20 @@ +[{ + "EC2.InstanceId": "^{{instanceId}}$", + "Environment": "^ec2:default$", + "PlatformType": "^AWS::EC2$", + "Operation": "GET /remote-service", + "Version": "^1$", + "Telemetry.Source": "^LocalRootSpan$", + "Host": "^ip(-[0-9]{1,3}){4}.*$" +}, +{ + "EC2.InstanceId": "^{{instanceId}}$", + "Environment": "^ec2:default$", + "PlatformType": "^AWS::EC2$", + "Operation": "GET /remote-service", + "Version": "^1$", + "RemoteService": "{{remoteServiceDeploymentName}}", + "RemoteOperation": "GET /healthcheck", + "Telemetry.Source": "^ClientSpan$", + "Host": "^ip(-[0-9]{1,3}){4}.*$" +}] \ No newline at end of file diff --git a/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/remote-service-metric.mustache b/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/remote-service-metric.mustache new file mode 100644 index 000000000..bb5445d2f --- /dev/null +++ b/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/remote-service-metric.mustache @@ -0,0 +1,312 @@ +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: GET /remote-service + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: GET /remote-service + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteOperation + value: GET /healthcheck + - + name: RemoteService + value: {{remoteServiceDeploymentName}} + +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{remoteServiceName}} + - + name: Environment + value: ec2:default + +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteService + value: {{remoteServiceDeploymentName}} + +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteOperation + value: GET /healthcheck + - + name: RemoteService + value: {{remoteServiceDeploymentName}} + +- + metricName: Latency + namespace: {{metricNamespace}} + dimensions: + - + name: RemoteService + value: {{remoteServiceDeploymentName}} + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: GET /remote-service + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: GET /remote-service + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteOperation + value: GET /healthcheck + - + name: RemoteService + value: {{remoteServiceDeploymentName}} + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Environment + value: ec2:default + - + name: Operation + value: GET /healthcheck + - + name: Service + value: {{remoteServiceName}} + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{remoteServiceName}} + - + name: Environment + value: ec2:default + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteService + value: {{remoteServiceDeploymentName}} + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteOperation + value: GET /healthcheck + - + name: RemoteService + value: {{remoteServiceDeploymentName}} + +- + metricName: Error + namespace: {{metricNamespace}} + dimensions: + - + name: RemoteService + value: {{remoteServiceDeploymentName}} + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: GET /remote-service + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Operation + value: GET /remote-service + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteOperation + value: GET /healthcheck + - + name: RemoteService + value: {{remoteServiceDeploymentName}} + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Environment + value: ec2:default + - + name: Operation + value: GET /healthcheck + - + name: Service + value: {{remoteServiceName}} + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{remoteServiceName}} + - + name: Environment + value: ec2:default + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteService + value: {{remoteServiceDeploymentName}} + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: Service + value: {{serviceName}} + - + name: Environment + value: ec2:default + - + name: RemoteOperation + value: GET /healthcheck + - + name: RemoteService + value: {{remoteServiceDeploymentName}} + +- + metricName: Fault + namespace: {{metricNamespace}} + dimensions: + - + name: RemoteService + value: {{remoteServiceDeploymentName}} diff --git a/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/remote-service-trace.mustache b/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/remote-service-trace.mustache new file mode 100644 index 000000000..bd5d2404f --- /dev/null +++ b/validator/src/main/resources/expected-data-template/dotnet/ec2/windows/remote-service-trace.mustache @@ -0,0 +1,77 @@ +[{ + "name": "^{{serviceName}}$", + "http": { + "request": { + "url": "^{{endpoint}}/remote-service$", + "method": "^GET$" + } + }, + "aws": { + "account_id": "^{{accountId}}$" + }, + "annotations": { + "aws.local.service": "^{{serviceName}}$", + "aws.local.operation": "^GET /remote-service$", + "aws.local.environment": "^ec2:default$" + }, + "metadata": { + "default": { + "EC2.InstanceId": "^{{instanceId}}$", + "PlatformType": "^AWS::EC2$", + "otel.resource.host.image.id": "^{{instanceAmi}}$", + "otel.resource.host.type": "^t3.large$", + "aws.span.kind": "^LOCAL_ROOT$" + } + }, + "subsegments": [ + { + "name": "^{{remoteServiceDeploymentName}}$", + "http": { + "request": { + "url": "^http://(([0-9]{1,3}.){3}[0-9]{1,3}):8081/healthcheck$", + "method": "^GET$" + } + }, + "annotations": { + "aws.local.service": "^{{serviceName}}$", + "aws.local.operation": "^GET /remote-service$", + "aws.remote.service": "^{{remoteServiceDeploymentName}}$", + "aws.remote.operation": "^GET /healthcheck$", + "aws.local.environment": "^ec2:default$" + }, + "metadata": { + "default": { + "EC2.InstanceId": "^{{instanceId}}$", + "PlatformType": "^AWS::EC2$", + "aws.span.kind": "^CLIENT$" + } + }, + "namespace": "^remote$" + } + ] +}, +{ + "name": "^{{remoteServiceName}}$", + "http": { + "request": { + "url": "^http://(([0-9]{1,3}.){3}[0-9]{1,3}):8081/healthcheck$", + "method": "^GET$" + } + }, + "annotations": { + "aws.local.service": "^{{remoteServiceName}}$", + "aws.local.operation": "^GET /healthcheck$", + "aws.local.environment": "^ec2:default$" + }, + "metadata": { + "default": { + "EC2.InstanceId": "^i-[A-Za-z0-9]{17}$", + "PlatformType": "^AWS::EC2$", + "otel.resource.host.image.id": "^{{instanceAmi}}$", + "otel.resource.host.type": "^t3.large$", + "aws.span.kind": "^LOCAL_ROOT$" + } + } +}] + + diff --git a/validator/src/main/resources/expected-data-template/dotnet/k8s/aws-sdk-call-log.mustache b/validator/src/main/resources/expected-data-template/dotnet/k8s/aws-sdk-call-log.mustache index 3870db763..72a85e6d1 100644 --- a/validator/src/main/resources/expected-data-template/dotnet/k8s/aws-sdk-call-log.mustache +++ b/validator/src/main/resources/expected-data-template/dotnet/k8s/aws-sdk-call-log.mustache @@ -7,7 +7,7 @@ "K8s.Workload": "^dotnet-sample-app-deployment-{{testingId}}$", "PlatformType": "^K8s$", "Service": "^{{serviceName}}$", - "Operation": "GET aws-sdk-call", + "Operation": "GET /aws-sdk-call", "Version": "^1$", "Telemetry.Source": "^LocalRootSpan$", "Host": "^ip(-[0-9]{1,3}){4}.*$" diff --git a/validator/src/main/resources/expected-data-template/dotnet/k8s/aws-sdk-call-metric.mustache b/validator/src/main/resources/expected-data-template/dotnet/k8s/aws-sdk-call-metric.mustache index be2ace17c..0648873c8 100644 --- a/validator/src/main/resources/expected-data-template/dotnet/k8s/aws-sdk-call-metric.mustache +++ b/validator/src/main/resources/expected-data-template/dotnet/k8s/aws-sdk-call-metric.mustache @@ -4,7 +4,7 @@ dimensions: - name: Operation - value: GET aws-sdk-call + value: GET /aws-sdk-call - name: Service value: {{serviceName}} @@ -129,7 +129,7 @@ dimensions: - name: Operation - value: GET aws-sdk-call + value: GET /aws-sdk-call - name: Service value: {{serviceName}} @@ -255,7 +255,7 @@ dimensions: - name: Operation - value: GET aws-sdk-call + value: GET /aws-sdk-call - name: Service value: {{serviceName}} diff --git a/validator/src/main/resources/expected-data-template/dotnet/k8s/aws-sdk-call-trace.mustache b/validator/src/main/resources/expected-data-template/dotnet/k8s/aws-sdk-call-trace.mustache index 4c17aefc4..374460077 100644 --- a/validator/src/main/resources/expected-data-template/dotnet/k8s/aws-sdk-call-trace.mustache +++ b/validator/src/main/resources/expected-data-template/dotnet/k8s/aws-sdk-call-trace.mustache @@ -11,7 +11,7 @@ }, "annotations": { "aws.local.service": "^{{serviceName}}$", - "aws.local.operation": "^GET aws-sdk-call$", + "aws.local.operation": "^GET /aws-sdk-call$", "aws.local.environment": "^k8s:{{platformInfo}}/{{appNamespace}}$" }, "metadata": { diff --git a/validator/src/main/resources/expected-data-template/dotnet/k8s/client-call-metric.mustache b/validator/src/main/resources/expected-data-template/dotnet/k8s/client-call-metric.mustache index 74b35db3a..e49a78825 100644 --- a/validator/src/main/resources/expected-data-template/dotnet/k8s/client-call-metric.mustache +++ b/validator/src/main/resources/expected-data-template/dotnet/k8s/client-call-metric.mustache @@ -7,7 +7,7 @@ value: {{serviceName}} - name: Operation - value: GET client-call + value: GET /client-call - name: Environment value: k8s:{{platformInfo}}/{{appNamespace}} @@ -97,7 +97,7 @@ value: {{serviceName}} - name: Operation - value: GET client-call + value: GET /client-call - name: Environment value: k8s:{{platformInfo}}/{{appNamespace}} @@ -187,7 +187,7 @@ value: {{serviceName}} - name: Operation - value: GET client-call + value: GET /client-call - name: Environment value: k8s:{{platformInfo}}/{{appNamespace}} diff --git a/validator/src/main/resources/expected-data-template/dotnet/k8s/outgoing-http-call-log.mustache b/validator/src/main/resources/expected-data-template/dotnet/k8s/outgoing-http-call-log.mustache index 96cf074d2..a37a63490 100644 --- a/validator/src/main/resources/expected-data-template/dotnet/k8s/outgoing-http-call-log.mustache +++ b/validator/src/main/resources/expected-data-template/dotnet/k8s/outgoing-http-call-log.mustache @@ -7,7 +7,7 @@ "K8s.Workload": "^dotnet-sample-app-deployment-{{testingId}}$", "PlatformType": "^K8s$", "Service": "^{{serviceName}}$", - "Operation": "GET outgoing-http-call", + "Operation": "GET /outgoing-http-call", "Version": "^1$", "Telemetry.Source": "^LocalRootSpan$", "Host": "^ip(-[0-9]{1,3}){4}.*$" diff --git a/validator/src/main/resources/expected-data-template/dotnet/k8s/outgoing-http-call-metric.mustache b/validator/src/main/resources/expected-data-template/dotnet/k8s/outgoing-http-call-metric.mustache index 83b87f1c1..102f2727e 100644 --- a/validator/src/main/resources/expected-data-template/dotnet/k8s/outgoing-http-call-metric.mustache +++ b/validator/src/main/resources/expected-data-template/dotnet/k8s/outgoing-http-call-metric.mustache @@ -4,7 +4,7 @@ dimensions: - name: Operation - value: GET outgoing-http-call + value: GET /outgoing-http-call - name: Service value: {{serviceName}} @@ -80,7 +80,7 @@ dimensions: - name: Operation - value: GET outgoing-http-call + value: GET /outgoing-http-call - name: Service value: {{serviceName}} @@ -156,7 +156,7 @@ dimensions: - name: Operation - value: GET outgoing-http-call + value: GET /outgoing-http-call - name: Service value: {{serviceName}} diff --git a/validator/src/main/resources/expected-data-template/dotnet/k8s/outgoing-http-call-trace.mustache b/validator/src/main/resources/expected-data-template/dotnet/k8s/outgoing-http-call-trace.mustache index 8dfb15916..22f4494b4 100644 --- a/validator/src/main/resources/expected-data-template/dotnet/k8s/outgoing-http-call-trace.mustache +++ b/validator/src/main/resources/expected-data-template/dotnet/k8s/outgoing-http-call-trace.mustache @@ -11,7 +11,7 @@ }, "annotations": { "aws.local.service": "^{{serviceName}}$", - "aws.local.operation": "^GET outgoing-http-call$", + "aws.local.operation": "^GET /outgoing-http-call$", "aws.local.environment": "^k8s:{{platformInfo}}/{{appNamespace}}$" }, "metadata": { diff --git a/validator/src/main/resources/expected-data-template/dotnet/k8s/remote-service-log.mustache b/validator/src/main/resources/expected-data-template/dotnet/k8s/remote-service-log.mustache index 6331b0480..ab1cbd19b 100644 --- a/validator/src/main/resources/expected-data-template/dotnet/k8s/remote-service-log.mustache +++ b/validator/src/main/resources/expected-data-template/dotnet/k8s/remote-service-log.mustache @@ -7,7 +7,7 @@ "K8s.Workload": "^dotnet-sample-app-deployment-{{testingId}}$", "PlatformType": "^K8s$", "Service": "^{{serviceName}}$", - "Operation": "GET remote-service", + "Operation": "GET /remote-service", "Version": "^1$", "Telemetry.Source": "^LocalRootSpan$", "Host": "^ip(-[0-9]{1,3}){4}.*$" diff --git a/validator/src/main/resources/expected-data-template/dotnet/k8s/remote-service-metric.mustache b/validator/src/main/resources/expected-data-template/dotnet/k8s/remote-service-metric.mustache index b26243617..d74ea2273 100644 --- a/validator/src/main/resources/expected-data-template/dotnet/k8s/remote-service-metric.mustache +++ b/validator/src/main/resources/expected-data-template/dotnet/k8s/remote-service-metric.mustache @@ -4,7 +4,7 @@ dimensions: - name: Operation - value: GET remote-service + value: GET /remote-service - name: Service value: {{serviceName}} @@ -41,7 +41,7 @@ value: k8s:{{platformInfo}}/{{appNamespace}} - name: Operation - value: GET healthcheck + value: GET /healthcheck - name: Service value: {{remoteServiceDeploymentName}} @@ -173,7 +173,7 @@ dimensions: - name: Operation - value: GET remote-service + value: GET /remote-service - name: Service value: {{serviceName}} @@ -210,7 +210,7 @@ value: k8s:{{platformInfo}}/{{appNamespace}} - name: Operation - value: GET healthcheck + value: GET /healthcheck - name: Service value: {{remoteServiceDeploymentName}} @@ -342,7 +342,7 @@ dimensions: - name: Operation - value: GET remote-service + value: GET /remote-service - name: Service value: {{serviceName}} @@ -379,7 +379,7 @@ value: k8s:{{platformInfo}}/{{appNamespace}} - name: Operation - value: GET healthcheck + value: GET /healthcheck - name: Service value: {{remoteServiceDeploymentName}} diff --git a/validator/src/main/resources/expected-data-template/dotnet/k8s/remote-service-trace.mustache b/validator/src/main/resources/expected-data-template/dotnet/k8s/remote-service-trace.mustache index add3ad454..000fa41db 100644 --- a/validator/src/main/resources/expected-data-template/dotnet/k8s/remote-service-trace.mustache +++ b/validator/src/main/resources/expected-data-template/dotnet/k8s/remote-service-trace.mustache @@ -11,7 +11,7 @@ }, "annotations": { "aws.local.service": "^{{serviceName}}$", - "aws.local.operation": "^GET remote-service$", + "aws.local.operation": "^GET /remote-service$", "aws.local.environment": "^k8s:{{platformInfo}}/{{appNamespace}}$" }, "metadata": { @@ -63,7 +63,7 @@ }, "annotations": { "aws.local.service": "^{{remoteServiceDeploymentName}}$", - "aws.local.operation": "^GET healthcheck$", + "aws.local.operation": "^GET /healthcheck$", "aws.local.environment": "^k8s:{{platformInfo}}/{{appNamespace}}$" }, "metadata": { diff --git a/validator/src/main/resources/expected-data-template/java/ecs/hc-trace.mustache b/validator/src/main/resources/expected-data-template/java/ecs/hc-trace.mustache index c41e9fd61..229561f4a 100644 --- a/validator/src/main/resources/expected-data-template/java/ecs/hc-trace.mustache +++ b/validator/src/main/resources/expected-data-template/java/ecs/hc-trace.mustache @@ -5,9 +5,6 @@ "request": { "url": "^http://localhost:8080/$", "method": "^GET$" - }, - "response": { - "status": "^200$" } }, "aws": { diff --git a/validator/src/main/resources/expected-data-template/python/ecs/hc-trace.mustache b/validator/src/main/resources/expected-data-template/python/ecs/hc-trace.mustache index c41e9fd61..229561f4a 100644 --- a/validator/src/main/resources/expected-data-template/python/ecs/hc-trace.mustache +++ b/validator/src/main/resources/expected-data-template/python/ecs/hc-trace.mustache @@ -5,9 +5,6 @@ "request": { "url": "^http://localhost:8080/$", "method": "^GET$" - }, - "response": { - "status": "^200$" } }, "aws": { diff --git a/validator/src/main/resources/validations/dotnet/ec2/windows/log-validation.yml b/validator/src/main/resources/validations/dotnet/ec2/windows/log-validation.yml new file mode 100644 index 000000000..3c91dc73c --- /dev/null +++ b/validator/src/main/resources/validations/dotnet/ec2/windows/log-validation.yml @@ -0,0 +1,25 @@ +- + validationType: "cw-log" + httpPath: "/outgoing-http-call" + httpMethod: "get" + callingType: "http" + expectedLogStructureTemplate: "DOTNET_EC2_WINDOWS_DEFAULT_OUTGOING_HTTP_CALL_LOG" +- + validationType: "cw-log" + httpPath: "/aws-sdk-call" + httpMethod: "get" + callingType: "http-with-query" + expectedLogStructureTemplate: "DOTNET_EC2_WINDOWS_DEFAULT_AWS_SDK_CALL_LOG" +- + validationType: "cw-log" + httpPath: "/remote-service" + httpMethod: "get" + callingType: "http-with-query" + expectedLogStructureTemplate: "DOTNET_EC2_WINDOWS_DEFAULT_REMOTE_SERVICE_LOG" +- + validationType: "cw-log" + httpPath: "/client-call" + httpMethod: "get" + callingType: "http" + expectedLogStructureTemplate: "DOTNET_EC2_WINDOWS_DEFAULT_CLIENT_CALL_LOG" + diff --git a/validator/src/main/resources/validations/dotnet/ec2/windows/metric-validation.yml b/validator/src/main/resources/validations/dotnet/ec2/windows/metric-validation.yml new file mode 100644 index 000000000..6ee4c7e86 --- /dev/null +++ b/validator/src/main/resources/validations/dotnet/ec2/windows/metric-validation.yml @@ -0,0 +1,25 @@ +- + validationType: "cw-metric" + httpPath: "/outgoing-http-call" + httpMethod: "get" + callingType: "http" + expectedMetricTemplate: "DOTNET_EC2_WINDOWS_DEFAULT_OUTGOING_HTTP_CALL_METRIC" +- + validationType: "cw-metric" + httpPath: "/aws-sdk-call" + httpMethod: "get" + callingType: "http-with-query" + expectedMetricTemplate: "DOTNET_EC2_WINDOWS_DEFAULT_AWS_SDK_CALL_METRIC" +- + validationType: "cw-metric" + httpPath: "/remote-service" + httpMethod: "get" + callingType: "http-with-query" + expectedMetricTemplate: "DOTNET_EC2_WINDOWS_DEFAULT_REMOTE_SERVICE_METRIC" +- + validationType: "cw-metric" + httpPath: "/client-call" + httpMethod: "get" + callingType: "http" + expectedMetricTemplate: "DOTNET_EC2_WINDOWS_DEFAULT_CLIENT_CALL_METRIC" + diff --git a/validator/src/main/resources/validations/dotnet/ec2/windows/trace-validation.yml b/validator/src/main/resources/validations/dotnet/ec2/windows/trace-validation.yml new file mode 100644 index 000000000..f9b96e830 --- /dev/null +++ b/validator/src/main/resources/validations/dotnet/ec2/windows/trace-validation.yml @@ -0,0 +1,26 @@ +- + validationType: "trace" + httpPath: "/outgoing-http-call" + httpMethod: "get" + callingType: "http" + expectedTraceTemplate: "DOTNET_EC2_WINDOWS_DEFAULT_OUTGOING_HTTP_CALL_TRACE" +- + validationType: "trace" + httpPath: "/aws-sdk-call" + httpMethod: "get" + callingType: "http-with-query" + expectedTraceTemplate: "DOTNET_EC2_WINDOWS_DEFAULT_AWS_SDK_CALL_TRACE" + +# Because of a time sync issue, block the remote service trace check for now +#- +# validationType: "trace" +# httpPath: "/remote-service" +# httpMethod: "get" +# callingType: "http-with-query" +# expectedTraceTemplate: "DOTNET_EC2_WINDOWS_DEFAULT_REMOTE_SERVICE_TRACE" +- + validationType: "trace" + httpPath: "/client-call" + httpMethod: "get" + callingType: "http" + expectedTraceTemplate: "DOTNET_EC2_WINDOWS_DEFAULT_CLIENT_CALL_TRACE" \ No newline at end of file diff --git a/validator/src/main/resources/validations/dotnet/k8s/log-validation.yml b/validator/src/main/resources/validations/dotnet/k8s/log-validation.yml index 39b700be3..2d8b35261 100644 --- a/validator/src/main/resources/validations/dotnet/k8s/log-validation.yml +++ b/validator/src/main/resources/validations/dotnet/k8s/log-validation.yml @@ -1,24 +1,24 @@ - validationType: "cw-log" - httpPath: "outgoing-http-call" + httpPath: "/outgoing-http-call" httpMethod: "get" callingType: "http" expectedLogStructureTemplate: "DOTNET_K8S_OUTGOING_HTTP_CALL_LOG" - validationType: "cw-log" - httpPath: "aws-sdk-call" + httpPath: "/aws-sdk-call" httpMethod: "get" callingType: "http-with-query" expectedLogStructureTemplate: "DOTNET_K8S_AWS_SDK_CALL_LOG" - validationType: "cw-log" - httpPath: "remote-service" + httpPath: "/remote-service" httpMethod: "get" callingType: "http-with-query" expectedLogStructureTemplate: "DOTNET_K8S_REMOTE_SERVICE_LOG" - validationType: "cw-log" - httpPath: "client-call" + httpPath: "/client-call" httpMethod: "get" callingType: "http" expectedLogStructureTemplate: "DOTNET_K8S_CLIENT_CALL_LOG" \ No newline at end of file diff --git a/validator/src/main/resources/validations/dotnet/k8s/metric-validation.yml b/validator/src/main/resources/validations/dotnet/k8s/metric-validation.yml index 2acc34b15..5c1cd06f5 100644 --- a/validator/src/main/resources/validations/dotnet/k8s/metric-validation.yml +++ b/validator/src/main/resources/validations/dotnet/k8s/metric-validation.yml @@ -1,24 +1,24 @@ - validationType: "cw-metric" - httpPath: "outgoing-http-call" + httpPath: "/outgoing-http-call" httpMethod: "get" callingType: "http" expectedMetricTemplate: "DOTNET_K8S_OUTGOING_HTTP_CALL_METRIC" - validationType: "cw-metric" - httpPath: "aws-sdk-call" + httpPath: "/aws-sdk-call" httpMethod: "get" callingType: "http-with-query" expectedMetricTemplate: "DOTNET_K8S_AWS_SDK_CALL_METRIC" - validationType: "cw-metric" - httpPath: "remote-service" + httpPath: "/remote-service" httpMethod: "get" callingType: "http-with-query" expectedMetricTemplate: "DOTNET_K8S_REMOTE_SERVICE_METRIC" - validationType: "cw-metric" - httpPath: "client-call" + httpPath: "/client-call" httpMethod: "get" callingType: "http" expectedMetricTemplate: "DOTNET_K8S_CLIENT_CALL_METRIC" \ No newline at end of file diff --git a/validator/src/main/resources/validations/dotnet/k8s/trace-validation.yml b/validator/src/main/resources/validations/dotnet/k8s/trace-validation.yml index 53a6b39bb..705686df8 100644 --- a/validator/src/main/resources/validations/dotnet/k8s/trace-validation.yml +++ b/validator/src/main/resources/validations/dotnet/k8s/trace-validation.yml @@ -1,24 +1,24 @@ - validationType: "trace" - httpPath: "outgoing-http-call" + httpPath: "/outgoing-http-call" httpMethod: "get" callingType: "http" expectedTraceTemplate: "DOTNET_K8S_OUTGOING_HTTP_CALL_TRACE" - validationType: "trace" - httpPath: "aws-sdk-call" + httpPath: "/aws-sdk-call" httpMethod: "get" callingType: "http-with-query" expectedTraceTemplate: "DOTNET_K8S_AWS_SDK_CALL_TRACE" - validationType: "trace" - httpPath: "remote-service" + httpPath: "/remote-service" httpMethod: "get" callingType: "http-with-query" expectedTraceTemplate: "DOTNET_K8S_REMOTE_SERVICE_TRACE" - validationType: "trace" - httpPath: "client-call" + httpPath: "/client-call" httpMethod: "get" callingType: "http" expectedTraceTemplate: "DOTNET_K8S_CLIENT_CALL_TRACE" \ No newline at end of file