From e3923f335eb6ec41e1099cb5ffd9cb107b7b3214 Mon Sep 17 00:00:00 2001 From: Gary Sassano <10464497+garysassano@users.noreply.github.com> Date: Fri, 17 Jan 2025 14:39:51 +0100 Subject: [PATCH 1/6] feat(detector-aws): add attributes to aws lambda detector --- .../src/detectors/AwsLambdaDetectorSync.ts | 47 ++++++++++---- .../test/detectors/AwsLambdaDetector.test.ts | 1 + .../detectors/AwsLambdaDetectorSync.test.ts | 64 +++++++++++++++---- 3 files changed, 85 insertions(+), 27 deletions(-) diff --git a/detectors/node/opentelemetry-resource-detector-aws/src/detectors/AwsLambdaDetectorSync.ts b/detectors/node/opentelemetry-resource-detector-aws/src/detectors/AwsLambdaDetectorSync.ts index da7187e565..7d0a503aad 100644 --- a/detectors/node/opentelemetry-resource-detector-aws/src/detectors/AwsLambdaDetectorSync.ts +++ b/detectors/node/opentelemetry-resource-detector-aws/src/detectors/AwsLambdaDetectorSync.ts @@ -22,43 +22,62 @@ import { ResourceDetectionConfig, } from '@opentelemetry/resources'; import { + // AWS attributes + ATTR_AWS_LOG_GROUP_NAMES, + // Cloud attributes ATTR_CLOUD_PROVIDER, ATTR_CLOUD_PLATFORM, ATTR_CLOUD_REGION, - ATTR_FAAS_VERSION, - ATTR_FAAS_NAME, + // Cloud values (AWS) CLOUD_PROVIDER_VALUE_AWS, CLOUD_PLATFORM_VALUE_AWS_LAMBDA, + // FaaS attributes + ATTR_FAAS_NAME, + ATTR_FAAS_VERSION, + ATTR_FAAS_INSTANCE, + ATTR_FAAS_MAX_MEMORY, } from '@opentelemetry/semantic-conventions/incubating'; /** * The AwsLambdaDetector can be used to detect if a process is running in AWS Lambda * and return a {@link Resource} populated with data about the environment. * Returns an empty Resource if detection fails. + * + * AWS Lambda documentation for available environment variables within the Lambda runtimes. + * @see https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime */ export class AwsLambdaDetectorSync implements DetectorSync { detect(_config?: ResourceDetectionConfig): IResource { - const functionName = process.env.AWS_LAMBDA_FUNCTION_NAME; - if (!functionName) { + // Check if running inside AWS Lambda environment + const executionEnv = process.env.AWS_EXECUTION_ENV; + if (!executionEnv?.startsWith('AWS_Lambda_')) { return Resource.empty(); } - const functionVersion = process.env.AWS_LAMBDA_FUNCTION_VERSION; + // These environment variables are guaranteed to be present in AWS Lambda const region = process.env.AWS_REGION; + const functionName = process.env.AWS_LAMBDA_FUNCTION_NAME; + const functionVersion = process.env.AWS_LAMBDA_FUNCTION_VERSION; + const memorySize = process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE; + + // These environment variables are not available in Lambda SnapStart + const logGroupName = process.env.AWS_LAMBDA_LOG_GROUP_NAME; + const logStreamName = process.env.AWS_LAMBDA_LOG_STREAM_NAME; const attributes: ResourceAttributes = { - [ATTR_CLOUD_PROVIDER]: String(CLOUD_PROVIDER_VALUE_AWS), - [ATTR_CLOUD_PLATFORM]: String(CLOUD_PLATFORM_VALUE_AWS_LAMBDA), + [ATTR_CLOUD_PROVIDER]: CLOUD_PROVIDER_VALUE_AWS, + [ATTR_CLOUD_PLATFORM]: CLOUD_PLATFORM_VALUE_AWS_LAMBDA, + [ATTR_CLOUD_REGION]: region, + [ATTR_FAAS_NAME]: functionName, + [ATTR_FAAS_VERSION]: functionVersion, + [ATTR_FAAS_MAX_MEMORY]: parseInt(memorySize!) * 1024 * 1024, }; - if (region) { - attributes[ATTR_CLOUD_REGION] = region; - } - if (functionName) { - attributes[ATTR_FAAS_NAME] = functionName; + if (logGroupName) { + attributes[ATTR_AWS_LOG_GROUP_NAMES] = [logGroupName]; } - if (functionVersion) { - attributes[ATTR_FAAS_VERSION] = functionVersion; + if (logStreamName) { + attributes[ATTR_FAAS_INSTANCE] = logStreamName; } return new Resource(attributes); diff --git a/detectors/node/opentelemetry-resource-detector-aws/test/detectors/AwsLambdaDetector.test.ts b/detectors/node/opentelemetry-resource-detector-aws/test/detectors/AwsLambdaDetector.test.ts index daaa34c61b..f4ba622fae 100644 --- a/detectors/node/opentelemetry-resource-detector-aws/test/detectors/AwsLambdaDetector.test.ts +++ b/detectors/node/opentelemetry-resource-detector-aws/test/detectors/AwsLambdaDetector.test.ts @@ -35,6 +35,7 @@ describe('awsLambdaDetector', () => { describe('on lambda', () => { it('fills resource', async () => { + process.env.AWS_EXECUTION_ENV = 'AWS_Lambda_nodejs22.x'; process.env.AWS_LAMBDA_FUNCTION_NAME = 'name'; process.env.AWS_LAMBDA_FUNCTION_VERSION = 'v1'; process.env.AWS_REGION = 'us-east-1'; diff --git a/detectors/node/opentelemetry-resource-detector-aws/test/detectors/AwsLambdaDetectorSync.test.ts b/detectors/node/opentelemetry-resource-detector-aws/test/detectors/AwsLambdaDetectorSync.test.ts index e849dc436f..89858c39c6 100644 --- a/detectors/node/opentelemetry-resource-detector-aws/test/detectors/AwsLambdaDetectorSync.test.ts +++ b/detectors/node/opentelemetry-resource-detector-aws/test/detectors/AwsLambdaDetectorSync.test.ts @@ -15,10 +15,19 @@ */ import * as assert from 'assert'; +import { assertEmptyResource } from '@opentelemetry/contrib-test-utils'; import { - assertCloudResource, - assertEmptyResource, -} from '@opentelemetry/contrib-test-utils'; + ATTR_CLOUD_PROVIDER, + ATTR_CLOUD_PLATFORM, + ATTR_CLOUD_REGION, + ATTR_FAAS_NAME, + ATTR_FAAS_VERSION, + ATTR_FAAS_INSTANCE, + ATTR_FAAS_MAX_MEMORY, + ATTR_AWS_LOG_GROUP_NAMES, + CLOUD_PROVIDER_VALUE_AWS, + CLOUD_PLATFORM_VALUE_AWS_LAMBDA, +} from '@opentelemetry/semantic-conventions/incubating'; import { awsLambdaDetectorSync } from '../../src'; @@ -35,25 +44,54 @@ describe('awsLambdaDetectorSync', () => { describe('on lambda', () => { it('fills resource', async () => { + process.env.AWS_EXECUTION_ENV = 'AWS_Lambda_nodejs22.x'; + process.env.AWS_REGION = 'us-east-1'; process.env.AWS_LAMBDA_FUNCTION_NAME = 'name'; process.env.AWS_LAMBDA_FUNCTION_VERSION = 'v1'; - process.env.AWS_REGION = 'us-east-1'; + process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE = '128'; + process.env.AWS_LAMBDA_LOG_GROUP_NAME = '/aws/lambda/name'; + process.env.AWS_LAMBDA_LOG_STREAM_NAME = '2024/03/14/[$LATEST]123456'; const resource = awsLambdaDetectorSync.detect(); - assertCloudResource(resource, { - provider: 'aws', - region: 'us-east-1', - }); - - assert.strictEqual(resource.attributes['faas.name'], 'name'); - assert.strictEqual(resource.attributes['faas.version'], 'v1'); + assert.strictEqual( + resource.attributes[ATTR_CLOUD_PROVIDER], + CLOUD_PROVIDER_VALUE_AWS + ); + assert.strictEqual( + resource.attributes[ATTR_CLOUD_PLATFORM], + CLOUD_PLATFORM_VALUE_AWS_LAMBDA + ); + assert.strictEqual(resource.attributes[ATTR_CLOUD_REGION], 'us-east-1'); + assert.strictEqual(resource.attributes[ATTR_FAAS_NAME], 'name'); + assert.strictEqual(resource.attributes[ATTR_FAAS_VERSION], 'v1'); + assert.strictEqual( + resource.attributes[ATTR_FAAS_INSTANCE], + '2024/03/14/[$LATEST]123456' + ); + assert.strictEqual( + resource.attributes[ATTR_FAAS_MAX_MEMORY], + 128 * 1024 * 1024 + ); + assert.deepStrictEqual(resource.attributes[ATTR_AWS_LOG_GROUP_NAMES], [ + '/aws/lambda/name', + ]); }); }); describe('not on lambda', () => { - it('returns empty resource', async () => { - process.env.AWS_LAMBDA_FUNCTION_VERSION = 'v1'; + it('returns empty resource if AWS_EXECUTION_ENV is not set', async () => { + process.env.AWS_LAMBDA_FUNCTION_NAME = 'name'; + process.env.AWS_REGION = 'us-east-1'; + + const resource = awsLambdaDetectorSync.detect(); + + assertEmptyResource(resource); + }); + + it('returns empty resource if AWS_EXECUTION_ENV is not Lambda', async () => { + process.env.AWS_EXECUTION_ENV = 'AWS_ECS_EC2'; + process.env.AWS_LAMBDA_FUNCTION_NAME = 'name'; process.env.AWS_REGION = 'us-east-1'; const resource = awsLambdaDetectorSync.detect(); From 4580d2671f0f21ae2ecb2f354bb6534d1cfd035f Mon Sep 17 00:00:00 2001 From: Gary Sassano <10464497+garysassano@users.noreply.github.com> Date: Tue, 21 Jan 2025 01:22:43 +0100 Subject: [PATCH 2/6] add missing consts --- .../src/detectors/AwsLambdaDetectorSync.ts | 7 +++--- .../src/semconv.ts | 22 +++++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/detectors/node/opentelemetry-resource-detector-aws/src/detectors/AwsLambdaDetectorSync.ts b/detectors/node/opentelemetry-resource-detector-aws/src/detectors/AwsLambdaDetectorSync.ts index 7ed346deed..cb3b8eb41c 100644 --- a/detectors/node/opentelemetry-resource-detector-aws/src/detectors/AwsLambdaDetectorSync.ts +++ b/detectors/node/opentelemetry-resource-detector-aws/src/detectors/AwsLambdaDetectorSync.ts @@ -22,13 +22,14 @@ import { ResourceDetectionConfig, } from '@opentelemetry/resources'; import { - // AWS attributes ATTR_AWS_LOG_GROUP_NAMES, - // Cloud attributes ATTR_CLOUD_PROVIDER, ATTR_CLOUD_PLATFORM, ATTR_CLOUD_REGION, - // Cloud values (AWS) + ATTR_FAAS_NAME, + ATTR_FAAS_VERSION, + ATTR_FAAS_INSTANCE, + ATTR_FAAS_MAX_MEMORY, CLOUD_PROVIDER_VALUE_AWS, CLOUD_PLATFORM_VALUE_AWS_LAMBDA, } from '../semconv'; diff --git a/detectors/node/opentelemetry-resource-detector-aws/src/semconv.ts b/detectors/node/opentelemetry-resource-detector-aws/src/semconv.ts index 3d34526643..bbf3a8e480 100644 --- a/detectors/node/opentelemetry-resource-detector-aws/src/semconv.ts +++ b/detectors/node/opentelemetry-resource-detector-aws/src/semconv.ts @@ -210,6 +210,28 @@ export const ATTR_CONTAINER_NAME = 'container.name'; */ export const ATTR_FAAS_NAME = 'faas.name'; +/** + * The execution environment ID as a string, that will be potentially reused for other invocations to the same function/function version. + * + * @example 2021/06/28/[$LATEST]2f399eb14537447da05ab2a2e39309de + * + * @note * **AWS Lambda:** Use the (full) log stream name. + * + * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. + */ +export const ATTR_FAAS_INSTANCE = 'faas.instance' as const; + +/** + * The amount of memory available to the serverless function converted to Bytes. + * + * @example 134217728 + * + * @note It's recommended to set this attribute since e.g. too little memory can easily stop a Java AWS Lambda function from working correctly. On AWS Lambda, the environment variable `AWS_LAMBDA_FUNCTION_MEMORY_SIZE` provides this information (which must be multiplied by 1,048,576). + * + * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. + */ +export const ATTR_FAAS_MAX_MEMORY = 'faas.max_memory' as const; + /** * The immutable version of the function being executed. * From ff814dc585157ea228bb828f4c71c114f2385898 Mon Sep 17 00:00:00 2001 From: Gary Sassano <10464497+garysassano@users.noreply.github.com> Date: Tue, 21 Jan 2025 01:24:41 +0100 Subject: [PATCH 3/6] remove semconv incubating from test --- .../test/detectors/AwsLambdaDetectorSync.test.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/detectors/node/opentelemetry-resource-detector-aws/test/detectors/AwsLambdaDetectorSync.test.ts b/detectors/node/opentelemetry-resource-detector-aws/test/detectors/AwsLambdaDetectorSync.test.ts index 89858c39c6..db468cb707 100644 --- a/detectors/node/opentelemetry-resource-detector-aws/test/detectors/AwsLambdaDetectorSync.test.ts +++ b/detectors/node/opentelemetry-resource-detector-aws/test/detectors/AwsLambdaDetectorSync.test.ts @@ -16,6 +16,7 @@ import * as assert from 'assert'; import { assertEmptyResource } from '@opentelemetry/contrib-test-utils'; +import { awsLambdaDetectorSync } from '../../src'; import { ATTR_CLOUD_PROVIDER, ATTR_CLOUD_PLATFORM, @@ -27,9 +28,7 @@ import { ATTR_AWS_LOG_GROUP_NAMES, CLOUD_PROVIDER_VALUE_AWS, CLOUD_PLATFORM_VALUE_AWS_LAMBDA, -} from '@opentelemetry/semantic-conventions/incubating'; - -import { awsLambdaDetectorSync } from '../../src'; +} from '../../src/semconv'; describe('awsLambdaDetectorSync', () => { let oldEnv: NodeJS.ProcessEnv; From feb4552128fa6f260d6db0609d5f221102f52e42 Mon Sep 17 00:00:00 2001 From: Gary Sassano <10464497+garysassano@users.noreply.github.com> Date: Tue, 21 Jan 2025 01:26:57 +0100 Subject: [PATCH 4/6] move link --- .../src/detectors/AwsLambdaDetectorSync.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/detectors/node/opentelemetry-resource-detector-aws/src/detectors/AwsLambdaDetectorSync.ts b/detectors/node/opentelemetry-resource-detector-aws/src/detectors/AwsLambdaDetectorSync.ts index cb3b8eb41c..bfb55249af 100644 --- a/detectors/node/opentelemetry-resource-detector-aws/src/detectors/AwsLambdaDetectorSync.ts +++ b/detectors/node/opentelemetry-resource-detector-aws/src/detectors/AwsLambdaDetectorSync.ts @@ -38,9 +38,6 @@ import { * The AwsLambdaDetector can be used to detect if a process is running in AWS Lambda * and return a {@link Resource} populated with data about the environment. * Returns an empty Resource if detection fails. - * - * AWS Lambda documentation for available environment variables within the Lambda runtimes. - * @see https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime */ export class AwsLambdaDetectorSync implements DetectorSync { detect(_config?: ResourceDetectionConfig): IResource { @@ -51,6 +48,7 @@ export class AwsLambdaDetectorSync implements DetectorSync { } // These environment variables are guaranteed to be present in AWS Lambda + // https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime const region = process.env.AWS_REGION; const functionName = process.env.AWS_LAMBDA_FUNCTION_NAME; const functionVersion = process.env.AWS_LAMBDA_FUNCTION_VERSION; From 90ec5c119c88f06d9790e0caafcf4d2f6be601a2 Mon Sep 17 00:00:00 2001 From: Gary Sassano <10464497+garysassano@users.noreply.github.com> Date: Tue, 21 Jan 2025 01:28:32 +0100 Subject: [PATCH 5/6] remove as const --- .../node/opentelemetry-resource-detector-aws/src/semconv.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/detectors/node/opentelemetry-resource-detector-aws/src/semconv.ts b/detectors/node/opentelemetry-resource-detector-aws/src/semconv.ts index bbf3a8e480..d12c459a10 100644 --- a/detectors/node/opentelemetry-resource-detector-aws/src/semconv.ts +++ b/detectors/node/opentelemetry-resource-detector-aws/src/semconv.ts @@ -219,7 +219,7 @@ export const ATTR_FAAS_NAME = 'faas.name'; * * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. */ -export const ATTR_FAAS_INSTANCE = 'faas.instance' as const; +export const ATTR_FAAS_INSTANCE = 'faas.instance'; /** * The amount of memory available to the serverless function converted to Bytes. @@ -230,7 +230,7 @@ export const ATTR_FAAS_INSTANCE = 'faas.instance' as const; * * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. */ -export const ATTR_FAAS_MAX_MEMORY = 'faas.max_memory' as const; +export const ATTR_FAAS_MAX_MEMORY = 'faas.max_memory'; /** * The immutable version of the function being executed. From 77c19b48b5196fbfbef6aeaf6adce8f77c46363b Mon Sep 17 00:00:00 2001 From: Gary Sassano <10464497+garysassano@users.noreply.github.com> Date: Tue, 21 Jan 2025 01:36:48 +0100 Subject: [PATCH 6/6] update comments --- .../src/detectors/AwsLambdaDetectorSync.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/detectors/node/opentelemetry-resource-detector-aws/src/detectors/AwsLambdaDetectorSync.ts b/detectors/node/opentelemetry-resource-detector-aws/src/detectors/AwsLambdaDetectorSync.ts index bfb55249af..1f7176ce8c 100644 --- a/detectors/node/opentelemetry-resource-detector-aws/src/detectors/AwsLambdaDetectorSync.ts +++ b/detectors/node/opentelemetry-resource-detector-aws/src/detectors/AwsLambdaDetectorSync.ts @@ -47,14 +47,14 @@ export class AwsLambdaDetectorSync implements DetectorSync { return Resource.empty(); } - // These environment variables are guaranteed to be present in AWS Lambda + // These environment variables are guaranteed to be present in Lambda environment // https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime const region = process.env.AWS_REGION; const functionName = process.env.AWS_LAMBDA_FUNCTION_NAME; const functionVersion = process.env.AWS_LAMBDA_FUNCTION_VERSION; const memorySize = process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE; - // These environment variables are not available in Lambda SnapStart + // These environment variables are not available in Lambda SnapStart functions const logGroupName = process.env.AWS_LAMBDA_LOG_GROUP_NAME; const logStreamName = process.env.AWS_LAMBDA_LOG_STREAM_NAME;