fix(console): Re-patch console in AWS Lambda runtimes#20337
Conversation
size-limit report 📦
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 249d85d. Configure here.
isaacs
left a comment
There was a problem hiding this comment.
Mostly just some questions and edge cases to consider, but this is a very straightforward way around AWS's instrumentation thwarting ours.
Out of scope for this PR, but it does make me wonder if there's a way to abstract this into core/src/utils/object.ts wrapMethod or something. If we find ourselves in this position again, we can consider doing that. Probably premature otherwise, since just wrapping as a plain old method assignment is usually fine.
Tests look good (rubber-stamp LGTM, I did not run the tests.)
| triggerHandlers('console', { args, level } as HandlerDataConsole); | ||
|
|
||
| const log = originalConsoleMethods[level]; | ||
| log?.apply(GLOBAL_OBJ.console, args); |
There was a problem hiding this comment.
| log?.apply(GLOBAL_OBJ.console, args); | |
| return log?.apply(this, args); |
| typeof newValue === 'function' && | ||
| newValue !== wrapper && | ||
| newValue !== originalConsoleMethods[level] && | ||
| !(newValue as WrappedFunction).__sentry_original__ |
There was a problem hiding this comment.
Clobbering the wrapper if it's a sentry wrapped function makes sense (since that's likely ourselves doing it), but I'm unclear why you're allowing it to be set back to the originalConsoleMethods[level].
That would mean:
const original = console.log
// Sentry setup happens
console.log = someAwsThing;
// later...
console.log = original; // lose the Sentry instrumentation!It seems like setting it to the original should just set the consoleDelegate, no?
There was a problem hiding this comment.
True, that's probably a bug. I'm gonna look into that. Currently, it makes sure that the consoleSandbox still works.
There was a problem hiding this comment.
Updated and added a test for that - consoleSandbox also still works.

On AWS Lambda, the Node.js runtime replaces
console.*methods with its own loggers. This means Sentry's console instrumentation gets silently overwritten, and integrations likeconsoleLoggingIntegrationstop capturing console output entirely.This PR fixes that by introducing a
defineProperty-based patching strategy for Lambda environments. Instead of simply assigning a wrapper toconsole.log(which Lambda can overwrite), we define a getter/setter on the console property. When the Lambda runtime assigns its logger, the setter intercepts it, stores the new function as the underlying delegate, and keeps Sentry's wrapper in place. The handler continues to fire, and the Lambda logger still gets called underneath (I checked that manually - the log is still shown in the CloudWatch logs).This behavior is guarded behind
process.env.LAMBDA_TASK_ROOT, so non-Lambda environments continue to use the existingfill()-based patching with zero behavioral change. IfdefinePropertyfails for any reason, it falls back tofill().The setter also handles
consoleSandboxcorrectly (recognizes when it restores the original method and allows it through), and defers to other Sentry wrappers by checking for__sentry_original__.Closes #18238