Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix wrapping ESM files with absolute path #5094

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions experimental/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ All notable changes to experimental packages in this project will be documented

### :bug: (Bug Fix)

* fix(instrumentation): Fix wrapping ESM files with absolute path [#5094](https://github.com/open-telemetry/opentelemetry-js/pull/5094) @serkan-ozal

### :books: (Refine Doc)

### :house: (Internal)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,11 @@ export abstract class InstrumentationBase<
this._warnOnPreloadedModules();
for (const module of this._modules) {
const hookFn: HookFn = (exports, name, baseDir) => {
if (!baseDir && path.isAbsolute(name)) {
const parsedPath = path.parse(name);
name = parsedPath.name;
baseDir = parsedPath.dir;
}
return this._onRequire<typeof exports>(module, exports, name, baseDir);
};
const onRequire: OnRequireFn = (exports, name, baseDir) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,15 @@ import * as assert from 'assert';
import {
InstrumentationBase,
InstrumentationNodeModuleDefinition,
InstrumentationNodeModuleFile,
} from '../../build/src/index.js';
import * as exported from 'test-esm-module';
import * as exportedAbsolute from './esm/test.mjs';

import path from 'path';
import url from 'url';

const TEST_DIR_NAME = path.dirname(url.fileURLToPath(import.meta.url));

class TestInstrumentationWrapFn extends InstrumentationBase {
constructor(config) {
Expand Down Expand Up @@ -95,6 +102,45 @@ class TestInstrumentationSimple extends InstrumentationBase {
);
}
}

class TestAbsoluteFileInstrumentationPatchFn extends InstrumentationBase {
constructor(config) {
super('test-esm-instrumentation', '0.0.1', config);
}
init() {
return new InstrumentationNodeModuleDefinition(
path.join(TEST_DIR_NAME, '/esm/test.mjs'),
['*'],
undefined,
undefined,
[
new InstrumentationNodeModuleFile(
'test',
['*'],
moduleExports => {
const wrapRetval = this._wrap(moduleExports, 'testFunction', () => {
return function wrappedTestFunction() {
return 'patched';
};
});
assert.strictEqual(typeof wrapRetval, 'function');
assert.strictEqual(
wrapRetval.name,
'wrappedTestFunction',
'_wrap(..., "testFunction", ...) return value is the wrapped function'
);
return moduleExports;
},
moduleExports => {
this._unwrap(moduleExports, 'testFunction');
return moduleExports;
}
)
]
)
}
}

describe('when loading esm module', () => {
const instrumentationWrap = new TestInstrumentationWrapFn({
enabled: false,
Expand Down Expand Up @@ -140,4 +186,23 @@ describe('when loading esm module', () => {
assert.deepEqual(exported.testFunction(), 'original');
assert.deepEqual(exported.secondTestFunction(), 'original');
});

it('should patch function from a file with absolute path', async () => {
const instrumentation = new TestAbsoluteFileInstrumentationPatchFn({
enabled: false,
});
instrumentation.enable();
assert.deepEqual(exportedAbsolute.testFunction(), 'patched');
});

it('should unwrap a patched function from a file with absolute path', async () => {
const instrumentation = new TestAbsoluteFileInstrumentationPatchFn({
enabled: false,
});

instrumentation.enable();
// disable to trigger unwrap
instrumentation.disable();
assert.deepEqual(exported.testFunction(), 'original');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const testFunction = () => {
return 'original';
};
Loading