-
Notifications
You must be signed in to change notification settings - Fork 228
/
Copy pathlambda.js
105 lines (94 loc) · 3.19 KB
/
lambda.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
'use strict'
const shimmer = require('./instrumentation/shimmer')
module.exports = function elasticApmAwsLambda (agent) {
function captureContext (trans, payload, context, result) {
trans.setCustomContext({
lambda: {
functionName: context.functionName,
functionVersion: context.functionVersion,
invokedFunctionArn: context.invokedFunctionArn,
memoryLimitInMB: context.memoryLimitInMB,
awsRequestId: context.awsRequestId,
logGroupName: context.logGroupName,
logStreamName: context.logStreamName,
executionEnv: process.env.AWS_EXECUTION_ENV,
region: process.env.AWS_REGION,
input: payload,
output: result
}
})
}
function wrapContext (trans, payload, context) {
shimmer.wrap(context, 'succeed', (succeed) => {
return function wrappedSucceed (result) {
const bound = succeed.bind(this, result)
const done = captureAndMakeCompleter(trans, payload, context, result, bound)
done()
}
})
shimmer.wrap(context, 'fail', (fail) => {
return function wrappedFail (err) {
const bound = fail.bind(this, err)
const done = captureAndMakeCompleter(trans, payload, context, undefined, bound)
agent.captureError(err, done)
}
})
shimmer.wrap(context, 'done', (done) => {
return wrapLambdaCallback(trans, payload, context, done)
})
}
function captureAndMakeCompleter (trans, payload, context, result, callback) {
captureContext(trans, payload, context, result)
trans.end()
return () => {
agent.flush((err) => {
if (err) agent.logger.error('Flush error:', err.message)
callback()
})
}
}
function wrapLambdaCallback (trans, payload, context, callback) {
return function wrappedLambdaCallback (err, result) {
const bound = callback.bind(this, err, result)
const done = captureAndMakeCompleter(trans, payload, context, result, bound)
if (err) {
agent.captureError(err, done)
} else {
done()
}
}
}
return function wrapLambda (type, fn) {
if (typeof type === 'function') {
fn = type
type = 'lambda'
}
return function wrappedLambda (payload, context, callback) {
let parentId
if (payload.headers !== undefined) {
for (const [key, value] of Object.entries(payload.headers)) {
const lowerCaseKey = key.toLowerCase()
if (lowerCaseKey === 'elastic-apm-traceparent') {
parentId = value
break
} else if (lowerCaseKey === 'traceparent') {
/**
* We do not break here because we want to make sure to use
* elastic-apm-traceparent if available.
*/
parentId = value
}
}
}
const trans = agent.startTransaction(context.functionName, type, {
childOf: parentId
})
// Wrap context and callback to finish and send transaction
wrapContext(trans, payload, context)
if (typeof callback === 'function') {
callback = wrapLambdaCallback(trans, payload, context, callback)
}
return fn.call(this, payload, context, callback)
}
}
}