Skip to content

Commit

Permalink
feat(koa): add a config option to allow layers to be ignored by type (o…
Browse files Browse the repository at this point in the history
…pen-telemetry#646)

* feat(koa): Adds config option to allow selected layers to be ignored
* Fixes linting errors
  • Loading branch information
agustindaguerre authored Nov 19, 2021
1 parent aff24b8 commit 572ed66
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 5 deletions.
11 changes: 11 additions & 0 deletions plugins/node/opentelemetry-instrumentation-koa/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,17 @@ registerInstrumentations({

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 Instrumentation Options

| Options | Type | Example | Description |
| ------- | ---- | ------- | ----------- |
| `ignoreLayersType`| `KoaLayerType[]` | `['middleware']` | Ignore layers of specified type. |

`ignoreLayersType` accepts an array of `KoaLayerType` which can take the following string values:

- `router`,
- `middleware`.

## 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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import * as api from '@opentelemetry/api';
import {
isWrapped,
InstrumentationBase,
InstrumentationConfig,
InstrumentationNodeModuleDefinition,
} from '@opentelemetry/instrumentation';

Expand All @@ -29,16 +28,17 @@ import {
KoaComponentName,
kLayerPatched,
KoaLayerType,
KoaInstrumentationConfig,
} from './types';
import { AttributeNames } from './enums/AttributeNames';
import { VERSION } from './version';
import { getMiddlewareMetadata } from './utils';
import { getMiddlewareMetadata, isLayerIgnored } from './utils';
import { getRPCMetadata, RPCType, setRPCMetadata } from '@opentelemetry/core';

/** Koa instrumentation for OpenTelemetry */
export class KoaInstrumentation extends InstrumentationBase<typeof koa> {
static readonly component = KoaComponentName;
constructor(config?: InstrumentationConfig) {
constructor(config?: KoaInstrumentationConfig) {
super('@opentelemetry/instrumentation-koa', VERSION, config);
}
protected init() {
Expand Down Expand Up @@ -126,7 +126,13 @@ export class KoaInstrumentation extends InstrumentationBase<typeof koa> {
isRouter: boolean,
layerPath?: string
): KoaMiddleware {
if (middlewareLayer[kLayerPatched] === true) return middlewareLayer;
const layerType = isRouter ? KoaLayerType.ROUTER : KoaLayerType.MIDDLEWARE;
// Skip patching layer if its ignored in the config
if (
middlewareLayer[kLayerPatched] === true ||
isLayerIgnored(layerType, this._config)
)
return middlewareLayer;
middlewareLayer[kLayerPatched] = true;
api.diag.debug('patching Koa middleware layer');
return async (context: KoaContext, next: koa.Next) => {
Expand Down
9 changes: 9 additions & 0 deletions plugins/node/opentelemetry-instrumentation-koa/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import type { Middleware, ParameterizedContext, DefaultState } from 'koa';
import type { RouterParamContext } from '@koa/router';
import type * as Router from '@koa/router';
import { InstrumentationConfig } from '@opentelemetry/instrumentation';

/**
* This symbol is used to mark a Koa layer as being already instrumented
Expand All @@ -30,6 +31,14 @@ export type KoaMiddleware = Middleware<DefaultState, KoaContext> & {

export type KoaContext = ParameterizedContext<DefaultState, RouterParamContext>;

/**
* Options available for the Koa Instrumentation (see [documentation](https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-Instrumentation-koa#koa-Instrumentation-options))
*/
export interface KoaInstrumentationConfig extends InstrumentationConfig {
/** Ignore specific layers based on their type */
ignoreLayersType?: KoaLayerType[];
}

export enum KoaLayerType {
ROUTER = 'router',
MIDDLEWARE = 'middleware',
Expand Down
23 changes: 22 additions & 1 deletion plugins/node/opentelemetry-instrumentation-koa/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { KoaContext, KoaMiddleware, KoaLayerType } from './types';
import {
KoaContext,
KoaMiddleware,
KoaLayerType,
KoaInstrumentationConfig,
} from './types';
import { AttributeNames } from './enums/AttributeNames';
import { SpanAttributes } from '@opentelemetry/api';
import { SemanticAttributes } from '@opentelemetry/semantic-conventions';
Expand Down Expand Up @@ -46,3 +51,19 @@ export const getMiddlewareMetadata = (
};
}
};

/**
* Check whether the given request is ignored by configuration
* @param [list] List of ignore patterns
* @param [onException] callback for doing something when an exception has
* occurred
*/
export const isLayerIgnored = (
type: KoaLayerType,
config?: KoaInstrumentationConfig
): boolean => {
return !!(
Array.isArray(config?.ignoreLayersType) &&
config?.ignoreLayersType?.includes(type)
);
};
61 changes: 61 additions & 0 deletions plugins/node/opentelemetry-instrumentation-koa/test/utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* 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.
*/

import * as utils from '../src/utils';
import * as assert from 'assert';
import { KoaInstrumentationConfig, KoaLayerType } from '../src/types';

describe('Utils', () => {
describe('isLayerIgnored()', () => {
it('should not fail with invalid config', () => {
assert.strictEqual(utils.isLayerIgnored(KoaLayerType.MIDDLEWARE), false);
assert.strictEqual(
utils.isLayerIgnored(
KoaLayerType.MIDDLEWARE,
{} as KoaInstrumentationConfig
),
false
);
assert.strictEqual(
utils.isLayerIgnored(KoaLayerType.MIDDLEWARE, {
ignoreLayersType: {},
} as KoaInstrumentationConfig),
false
);
assert.strictEqual(
utils.isLayerIgnored(KoaLayerType.ROUTER, {
ignoreLayersType: {},
} as KoaInstrumentationConfig),
false
);
});

it('should ignore based on type', () => {
assert.strictEqual(
utils.isLayerIgnored(KoaLayerType.MIDDLEWARE, {
ignoreLayersType: [KoaLayerType.MIDDLEWARE],
}),
true
);
assert.strictEqual(
utils.isLayerIgnored(KoaLayerType.ROUTER, {
ignoreLayersType: [KoaLayerType.MIDDLEWARE],
}),
false
);
});
});
});

0 comments on commit 572ed66

Please sign in to comment.