Skip to content

Conversation

@syed-ahsan-ishtiaque
Copy link

@syed-ahsan-ishtiaque syed-ahsan-ishtiaque commented Dec 5, 2025

Summary

When both OTEL_AWS_APPLICATION_SIGNALS_ENABLED and OTEL_AWS_APPLICATION_SIGNALS_EMF_EXPORT_ENABLED are set to true, EMF metrics will now include Service and Environment as dimensions:

  • Service: Extracted from service.name resource attribute, falls back to "UnknownService"
  • Environment: Extracted from deployment.environment resource attribute, falls back to "lambda:default"
  • Dimensions are not added if user already set them (case-insensitive check)

For Lambda, both env vars default to true via the otel-instrument wrapper script.

Changes

  1. src/exporter/aws/metrics/emf-exporter-base.ts

    • Added isApplicationSignalsEmfExportEnabled() to check both env vars
    • Added hasDimensionCaseInsensitive() for case-insensitive dimension checking
    • Added addApplicationSignalsDimensions() to inject Service/Environment dimensions
    • Modified createEmfLog() to call the new method
  2. lambda-layer/packages/layer/scripts/otel-instrument

    • Added default OTEL_AWS_APPLICATION_SIGNALS_EMF_EXPORT_ENABLED="true" for Lambda
  3. test/exporter/aws/metrics/aws-cloudwatch-emf-exporter.test.ts

    • Added 12 new test cases covering all scenarios

Test plan

  • npm run lint passes (0 errors)
  • npm run compile builds successfully
  • All 544 unit tests pass
  • Integration test on Lambda verified Service/Environment dimensions in CloudWatch metrics

Manual Testing

Lambda Code

import { metrics, trace } from '@opentelemetry/api';
import { S3Client, ListBucketsCommand } from '@aws-sdk/client-s3';

const tracer = trace.getTracer('test-tracer');
const meter = metrics.getMeter('test-meter');
const requestCounter = meter.createCounter('test.requests', {
  unit: '1',
  description: 'Test request counter'
});

const s3Client = new S3Client({});

export const handler = async (event, context) => {
  // Custom metric emission
  requestCounter.add(1, { operation: 'test' });

  // AWS SDK call
  try {
    await s3Client.send(new ListBucketsCommand({}));
  } catch (e) {
    console.log('S3 call error (expected if no permissions):', e.message);
  }

  // Custom span with HTTP call
  const span = tracer.startSpan('my-custom-span');
  span.setAttribute('key1', 'value1');
  try {
    const response = await fetch('https://aws.amazon.com');
    span.setAttribute('http.status_code', response.status);
    console.log('HTTP call to aws.amazon.com status:', response.status);
  } catch (e) {
    console.log('HTTP call error:', e.message);
    span.setAttribute('error', true);
  }
  span.end();

  return {
    statusCode: 200,
    body: JSON.stringify({
      message: 'Metrics and traces emitted',
      functionName: process.env.AWS_LAMBDA_FUNCTION_NAME
    })
  };
};

CW Metrics

image

Application Signals Related Metrics

image

🤖 Generated with Claude Code

@syed-ahsan-ishtiaque syed-ahsan-ishtiaque requested a review from a team as a code owner December 5, 2025 07:06
When both OTEL_AWS_APPLICATION_SIGNALS_ENABLED and
OTEL_AWS_APPLICATION_SIGNALS_EMF_EXPORT_ENABLED are set to true,
EMF metrics will now include Service and Environment as dimensions:

- Service: extracted from service.name resource attribute,
  falls back to "UnknownService"
- Environment: extracted from deployment.environment resource
  attribute, falls back to "lambda:default"
- Dimensions are not added if user already set them (case-insensitive)

For Lambda, both env vars default to true via otel-instrument wrapper.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants