Skip to content

Commit

Permalink
Moving Koa to instrumentation (#357)
Browse files Browse the repository at this point in the history
* chore: moving koa to instrumentation

* chore: updating example

* chore: updating doc

* chore: reviews
  • Loading branch information
obecny authored Feb 25, 2021
1 parent a30b8aa commit 74d371c
Show file tree
Hide file tree
Showing 19 changed files with 238 additions and 293 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ OpenTelemetry can collect tracing data automatically using plugins. Vendors/User
- [@opentelemetry/plugin-express][otel-plugin-express]
- [@opentelemetry/plugin-dns][otel-plugin-dns]
- [@opentelemetry/hapi-instrumentation][otel-contrib-hapi-instrumentation]
- [@opentelemetry/koa-instrumentation][otel-contrib-koa-instrumentation]
- [@opentelemetry/instrumentation-koa][otel-contrib-instrumentation-koa]
- [@opentelemetry/instrumentation-graphql][otel-contrib-instrumentation-graphql]

### Web Plugins
Expand Down Expand Up @@ -135,5 +135,5 @@ Apache 2.0 - See [LICENSE][license-url] for more information.
[otel-plugin-express]: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-plugin-express
[otel-plugins-node-core-and-contrib]: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/metapackages/plugins-node-core-and-contrib
[otel-contrib-hapi-instrumentation]: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-hapi-instrumentation
[otel-contrib-koa-instrumentation]: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-koa-instrumentation
[otel-contrib-instrumentation-koa]: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-koa
[otel-contrib-instrumentation-graphql]: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-graphql
5 changes: 3 additions & 2 deletions examples/koa/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,10 @@
"@opentelemetry/api": "^0.15.0",
"@opentelemetry/exporter-jaeger": "^0.15.0",
"@opentelemetry/exporter-zipkin": "^0.15.0",
"@opentelemetry/koa-instrumentation": "^0.13.0",
"@opentelemetry/instrumentation": "^0.15.0",
"@opentelemetry/instrumentation-http": "^0.15.0",
"@opentelemetry/instrumentation-koa": "^0.13.1",
"@opentelemetry/node": "^0.15.0",
"@opentelemetry/plugin-http": "^0.15.0",
"@opentelemetry/tracing": "^0.15.0",
"axios": "^0.19.0",
"koa": "^2.13.0"
Expand Down
9 changes: 5 additions & 4 deletions examples/koa/server.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
'use strict';

// eslint-disable-next-line
const tracer = require('./tracer')('example-koa-server');
const api = require('@opentelemetry/api');

require('./tracer')('example-koa-server');

// Adding Koa router (if desired)
const router = require('@koa/router')();
Expand All @@ -28,7 +29,7 @@ const posts = ['post 0', 'post 1', 'post 2'];

function addPost(ctx) {
posts.push(`post ${posts.length}`);
const currentSpan = tracer.getCurrentSpan();
const currentSpan = api.getSpan(api.context.active());
currentSpan.addEvent('Added post');
currentSpan.setAttribute('Date', new Date());
ctx.body = `Added post: ${posts[posts.length - 1]}`;
Expand All @@ -47,7 +48,7 @@ async function showNewPost(ctx) {

function runTest(ctx) {
console.log('runTest');
const currentSpan = tracer.getCurrentSpan();
const currentSpan = api.getSpan(api.context.active());
const { traceId } = currentSpan.context();
console.log(`traceid: ${traceId}`);
console.log(`Jaeger URL: http://localhost:16686/trace/${traceId}`);
Expand Down
30 changes: 15 additions & 15 deletions examples/koa/tracer.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
'use strict';

const opentelemetry = require('@opentelemetry/api');
const { KoaInstrumentation } = require('@opentelemetry/instrumentation-koa');
const { HttpInstrumentation } = require('@opentelemetry/instrumentation-http');

const api = require('@opentelemetry/api');
const { registerInstrumentations } = require('@opentelemetry/instrumentation');
const { NodeTracerProvider } = require('@opentelemetry/node');
const { SimpleSpanProcessor } = require('@opentelemetry/tracing');
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
Expand All @@ -9,19 +13,7 @@ const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
const EXPORTER = process.env.EXPORTER || '';

module.exports = (serviceName) => {
const provider = new NodeTracerProvider({
plugins: {
koa: {
enabled: true,
path: '@opentelemetry/koa-instrumentation',
enhancedDatabaseReporting: true,
},
http: {
enabled: true,
path: '@opentelemetry/plugin-http',
},
},
});
const provider = new NodeTracerProvider();

let exporter;
if (EXPORTER === 'jaeger') {
Expand All @@ -31,8 +23,16 @@ module.exports = (serviceName) => {
}
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));

registerInstrumentations({
instrumentations: [
new KoaInstrumentation(),
new HttpInstrumentation(),
],
tracerProvider: provider,
});

// Initialize the OpenTelemetry APIs to use the NodeTracerProvider bindings
provider.register();

return opentelemetry.trace.getTracer('koa-example');
return api.trace.getTracer('koa-example');
};
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
"version": "0.13.1",
"description": "This is a repository for OpenTelemetry JavaScript contributions.",
"repository": {
"type" : "git",
"url" : "https://github.com/open-telemetry/opentelemetry-js-contrib.git"
"type": "git",
"url": "https://github.com/open-telemetry/opentelemetry-js-contrib.git"
},
"publishConfig": {
"access": "public"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ For automatic instrumentation see the
## Installation

```bash
npm install --save @opentelemetry/koa-instrumentation
npm install --save @opentelemetry/instrumentation-koa
```
### Supported Versions
- Koa `^2.0.0`
Expand All @@ -21,33 +21,47 @@ npm install --save @opentelemetry/koa-instrumentation

OpenTelemetry Koa Instrumentation allows the user to automatically collect trace data and export them to their backend of choice, to give observability to distributed systems.

To load a specific instrumentation (Koa in this case), specify it in the Node Tracer's configuration.
To load all of the [default supported plugins](https://github.com/open-telemetry/opentelemetry-js#plugins), use the below approach. Each plugin is only loaded when the module that it patches is loaded; in other words, there is no computational overhead for listing plugins for unused modules.

```js
const { NodeTracerProvider } = require('@opentelemetry/node');

const provider = new NodeTracerProvider({
plugins: {
koa: {
enabled: true,
// You may use a package name or absolute path to the file.
path: '@opentelemetry/koa-instrumentation',
}
}
const provider = new NodeTracerProvider();
const { registerInstrumentations } = require('@opentelemetry/instrumentation');
registerInstrumentations({
tracerProvider: provider,
});
```

To load all of the [supported instrumentations](https://github.com/open-telemetry/opentelemetry-js#plugins), use below approach. Each instrumentation is only loaded when the module that it patches is loaded; in other words, there is no computational overhead for listing instrumentations for unused modules.
If instead you would just want to load a specific instrumentation only (**koa** in this case);

```js
const { NodeTracerProvider } = require('@opentelemetry/node');
const { KoaInstrumentation } = require('@opentelemetry/instrumentation-koa');
const provider = new NodeTracerProvider();
const koaInstrumentation = new KoaInstrumentation();
koaInstrumentation.setTracerProvider(provider);
```

You can combine loading default plugins and KoaInstrumentation at the same time:

```js
const { NodeTracerProvider } = require('@opentelemetry/node');
const { KoaInstrumentation } = require('@opentelemetry/instrumentation-koa');
const { registerInstrumentations } = require('@opentelemetry/instrumentation');
const provider = new NodeTracerProvider();
registerInstrumentations({
instrumentations: [
new KoaInstrumentation(),
],
tracerProvider: provider,
});
```

See [examples/koa](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/examples/koa) for a short example using both Koa and @koa/router

## Koa Packages

This package provides automatic tracing for middleware added using either the core [`Koa`](https://github.com/koajs/koa) package or the [`@koa/router`](https://github.com/koajs/router) package.
This package provides automatic tracing for middleware added using either the core [`Koa`](https://github.com/koajs/koa) package or the [`@koa/router`](https://github.com/koajs/router) package.

## Useful links
- For more information on OpenTelemetry, visit: <https://opentelemetry.io/>
Expand All @@ -62,7 +76,7 @@ Apache 2.0 - See [LICENSE][license-url] for more information.
[gitter-url]: https://gitter.im/open-telemetry/opentelemetry-node?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
[license-url]: https://github.com/open-telemetry/opentelemetry-js-contrib/blob/main/LICENSE
[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat
[dependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js-contrib/status.svg?path=plugins/node/opentelemetry-koa-instrumentation
[dependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js-contrib?path=plugins/node/opentelemetry-koa-instrumentation
[devDependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js-contrib/dev-status.svg?path=plugins/node/opentelemetry-koa-instrumentation
[devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js-contrib?path=plugins/node/opentelemetry-koa-instrumentation&type=dev
[dependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js-contrib/status.svg?path=plugins/node/opentelemetry-instrumentation-koa
[dependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js-contrib?path=plugins/node/opentelemetry-instrumentation-koa
[devDependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js-contrib/dev-status.svg?path=plugins/node/opentelemetry-instrumentation-koa
[devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js-contrib?path=plugins/node/opentelemetry-instrumentation-koa&type=dev
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "@opentelemetry/koa-instrumentation",
"name": "@opentelemetry/instrumentation-koa",
"version": "0.13.1",
"description": "OpenTelemetry Koa automatic instrumentation package.",
"main": "build/src/index.js",
Expand Down Expand Up @@ -51,7 +51,6 @@
"@types/koa__router": "8.0.2",
"@types/mocha": "7.0.2",
"@types/node": "12.12.47",
"@types/shimmer": "1.0.1",
"codecov": "3.7.1",
"gts": "3.1.0",
"koa": "2.13.0",
Expand All @@ -67,7 +66,7 @@
"dependencies": {
"@opentelemetry/api": "^0.15.0",
"@opentelemetry/core": "^0.15.0",
"@opentelemetry/semantic-conventions": "^0.15.0",
"shimmer": "^1.2.1"
"@opentelemetry/instrumentation": "^0.15.0",
"@opentelemetry/semantic-conventions": "^0.15.0"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,14 @@
*/

import * as api from '@opentelemetry/api';
import { BasePlugin } from '@opentelemetry/core';
import {
isWrapped,
InstrumentationBase,
InstrumentationConfig,
InstrumentationNodeModuleDefinition,
} from '@opentelemetry/instrumentation';

import type * as koa from 'koa';
import * as shimmer from 'shimmer';
import {
KoaMiddleware,
KoaContext,
Expand All @@ -28,34 +33,35 @@ import { VERSION } from './version';
import { getMiddlewareMetadata } from './utils';

/** Koa instrumentation for OpenTelemetry */
export class KoaInstrumentation extends BasePlugin<typeof koa> {
export class KoaInstrumentation extends InstrumentationBase<typeof koa> {
static readonly component = KoaComponentName;
readonly supportedVersions = ['^2.0.0'];

constructor(readonly moduleName: string) {
super('@opentelemetry/koa-instrumentation', VERSION);
}

/**
* Patches Koa operations by wrapping the Koa.use function
*/
protected patch(): typeof koa {
this._logger.debug('Patching Koa');
if (this._moduleExports == null) {
return this._moduleExports;
}
this._logger.debug('Patching Koa.use');
shimmer.wrap(this._moduleExports.prototype, 'use', this._getKoaUsePatch);

return this._moduleExports;
constructor(config?: InstrumentationConfig) {
super('@opentelemetry/instrumentation-koa', VERSION, config);
}

/**
* Unpatches all Koa operations
*/
protected unpatch(): void {
this._logger.debug('Unpatching Koa');
shimmer.unwrap(this._moduleExports.prototype, 'use');
protected init() {
return new InstrumentationNodeModuleDefinition<typeof koa>(
'koa',
['^2.0.0'],
moduleExports => {
if (moduleExports == null) {
return moduleExports;
}
if (isWrapped(moduleExports.prototype.use)) {
this._unwrap(moduleExports.prototype, 'use');
}
this._wrap(
moduleExports.prototype,
'use',
this._getKoaUsePatch.bind(this)
);
return moduleExports;
},
moduleExports => {
if (isWrapped(moduleExports.prototype.use)) {
this._unwrap(moduleExports.prototype, 'use');
}
}
);
}

/**
Expand All @@ -64,6 +70,7 @@ export class KoaInstrumentation extends BasePlugin<typeof koa> {
* @param {KoaMiddleware} middleware - the original middleware function
*/
private _getKoaUsePatch(original: (middleware: KoaMiddleware) => koa) {
const plugin = this;
return function use(this: koa, middlewareFunction: KoaMiddleware) {
let patchedFunction: KoaMiddleware;
if (middlewareFunction.router) {
Expand Down Expand Up @@ -127,7 +134,7 @@ export class KoaInstrumentation extends BasePlugin<typeof koa> {
isRouter,
layerPath
);
const span = this._tracer.startSpan(metadata.name, {
const span = this.tracer.startSpan(metadata.name, {
attributes: metadata.attributes,
});

Expand All @@ -147,5 +154,3 @@ export class KoaInstrumentation extends BasePlugin<typeof koa> {
};
}
}

export const plugin = new KoaInstrumentation(KoaComponentName);
Loading

0 comments on commit 74d371c

Please sign in to comment.