Skip to content

Commit

Permalink
Merge branch 'main' into tm-instr-runtime-node-dep-versions
Browse files Browse the repository at this point in the history
  • Loading branch information
pichlermarc authored Mar 6, 2024
2 parents 5a5fc2e + 7106313 commit 5041a0a
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 1 deletion.
2 changes: 2 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"devDependencies": {
"@opentelemetry/api": "^1.3.0",
"@opentelemetry/context-async-hooks": "^1.8.0",
"@opentelemetry/contrib-test-utils": "^0.36.0",
"@opentelemetry/sdk-trace-base": "^1.8.0",
"@opentelemetry/sdk-trace-node": "^1.8.0",
"@types/express": "4.17.18",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

import { SpanStatusCode, context, trace } from '@opentelemetry/api';
import { SpanStatusCode, context, SpanKind, trace } from '@opentelemetry/api';
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks';
import {
Expand All @@ -26,6 +26,7 @@ import { AttributeNames } from '../src/enums/AttributeNames';
import { ExpressInstrumentation } from '../src';
import { createServer, httpRequest, serverWithMiddleware } from './utils';
import { SemanticAttributes } from '@opentelemetry/semantic-conventions';
import * as testUtils from '@opentelemetry/contrib-test-utils';

const instrumentation = new ExpressInstrumentation();
instrumentation.enable();
Expand Down Expand Up @@ -493,4 +494,43 @@ describe('ExpressInstrumentation', () => {
);
});
});
it('should work with ESM usage', async () => {
await testUtils.runTestFixture({
cwd: __dirname,
argv: ['fixtures/use-express.mjs'],
env: {
NODE_OPTIONS:
'--experimental-loader=@opentelemetry/instrumentation/hook.mjs',
NODE_NO_WARNINGS: '1',
},
checkResult: (err, stdout, stderr) => {
assert.ifError(err);
},
checkCollector: (collector: testUtils.TestCollector) => {
// use-express.mjs creates an express app with a 'GET /post/:id' endpoint and
// a `simpleMiddleware`, then makes a single 'GET /post/0' request. We
// expect to see spans like this:
// span 'GET /post/:id'
// `- span 'middleware - query'
// `- span 'middleware - expressInit'
// `- span 'middleware - simpleMiddleware'
// `- span 'request handler - /post/:id'
const spans = collector.sortedSpans;
assert.strictEqual(spans[0].name, 'GET /post/:id');
assert.strictEqual(spans[0].kind, SpanKind.CLIENT);
assert.strictEqual(spans[1].name, 'middleware - query');
assert.strictEqual(spans[1].kind, SpanKind.SERVER);
assert.strictEqual(spans[1].parentSpanId, spans[0].spanId);
assert.strictEqual(spans[2].name, 'middleware - expressInit');
assert.strictEqual(spans[2].kind, SpanKind.SERVER);
assert.strictEqual(spans[2].parentSpanId, spans[0].spanId);
assert.strictEqual(spans[3].name, 'middleware - simpleMiddleware');
assert.strictEqual(spans[3].kind, SpanKind.SERVER);
assert.strictEqual(spans[3].parentSpanId, spans[0].spanId);
assert.strictEqual(spans[4].name, 'request handler - /post/:id');
assert.strictEqual(spans[4].kind, SpanKind.SERVER);
assert.strictEqual(spans[4].parentSpanId, spans[0].spanId);
},
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

// Use express from an ES module:
// node --experimental-loader=@opentelemetry/instrumentation/hook.mjs use-express.mjs

import { promisify } from 'util';
import { createTestNodeSdk } from '@opentelemetry/contrib-test-utils';

import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
import { ExpressInstrumentation } from '../../build/src/index.js';

const sdk = createTestNodeSdk({
serviceName: 'use-express',
instrumentations: [
new HttpInstrumentation(),
new ExpressInstrumentation()
]
})
sdk.start();

import express from 'express';
import * as http from 'http';

const app = express();

app.use(async function simpleMiddleware(req, res, next) {
// Wait a short delay to ensure this "middleware - ..." span clearly starts
// before the "router - ..." span. The test rely on a start-time-based sort
// of the produced spans. If they start in the same millisecond, then tests
// can be flaky.
await promisify(setTimeout)(10);
next();
});

app.get('/post/:id', (req, res) => {
res.send(`Post id: ${req.params.id}`);
});

const server = http.createServer(app);
await new Promise(resolve => server.listen(0, resolve));
const port = server.address().port;

await new Promise(resolve => {
http.get(`http://localhost:${port}/post/0`, (res) => {
res.resume();
res.on('end', () => {
resolve();
});
})
});

await new Promise(resolve => server.close(resolve));
await sdk.shutdown();

0 comments on commit 5041a0a

Please sign in to comment.