Skip to content

Commit f6de93c

Browse files
authored
fix: support Lambda instrumentation for contextManager: 'patch'; refactor Lambda tests (#3305)
Changes in #3285 broke Lambda instrumentation if the deprecated `contextManager:'patch' config var was used. This restores support for that, FWIW. Also, refactoring so we can drop AgentMock and TransactionMock under test/lambda/... to simplify: - roll promises.test.js into the main test file - roll trace-context.test.js into the main lambda test file - roll transaction.test.js into main lambda test file - rename main lambda test file to lambda.test.js - drop now unused MockAgent
1 parent 3bd83ae commit f6de93c

19 files changed

+1006
-1761
lines changed

docs/lambda.asciidoc

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,14 @@ Your Lambda function invocations should be traced from now on.
6161
=== Features
6262

6363
The AWS Lambda instrumentation will report a transaction for all function invocations
64-
and trace any <<compatibility-frameworks,support modules>>. In addition, the
64+
and trace any <<compatibility-frameworks,supported modules>>. In addition, the
6565
created transactions will capture additional data for a number of Lambda
66-
trigger types -- API Gateway, SNS, SQS, S3 (with the trigger is a single event),
66+
trigger types -- API Gateway, SNS, SQS, S3 (when the trigger is a single event),
6767
and ELB.
6868

6969
A transaction will be reported for Lambda invocations that fail due to a
7070
timeout, crash, `uncaughtException`, or `unhandledRejection`. (This requires
71-
APM agent v3.46.0 or later and
71+
APM agent v3.45.0 or later and
7272
https://www.elastic.co/guide/en/apm/lambda/current/aws-lambda-arch.html[Elastic's APM Lambda extension]
7373
version 1.4.0 or later.)
7474

@@ -80,4 +80,5 @@ version 1.4.0 or later.)
8080
* System and custom metrics are not collected for Lambda functions. This is both because most of those are irrelevant
8181
and because the interval-based event sending model is not suitable for FaaS environments.
8282
* Lambda instrumentation does not currently work when the (deprecated) <<context-manager,`contextManager: 'patch'`>> configuration setting is used.
83-
* The APM agent does not yet support a Lambda handler module that uses ECMAScript modules (ESM). That means a your handler file name should end with ".js" (and not have `"type": "module"` in package.json if you have one) or end with ".cjs". A handler file that uses the ".mjs" suffix will not be instrumented by the APM agent.
83+
* The APM agent does not yet support a Lambda handler module that uses ECMAScript modules (ESM). That means your handler file name should end with ".js" (and not have `"type": "module"` in package.json if you have one) or end with ".cjs". A handler file that uses the ".mjs" suffix will not be instrumented by the APM agent.
84+

lib/lambda.js

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,7 @@ function setS3SingleData (trans, event, context, faasId, isColdStart) {
438438

439439
function elasticApmAwsLambda (agent) {
440440
const log = agent.logger
441+
const ins = agent._instrumentation
441442

442443
/**
443444
* Register this transaction with the Lambda extension, if possible. This
@@ -527,34 +528,43 @@ function elasticApmAwsLambda (agent) {
527528
})
528529
}
529530

530-
function wrapContext (trans, event, context, triggerType) {
531+
function wrapContext (runContext, trans, event, context, triggerType) {
531532
shimmer.wrap(context, 'succeed', (origSucceed) => {
532-
return function wrappedSucceed (result) {
533-
endAndFlushTransaction(null, result, trans, event, context, triggerType, function () {
534-
origSucceed(result)
535-
})
536-
}
533+
return ins.bindFunctionToRunContext(
534+
runContext,
535+
function wrappedSucceed (result) {
536+
endAndFlushTransaction(null, result, trans, event, context, triggerType, function () {
537+
origSucceed(result)
538+
})
539+
}
540+
)
537541
})
538542

539543
shimmer.wrap(context, 'fail', (origFail) => {
540-
return function wrappedFail (err) {
541-
endAndFlushTransaction(err, null, trans, event, context, triggerType, function () {
542-
origFail(err)
543-
})
544-
}
544+
return ins.bindFunctionToRunContext(
545+
runContext,
546+
function wrappedFail (err) {
547+
endAndFlushTransaction(err, null, trans, event, context, triggerType, function () {
548+
origFail(err)
549+
})
550+
}
551+
)
545552
})
546553

547554
shimmer.wrap(context, 'done', (origDone) => {
548-
return wrapLambdaCallback(trans, event, context, triggerType, origDone)
555+
return wrapLambdaCallback(runContext, trans, event, context, triggerType, origDone)
549556
})
550557
}
551558

552-
function wrapLambdaCallback (trans, event, context, triggerType, callback) {
553-
return function wrappedLambdaCallback (err, result) {
554-
endAndFlushTransaction(err, result, trans, event, context, triggerType, () => {
555-
callback(err, result)
556-
})
557-
}
559+
function wrapLambdaCallback (runContext, trans, event, context, triggerType, callback) {
560+
return ins.bindFunctionToRunContext(
561+
runContext,
562+
function wrappedLambdaCallback (err, result) {
563+
endAndFlushTransaction(err, result, trans, event, context, triggerType, () => {
564+
callback(err, result)
565+
})
566+
}
567+
)
558568
}
559569

560570
return function wrapLambdaHandler (type, fn) {
@@ -644,13 +654,14 @@ function elasticApmAwsLambda (agent) {
644654
// Note: Wrapping context needs to happen *before any `await` calls* in
645655
// this function, otherwise the Lambda Node.js Runtime will call the
646656
// *unwrapped* `context.{succeed,fail,done}()` methods.
647-
wrapContext(trans, event, context, triggerType)
648-
const wrappedCallback = wrapLambdaCallback(trans, event, context, triggerType, callback)
657+
const transRunContext = ins.currRunContext()
658+
wrapContext(transRunContext, trans, event, context, triggerType)
659+
const wrappedCallback = wrapLambdaCallback(transRunContext, trans, event, context, triggerType, callback)
649660

650661
await registerTransaction(trans, context.awsRequestId)
651662

652663
try {
653-
var retval = fn.call(this, event, context, wrappedCallback)
664+
const retval = ins.withRunContext(transRunContext, fn, this, event, context, wrappedCallback)
654665
if (retval instanceof Promise) {
655666
return retval
656667
} else {

test/lambda/callbacks.test.js

Lines changed: 0 additions & 100 deletions
This file was deleted.

test/lambda/context.test.js

Lines changed: 0 additions & 132 deletions
This file was deleted.

0 commit comments

Comments
 (0)