Skip to content

Commit

Permalink
feat: added base tests for Koa core and Koa router
Browse files Browse the repository at this point in the history
  • Loading branch information
carolinee21 committed Jul 8, 2020
1 parent 1b35f8b commit d8f72f4
Show file tree
Hide file tree
Showing 2 changed files with 342 additions and 0 deletions.
149 changes: 149 additions & 0 deletions plugins/node/opentelemetry-plugin-koa/test/koa-router.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/*!
* Copyright 2020, 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.
*/

import { context } from '@opentelemetry/api';
import { NoopLogger } from '@opentelemetry/core';
import { NodeTracerProvider } from '@opentelemetry/node';
import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks';
import {
InMemorySpanExporter,
SimpleSpanProcessor,
} from '@opentelemetry/tracing';
import * as assert from 'assert';
import * as koa from 'koa';
import * as KoaRouter from '@koa/router';
// const router = require('@koa/router')();

import * as http from 'http';
import { AddressInfo } from 'net';
import { plugin } from '../src';
import {
AttributeNames
} from '../src/types';


const httpRequest = {
get: (options: http.ClientRequestArgs | string) => {
return new Promise((resolve, reject) => {
return http.get(options, resp => {
let data = '';
resp.on('data', chunk => {
data += chunk;
});
resp.on('end', () => {
resolve(data);
});
resp.on('error', err => {
reject(err);
});
});
});
},
};


describe('Koa Plugin', () => {
const logger = new NoopLogger();
const provider = new NodeTracerProvider();
const memoryExporter = new InMemorySpanExporter();
const spanProcessor = new SimpleSpanProcessor(memoryExporter);
provider.addSpanProcessor(spanProcessor);
const tracer = provider.getTracer('default');
let contextManager: AsyncHooksContextManager;

before(() => {
plugin.enable(koa, provider, logger);
});

beforeEach(() => {
contextManager = new AsyncHooksContextManager();
context.setGlobalContextManager(contextManager.enable());
});

afterEach(() => {
memoryExporter.reset();
context.disable();
});

describe('Instrumenting @koa/router calls', () => {
it('should create a child span for middlewares', async () => {
const rootSpan = tracer.startSpan('rootSpan');
const app = new koa();
app.use((ctx, next) => tracer.withSpan(rootSpan, next));

const router = new KoaRouter();
router.get('/', (ctx) => {
ctx.body = "list"
});
router.get('/post/new', (ctx) => {
ctx.body = "add"
});
router.get('/post/:id', (ctx) => {
const id = ctx.params.id;
console.log("id is: " + id);
});

router.post('/post', async (ctx) => {
const post = ctx.body;
post.created_at = new Date();
ctx.redirect('/');
});

app.use(router.routes());

const server = http.createServer(app.callback());
await new Promise(resolve => server.listen(0, resolve));
const port = (server.address() as AddressInfo).port;
assert.strictEqual(memoryExporter.getFinishedSpans().length, 0);


await tracer.withSpan(rootSpan, async () => {
await httpRequest.get(`http://localhost:${port}/post/0`);
rootSpan.end();


const requestHandlerSpan = memoryExporter
.getFinishedSpans()
.find(span => span.name.includes('/post/:id'));
assert.notStrictEqual(requestHandlerSpan, undefined);
assert.strictEqual(
requestHandlerSpan?.attributes[AttributeNames.COMPONENT],
'koa'
);

assert.strictEqual(
requestHandlerSpan?.attributes[AttributeNames.KOA_TYPE],
'middleware'
);

assert.strictEqual(
requestHandlerSpan?.attributes[AttributeNames.PATH],
'/post/:id'
);

let exportedRootSpan = memoryExporter
.getFinishedSpans()
.find(span => span.name === 'rootSpan');
assert.notStrictEqual(exportedRootSpan, undefined);
});
server.close();
});



});
});

193 changes: 193 additions & 0 deletions plugins/node/opentelemetry-plugin-koa/test/koa.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
/*!
* Copyright 2020, 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.
*/

import { context } from '@opentelemetry/api';
import { NoopLogger } from '@opentelemetry/core';
import { NodeTracerProvider } from '@opentelemetry/node';
import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks';
import {
InMemorySpanExporter,
SimpleSpanProcessor,
} from '@opentelemetry/tracing';
import * as assert from 'assert';
import * as koa from 'koa';
import * as http from 'http';
import { AddressInfo } from 'net';
import { plugin } from '../src';
import {
AttributeNames
} from '../src/types';


const httpRequest = {
get: (options: http.ClientRequestArgs | string) => {
return new Promise((resolve, reject) => {
return http.get(options, resp => {
let data = '';
resp.on('data', chunk => {
data += chunk;
});
resp.on('end', () => {
resolve(data);
});
resp.on('error', err => {
reject(err);
});
});
});
},
};


describe('Koa Plugin', () => {
const logger = new NoopLogger();
const provider = new NodeTracerProvider();
const memoryExporter = new InMemorySpanExporter();
const spanProcessor = new SimpleSpanProcessor(memoryExporter);
provider.addSpanProcessor(spanProcessor);
const tracer = provider.getTracer('default');
let contextManager: AsyncHooksContextManager;

before(() => {
plugin.enable(koa, provider, logger);
});

beforeEach(() => {
contextManager = new AsyncHooksContextManager();
context.setGlobalContextManager(contextManager.enable());
});

afterEach(() => {
memoryExporter.reset();
context.disable();
});

describe('Instrumenting core middleware calls', () => {
it('should create a child span for middlewares', async () => {
const rootSpan = tracer.startSpan('rootSpan');
const app = new koa();
app.use((ctx, next) => tracer.withSpan(rootSpan, next));
app.use(function customMiddleware(ctx, next) {
for (let i = 0; i < 1000000; i++) {
continue;
}
return next();
});
app.use(function simpleResponse(ctx, next) {
ctx.body = 'test';
return next();
});

app.use(function (ctx, next) {
ctx.body = 'anonymous';
return next();
});

const server = http.createServer(app.callback());
await new Promise(resolve => server.listen(0, resolve));
const port = (server.address() as AddressInfo).port;
assert.strictEqual(memoryExporter.getFinishedSpans().length, 0);


await tracer.withSpan(rootSpan, async () => {
await httpRequest.get(`http://localhost:${port}`);
rootSpan.end();
assert.notStrictEqual(
memoryExporter
.getFinishedSpans()
.find(span => span.name.includes('customMiddleware')),
undefined
);

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

const requestHandlerSpan = memoryExporter
.getFinishedSpans()
.find(span => span.name.includes('middleware'));
assert.notStrictEqual(requestHandlerSpan, undefined);
assert.strictEqual(
requestHandlerSpan?.attributes[AttributeNames.COMPONENT],
'koa'
);

assert.strictEqual(
requestHandlerSpan?.attributes[AttributeNames.KOA_TYPE],
'middleware'
);
let exportedRootSpan = memoryExporter
.getFinishedSpans()
.find(span => span.name === 'rootSpan');
assert.notStrictEqual(exportedRootSpan, undefined);
});
server.close();
});

it('should not create span if there is no parent span', async () => {
const app = new koa();
app.use(function customMiddleware(ctx, next) {
for (let i = 0; i < 1000000; i++) {
continue;
}
return next();
});
app.use(function response(ctx, next) {
ctx.status = 200;
ctx.body = 'test';
return next();
});

const server = http.createServer(app.callback());
await new Promise(resolve => server.listen(0, resolve));
const port = (server.address() as AddressInfo).port;
assert.strictEqual(memoryExporter.getFinishedSpans().length, 0);
const res = await httpRequest.get(`http://localhost:${port}`);
assert.strictEqual(memoryExporter.getFinishedSpans().length, 0);
assert.strictEqual(res, 'test');
server.close();
});

});


describe('Disabling plugin', () => {
it('should not create new spans', async () => {
plugin.disable();
const rootSpan = tracer.startSpan('rootSpan');
const app = new koa();
app.use(function customMiddleware(ctx, next) {
for (let i = 0; i < 1000; i++) {
continue;
}
return next();
});
const server = http.createServer(app.callback());
await new Promise(resolve => server.listen(0, resolve));
const port = (server.address() as AddressInfo).port;
assert.strictEqual(memoryExporter.getFinishedSpans().length, 0);
await tracer.withSpan(rootSpan, async () => {
await httpRequest.get(`http://localhost:${port}`);
rootSpan.end();
assert.deepEqual(memoryExporter.getFinishedSpans().length, 1);
assert.notStrictEqual(memoryExporter.getFinishedSpans()[0], undefined);
});
server.close();
});
});
});

0 comments on commit d8f72f4

Please sign in to comment.