Skip to content

Commit 3ddb3a9

Browse files
Merge pull request #1 from honeycombio/purvi/esm-tests
ESM test & small refactor
2 parents 33e544c + 7110c37 commit 3ddb3a9

File tree

4 files changed

+94
-29
lines changed

4 files changed

+94
-29
lines changed

examples/esm-http-ts/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { registerInstrumentations } from '@opentelemetry/instrumentation';
2-
import { trace } from '@opentelemetry/api';
2+
import { trace, DiagConsoleLogger, DiagLogLevel, diag } from '@opentelemetry/api';
33
import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
44
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
55
import {
@@ -10,6 +10,7 @@ import { Resource } from '@opentelemetry/resources';
1010
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions';
1111
import http from 'http';
1212

13+
diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.DEBUG);
1314
const tracerProvider = new NodeTracerProvider({
1415
resource: new Resource({
1516
[SemanticResourceAttributes.SERVICE_NAME]: 'esm-http-ts-example',

experimental/packages/opentelemetry-instrumentation/src/instrumentation.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,28 @@ export abstract class InstrumentationAbstract<T = any>
6161
}
6262

6363
/* Api to wrap instrumented method */
64-
protected _wrap = shimmer.wrap;
64+
protected _wrap = (
65+
moduleExports: any,
66+
name: string,
67+
wrapper: (originalFn: any) => any
68+
) => {
69+
try {
70+
return shimmer.wrap(moduleExports, name, wrapper);
71+
} catch (e) {
72+
// shimmer doesn't handle Proxy objects well
73+
// if there is an error from import in the middle providing
74+
// a Proxy of a Module we have to pass it to shimmer as a regular object
75+
const wrapped: any = shimmer.wrap(
76+
Object.assign({}, moduleExports),
77+
name,
78+
wrapper
79+
);
80+
Object.defineProperty(moduleExports, name, {
81+
value: wrapped,
82+
});
83+
return moduleExports;
84+
}
85+
};
6586
/* Api to unwrap instrumented methods */
6687
protected _unwrap = shimmer.unwrap;
6788
/* Api to mass wrap instrumented method */

experimental/packages/opentelemetry-instrumentation/src/platform/node/instrumentation.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ export abstract class InstrumentationBase<T = any>
172172
const hookFn: ImportInTheMiddle.HookFn = (exports, name, baseDir) => {
173173
return this._onRequire<typeof exports>(
174174
module as unknown as InstrumentationModuleDefinition<typeof exports>,
175-
Object.assign({}, exports),
175+
exports,
176176
name,
177177
baseDir
178178
);
@@ -197,11 +197,13 @@ export abstract class InstrumentationBase<T = any>
197197
: this._requireInTheMiddleSingleton.register(module.name, onRequire);
198198

199199
this._hooks.push(hook);
200-
new (ImportInTheMiddle as unknown as typeof ImportInTheMiddle.default)(
201-
[module.name],
202-
{ internals: true },
203-
<HookFn>hookFn
204-
);
200+
const esmHook =
201+
new (ImportInTheMiddle as unknown as typeof ImportInTheMiddle.default)(
202+
[module.name],
203+
{ internals: false },
204+
<HookFn>hookFn
205+
);
206+
this._hooks.push(esmHook);
205207
}
206208
}
207209

experimental/packages/opentelemetry-instrumentation/test/node/EsmInstrumentation.test.mjs

Lines changed: 62 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,32 +18,73 @@ import * as assert from 'assert';
1818
import {
1919
InstrumentationBase,
2020
InstrumentationNodeModuleDefinition,
21+
isWrapped,
2122
} from '../../build/src/index.js';
23+
import * as exported from 'test-esm-module';
2224

23-
describe('when loading esm module', () => {
24-
it('should patch module file', async () => {
25-
class TestInstrumentation extends InstrumentationBase {
26-
constructor() {
27-
super('test-esm-instrumentation', '0.0.1');
25+
class TestInstrumentationWrapFn extends InstrumentationBase {
26+
constructor(config) {
27+
super('test-esm-instrumentation', '0.0.1', config);
28+
}
29+
init() {
30+
console.log('test-esm-instrumentation initialized!');
31+
return new InstrumentationNodeModuleDefinition(
32+
'test-esm-module',
33+
['*'],
34+
moduleExports => {
35+
this._wrap(moduleExports, 'testFunction', () => {
36+
return () => 'a different result';
37+
});
38+
return moduleExports;
39+
},
40+
moduleExports => {
41+
this._unwrap(moduleExports, 'testFunction');
42+
console.log('second');
43+
return moduleExports;
2844
}
29-
init() {
30-
console.log('test-esm-instrumentation initialized!');
31-
return new InstrumentationNodeModuleDefinition(
32-
'test-esm-module',
33-
['*'],
34-
moduleExports => {
35-
console.log('patch');
36-
moduleExports.testConstant = 43;
37-
}
38-
);
45+
);
46+
}
47+
}
48+
49+
class TestInstrumentationSimple extends InstrumentationBase {
50+
constructor(config) {
51+
super('test-esm-instrumentation', '0.0.1', config);
52+
}
53+
init() {
54+
console.log('test-esm-instrumentation initialized!');
55+
return new InstrumentationNodeModuleDefinition(
56+
'test-esm-module',
57+
['*'],
58+
moduleExports => {
59+
moduleExports.testConstant = 43;
60+
return moduleExports;
3961
}
40-
}
41-
const instrumentation = new TestInstrumentation();
62+
);
63+
}
64+
}
65+
describe('when loading esm module', () => {
66+
const instrumentationWrap = new TestInstrumentationWrapFn({
67+
enabled: false,
68+
});
69+
70+
it('should patch module file directly', async () => {
71+
const instrumentation = new TestInstrumentationSimple({
72+
enabled: false,
73+
});
4274
instrumentation.enable();
43-
// const exported = await import('test-esm-module');
44-
// assert.deepEqual(exported.testConstant, 43);
75+
assert.deepEqual(exported.testConstant, 43);
76+
});
4577

46-
// error from import-in-the-middle register
47-
// TypeError: setters.get(...)[name] is not a function
78+
it('should patch a module with the wrap function', async () => {
79+
instrumentationWrap.enable();
80+
assert.deepEqual(exported.testFunction(), 'a different result');
4881
});
82+
83+
// it('should be able to unwrap a patched function', async () => {
84+
// // disable to trigger unwrap
85+
// const exported = await import('test-esm-module');
86+
// instrumentationWrap.enable();
87+
// instrumentationWrap.disable();
88+
// assert.deepEqual(exported.testFunction(), 'test');
89+
// });
4990
});

0 commit comments

Comments
 (0)