Skip to content

Commit

Permalink
fix(koa): End span and record exception when a middleware throws an e…
Browse files Browse the repository at this point in the history
…xception
  • Loading branch information
oguzbilgener committed Dec 15, 2020
1 parent 49db1b2 commit 03c1076
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 3 deletions.
11 changes: 8 additions & 3 deletions plugins/node/opentelemetry-koa-instrumentation/src/koa.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,14 @@ export class KoaInstrumentation extends BasePlugin<typeof koa> {
});

return this._tracer.withSpan(span, async () => {
const result = await middlewareLayer(context, next);
span.end();
return result;
try {
return await middlewareLayer(context, next);
} catch (err) {
span.recordException(err);
throw err;
} finally {
span.end();
}
});
};
}
Expand Down
42 changes: 42 additions & 0 deletions plugins/node/opentelemetry-koa-instrumentation/test/koa.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ import {
InMemorySpanExporter,
SimpleSpanProcessor,
} from '@opentelemetry/tracing';
import {
ExceptionAttribute,
ExceptionEventName,
} from '@opentelemetry/semantic-conventions';
import * as assert from 'assert';
import * as koa from 'koa';
import * as http from 'http';
Expand Down Expand Up @@ -106,6 +110,10 @@ describe('Koa Instrumentation - Core Tests', () => {
ctx.body = `${ctx.method} ${ctx.url} - ${ms}ms`;
};

const failingMiddleware: koa.Middleware = async (_ctx, _next) => {
throw new Error('I failed!');
};

describe('Instrumenting core middleware calls', () => {
it('should create a child span for middlewares', async () => {
const rootSpan = tracer.startSpan('rootSpan');
Expand Down Expand Up @@ -193,6 +201,40 @@ describe('Koa Instrumentation - Core Tests', () => {
assert.notStrictEqual(exportedRootSpan, undefined);
});
});

it('should propagate exceptions in the middleware while marking the span with an exception', async () => {
const rootSpan = tracer.startSpan('rootSpan');
app.use((_ctx, next) => tracer.withSpan(rootSpan, next));
app.use(failingMiddleware);
const res = await httpRequest.get(`http://localhost:${port}`);
assert.deepStrictEqual(res, 'Internal Server Error');

rootSpan.end();
assert.deepStrictEqual(memoryExporter.getFinishedSpans().length, 3);

const requestHandlerSpan = memoryExporter
.getFinishedSpans()
.find(span => span.name.includes('failingMiddleware'));
assert.notStrictEqual(requestHandlerSpan, undefined);

assert.strictEqual(
requestHandlerSpan?.attributes[AttributeNames.KOA_TYPE],
KoaLayerType.MIDDLEWARE
);
const exportedRootSpan = memoryExporter
.getFinishedSpans()
.find(span => span.name === 'rootSpan');
assert.ok(exportedRootSpan);
const exceptionEvent = requestHandlerSpan.events.find(
event => event.name === ExceptionEventName
);
assert.ok(exceptionEvent, 'There should be an exception event recorded');
assert.deepStrictEqual(exceptionEvent.name, 'exception');
assert.deepStrictEqual(
exceptionEvent.attributes![ExceptionAttribute.MESSAGE],
'I failed!'
);
});
});

describe('Disabling koa instrumentation', () => {
Expand Down

0 comments on commit 03c1076

Please sign in to comment.