-
Notifications
You must be signed in to change notification settings - Fork 44
Expand file tree
/
Copy pathindex.js
More file actions
154 lines (125 loc) · 4.44 KB
/
Copy pathindex.js
File metadata and controls
154 lines (125 loc) · 4.44 KB
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
'use strict'
process.env.NEW_RELIC_APP_NAME = process.env.NEW_RELIC_APP_NAME || process.env.AWS_LAMBDA_FUNCTION_NAME
process.env.NEW_RELIC_DISTRIBUTED_TRACING_ENABLED = process.env.NEW_RELIC_DISTRIBUTED_TRACING_ENABLED || 'true'
process.env.NEW_RELIC_NO_CONFIG_FILE = process.env.NEW_RELIC_NO_CONFIG_FILE || 'true'
process.env.NEW_RELIC_TRUSTED_ACCOUNT_KEY =
process.env.NEW_RELIC_TRUSTED_ACCOUNT_KEY || process.env.NEW_RELIC_ACCOUNT_ID
if (process.env.LAMBDA_TASK_ROOT && typeof process.env.NEW_RELIC_SERVERLESS_MODE_ENABLED !== 'undefined') {
delete process.env.NEW_RELIC_SERVERLESS_MODE_ENABLED
}
const newrelic = require('newrelic')
const fs = require('node:fs')
const path = require('node:path')
function getHandlerPath() {
let handler
const { NEW_RELIC_LAMBDA_HANDLER } = process.env
if (!NEW_RELIC_LAMBDA_HANDLER) {
throw new Error('No NEW_RELIC_LAMBDA_HANDLER environment variable set.')
} else {
handler = NEW_RELIC_LAMBDA_HANDLER
}
const parts = handler.split('.')
if (parts.length < 2) {
throw new Error(
`Improperly formatted handler environment variable: ${handler}`
)
}
const handlerToWrap = parts.slice(1).join('.')
const moduleToImport = handler.slice(0, handler.indexOf('.'))
return { moduleToImport, handlerToWrap }
}
function resolveHandler(object, nestedProperty) {
return nestedProperty.split('.').reduce((nested, key) => {
return nested && nested[key]
}, object)
}
function handleRequireImportError(e, moduleToImport) {
if (e.code === 'MODULE_NOT_FOUND') {
return new Error(`Unable to import module '${moduleToImport}'`)
}
return e
}
function getFullyQualifiedModulePath(modulePath, extensions) {
let fullModulePath
extensions.forEach((extension) => {
const filePath = modulePath + extension
if (fs.existsSync(filePath)) {
fullModulePath = filePath
return
}
})
if (!fullModulePath) {
throw new Error(
`Unable to resolve module file at ${modulePath} with the following extensions: ${extensions.join(',')}`
)
}
return fullModulePath
}
async function getModuleWithImport(appRoot, moduleToImport) {
const modulePath = path.resolve(appRoot, moduleToImport)
const validExtensions = ['.mjs', '.js']
const fullModulePath = getFullyQualifiedModulePath(modulePath, validExtensions)
try {
return await import(fullModulePath)
} catch (err) {
throw handleRequireImportError(err, moduleToImport)
}
}
function getModuleWithRequire(appRoot, moduleToImport) {
const modulePath = path.resolve(appRoot, moduleToImport)
const validExtensions = ['.cjs', '.js']
const fullModulePath = getFullyQualifiedModulePath(modulePath, validExtensions)
try {
return require(fullModulePath)
} catch (err) {
throw handleRequireImportError(err, moduleToImport)
}
}
function validateHandlerDefinition(userHandler, handlerName, moduleName) {
if (typeof userHandler === 'undefined') {
throw new Error(
`Handler '${handlerName}' missing on module '${moduleName}'`
)
}
if (typeof userHandler !== 'function') {
throw new Error(
`Handler '${handlerName}' from '${moduleName}' is not a function`
)
}
}
let wrappedHandler
let patchedHandlerPromise
const { LAMBDA_TASK_ROOT = '.' } = process.env
const { moduleToImport, handlerToWrap } = getHandlerPath()
if (process.env.NEW_RELIC_USE_ESM === 'true') {
patchedHandlerPromise = getHandler().then(userHandler => {
return newrelic.setLambdaHandler(userHandler)
})
} else {
wrappedHandler = newrelic.setLambdaHandler(getHandlerSync())
}
async function getHandler() {
const userApp = await getModuleWithImport(LAMBDA_TASK_ROOT, moduleToImport)
const userHandler = resolveHandler(userApp, handlerToWrap)
validateHandlerDefinition(userHandler, handlerToWrap, moduleToImport)
return userHandler
}
function getHandlerSync() {
const userApp = getModuleWithRequire(LAMBDA_TASK_ROOT, moduleToImport)
const userHandler = resolveHandler(userApp, handlerToWrap)
validateHandlerDefinition(userHandler, handlerToWrap, moduleToImport)
return userHandler
}
async function patchHandler() {
const args = Array.prototype.slice.call(arguments)
return patchedHandlerPromise
.then(_wrappedHandler => _wrappedHandler.apply(this, args))
}
function patchHandlerSync() {
const args = Array.prototype.slice.call(arguments)
return wrappedHandler.apply(this, args)
}
module.exports = {
handler: process.env.NEW_RELIC_USE_ESM === 'true' ? patchHandler : patchHandlerSync,
getHandlerPath
}