From 32bf6003cf575a35bdea1ded2344778b8a33827d Mon Sep 17 00:00:00 2001 From: Vherremi Date: Thu, 30 Oct 2025 10:44:59 -0700 Subject: [PATCH 01/11] Testing Node custom metrics --- .github/workflows/node-ec2-default-test.yml | 20 +- .github/workflows/test.yml | 23 ++ sample-apps/node/frontend-service/index.js | 54 ++++- .../node/frontend-service/package.json | 13 +- .../ec2/default/amazon-cloudwatch-agent.json | 6 +- terraform/node/ec2/default/main.tf | 15 +- .../PredefinedExpectedTemplate.java | 3 + .../default/aws-otel-custom-metrics.mustache | 228 ++++++++++++++++++ .../ec2/default/custom-metric-validation.yml | 6 + 9 files changed, 355 insertions(+), 13 deletions(-) create mode 100644 .github/workflows/test.yml create mode 100644 validator/src/main/resources/expected-data-template/node/ec2/default/aws-otel-custom-metrics.mustache create mode 100644 validator/src/main/resources/validations/node/ec2/default/custom-metric-validation.yml diff --git a/.github/workflows/node-ec2-default-test.yml b/.github/workflows/node-ec2-default-test.yml index 0e9199f0c..6048acf32 100644 --- a/.github/workflows/node-ec2-default-test.yml +++ b/.github/workflows/node-ec2-default-test.yml @@ -45,7 +45,7 @@ env: NODE_VERSION: ${{ inputs.node-version }} CPU_ARCHITECTURE: ${{ inputs.cpu-architecture }} ADOT_INSTRUMENTATION_NAME: ${{ inputs.staging-instrumentation-name }} - SAMPLE_APP_ZIP: s3://aws-appsignals-sample-app-prod-${{ inputs.aws-region }}/node-sample-app.zip + SAMPLE_APP_ZIP: s3://aws-appsignals-sample-app-prod-${{ inputs.aws-region }}/node-sample-app-delete-me.zip E2E_TEST_ACCOUNT_ID: ${{ secrets.APPLICATION_SIGNALS_E2E_TEST_ACCOUNT_ID }} E2E_TEST_ROLE_NAME: ${{ secrets.APPLICATION_SIGNALS_E2E_TEST_ROLE_NAME }} METRIC_NAMESPACE: ApplicationSignals @@ -244,6 +244,24 @@ jobs: --instance-id ${{ env.MAIN_SERVICE_INSTANCE_ID }} --rollup' + - name: Validate custom metrics + id: CWagent metric-validation + if: (success() || steps.log-validation.outcome == 'failure') && !cancelled() + run: ./gradlew validator:run --args='-c node/ec2/default/metric-validation.yml + --testing-id ${{ env.TESTING_ID }} + --endpoint http://${{ env.MAIN_SERVICE_ENDPOINT }} + --remote-service-deployment-name ${{ env.REMOTE_SERVICE_IP }}:8001 + --region ${{ inputs.aws-region }} + --account-id ${{ env.ACCOUNT_ID }} + --metric-namespace CWAgent + --log-group ${{ env.LOG_GROUP_NAME }} + --service-name node-sample-application-${{ env.TESTING_ID }} + --remote-service-name node-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() diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 000000000..599a069e9 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,23 @@ +## 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: Test +on: + push: + branches: + - Node_Custom_metrics + +permissions: + id-token: write + contents: read + +jobs: + python-ec2-default: + uses: ./.github/workflows/node-ec2-default-test.yml + secrets: inherit + with: + caller-workflow-name: 'test' + aws-region: 'us-east-1' \ No newline at end of file diff --git a/sample-apps/node/frontend-service/index.js b/sample-apps/node/frontend-service/index.js index 6b16dae9b..1c5698304 100644 --- a/sample-apps/node/frontend-service/index.js +++ b/sample-apps/node/frontend-service/index.js @@ -5,6 +5,12 @@ const express = require('express'); const mysql = require('mysql2'); const bunyan = require('bunyan'); const { S3Client, GetBucketLocationCommand } = require('@aws-sdk/client-s3'); +const opentelemetry = require('@opentelemetry/sdk-node'); +const { MeterProvider, PeriodicExportingMetricReader, ConsoleMetricExporter } = require('@opentelemetry/sdk-metrics'); +const { OTLPMetricExporter } = require('@opentelemetry/exporter-metrics-otlp-proto'); +const { metrics } = require('@opentelemetry/api'); +const { Resource } = require('@opentelemetry/resources'); +const { randomInt } = require('crypto'); const PORT = parseInt(process.env.SAMPLE_APP_PORT || '8000', 10); @@ -13,6 +19,42 @@ const app = express(); // Create bunyan logger const logger = bunyan.createLogger({name: 'express-app', level: 'info'}); +// Custom export pipeline - runs alongside existing CWAgent & ADOT setup +const pipelineResource = new Resource({ + 'service.name': `node-sample-application-${process.env.TESTING_ID}`, + 'deployment.environment.name': 'ec2:default', + 'Telemetry.Source': 'CustomMetric' +}); + +const pipelineMetricExporter = new OTLPMetricExporter({ + url: 'http://localhost:4318/v1/metrics' +}); + +const pipelineMetricReader = new PeriodicExportingMetricReader({ + exporter: pipelineMetricExporter, + exportIntervalMillis: 5000 +}); + +const pipelineMeterProvider = new MeterProvider({ + resource: pipelineResource, + readers: [pipelineMetricReader] +}); + +const pipelineMeter = pipelineMeterProvider.getMeter('myMeter'); + +const meter = metrics.getMeter('myMeter'); +const agent_based_counter = meter.createCounter('agent_based_counter', {description: 'agent export counter'}); +const agent_based_histogram = meter.createHistogram('agent_based_histogram', {description: 'agent export histogram'}); +const agent_based_gauge = meter.createUpDownCounter('agent_based_gauge', {description: 'agent export gauge'}); + +const custom_pipeline_counter = pipelineMeter.createCounter('custom_pipeline_counter', {unit: '1', description: 'pipeline export counter'}); +const custom_pipeline_histogram = pipelineMeter.createHistogram('custom_pipeline_histogram', {description: 'pipeline export histogram'}); +const custom_pipeline_gauge = pipelineMeter.createUpDownCounter('custom_pipeline_gauge', {unit: '1', description: 'pipeline export gauge'}); + +app.get('/', (req, res) => { + res.send('Node.js Application Started! Available endpoints: /healthcheck, /aws-sdk-call, /outgoing-http-call, /remote-service, /client-call, /mysql'); +}); + app.get('/healthcheck', (req, res) => { logger.info('/healthcheck called successfully'); res.send('healthcheck'); @@ -44,9 +86,15 @@ app.get('/aws-sdk-call', async (req, res) => { const s3Client = new S3Client({ region: 'us-east-1' }); const bucketName = 'e2e-test-bucket-name-' + (req.query.testingId || 'MISSING_ID'); - // Add custom warning log for validation testing - const warningMsg = "This is a custom log for validation testing"; - logger.warn(warningMsg); + // Increment counter/histogram/gauge for agent export + agent_based_counter.add(1, { Operation : 'counter' }); + agent_based_histogram.record(randomInt(100,1001), { Operation : 'histogram' }); + agent_based_gauge.add(randomInt(-10, 11), { Operation : 'gauge' }); + + // Increment counter/histogram/gauge for pipeline export + custom_pipeline_counter.add(1, { Operation : 'pipeline_counter' }); + custom_pipeline_histogram.record(randomInt(100,1001), { Operation : 'pipeline_histogram' }); + custom_pipeline_gauge.add(randomInt(-10, 11), { Operation : 'pipeline_gauge' }); try { await s3Client.send( diff --git a/sample-apps/node/frontend-service/package.json b/sample-apps/node/frontend-service/package.json index cc785a202..90a2e266a 100644 --- a/sample-apps/node/frontend-service/package.json +++ b/sample-apps/node/frontend-service/package.json @@ -10,11 +10,18 @@ "author": "", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/client-s3": "3.621.0", + "@aws-sdk/client-s3": "^3.621.0", + "@aws/aws-distro-opentelemetry-node-autoinstrumentation": "^0.8.0", + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/exporter-metrics-otlp-proto": "^0.57.1", + "@opentelemetry/resources": "^1.30.1", + "@opentelemetry/sdk-metrics": "^1.30.1", + "@opentelemetry/semantic-conventions": "^1.37.0", + "@opentelemetry/sdk-node": ".207.0", "@types/express": "^4.17.21", "@types/node": "^20.14.6", + "bunyan": "^1.8.15", "express": "^4.21.2", - "mysql2": "^3.11.0", - "bunyan": "^1.8.15" + "mysql2": "^3.15.3" } } diff --git a/terraform/node/ec2/default/amazon-cloudwatch-agent.json b/terraform/node/ec2/default/amazon-cloudwatch-agent.json index a98a40d36..f65bfe32e 100644 --- a/terraform/node/ec2/default/amazon-cloudwatch-agent.json +++ b/terraform/node/ec2/default/amazon-cloudwatch-agent.json @@ -10,7 +10,11 @@ }, "logs": { "metrics_collected": { - "application_signals": {} + "application_signals": {}, + "otlp": { + "grpc_endpoint": "0.0.0.0:4317", + "http_endpoint": "0.0.0.0:4318" + } } } } \ No newline at end of file diff --git a/terraform/node/ec2/default/main.tf b/terraform/node/ec2/default/main.tf index 5b8c8745c..aa0b5e4eb 100644 --- a/terraform/node/ec2/default/main.tf +++ b/terraform/node/ec2/default/main.tf @@ -141,8 +141,8 @@ resource "null_resource" "main_service_setup" { sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c file:./amazon-cloudwatch-agent.json # Get and run the sample application with configuration - aws s3 cp ${var.sample_app_zip} ./node-sample-app.zip - unzip -o node-sample-app.zip + aws s3 cp ${var.sample_app_zip} ./node-sample-app-delete-me.zip + unzip -o node-sample-app-delete-me.zip # Enter appropriate service folder cd frontend-service @@ -159,7 +159,7 @@ resource "null_resource" "main_service_setup" { # Export environment variables for instrumentation # Note: We use OTEL_NODE_DISABLED_INSTRUMENTATIONS=fs,dns,express to avoid # having to validate around the telemetry generated for middleware - tmux send-keys -t frontend 'export OTEL_METRICS_EXPORTER=none' C-m + tmux send-keys -t frontend 'export OTEL_METRICS_EXPORTER=otlp' C-m tmux send-keys -t frontend 'export OTEL_TRACES_EXPORTER=otlp' C-m tmux send-keys -t frontend 'export OTEL_AWS_APPLICATION_SIGNALS_ENABLED=true' C-m tmux send-keys -t frontend 'export OTEL_AWS_APPLICATION_SIGNALS_RUNTIME_ENABLED=false' C-m @@ -167,6 +167,11 @@ resource "null_resource" "main_service_setup" { tmux send-keys -t frontend 'export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:4316/v1/traces' C-m tmux send-keys -t frontend 'export OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=http/protobuf' C-m tmux send-keys -t frontend 'export OTEL_EXPORTER_OTLP_METRICS_PROTOCOL=http/protobuf' C-m + tmux send-keys -t frontend 'export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://localhost:4318/v1/metrics' C-m + tmux send-keys -t frontend 'export OTEL_EXPORTER_OTLP_METRICS_INSECURE=true' C-m + tmux send-keys -t frontend 'export OTEL_RESOURCE_ATTRIBUTES="service.name=node-sample-application-${var.test_id},deployment.environment.name=ec2:default"' C-m + tmux send-keys -t frontend 'export TESTING_ID=${var.test_id}' C-m + tmux send-keys -t frontend 'export AWS_REGION=${var.aws_region}' C-m tmux send-keys -t frontend 'export OTEL_NODE_DISABLED_INSTRUMENTATIONS=fs,dns,express' C-m tmux send-keys -t frontend 'export OTEL_SERVICE_NAME=node-sample-application-${var.test_id}' C-m tmux send-keys -t frontend 'export OTEL_TRACES_SAMPLER=always_on' C-m @@ -258,8 +263,8 @@ resource "null_resource" "remote_service_setup" { sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c file:./amazon-cloudwatch-agent.json # Get and run the sample application with configuration - aws s3 cp ${var.sample_app_zip} ./node-sample-app.zip - unzip -o node-sample-app.zip + aws s3 cp ${var.sample_app_zip} ./node-sample-app-delete-me.zip + unzip -o node-sample-app-delete-me.zip # Enter appropriate service folder cd remote-service 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 9346119ee..b293de87f 100644 --- a/validator/src/main/java/com/amazon/aoc/fileconfigs/PredefinedExpectedTemplate.java +++ b/validator/src/main/java/com/amazon/aoc/fileconfigs/PredefinedExpectedTemplate.java @@ -422,6 +422,9 @@ public enum PredefinedExpectedTemplate implements FileConfig { NODE_EC2_DEFAULT_AWS_SDK_CALL_METRIC("/expected-data-template/node/ec2/default/aws-sdk-call-metric.mustache"), NODE_EC2_DEFAULT_AWS_SDK_CALL_TRACE("/expected-data-template/node/ec2/default/aws-sdk-call-trace.mustache"), + /** Node EC2 Default Custom Metrics Test Case Validations */ + NODE_EC2_DEFAULT_AWS_OTEL_CUSTOM_METRIC("/expected-data-template/node/ec2/default/aws-otel-custom-metrics.mustache"), + NODE_EC2_DEFAULT_REMOTE_SERVICE_LOG("/expected-data-template/node/ec2/default/remote-service-log.mustache"), NODE_EC2_DEFAULT_REMOTE_SERVICE_METRIC("/expected-data-template/node/ec2/default/remote-service-metric.mustache"), NODE_EC2_DEFAULT_REMOTE_SERVICE_TRACE("/expected-data-template/node/ec2/default/remote-service-trace.mustache"), diff --git a/validator/src/main/resources/expected-data-template/node/ec2/default/aws-otel-custom-metrics.mustache b/validator/src/main/resources/expected-data-template/node/ec2/default/aws-otel-custom-metrics.mustache new file mode 100644 index 000000000..b019c2df4 --- /dev/null +++ b/validator/src/main/resources/expected-data-template/node/ec2/default/aws-otel-custom-metrics.mustache @@ -0,0 +1,228 @@ +# OpenTelemetry Custom Metrics Validation Templates - AWS SDK Call Only +# ANY_VALUE defines a string to = 'ANY_VALUE' to pass validation testing +# Custom export templates +- + metricName: agent_based_counter + namespace: {{metricNamespace}} + dimensions: + - + name: deployment.environment.name + value: ec2:default + - + name: aws.local.service + value: {{serviceName}} + - + name: cloud.region + value: {{region}} + - + name: service.name + value: {{serviceName}} + - + name: Operation + value: counter + - + name: host.type + value: ANY_VALUE + - + name: cloud.availability_zone + value: ANY_VALUE + - + name: telemetry.sdk.name + value: opentelemetry + - + name: telemetry.sdk.language + value: node + - + name: cloud.provider + value: aws + - + name: cloud.account.id + value: {{accountId}} + - + name: host.name + value: ANY_VALUE + - + name: telemetry.sdk.version + value: ANY_VALUE + - + name: host.id + value: ANY_VALUE + - + name: telemetry.auto.version + value: ANY_VALUE + - + name: cloud.platform + value: aws_ec2 +- + metricName: agent_based_histogram + namespace: {{metricNamespace}} + dimensions: + - + name: deployment.environment.name + value: ec2:default + - + name: aws.local.service + value: {{serviceName}} + - + name: cloud.region + value: {{region}} + - + name: service.name + value: {{serviceName}} + - + name: Operation + value: histogram + - + name: host.type + value: ANY_VALUE + - + name: cloud.availability_zone + value: ANY_VALUE + - + name: telemetry.sdk.name + value: opentelemetry + - + name: telemetry.sdk.language + value: node + - + name: cloud.provider + value: aws + - + name: cloud.account.id + value: {{accountId}} + - + name: host.name + value: ANY_VALUE + - + name: telemetry.sdk.version + value: ANY_VALUE + - + name: host.id + value: ANY_VALUE + - + name: telemetry.auto.version + value: ANY_VALUE + - + name: cloud.platform + value: aws_ec2 +- + metricName: agent_based_gauge + namespace: {{metricNamespace}} + dimensions: + - + name: deployment.environment.name + value: ec2:default + - + name: aws.local.service + value: {{serviceName}} + - + name: cloud.region + value: {{region}} + - + name: service.name + value: {{serviceName}} + - + name: Operation + value: gauge + - + name: host.type + value: ANY_VALUE + - + name: cloud.availability_zone + value: ANY_VALUE + - + name: telemetry.sdk.name + value: opentelemetry + - + name: telemetry.sdk.language + value: node + - + name: cloud.provider + value: aws + - + name: cloud.account.id + value: {{accountId}} + - + name: host.name + value: ANY_VALUE + - + name: telemetry.sdk.version + value: ANY_VALUE + - + name: host.id + value: ANY_VALUE + - + name: telemetry.auto.version + value: ANY_VALUE + - + name: cloud.platform + value: aws_ec2 + value: aws_ec2 + +# Export pipeline metrics +- + metricName: custom_pipeline_counter + namespace: {{metricNamespace}} + dimensions: + - + name: deployment.environment.name + value: ec2:default + - + name: service.name + value: {{serviceName}} + - + name: Operation + value: pipeline_counter + - + name: telemetry.sdk.name + value: opentelemetry + - + name: telemetry.sdk.language + value: node + - + name: telemetry.sdk.version + value: ANY_VALUE +- + metricName: custom_pipeline_histogram + namespace: {{metricNamespace}} + dimensions: + - + name: deployment.environment.name + value: ec2:default + - + name: service.name + value: {{serviceName}} + - + name: Operation + value: pipeline_histogram + - + name: telemetry.sdk.name + value: opentelemetry + - + name: telemetry.sdk.language + value: node + - + name: telemetry.sdk.version + value: ANY_VALUE +- + metricName: custom_pipeline_gauge + namespace: {{metricNamespace}} + dimensions: + - + name: deployment.environment.name + value: ec2:default + - + name: service.name + value: {{serviceName}} + - + name: Operation + value: pipeline_gauge + - + name: telemetry.sdk.name + value: opentelemetry + - + name: telemetry.sdk.language + value: node + - + name: telemetry.sdk.version + value: ANY_VALUE \ No newline at end of file diff --git a/validator/src/main/resources/validations/node/ec2/default/custom-metric-validation.yml b/validator/src/main/resources/validations/node/ec2/default/custom-metric-validation.yml new file mode 100644 index 000000000..4d8cd718a --- /dev/null +++ b/validator/src/main/resources/validations/node/ec2/default/custom-metric-validation.yml @@ -0,0 +1,6 @@ +- + validationType: "cw-metric" + httpPath: "aws-sdk-call" + httpMethod: "get" + callingType: "http-with-query" + expectedMetricTemplate: "NODE_EC2_DEFAULT_AWS_OTEL_CUSTOM_METRIC" \ No newline at end of file From 83503ea83e85471b5e663884bbe8667631ed352a Mon Sep 17 00:00:00 2001 From: Vherremi Date: Sun, 9 Nov 2025 12:33:40 -0800 Subject: [PATCH 02/11] node-ec2-default test 1 --- .github/workflows/node-ec2-default-test.yml | 6 +- .github/workflows/test.yml | 2 +- sample-apps/node/frontend-service/index.js | 78 +++++++++++++-------- 3 files changed, 53 insertions(+), 33 deletions(-) diff --git a/.github/workflows/node-ec2-default-test.yml b/.github/workflows/node-ec2-default-test.yml index 6048acf32..49e4ead52 100644 --- a/.github/workflows/node-ec2-default-test.yml +++ b/.github/workflows/node-ec2-default-test.yml @@ -245,7 +245,7 @@ jobs: --rollup' - name: Validate custom metrics - id: CWagent metric-validation + id: cwagent-metric-validation if: (success() || steps.log-validation.outcome == 'failure') && !cancelled() run: ./gradlew validator:run --args='-c node/ec2/default/metric-validation.yml --testing-id ${{ env.TESTING_ID }} @@ -264,7 +264,7 @@ jobs: - name: Validate generated traces id: trace-validation - if: (success() || steps.log-validation.outcome == 'failure' || steps.metric-validation.outcome == 'failure') && !cancelled() + if: (success() || steps.log-validation.outcome == 'failure' || steps.metric-validation.outcome == 'failure' || steps.cwagent-metric-validation.outcome == 'failure') && !cancelled() run: ./gradlew validator:run --args='-c node/ec2/default/trace-validation.yml --testing-id ${{ env.TESTING_ID }} --endpoint http://${{ env.MAIN_SERVICE_ENDPOINT }} @@ -291,7 +291,7 @@ jobs: if: always() id: validation-result run: | - if [ "${{ steps.log-validation.outcome }}" = "success" ] && [ "${{ steps.metric-validation.outcome }}" = "success" ] && [ "${{ steps.trace-validation.outcome }}" = "success" ]; then + if [ "${{ steps.log-validation.outcome }}" = "success" ] && [ "${{ steps.cwagent-metric-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 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 599a069e9..d9759b38e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,7 +15,7 @@ permissions: contents: read jobs: - python-ec2-default: + node-ec2-default: uses: ./.github/workflows/node-ec2-default-test.yml secrets: inherit with: diff --git a/sample-apps/node/frontend-service/index.js b/sample-apps/node/frontend-service/index.js index 1c5698304..b5a277da1 100644 --- a/sample-apps/node/frontend-service/index.js +++ b/sample-apps/node/frontend-service/index.js @@ -6,10 +6,7 @@ const mysql = require('mysql2'); const bunyan = require('bunyan'); const { S3Client, GetBucketLocationCommand } = require('@aws-sdk/client-s3'); const opentelemetry = require('@opentelemetry/sdk-node'); -const { MeterProvider, PeriodicExportingMetricReader, ConsoleMetricExporter } = require('@opentelemetry/sdk-metrics'); -const { OTLPMetricExporter } = require('@opentelemetry/exporter-metrics-otlp-proto'); const { metrics } = require('@opentelemetry/api'); -const { Resource } = require('@opentelemetry/resources'); const { randomInt } = require('crypto'); const PORT = parseInt(process.env.SAMPLE_APP_PORT || '8000', 10); @@ -19,38 +16,57 @@ const app = express(); // Create bunyan logger const logger = bunyan.createLogger({name: 'express-app', level: 'info'}); -// Custom export pipeline - runs alongside existing CWAgent & ADOT setup -const pipelineResource = new Resource({ - 'service.name': `node-sample-application-${process.env.TESTING_ID}`, - 'deployment.environment.name': 'ec2:default', - 'Telemetry.Source': 'CustomMetric' -}); - -const pipelineMetricExporter = new OTLPMetricExporter({ - url: 'http://localhost:4318/v1/metrics' -}); - -const pipelineMetricReader = new PeriodicExportingMetricReader({ - exporter: pipelineMetricExporter, - exportIntervalMillis: 5000 -}); +let pipelineMeter = null; + +if (process.env.SERVICE_NAME && process.env.DEPLOYMENT_ENVIRONMENT_NAME) { + const { Resource } = require('@opentelemetry/resources'); + const { MeterProvider, PeriodicExportingMetricReader } = require('@opentelemetry/sdk-metrics'); + const { OTLPMetricExporter } = require('@opentelemetry/exporter-metrics-otlp-proto'); + + const serviceName = process.env.SERVICE_NAME; + const deploymentEnv = process.env.DEPLOYMENT_ENVIRONMENT_NAME; + + const pipelineResource = new Resource({ + // SEMRESATTRS_DEPLOYMENT_ENVIRONMENT_NAME maps to dimension 'deployment.name' so "deployment.environment.name" used + // to assign value correctly. + 'service.name': serviceName, + 'deployment.environment.name': deploymentEnv + }); -const pipelineMeterProvider = new MeterProvider({ - resource: pipelineResource, - readers: [pipelineMetricReader] -}); + const pipelineMetricExporter = new OTLPMetricExporter({ + url: 'http://localhost:4318/v1/metrics' + }); + + const pipelineMetricReader = new PeriodicExportingMetricReader({ + exporter: pipelineMetricExporter, + exportIntervalMillis: 1000 + }); + + const pipelineMeterProvider = new MeterProvider({ + resource: pipelineResource, + readers: [pipelineMetricReader] + }); + + pipelineMeter = pipelineMeterProvider.getMeter('myMeter'); +} -const pipelineMeter = pipelineMeterProvider.getMeter('myMeter'); const meter = metrics.getMeter('myMeter'); const agent_based_counter = meter.createCounter('agent_based_counter', {description: 'agent export counter'}); const agent_based_histogram = meter.createHistogram('agent_based_histogram', {description: 'agent export histogram'}); const agent_based_gauge = meter.createUpDownCounter('agent_based_gauge', {description: 'agent export gauge'}); -const custom_pipeline_counter = pipelineMeter.createCounter('custom_pipeline_counter', {unit: '1', description: 'pipeline export counter'}); -const custom_pipeline_histogram = pipelineMeter.createHistogram('custom_pipeline_histogram', {description: 'pipeline export histogram'}); -const custom_pipeline_gauge = pipelineMeter.createUpDownCounter('custom_pipeline_gauge', {unit: '1', description: 'pipeline export gauge'}); +let custom_pipeline_counter = null; +let custom_pipeline_histogram = null; +let custom_pipeline_gauge = null; + +if (pipelineMeter) { + custom_pipeline_counter = pipelineMeter.createCounter('custom_pipeline_counter', {unit: '1', description: 'pipeline export counter'}); + custom_pipeline_histogram = pipelineMeter.createHistogram('custom_pipeline_histogram', {description: 'pipeline export histogram'}); + custom_pipeline_gauge = pipelineMeter.createUpDownCounter('custom_pipeline_gauge', {unit: '1', description: 'pipeline export gauge'}); +} +console.log('=== Metrics Setup Complete ==='); app.get('/', (req, res) => { res.send('Node.js Application Started! Available endpoints: /healthcheck, /aws-sdk-call, /outgoing-http-call, /remote-service, /client-call, /mysql'); }); @@ -92,9 +108,11 @@ app.get('/aws-sdk-call', async (req, res) => { agent_based_gauge.add(randomInt(-10, 11), { Operation : 'gauge' }); // Increment counter/histogram/gauge for pipeline export - custom_pipeline_counter.add(1, { Operation : 'pipeline_counter' }); - custom_pipeline_histogram.record(randomInt(100,1001), { Operation : 'pipeline_histogram' }); - custom_pipeline_gauge.add(randomInt(-10, 11), { Operation : 'pipeline_gauge' }); + if (custom_pipeline_counter) { + custom_pipeline_counter.add(1, { Operation : 'pipeline_counter' }); + custom_pipeline_histogram.record(randomInt(100,1001), { Operation : 'pipeline_histogram' }); + custom_pipeline_gauge.add(randomInt(-10, 11), { Operation : 'pipeline_gauge' }); + } try { await s3Client.send( @@ -168,6 +186,8 @@ app.get('/client-call', (req, res) => { makeAsyncCall = true; }); + + app.get('/mysql', (req, res) => { // Create a connection to the MySQL database const connection = mysql.createConnection({ From 6d9bfa54eb152e8bb324ae8ce58e9389ca12ec76 Mon Sep 17 00:00:00 2001 From: Vherremi Date: Sun, 9 Nov 2025 12:42:30 -0800 Subject: [PATCH 03/11] updating sdk-node version --- sample-apps/node/frontend-service/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sample-apps/node/frontend-service/package.json b/sample-apps/node/frontend-service/package.json index 90a2e266a..98c42f860 100644 --- a/sample-apps/node/frontend-service/package.json +++ b/sample-apps/node/frontend-service/package.json @@ -17,7 +17,7 @@ "@opentelemetry/resources": "^1.30.1", "@opentelemetry/sdk-metrics": "^1.30.1", "@opentelemetry/semantic-conventions": "^1.37.0", - "@opentelemetry/sdk-node": ".207.0", + "@opentelemetry/sdk-node": "^0.57.0", "@types/express": "^4.17.21", "@types/node": "^20.14.6", "bunyan": "^1.8.15", From 1db37441a03adc35c4c9760cb52bbfa5db79aa71 Mon Sep 17 00:00:00 2001 From: Vherremi Date: Sun, 9 Nov 2025 18:21:32 -0800 Subject: [PATCH 04/11] node-ec2-default test 2 --- .github/workflows/node-ec2-default-test.yml | 2 +- sample-apps/node/frontend-service/index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/node-ec2-default-test.yml b/.github/workflows/node-ec2-default-test.yml index 49e4ead52..56e089f0b 100644 --- a/.github/workflows/node-ec2-default-test.yml +++ b/.github/workflows/node-ec2-default-test.yml @@ -247,7 +247,7 @@ jobs: - name: Validate custom metrics id: cwagent-metric-validation if: (success() || steps.log-validation.outcome == 'failure') && !cancelled() - run: ./gradlew validator:run --args='-c node/ec2/default/metric-validation.yml + run: ./gradlew validator:run --args='-c node/ec2/default/custom-metric-validation.yml --testing-id ${{ env.TESTING_ID }} --endpoint http://${{ env.MAIN_SERVICE_ENDPOINT }} --remote-service-deployment-name ${{ env.REMOTE_SERVICE_IP }}:8001 diff --git a/sample-apps/node/frontend-service/index.js b/sample-apps/node/frontend-service/index.js index b5a277da1..0085a7bc2 100644 --- a/sample-apps/node/frontend-service/index.js +++ b/sample-apps/node/frontend-service/index.js @@ -34,7 +34,7 @@ if (process.env.SERVICE_NAME && process.env.DEPLOYMENT_ENVIRONMENT_NAME) { }); const pipelineMetricExporter = new OTLPMetricExporter({ - url: 'http://localhost:4318/v1/metrics' + url: 'http://localhost:4317' }); const pipelineMetricReader = new PeriodicExportingMetricReader({ From f0eb34a9f12de8f986787cce244420b01770ca04 Mon Sep 17 00:00:00 2001 From: Vherremi Date: Tue, 11 Nov 2025 08:57:13 -0800 Subject: [PATCH 05/11] node-ec2-default test 3 --- sample-apps/node/frontend-service/index.js | 9 +++++---- sample-apps/node/frontend-service/package.json | 11 +++++------ terraform/node/ec2/default/main.tf | 7 +++++-- .../ec2/default/aws-otel-custom-metrics.mustache | 12 ++++++------ 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/sample-apps/node/frontend-service/index.js b/sample-apps/node/frontend-service/index.js index 0085a7bc2..17fa27f07 100644 --- a/sample-apps/node/frontend-service/index.js +++ b/sample-apps/node/frontend-service/index.js @@ -9,6 +9,7 @@ const opentelemetry = require('@opentelemetry/sdk-node'); const { metrics } = require('@opentelemetry/api'); const { randomInt } = require('crypto'); + const PORT = parseInt(process.env.SAMPLE_APP_PORT || '8000', 10); const app = express(); @@ -19,14 +20,14 @@ const logger = bunyan.createLogger({name: 'express-app', level: 'info'}); let pipelineMeter = null; if (process.env.SERVICE_NAME && process.env.DEPLOYMENT_ENVIRONMENT_NAME) { - const { Resource } = require('@opentelemetry/resources'); + const { resourceFromAttributes } = require('@opentelemetry/resources'); const { MeterProvider, PeriodicExportingMetricReader } = require('@opentelemetry/sdk-metrics'); const { OTLPMetricExporter } = require('@opentelemetry/exporter-metrics-otlp-proto'); const serviceName = process.env.SERVICE_NAME; const deploymentEnv = process.env.DEPLOYMENT_ENVIRONMENT_NAME; - const pipelineResource = new Resource({ + const pipelineResource = resourceFromAttributes({ // SEMRESATTRS_DEPLOYMENT_ENVIRONMENT_NAME maps to dimension 'deployment.name' so "deployment.environment.name" used // to assign value correctly. 'service.name': serviceName, @@ -34,7 +35,7 @@ if (process.env.SERVICE_NAME && process.env.DEPLOYMENT_ENVIRONMENT_NAME) { }); const pipelineMetricExporter = new OTLPMetricExporter({ - url: 'http://localhost:4317' + url: 'http://localhost:4318/v1/metrics' }); const pipelineMetricReader = new PeriodicExportingMetricReader({ @@ -66,7 +67,7 @@ if (pipelineMeter) { custom_pipeline_gauge = pipelineMeter.createUpDownCounter('custom_pipeline_gauge', {unit: '1', description: 'pipeline export gauge'}); } -console.log('=== Metrics Setup Complete ==='); + app.get('/', (req, res) => { res.send('Node.js Application Started! Available endpoints: /healthcheck, /aws-sdk-call, /outgoing-http-call, /remote-service, /client-call, /mysql'); }); diff --git a/sample-apps/node/frontend-service/package.json b/sample-apps/node/frontend-service/package.json index 98c42f860..a4a00a3cd 100644 --- a/sample-apps/node/frontend-service/package.json +++ b/sample-apps/node/frontend-service/package.json @@ -13,15 +13,14 @@ "@aws-sdk/client-s3": "^3.621.0", "@aws/aws-distro-opentelemetry-node-autoinstrumentation": "^0.8.0", "@opentelemetry/api": "^1.9.0", - "@opentelemetry/exporter-metrics-otlp-proto": "^0.57.1", - "@opentelemetry/resources": "^1.30.1", - "@opentelemetry/sdk-metrics": "^1.30.1", - "@opentelemetry/semantic-conventions": "^1.37.0", - "@opentelemetry/sdk-node": "^0.57.0", + "@opentelemetry/exporter-metrics-otlp-proto": "^0.208.0", + "@opentelemetry/resources": "^2.2.0", + "@opentelemetry/sdk-metrics": "^2.2.0", + "@opentelemetry/sdk-node": "^0.208.0", "@types/express": "^4.17.21", "@types/node": "^20.14.6", "bunyan": "^1.8.15", "express": "^4.21.2", - "mysql2": "^3.15.3" + "mysql2": "^3.11.0" } } diff --git a/terraform/node/ec2/default/main.tf b/terraform/node/ec2/default/main.tf index aa0b5e4eb..3009924a9 100644 --- a/terraform/node/ec2/default/main.tf +++ b/terraform/node/ec2/default/main.tf @@ -169,11 +169,14 @@ resource "null_resource" "main_service_setup" { tmux send-keys -t frontend 'export OTEL_EXPORTER_OTLP_METRICS_PROTOCOL=http/protobuf' C-m tmux send-keys -t frontend 'export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://localhost:4318/v1/metrics' C-m tmux send-keys -t frontend 'export OTEL_EXPORTER_OTLP_METRICS_INSECURE=true' C-m - tmux send-keys -t frontend 'export OTEL_RESOURCE_ATTRIBUTES="service.name=node-sample-application-${var.test_id},deployment.environment.name=ec2:default"' C-m + tmux send-keys -t frontend 'export SERVICE_NAME=node-sample-application-${var.test_id}' C-m + tmux send-keys -t frontend 'export DEPLOYMENT_ENVIRONMENT_NAME=ec2:default' C-m + tmux send-keys -t frontend 'export OTEL_RESOURCE_ATTRIBUTES="service.name=$$SERVICE_NAME,deployment.environment.name=$$DEPLOYMENT_ENVIRONMENT_NAME"' C-m + tmux send-keys -t frontend 'export AWS_REGION=${var.aws_region}' C-m tmux send-keys -t frontend 'export TESTING_ID=${var.test_id}' C-m tmux send-keys -t frontend 'export AWS_REGION=${var.aws_region}' C-m tmux send-keys -t frontend 'export OTEL_NODE_DISABLED_INSTRUMENTATIONS=fs,dns,express' C-m - tmux send-keys -t frontend 'export OTEL_SERVICE_NAME=node-sample-application-${var.test_id}' C-m + tmux send-keys -t frontend 'export OTEL_SERVICE_NAME=$$SERVICE_NAME' C-m tmux send-keys -t frontend 'export OTEL_TRACES_SAMPLER=always_on' C-m tmux send-keys -t frontend 'node --require "@aws/aws-distro-opentelemetry-node-autoinstrumentation/register" index.js' C-m diff --git a/validator/src/main/resources/expected-data-template/node/ec2/default/aws-otel-custom-metrics.mustache b/validator/src/main/resources/expected-data-template/node/ec2/default/aws-otel-custom-metrics.mustache index b019c2df4..ff9878982 100644 --- a/validator/src/main/resources/expected-data-template/node/ec2/default/aws-otel-custom-metrics.mustache +++ b/validator/src/main/resources/expected-data-template/node/ec2/default/aws-otel-custom-metrics.mustache @@ -31,7 +31,7 @@ value: opentelemetry - name: telemetry.sdk.language - value: node + value: nodejs - name: cloud.provider value: aws @@ -83,7 +83,7 @@ value: opentelemetry - name: telemetry.sdk.language - value: node + value: nodejs - name: cloud.provider value: aws @@ -135,7 +135,7 @@ value: opentelemetry - name: telemetry.sdk.language - value: node + value: nodejs - name: cloud.provider value: aws @@ -178,7 +178,7 @@ value: opentelemetry - name: telemetry.sdk.language - value: node + value: nodejs - name: telemetry.sdk.version value: ANY_VALUE @@ -200,7 +200,7 @@ value: opentelemetry - name: telemetry.sdk.language - value: node + value: nodejs - name: telemetry.sdk.version value: ANY_VALUE @@ -222,7 +222,7 @@ value: opentelemetry - name: telemetry.sdk.language - value: node + value: nodejs - name: telemetry.sdk.version value: ANY_VALUE \ No newline at end of file From bf956c7251445c381e7e4458272580a6ece25c7d Mon Sep 17 00:00:00 2001 From: Vherremi Date: Tue, 11 Nov 2025 09:28:57 -0800 Subject: [PATCH 06/11] node-ec2-default test 4 --- terraform/node/ec2/default/main.tf | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/terraform/node/ec2/default/main.tf b/terraform/node/ec2/default/main.tf index 3009924a9..878a9d757 100644 --- a/terraform/node/ec2/default/main.tf +++ b/terraform/node/ec2/default/main.tf @@ -174,9 +174,8 @@ resource "null_resource" "main_service_setup" { tmux send-keys -t frontend 'export OTEL_RESOURCE_ATTRIBUTES="service.name=$$SERVICE_NAME,deployment.environment.name=$$DEPLOYMENT_ENVIRONMENT_NAME"' C-m tmux send-keys -t frontend 'export AWS_REGION=${var.aws_region}' C-m tmux send-keys -t frontend 'export TESTING_ID=${var.test_id}' C-m - tmux send-keys -t frontend 'export AWS_REGION=${var.aws_region}' C-m tmux send-keys -t frontend 'export OTEL_NODE_DISABLED_INSTRUMENTATIONS=fs,dns,express' C-m - tmux send-keys -t frontend 'export OTEL_SERVICE_NAME=$$SERVICE_NAME' C-m + tmux send-keys -t frontend 'export OTEL_SERVICE_NAME=node-sample-application-${var.test_id}' C-m tmux send-keys -t frontend 'export OTEL_TRACES_SAMPLER=always_on' C-m tmux send-keys -t frontend 'node --require "@aws/aws-distro-opentelemetry-node-autoinstrumentation/register" index.js' C-m From 997d582b465d8840ef7615ddb6e30f9d17865808 Mon Sep 17 00:00:00 2001 From: Vherremi Date: Tue, 11 Nov 2025 10:11:04 -0800 Subject: [PATCH 07/11] node-ec2-default test 5 revertin back to last test code that didn't crash app --- sample-apps/node/frontend-service/index.js | 9 ++++----- sample-apps/node/frontend-service/package.json | 11 ++++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/sample-apps/node/frontend-service/index.js b/sample-apps/node/frontend-service/index.js index 17fa27f07..0085a7bc2 100644 --- a/sample-apps/node/frontend-service/index.js +++ b/sample-apps/node/frontend-service/index.js @@ -9,7 +9,6 @@ const opentelemetry = require('@opentelemetry/sdk-node'); const { metrics } = require('@opentelemetry/api'); const { randomInt } = require('crypto'); - const PORT = parseInt(process.env.SAMPLE_APP_PORT || '8000', 10); const app = express(); @@ -20,14 +19,14 @@ const logger = bunyan.createLogger({name: 'express-app', level: 'info'}); let pipelineMeter = null; if (process.env.SERVICE_NAME && process.env.DEPLOYMENT_ENVIRONMENT_NAME) { - const { resourceFromAttributes } = require('@opentelemetry/resources'); + const { Resource } = require('@opentelemetry/resources'); const { MeterProvider, PeriodicExportingMetricReader } = require('@opentelemetry/sdk-metrics'); const { OTLPMetricExporter } = require('@opentelemetry/exporter-metrics-otlp-proto'); const serviceName = process.env.SERVICE_NAME; const deploymentEnv = process.env.DEPLOYMENT_ENVIRONMENT_NAME; - const pipelineResource = resourceFromAttributes({ + const pipelineResource = new Resource({ // SEMRESATTRS_DEPLOYMENT_ENVIRONMENT_NAME maps to dimension 'deployment.name' so "deployment.environment.name" used // to assign value correctly. 'service.name': serviceName, @@ -35,7 +34,7 @@ if (process.env.SERVICE_NAME && process.env.DEPLOYMENT_ENVIRONMENT_NAME) { }); const pipelineMetricExporter = new OTLPMetricExporter({ - url: 'http://localhost:4318/v1/metrics' + url: 'http://localhost:4317' }); const pipelineMetricReader = new PeriodicExportingMetricReader({ @@ -67,7 +66,7 @@ if (pipelineMeter) { custom_pipeline_gauge = pipelineMeter.createUpDownCounter('custom_pipeline_gauge', {unit: '1', description: 'pipeline export gauge'}); } - +console.log('=== Metrics Setup Complete ==='); app.get('/', (req, res) => { res.send('Node.js Application Started! Available endpoints: /healthcheck, /aws-sdk-call, /outgoing-http-call, /remote-service, /client-call, /mysql'); }); diff --git a/sample-apps/node/frontend-service/package.json b/sample-apps/node/frontend-service/package.json index a4a00a3cd..98c42f860 100644 --- a/sample-apps/node/frontend-service/package.json +++ b/sample-apps/node/frontend-service/package.json @@ -13,14 +13,15 @@ "@aws-sdk/client-s3": "^3.621.0", "@aws/aws-distro-opentelemetry-node-autoinstrumentation": "^0.8.0", "@opentelemetry/api": "^1.9.0", - "@opentelemetry/exporter-metrics-otlp-proto": "^0.208.0", - "@opentelemetry/resources": "^2.2.0", - "@opentelemetry/sdk-metrics": "^2.2.0", - "@opentelemetry/sdk-node": "^0.208.0", + "@opentelemetry/exporter-metrics-otlp-proto": "^0.57.1", + "@opentelemetry/resources": "^1.30.1", + "@opentelemetry/sdk-metrics": "^1.30.1", + "@opentelemetry/semantic-conventions": "^1.37.0", + "@opentelemetry/sdk-node": "^0.57.0", "@types/express": "^4.17.21", "@types/node": "^20.14.6", "bunyan": "^1.8.15", "express": "^4.21.2", - "mysql2": "^3.11.0" + "mysql2": "^3.15.3" } } From 6acaa49c5c168f5826d2602ea3a00e9abb93c24e Mon Sep 17 00:00:00 2001 From: Vherremi Date: Tue, 11 Nov 2025 10:26:01 -0800 Subject: [PATCH 08/11] node-ec2-default test 6 --- terraform/node/ec2/default/main.tf | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/terraform/node/ec2/default/main.tf b/terraform/node/ec2/default/main.tf index 878a9d757..b7788bb1b 100644 --- a/terraform/node/ec2/default/main.tf +++ b/terraform/node/ec2/default/main.tf @@ -169,13 +169,11 @@ resource "null_resource" "main_service_setup" { tmux send-keys -t frontend 'export OTEL_EXPORTER_OTLP_METRICS_PROTOCOL=http/protobuf' C-m tmux send-keys -t frontend 'export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://localhost:4318/v1/metrics' C-m tmux send-keys -t frontend 'export OTEL_EXPORTER_OTLP_METRICS_INSECURE=true' C-m - tmux send-keys -t frontend 'export SERVICE_NAME=node-sample-application-${var.test_id}' C-m - tmux send-keys -t frontend 'export DEPLOYMENT_ENVIRONMENT_NAME=ec2:default' C-m - tmux send-keys -t frontend 'export OTEL_RESOURCE_ATTRIBUTES="service.name=$$SERVICE_NAME,deployment.environment.name=$$DEPLOYMENT_ENVIRONMENT_NAME"' C-m - tmux send-keys -t frontend 'export AWS_REGION=${var.aws_region}' C-m - tmux send-keys -t frontend 'export TESTING_ID=${var.test_id}' C-m + tmux send-keys -t frontend 'export SERVICE_NAME=node-sample-application-${var.test_id} && export DEPLOYMENT_ENVIRONMENT_NAME=ec2:default && export OTEL_RESOURCE_ATTRIBUTES="service.name=$$SERVICE_NAME,deployment.environment.name=$$DEPLOYMENT_ENVIRONMENT_NAME"' C-m + tmux send-keys -t frontend "export AWS_REGION='$${AWS_REGION}'" C-m + tmux send-keys -t frontend "export TESTING_ID='$${TESTING_ID}'" C-m tmux send-keys -t frontend 'export OTEL_NODE_DISABLED_INSTRUMENTATIONS=fs,dns,express' C-m - tmux send-keys -t frontend 'export OTEL_SERVICE_NAME=node-sample-application-${var.test_id}' C-m + tmux send-keys -t frontend "export OTEL_SERVICE_NAME='$${SERVICE_NAME}'" C-m tmux send-keys -t frontend 'export OTEL_TRACES_SAMPLER=always_on' C-m tmux send-keys -t frontend 'node --require "@aws/aws-distro-opentelemetry-node-autoinstrumentation/register" index.js' C-m From 3057ec08a347726f7ec399b1fef8199c0e8798d0 Mon Sep 17 00:00:00 2001 From: Vherremi Date: Tue, 11 Nov 2025 10:40:55 -0800 Subject: [PATCH 09/11] node-ec2-default test 7 --- terraform/node/ec2/default/main.tf | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/terraform/node/ec2/default/main.tf b/terraform/node/ec2/default/main.tf index b7788bb1b..5f4cb5d5a 100644 --- a/terraform/node/ec2/default/main.tf +++ b/terraform/node/ec2/default/main.tf @@ -153,8 +153,15 @@ resource "null_resource" "main_service_setup" { # Get ADOT instrumentation and install it ${var.get_adot_instrumentation_command} - # Set up application tmux screen so it keeps running after closing the SSH connection - tmux new-session -d -s frontend + # Set up environment variables like Python does + export SERVICE_NAME='node-sample-application-${var.test_id}' + export DEPLOYMENT_ENVIRONMENT_NAME='ec2:default' + export OTEL_RESOURCE_ATTRIBUTES="service.name=$${SERVICE_NAME},deployment.environment.name=$${DEPLOYMENT_ENVIRONMENT_NAME}" + export AWS_REGION='${var.aws_region}' + export TESTING_ID='${var.test_id}' + + # Set up application tmux screen with bash shell + tmux new-session -d -s frontend bash # Export environment variables for instrumentation # Note: We use OTEL_NODE_DISABLED_INSTRUMENTATIONS=fs,dns,express to avoid @@ -169,11 +176,13 @@ resource "null_resource" "main_service_setup" { tmux send-keys -t frontend 'export OTEL_EXPORTER_OTLP_METRICS_PROTOCOL=http/protobuf' C-m tmux send-keys -t frontend 'export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://localhost:4318/v1/metrics' C-m tmux send-keys -t frontend 'export OTEL_EXPORTER_OTLP_METRICS_INSECURE=true' C-m - tmux send-keys -t frontend 'export SERVICE_NAME=node-sample-application-${var.test_id} && export DEPLOYMENT_ENVIRONMENT_NAME=ec2:default && export OTEL_RESOURCE_ATTRIBUTES="service.name=$$SERVICE_NAME,deployment.environment.name=$$DEPLOYMENT_ENVIRONMENT_NAME"' C-m - tmux send-keys -t frontend "export AWS_REGION='$${AWS_REGION}'" C-m - tmux send-keys -t frontend "export TESTING_ID='$${TESTING_ID}'" C-m + tmux send-keys -t frontend 'export SERVICE_NAME="$${SERVICE_NAME}"' C-m + tmux send-keys -t frontend 'export DEPLOYMENT_ENVIRONMENT_NAME="$${DEPLOYMENT_ENVIRONMENT_NAME}"' C-m + tmux send-keys -t frontend 'export OTEL_RESOURCE_ATTRIBUTES="$${OTEL_RESOURCE_ATTRIBUTES}"' C-m + tmux send-keys -t frontend 'export AWS_REGION="$${AWS_REGION}"' C-m + tmux send-keys -t frontend 'export TESTING_ID="$${TESTING_ID}"' C-m tmux send-keys -t frontend 'export OTEL_NODE_DISABLED_INSTRUMENTATIONS=fs,dns,express' C-m - tmux send-keys -t frontend "export OTEL_SERVICE_NAME='$${SERVICE_NAME}'" C-m + tmux send-keys -t frontend 'export OTEL_SERVICE_NAME=node-sample-application-${var.test_id}' C-m tmux send-keys -t frontend 'export OTEL_TRACES_SAMPLER=always_on' C-m tmux send-keys -t frontend 'node --require "@aws/aws-distro-opentelemetry-node-autoinstrumentation/register" index.js' C-m From 9b61eecf1b0b515610d98069daf36e2ae5381bce Mon Sep 17 00:00:00 2001 From: Vherremi Date: Tue, 11 Nov 2025 11:06:04 -0800 Subject: [PATCH 10/11] node-ec2-default test 8 --- terraform/node/ec2/default/main.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/terraform/node/ec2/default/main.tf b/terraform/node/ec2/default/main.tf index 5f4cb5d5a..d3200fac3 100644 --- a/terraform/node/ec2/default/main.tf +++ b/terraform/node/ec2/default/main.tf @@ -173,8 +173,8 @@ resource "null_resource" "main_service_setup" { tmux send-keys -t frontend 'export OTEL_AWS_APPLICATION_SIGNALS_EXPORTER_ENDPOINT=http://localhost:4316/v1/metrics' C-m tmux send-keys -t frontend 'export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:4316/v1/traces' C-m tmux send-keys -t frontend 'export OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=http/protobuf' C-m - tmux send-keys -t frontend 'export OTEL_EXPORTER_OTLP_METRICS_PROTOCOL=http/protobuf' C-m - tmux send-keys -t frontend 'export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://localhost:4318/v1/metrics' C-m + tmux send-keys -t frontend 'export OTEL_EXPORTER_OTLP_METRICS_PROTOCOL=grpc' C-m + tmux send-keys -t frontend 'export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://localhost:4317' C-m tmux send-keys -t frontend 'export OTEL_EXPORTER_OTLP_METRICS_INSECURE=true' C-m tmux send-keys -t frontend 'export SERVICE_NAME="$${SERVICE_NAME}"' C-m tmux send-keys -t frontend 'export DEPLOYMENT_ENVIRONMENT_NAME="$${DEPLOYMENT_ENVIRONMENT_NAME}"' C-m From 125fda8642e8c02a91f8f4c1a3e873a2642ce41f Mon Sep 17 00:00:00 2001 From: Vherremi Date: Tue, 11 Nov 2025 11:24:56 -0800 Subject: [PATCH 11/11] testing new endpoints --- terraform/node/ec2/default/main.tf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/terraform/node/ec2/default/main.tf b/terraform/node/ec2/default/main.tf index d3200fac3..91a5e46c9 100644 --- a/terraform/node/ec2/default/main.tf +++ b/terraform/node/ec2/default/main.tf @@ -170,9 +170,9 @@ resource "null_resource" "main_service_setup" { tmux send-keys -t frontend 'export OTEL_TRACES_EXPORTER=otlp' C-m tmux send-keys -t frontend 'export OTEL_AWS_APPLICATION_SIGNALS_ENABLED=true' C-m tmux send-keys -t frontend 'export OTEL_AWS_APPLICATION_SIGNALS_RUNTIME_ENABLED=false' C-m - tmux send-keys -t frontend 'export OTEL_AWS_APPLICATION_SIGNALS_EXPORTER_ENDPOINT=http://localhost:4316/v1/metrics' C-m - tmux send-keys -t frontend 'export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:4316/v1/traces' C-m - tmux send-keys -t frontend 'export OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=http/protobuf' C-m + tmux send-keys -t frontend 'export OTEL_AWS_APPLICATION_SIGNALS_EXPORTER_ENDPOINT=http://localhost:4315' C-m + tmux send-keys -t frontend 'export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:4315' C-m + tmux send-keys -t frontend 'export OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=grpc' C-m tmux send-keys -t frontend 'export OTEL_EXPORTER_OTLP_METRICS_PROTOCOL=grpc' C-m tmux send-keys -t frontend 'export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://localhost:4317' C-m tmux send-keys -t frontend 'export OTEL_EXPORTER_OTLP_METRICS_INSECURE=true' C-m