-
Notifications
You must be signed in to change notification settings - Fork 539
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(instrumentation-aws-lambda): support esm handlers and all other …
…patterns
- Loading branch information
1 parent
2b117bb
commit 4676273
Showing
17 changed files
with
1,021 additions
and
277 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
107 changes: 107 additions & 0 deletions
107
plugins/node/opentelemetry-instrumentation-aws-lambda/src/user-function.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
/** | ||
* Adapted from https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/blob/v3.1.0/src/UserFunction.js | ||
*/ | ||
|
||
import * as path from 'path'; | ||
import * as fs from 'fs'; | ||
import { LambdaModule } from './internal-types'; | ||
|
||
const FUNCTION_EXPR = /^([^.]*)\.(.*)$/; | ||
const RELATIVE_PATH_SUBSTRING = '..'; | ||
|
||
/** | ||
* Break the full handler string into two pieces, the module root and the actual | ||
* handler string. | ||
* Given './somepath/something/module.nestedobj.handler' this returns | ||
* ['./somepath/something', 'module.nestedobj.handler'] | ||
*/ | ||
export function moduleRootAndHandler( | ||
fullHandlerString: string | ||
): [moduleRoot: string, handler: string] { | ||
const handlerString = path.basename(fullHandlerString); | ||
const moduleRoot = fullHandlerString.substring( | ||
0, | ||
fullHandlerString.indexOf(handlerString) | ||
); | ||
return [moduleRoot, handlerString]; | ||
} | ||
|
||
/** | ||
* Split the handler string into two pieces: the module name and the path to | ||
* the handler function. | ||
*/ | ||
export function splitHandlerString( | ||
handler: string | ||
): [module: string | undefined, functionPath: string | undefined] { | ||
const match = handler.match(FUNCTION_EXPR); | ||
if (match && match.length === 3) { | ||
return [match[1], match[2]]; | ||
} else { | ||
return [undefined, undefined]; | ||
} | ||
} | ||
|
||
/** | ||
* Resolve the user's handler function key and its containing object from the module. | ||
*/ | ||
export function resolveHandler( | ||
object: object, | ||
nestedProperty: string | ||
): [container: LambdaModule | undefined, handlerKey: string | undefined] { | ||
const nestedPropertyKeys = nestedProperty.split('.'); | ||
const handlerKey = nestedPropertyKeys.pop(); | ||
|
||
const container = nestedPropertyKeys.reduce<object | undefined>( | ||
(nested, key) => { | ||
return nested && (nested as Partial<Record<string, object>>)[key]; | ||
}, | ||
object | ||
); | ||
|
||
if (container) { | ||
return [container as LambdaModule, handlerKey]; | ||
} else { | ||
return [undefined, undefined]; | ||
} | ||
} | ||
|
||
/** | ||
* Attempt to determine the user's module path. | ||
*/ | ||
export function tryPath( | ||
appRoot: string, | ||
moduleRoot: string, | ||
module: string | ||
): string | undefined { | ||
const lambdaStylePath = path.resolve(appRoot, moduleRoot, module); | ||
|
||
const extensionless = fs.existsSync(lambdaStylePath); | ||
if (extensionless) { | ||
return lambdaStylePath; | ||
} | ||
|
||
const extensioned = | ||
(fs.existsSync(lambdaStylePath + '.js') && lambdaStylePath + '.js') || | ||
(fs.existsSync(lambdaStylePath + '.mjs') && lambdaStylePath + '.mjs') || | ||
(fs.existsSync(lambdaStylePath + '.cjs') && lambdaStylePath + '.cjs'); | ||
if (extensioned) { | ||
return extensioned; | ||
} | ||
|
||
try { | ||
const nodeStylePath = require.resolve(module, { | ||
paths: [appRoot, moduleRoot], | ||
}); | ||
return nodeStylePath; | ||
} catch { | ||
return undefined; | ||
} | ||
} | ||
|
||
export function isInvalidHandler(fullHandlerString: string): boolean { | ||
if (fullHandlerString.includes(RELATIVE_PATH_SUBSTRING)) { | ||
return true; | ||
} else { | ||
return false; | ||
} | ||
} |
Oops, something went wrong.