Skip to content

Commit b3526ce

Browse files
committed
feat(aws): Add SENTRY_LAYER_EXTENSION to configure using the lambda layer
extension via env variables
1 parent ea20d8d commit b3526ce

File tree

3 files changed

+191
-2
lines changed

3 files changed

+191
-2
lines changed

packages/aws-serverless/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
"@opentelemetry/semantic-conventions": "^1.37.0",
7272
"@sentry/core": "10.22.0",
7373
"@sentry/node": "10.22.0",
74+
"@sentry/node-core": "10.22.0",
7475
"@types/aws-lambda": "^8.10.62"
7576
},
7677
"devDependencies": {

packages/aws-serverless/src/init.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { Integration, Options } from '@sentry/core';
22
import { applySdkMetadata, debug, getSDKSource } from '@sentry/core';
33
import type { NodeClient, NodeOptions } from '@sentry/node';
44
import { getDefaultIntegrationsWithoutPerformance, initWithoutDefaultIntegrations } from '@sentry/node';
5+
import { envToBool } from '@sentry/node-core';
56
import { DEBUG_BUILD } from './debug-build';
67
import { awsIntegration } from './integration/aws';
78
import { awsLambdaIntegration } from './integration/awslambda';
@@ -54,7 +55,10 @@ export function getDefaultIntegrations(_options: Options): Integration[] {
5455

5556
export interface AwsServerlessOptions extends NodeOptions {
5657
/**
57-
* If Sentry events should be proxied through the Lambda extension when using the Lambda layer. Defaults to `true` when using the Lambda layer.
58+
* If Sentry events should be proxied through the Lambda extension when using the Lambda layer.
59+
* Defaults to `true` when using the Lambda layer.
60+
*
61+
* Can also be configured via the `SENTRY_LAYER_EXTENSION` environment variable.
5862
*/
5963
useLayerExtension?: boolean;
6064
}
@@ -68,9 +72,23 @@ export function init(options: AwsServerlessOptions = {}): NodeClient | undefined
6872
const sdkSource = getSDKSource();
6973
const proxyWouldInterfere = shouldDisableLayerExtensionForProxy();
7074

75+
// Determine useLayerExtension value with the following priority:
76+
// 1. Explicit option value (if provided)
77+
// 2. Environment variable SENTRY_LAYER_EXTENSION (if set)
78+
// 3. Default logic based on sdkSource, tunnel, and proxy settings
79+
const useLayerExtensionFromEnv = envToBool(process.env.SENTRY_LAYER_EXTENSION, { strict: true });
80+
const defaultUseLayerExtension = sdkSource === 'aws-lambda-layer' && !options.tunnel && !proxyWouldInterfere;
81+
82+
const useLayerExtension =
83+
options.useLayerExtension !== undefined
84+
? options.useLayerExtension
85+
: useLayerExtensionFromEnv !== null
86+
? useLayerExtensionFromEnv
87+
: defaultUseLayerExtension;
88+
7189
const opts = {
7290
defaultIntegrations: getDefaultIntegrations(options),
73-
useLayerExtension: sdkSource === 'aws-lambda-layer' && !options.tunnel && !proxyWouldInterfere,
91+
useLayerExtension,
7492
...options,
7593
};
7694

packages/aws-serverless/test/init.test.ts

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ describe('init', () => {
2222
// Clean up environment variables between tests
2323
delete process.env.http_proxy;
2424
delete process.env.no_proxy;
25+
delete process.env.SENTRY_LAYER_EXTENSION;
2526
});
2627

2728
describe('Lambda extension setup', () => {
@@ -386,4 +387,173 @@ describe('init', () => {
386387
);
387388
});
388389
});
390+
391+
describe('SENTRY_LAYER_EXTENSION environment variable', () => {
392+
test('should enable useLayerExtension when SENTRY_LAYER_EXTENSION=true', () => {
393+
process.env.SENTRY_LAYER_EXTENSION = 'true';
394+
mockGetSDKSource.mockReturnValue('aws-lambda-layer');
395+
const options: AwsServerlessOptions = {};
396+
397+
init(options);
398+
399+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
400+
expect.objectContaining({
401+
useLayerExtension: true,
402+
tunnel: 'http://localhost:9000/envelope',
403+
}),
404+
);
405+
});
406+
407+
test('should disable useLayerExtension when SENTRY_LAYER_EXTENSION=false', () => {
408+
process.env.SENTRY_LAYER_EXTENSION = 'false';
409+
mockGetSDKSource.mockReturnValue('aws-lambda-layer');
410+
const options: AwsServerlessOptions = {};
411+
412+
init(options);
413+
414+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
415+
expect.objectContaining({
416+
useLayerExtension: false,
417+
}),
418+
);
419+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
420+
expect.not.objectContaining({
421+
tunnel: expect.any(String),
422+
}),
423+
);
424+
});
425+
426+
test('should support various truthy values (1, yes, on)', () => {
427+
const truthyValues = ['1', 'yes', 'on', 'y', 't'];
428+
429+
truthyValues.forEach(value => {
430+
mockGetSDKSource.mockReturnValue('aws-lambda-layer');
431+
process.env.SENTRY_LAYER_EXTENSION = value;
432+
433+
init({});
434+
435+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
436+
expect.objectContaining({
437+
useLayerExtension: true,
438+
}),
439+
);
440+
});
441+
});
442+
443+
test('should support various falsy values (0, no, off)', () => {
444+
const falsyValues = ['0', 'no', 'off', 'n', 'f'];
445+
446+
falsyValues.forEach(value => {
447+
mockGetSDKSource.mockReturnValue('aws-lambda-layer');
448+
process.env.SENTRY_LAYER_EXTENSION = value;
449+
450+
init({});
451+
452+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
453+
expect.objectContaining({
454+
useLayerExtension: false,
455+
}),
456+
);
457+
});
458+
});
459+
460+
test('should fall back to default behavior when SENTRY_LAYER_EXTENSION is not set', () => {
461+
mockGetSDKSource.mockReturnValue('aws-lambda-layer');
462+
const options: AwsServerlessOptions = {};
463+
464+
init(options);
465+
466+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
467+
expect.objectContaining({
468+
useLayerExtension: true,
469+
tunnel: 'http://localhost:9000/envelope',
470+
}),
471+
);
472+
});
473+
474+
test('should fall back to default behavior when SENTRY_LAYER_EXTENSION has invalid value', () => {
475+
process.env.SENTRY_LAYER_EXTENSION = 'invalid';
476+
mockGetSDKSource.mockReturnValue('aws-lambda-layer');
477+
const options: AwsServerlessOptions = {};
478+
479+
init(options);
480+
481+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
482+
expect.objectContaining({
483+
useLayerExtension: true,
484+
tunnel: 'http://localhost:9000/envelope',
485+
}),
486+
);
487+
});
488+
489+
test('should prioritize explicit option over environment variable', () => {
490+
process.env.SENTRY_LAYER_EXTENSION = 'true';
491+
mockGetSDKSource.mockReturnValue('aws-lambda-layer');
492+
const options: AwsServerlessOptions = {
493+
useLayerExtension: false,
494+
};
495+
496+
init(options);
497+
498+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
499+
expect.objectContaining({
500+
useLayerExtension: false,
501+
}),
502+
);
503+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
504+
expect.not.objectContaining({
505+
tunnel: expect.any(String),
506+
}),
507+
);
508+
});
509+
510+
test('should respect environment variable when explicit option is not provided', () => {
511+
process.env.SENTRY_LAYER_EXTENSION = 'false';
512+
mockGetSDKSource.mockReturnValue('aws-lambda-layer');
513+
const options: AwsServerlessOptions = {};
514+
515+
init(options);
516+
517+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
518+
expect.objectContaining({
519+
useLayerExtension: false,
520+
}),
521+
);
522+
});
523+
524+
test('should enable useLayerExtension via env var even with proxy when explicitly set', () => {
525+
process.env.http_proxy = 'http://proxy.example.com:8080';
526+
process.env.SENTRY_LAYER_EXTENSION = 'true';
527+
mockGetSDKSource.mockReturnValue('aws-lambda-layer');
528+
const options: AwsServerlessOptions = {};
529+
530+
init(options);
531+
532+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
533+
expect.objectContaining({
534+
useLayerExtension: true,
535+
tunnel: 'http://localhost:9000/envelope',
536+
}),
537+
);
538+
});
539+
540+
test('should disable useLayerExtension via env var even without proxy', () => {
541+
process.env.SENTRY_LAYER_EXTENSION = 'false';
542+
mockGetSDKSource.mockReturnValue('aws-lambda-layer');
543+
const options: AwsServerlessOptions = {};
544+
545+
init(options);
546+
547+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
548+
expect.objectContaining({
549+
useLayerExtension: false,
550+
}),
551+
);
552+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
553+
expect.not.objectContaining({
554+
tunnel: expect.any(String),
555+
}),
556+
);
557+
});
558+
});
389559
});

0 commit comments

Comments
 (0)