Skip to content

Commit

Permalink
Activate ESM loader hook of the "import-in-the-middle" library for ES…
Browse files Browse the repository at this point in the history
… (EcmaScript) based user handlers
  • Loading branch information
serkan-ozal committed Oct 29, 2024
1 parent 9a80ceb commit 69ec303
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 1 deletion.
2 changes: 1 addition & 1 deletion nodejs/packages/layer/scripts/otel-handler
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

set -ef -o pipefail

export NODE_OPTIONS="${NODE_OPTIONS} --require /opt/wrapper.js"
export NODE_OPTIONS="${NODE_OPTIONS} --import /opt/loader.mjs --require /opt/wrapper.js"

if [[ $OTEL_RESOURCE_ATTRIBUTES != *"service.name="* ]]; then
export OTEL_RESOURCE_ATTRIBUTES="service.name=${AWS_LAMBDA_FUNCTION_NAME},${OTEL_RESOURCE_ATTRIBUTES}"
Expand Down
71 changes: 71 additions & 0 deletions nodejs/packages/layer/src/loader.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { register } from 'module';
import * as path from 'path';
import * as fs from 'fs';

function _hasFolderPackageJsonTypeModule(folder) {
if (folder.endsWith('/node_modules')) {
return false;
}
let pj = path.join(folder, '/package.json');
if (fs.existsSync(pj)) {
try {
let pkg = JSON.parse(fs.readFileSync(pj).toString());
if (pkg) {
if (pkg.type === 'module') {
return true;
} else {
return false;
}
}
} catch (e) {
console.warn(`${pj} cannot be read, it will be ignored for ES module detection purposes.`, e);
return false;
}
}
if (folder === '/') {
return false;
}
return _hasFolderPackageJsonTypeModule(path.resolve(folder, '..'));
}

function _hasPackageJsonTypeModule(file) {
let jsPath = file + '.js';
if (fs.existsSync(jsPath)) {
return _hasFolderPackageJsonTypeModule(path.resolve(path.dirname(jsPath)));
}
return false;
}

function _resolveHandlerFileName() {
const taskRoot = process.env.LAMBDA_TASK_ROOT;
const handlerDef = process.env._HANDLER;
const handler = path.basename(handlerDef);
const moduleRoot = handlerDef.substr(0, handlerDef.length - handler.length);
const [module, _] = handler.split('.', 2);
return path.resolve(taskRoot, moduleRoot, module);
}

function _isHandlerAnESModule() {
const handlerFileName = _resolveHandlerFileName();
if (fs.existsSync(handlerFileName + '.mjs')) {
return true;
} else if (fs.existsSync(handlerFileName + '.cjs')) {
return false;
} else {
return _hasPackageJsonTypeModule(handlerFileName);
}
}

if (_isHandlerAnESModule()) {
/*
We could activate ESM loader hook of the "import-in-the-middle" library,
- by "--loader=import-in-the-middle/hook.mjs" Node CLI option, but "--loader" option has been deprecated
- or by "--import=import-in-the-middle/hook.mjs" Node CLI option, but in this case,
there will always be "import-in-the-middle" hook initialization overhead even for non-ESM (CommonJS) modules
Hence, instead, we initialize "import-in-the-middle" hook only for ES (EcmaScript) based user handlers
to prevent redundant "import-in-the-middle" hook initialization overhead during coldstart
of the CommonJS based user handlers.
*/
register('import-in-the-middle/hook.mjs', import.meta.url);
}

0 comments on commit 69ec303

Please sign in to comment.