Skip to content

Commit 7106313

Browse files
test(instr-express): add test for ESM (#1966)
* maint(instr-express): add test for ESM * dont use router in express test
1 parent 43fd4eb commit 7106313

File tree

4 files changed

+111
-1
lines changed

4 files changed

+111
-1
lines changed

package-lock.json

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

plugins/node/opentelemetry-instrumentation-express/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
"devDependencies": {
4747
"@opentelemetry/api": "^1.3.0",
4848
"@opentelemetry/context-async-hooks": "^1.8.0",
49+
"@opentelemetry/contrib-test-utils": "^0.36.0",
4950
"@opentelemetry/sdk-trace-base": "^1.8.0",
5051
"@opentelemetry/sdk-trace-node": "^1.8.0",
5152
"@types/express": "4.17.18",

plugins/node/opentelemetry-instrumentation-express/test/express.test.ts

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
import { SpanStatusCode, context, trace } from '@opentelemetry/api';
17+
import { SpanStatusCode, context, SpanKind, trace } from '@opentelemetry/api';
1818
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
1919
import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks';
2020
import {
@@ -26,6 +26,7 @@ import { AttributeNames } from '../src/enums/AttributeNames';
2626
import { ExpressInstrumentation } from '../src';
2727
import { createServer, httpRequest, serverWithMiddleware } from './utils';
2828
import { SemanticAttributes } from '@opentelemetry/semantic-conventions';
29+
import * as testUtils from '@opentelemetry/contrib-test-utils';
2930

3031
const instrumentation = new ExpressInstrumentation();
3132
instrumentation.enable();
@@ -493,4 +494,43 @@ describe('ExpressInstrumentation', () => {
493494
);
494495
});
495496
});
497+
it('should work with ESM usage', async () => {
498+
await testUtils.runTestFixture({
499+
cwd: __dirname,
500+
argv: ['fixtures/use-express.mjs'],
501+
env: {
502+
NODE_OPTIONS:
503+
'--experimental-loader=@opentelemetry/instrumentation/hook.mjs',
504+
NODE_NO_WARNINGS: '1',
505+
},
506+
checkResult: (err, stdout, stderr) => {
507+
assert.ifError(err);
508+
},
509+
checkCollector: (collector: testUtils.TestCollector) => {
510+
// use-express.mjs creates an express app with a 'GET /post/:id' endpoint and
511+
// a `simpleMiddleware`, then makes a single 'GET /post/0' request. We
512+
// expect to see spans like this:
513+
// span 'GET /post/:id'
514+
// `- span 'middleware - query'
515+
// `- span 'middleware - expressInit'
516+
// `- span 'middleware - simpleMiddleware'
517+
// `- span 'request handler - /post/:id'
518+
const spans = collector.sortedSpans;
519+
assert.strictEqual(spans[0].name, 'GET /post/:id');
520+
assert.strictEqual(spans[0].kind, SpanKind.CLIENT);
521+
assert.strictEqual(spans[1].name, 'middleware - query');
522+
assert.strictEqual(spans[1].kind, SpanKind.SERVER);
523+
assert.strictEqual(spans[1].parentSpanId, spans[0].spanId);
524+
assert.strictEqual(spans[2].name, 'middleware - expressInit');
525+
assert.strictEqual(spans[2].kind, SpanKind.SERVER);
526+
assert.strictEqual(spans[2].parentSpanId, spans[0].spanId);
527+
assert.strictEqual(spans[3].name, 'middleware - simpleMiddleware');
528+
assert.strictEqual(spans[3].kind, SpanKind.SERVER);
529+
assert.strictEqual(spans[3].parentSpanId, spans[0].spanId);
530+
assert.strictEqual(spans[4].name, 'request handler - /post/:id');
531+
assert.strictEqual(spans[4].kind, SpanKind.SERVER);
532+
assert.strictEqual(spans[4].parentSpanId, spans[0].spanId);
533+
},
534+
});
535+
});
496536
});
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
// Use express from an ES module:
18+
// node --experimental-loader=@opentelemetry/instrumentation/hook.mjs use-express.mjs
19+
20+
import { promisify } from 'util';
21+
import { createTestNodeSdk } from '@opentelemetry/contrib-test-utils';
22+
23+
import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
24+
import { ExpressInstrumentation } from '../../build/src/index.js';
25+
26+
const sdk = createTestNodeSdk({
27+
serviceName: 'use-express',
28+
instrumentations: [
29+
new HttpInstrumentation(),
30+
new ExpressInstrumentation()
31+
]
32+
})
33+
sdk.start();
34+
35+
import express from 'express';
36+
import * as http from 'http';
37+
38+
const app = express();
39+
40+
app.use(async function simpleMiddleware(req, res, next) {
41+
// Wait a short delay to ensure this "middleware - ..." span clearly starts
42+
// before the "router - ..." span. The test rely on a start-time-based sort
43+
// of the produced spans. If they start in the same millisecond, then tests
44+
// can be flaky.
45+
await promisify(setTimeout)(10);
46+
next();
47+
});
48+
49+
app.get('/post/:id', (req, res) => {
50+
res.send(`Post id: ${req.params.id}`);
51+
});
52+
53+
const server = http.createServer(app);
54+
await new Promise(resolve => server.listen(0, resolve));
55+
const port = server.address().port;
56+
57+
await new Promise(resolve => {
58+
http.get(`http://localhost:${port}/post/0`, (res) => {
59+
res.resume();
60+
res.on('end', () => {
61+
resolve();
62+
});
63+
})
64+
});
65+
66+
await new Promise(resolve => server.close(resolve));
67+
await sdk.shutdown();

0 commit comments

Comments
 (0)