Skip to content

Commit

Permalink
feat(detector-aws): add attributes to aws lambda detector
Browse files Browse the repository at this point in the history
  • Loading branch information
garysassano committed Jan 17, 2025
1 parent f97bd70 commit dfa4c57
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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, return early if not
const executionEnv = process.env.AWS_EXECUTION_ENV;
if (!executionEnv?.startsWith('AWS_Lambda_')) {
return Resource.empty();
}

const functionVersion = process.env.AWS_LAMBDA_FUNCTION_VERSION;
const region = process.env.AWS_REGION;
// 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!;

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_FAAS_NAME]: functionName,
[ATTR_CLOUD_REGION]: region,
[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;
// 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;

if (logStreamName) {
attributes[ATTR_FAAS_INSTANCE] = logStreamName;
}
if (functionVersion) {
attributes[ATTR_FAAS_VERSION] = functionVersion;
if (logGroupName) {
attributes[ATTR_AWS_LOG_GROUP_NAMES] = [logGroupName];
}

return new Resource(attributes);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,20 @@

import * as assert from 'assert';
import {
assertCloudResource,
assertEmptyResource,
} from '@opentelemetry/contrib-test-utils';
import {
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';

Expand All @@ -35,25 +46,40 @@ 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_EC2';
process.env.AWS_LAMBDA_FUNCTION_NAME = 'name';
process.env.AWS_REGION = 'us-east-1';

const resource = awsLambdaDetectorSync.detect();
Expand Down

0 comments on commit dfa4c57

Please sign in to comment.