Skip to content

feat(node): Add awsLambdaWebIntegration for Lambda Web Functions - #25355

Open
msonnb wants to merge 8 commits into
developfrom
ms/lambda-web-functions
Open

msonnb wants to merge 8 commits into
developfrom
ms/lambda-web-functions

Conversation

@msonnb

@msonnb msonnb commented Oct 14, 2026 •

Copy link
Copy Markdown
Member

This adds a new awsLambdaWebIntegration to the Node SDK for instrumenting Lambda Web Functions. Web Functions run standard Node HTTP servers like Express or Hono, without Lambda-specific handlers or adapters.

Enriches event contexts and segment spans with AWS metadata, request IDs, endpoint names, and cold-start information.

Closes #25317
conventions PR for new attributes: getsentry/sentry-conventions#715

@github-actions

github-actions Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

size-limit report 📦

Path Size % Change Change
@sentry/browser 29.83 kB - -
@sentry/browser - with treeshaking flags 27.96 kB - -
@sentry/browser - with treeshaking flags tracing without tracing 27.87 kB - -
@sentry/browser (incl. Tracing) 52.02 kB - -
@sentry/browser (incl. Tracing + Span Streaming) 52.02 kB - -
@sentry/browser (incl. Tracing, Profiling) 54.96 kB - -
@sentry/browser (incl. Tracing, Replay) 91.75 kB - -
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 80.62 kB - -
@sentry/browser (incl. Tracing, Replay with Canvas) 96.47 kB - -
@sentry/browser (incl. Tracing, Replay, Feedback) 109.43 kB - -
@sentry/browser (incl. Feedback) 47.35 kB - -
@sentry/browser (incl. sendFeedback) 34.89 kB - -
@sentry/browser (incl. FeedbackAsync) 40 kB - -
@sentry/browser (incl. Metrics) 30.85 kB - -
@sentry/browser (incl. Logs) 31.13 kB - -
@sentry/browser (incl. Metrics & Logs) 31.78 kB - -
@sentry/react 31.64 kB - -
@sentry/react (incl. Tracing) 54.34 kB - -
@sentry/vue 37.98 kB - -
@sentry/vue (incl. Tracing) 54.95 kB - -
@sentry/svelte 29.86 kB - -
@sentry/remix (Remix 3 client bundle) 57.02 kB - -
CDN Bundle 31.56 kB - -
CDN Bundle (incl. Tracing) 52.52 kB - -
CDN Bundle (incl. Logs, Metrics) 33.77 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) 54.46 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) 74.7 kB - -
CDN Bundle (incl. Tracing, Replay) 90.19 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 92.11 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) 96.34 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 98.28 kB - -
CDN Bundle - uncompressed 92.98 kB - -
CDN Bundle (incl. Tracing) - uncompressed 155.83 kB - -
CDN Bundle (incl. Logs, Metrics) - uncompressed 99.52 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 161.79 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 229.56 kB - -
CDN Bundle (incl. Tracing, Replay) - uncompressed 276 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 281.94 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 289.7 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 295.63 kB - -
@sentry/nextjs (client) 56.75 kB - -
@sentry/sveltekit (client) 52.41 kB - -
@sentry/core/server 41.12 kB - -
@sentry/core/browser 13.81 kB - -
@sentry/node 152.48 kB +0.34% +503 B 🔺
@sentry/node/import (ESM hook with diagnostics-channel injection) 83.78 kB - -
@sentry/node - without tracing 95.1 kB +0.6% +567 B 🔺
@sentry/node - without channel injection 130.68 kB +0.39% +507 B 🔺
@sentry/aws-serverless 103.23 kB +0.53% +537 B 🔺
@sentry/cloudflare (withSentry) - minified 210.38 kB - -
@sentry/cloudflare (withSentry) 521.61 kB - -
@sentry/nextjs/cloudflare (withSentry) - minified 228.06 kB - -

View base workflow run

msonnb and others added 3 commits October 14, 2026 10:45
@msonnb

msonnb commented Oct 14, 2026

Copy link
Copy Markdown
Member Author

bugbot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 8639881. Configure here.

msonnb and others added 4 commits October 14, 2026 12:06
Co-Authored-By: Codex <codex@openai.com>
Co-Authored-By: Codex <codex@openai.com>
@msonnb
msonnb marked this pull request as ready for review October 14, 2026 11:50
@msonnb
msonnb requested review from a team as code owners October 14, 2026 11:50
@msonnb
msonnb requested review from andreiborza, chargome, isaacs, mydea and s1gr1d and removed request for a team October 14, 2026 11:50
Comment on lines +29 to +30
'faas.max_memory': lambdaContext.memory_size,
'aws.lambda.initialization_type': lambdaContext.initialization_type,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we already have those attributes in conventions?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Def wanna make these not hard-coded once that lands and probably, wait on this until then. If we need to land this first for some reason, then we should open a tracking issue to make sure it's not forgotten.

@isaacs isaacs self-assigned this Oct 16, 2026

@isaacs isaacs left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main blocker is waiting for the conventions to land, obviously. This is a good approach overall.

Comment on lines +16 to +21
const cloudContext: SpanAttributes = {
[CLOUD_PROVIDER]: 'aws',
[CLOUD_PLATFORM]: 'aws_lambda',
[CLOUD_REGION]: process.env.AWS_REGION,
[CLOUD_ACCOUNT_ID]: process.env.AWS_ACCOUNT_ID,
};

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cloud_resource here overlaps nodeContextIntegration, and the result depends on integration order, which could be brittle.

nodeContextIntegration already detects AWS through AWS_REGION (packages/node/src/integrations/context.ts line 531) and sets cloud.platform to process.env.AWS_EXECUTION_ENV (for example AWS_Lambda_nodejs24.x). This PR sets cloud.platform to aws_lambda. Both integrations use "existing value wins" merging ({ ...defaults, ...event.contexts.cloud_resource } in processEvent, and safeSetSpanJSONAttributes in processSegmentSpan). So the integration that runs first wins, for events and for spans.

Today awsLambdaWebIntegration() sits just before nodeContextIntegration() in packages/node/src/sdk/index.ts line 70, so aws_lambda wins. The integration test proves this, because it sets AWS_EXECUTION_ENV. But nothing documents the dependency. If a user builds the list with integrations: defaults => [...] or defaultIntegrations: false and puts this integration after nodeContextIntegration, cloud.platform silently becomes AWS_Lambda_nodejs24.x-lite. A later reorder of the defaults would do the same, and only the integration test would catch it.

This PR also has two places that decide "what cloud am I in" for the same process.

Suggestion: move the Web Function cloud detection into getCloudResourceContext() in packages/node/src/integrations/context.ts (when AWS_LAMBDA_HTTP_ENDPOINT is set, return cloud.platform: 'aws_lambda' plus cloud.account.id). Then awsLambdaWebIntegration only handles the aws.lambda context and the per-request data, and the order no longer matters. Or, I guess, we could add a short comment at the default-list entry that says it must come before nodeContextIntegration, and why.

Comment on lines +29 to +30
'faas.max_memory': lambdaContext.memory_size,
'aws.lambda.initialization_type': lambdaContext.initialization_type,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Def wanna make these not hard-coded once that lands and probably, wait on this until then. If we need to land this first for some reason, then we should open a tracking issue to make sure it's not forgotten.

Comment on lines +39 to +41
if (getClient() !== client) {
return;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This guard doesn't actually do anything.

client.on('httpServerRequest', ...) registers the callback on this client only. The only emitter (packages/node/src/integrations/http/httpServerIntegration.ts line 127) calls emit on getClient(). So the callback only runs when getClient() === client. httpServerSpansIntegration subscribes to the same hook without a guard. Coverage confirms that line 40 is never hit.

Suggested change
if (getClient() !== client) {
return;
}

Comment on lines +47 to +62
const scope = getIsolationScope();
const requestContext: { cold_start: boolean; aws_request_id?: string; endpoint_name?: string } = {
...scope.getScopeData().contexts['aws.lambda'],
cold_start: coldStart,
};
if (typeof requestId === 'string') {
requestContext.aws_request_id = requestId;
} else {
delete requestContext.aws_request_id;
}
if (typeof endpointName === 'string') {
requestContext.endpoint_name = endpointName;
} else {
delete requestContext.endpoint_name;
}
scope.setContext('aws.lambda', requestContext);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Context values of undefined are dropped when the event is normalized, and the processSegmentSpan code already checks typeof ... === 'string'. So I think we can do this with a bit less code:

Suggested change
const scope = getIsolationScope();
const requestContext: { cold_start: boolean; aws_request_id?: string; endpoint_name?: string } = {
...scope.getScopeData().contexts['aws.lambda'],
cold_start: coldStart,
};
if (typeof requestId === 'string') {
requestContext.aws_request_id = requestId;
} else {
delete requestContext.aws_request_id;
}
if (typeof endpointName === 'string') {
requestContext.endpoint_name = endpointName;
} else {
delete requestContext.endpoint_name;
}
scope.setContext('aws.lambda', requestContext);
const scope = getIsolationScope();
scope.setContext('aws.lambda', {
...scope.getScopeData().contexts['aws.lambda'],
cold_start: coldStart,
aws_request_id: typeof requestId === 'string' ? requestId : undefined,
endpoint_name: typeof endpointName === 'string' ? endpointName : undefined,
});

Comment thread packages/bun/src/index.ts
modulesIntegration,
contextLinesIntegration,
nodeContextIntegration,
awsLambdaWebIntegration,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that in packages/elysia/src/index.ts line 77: Elysia re-exports nodeContextIntegration from @sentry/bun but not awsLambdaWebIntegration.

It's being added to @sentry/bun (so the consistentExports check passes), but @sentry/elysia, which re-exports a list from @sentry/bun, does not get it. consistentExports.ts doesn't check Elysia, so CI won't catch this. Of course, they're node-only, so it kind of doesn't make sense anyway.

Suggestion: either add awsLambdaWebIntegration to the Elysia export list for consistency, or (maybe more sensible? since they're node-only) add it to Bun's ignoreExports in dev-packages/e2e-tests/test-applications/node-exports-test-app/scripts/consistentExports.ts and remove it from here.

@github-actions

Copy link
Copy Markdown
Contributor

👋 @mydea, @chargome, @andreiborza — Please review this PR when you get a chance!

1 similar comment
@github-actions

Copy link
Copy Markdown
Contributor

👋 @mydea, @chargome, @andreiborza — Please review this PR when you get a chance!

@isaacs isaacs assigned msonnb and unassigned isaacs Oct 22, 2026

This branch has not been deployed

No deployments
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.

Add support for AWS Lambda Web Functions

3 participants