diff --git a/plugins/node/opentelemetry-instrumentation-koa/README.md b/plugins/node/opentelemetry-instrumentation-koa/README.md index aee8051ccd..a6aacd952d 100644 --- a/plugins/node/opentelemetry-instrumentation-koa/README.md +++ b/plugins/node/opentelemetry-instrumentation-koa/README.md @@ -52,6 +52,7 @@ Note that generator-based middleware are deprecated and won't be instrumented. | Options | Type | Example | Description | | ------------------ | ----------------------------------- | -------------------- | -------------------------------------------------------------------------------------------------------- | | `ignoreLayersType` | `KoaLayerType[]` | `['middleware']` | Ignore layers of specified type. | +| `ignoreLayersName` | `string[]` | `['logger']` | Ignore layers with specified names. | | `requestHook` | `KoaRequestCustomAttributeFunction` | `(span, info) => {}` | Function for adding custom attributes to Koa middleware layers. Receives params: `Span, KoaRequestInfo`. | `ignoreLayersType` accepts an array of `KoaLayerType` which can take the following string values: diff --git a/plugins/node/opentelemetry-instrumentation-koa/src/instrumentation.ts b/plugins/node/opentelemetry-instrumentation-koa/src/instrumentation.ts index ab6c2927be..7b2fe915ab 100644 --- a/plugins/node/opentelemetry-instrumentation-koa/src/instrumentation.ts +++ b/plugins/node/opentelemetry-instrumentation-koa/src/instrumentation.ts @@ -25,7 +25,11 @@ import { import type * as koa from 'koa'; import { KoaContext, KoaLayerType, KoaInstrumentationConfig } from './types'; import { VERSION } from './version'; -import { getMiddlewareMetadata, isLayerIgnored } from './utils'; +import { + getMiddlewareMetadata, + isLayerIgnored, + isLayerNameIgnored, +} from './utils'; import { getRPCMetadata, RPCType } from '@opentelemetry/core'; import { kLayerPatched, @@ -168,6 +172,11 @@ export class KoaInstrumentation extends InstrumentationBase { isRouter, layerPath ); + + if (isLayerNameIgnored(metadata.layerName, this.getConfig())) { + return middlewareLayer(context, next); + } + const span = this.tracer.startSpan(metadata.name, { attributes: metadata.attributes, }); diff --git a/plugins/node/opentelemetry-instrumentation-koa/src/types.ts b/plugins/node/opentelemetry-instrumentation-koa/src/types.ts index 3c249e3a6a..680694df94 100644 --- a/plugins/node/opentelemetry-instrumentation-koa/src/types.ts +++ b/plugins/node/opentelemetry-instrumentation-koa/src/types.ts @@ -46,6 +46,8 @@ export interface KoaRequestCustomAttributeFunction { export interface KoaInstrumentationConfig extends InstrumentationConfig { /** Ignore specific layers based on their type */ ignoreLayersType?: KoaLayerType[]; + /** Ignore specific layers based on their name */ + ignoreLayersName?: string[]; /** Function for adding custom attributes to each middleware layer span */ requestHook?: KoaRequestCustomAttributeFunction; } diff --git a/plugins/node/opentelemetry-instrumentation-koa/src/utils.ts b/plugins/node/opentelemetry-instrumentation-koa/src/utils.ts index 26c58fa6e3..a6d236756a 100644 --- a/plugins/node/opentelemetry-instrumentation-koa/src/utils.ts +++ b/plugins/node/opentelemetry-instrumentation-koa/src/utils.ts @@ -27,6 +27,7 @@ export const getMiddlewareMetadata = ( ): { attributes: Attributes; name: string; + layerName: string; } => { if (isRouter) { return { @@ -36,6 +37,7 @@ export const getMiddlewareMetadata = ( [SEMATTRS_HTTP_ROUTE]: layerPath?.toString(), }, name: context._matchedRouteName || `router - ${layerPath}`, + layerName: context._matchedRouteName || layerPath?.toString() || '', }; } else { return { @@ -44,6 +46,7 @@ export const getMiddlewareMetadata = ( [AttributeNames.KOA_TYPE]: KoaLayerType.MIDDLEWARE, }, name: `middleware - ${layer.name}`, + layerName: layer.name, }; } }; @@ -63,3 +66,19 @@ export const isLayerIgnored = ( config?.ignoreLayersType?.includes(type) ); }; + +/** + * Check whether the given request name is ignored by configuration + * @param [list] List of ignore name patterns + * @param [onException] callback for doing something when an exception has + * occurred + */ +export const isLayerNameIgnored = ( + layerName: string, + config?: KoaInstrumentationConfig +): boolean => { + return !!( + Array.isArray(config?.ignoreLayersName) && + config?.ignoreLayersName?.includes(layerName) + ); +}; diff --git a/plugins/node/opentelemetry-instrumentation-koa/test/koa.test.ts b/plugins/node/opentelemetry-instrumentation-koa/test/koa.test.ts index 8d97864208..ea46c6d072 100644 --- a/plugins/node/opentelemetry-instrumentation-koa/test/koa.test.ts +++ b/plugins/node/opentelemetry-instrumentation-koa/test/koa.test.ts @@ -721,7 +721,7 @@ describe('Koa Instrumentation', () => { '--experimental-loader=@opentelemetry/instrumentation/hook.mjs', NODE_NO_WARNINGS: '1', }, - checkResult: (err, stdout, stderr) => { + checkResult: (err: any, stdout: any, stderr: any) => { assert.ifError(err); }, checkCollector: (collector: testUtils.TestCollector) => { diff --git a/plugins/node/opentelemetry-instrumentation-koa/test/utils.test.ts b/plugins/node/opentelemetry-instrumentation-koa/test/utils.test.ts index b9a1ab4160..85b6ba0af9 100644 --- a/plugins/node/opentelemetry-instrumentation-koa/test/utils.test.ts +++ b/plugins/node/opentelemetry-instrumentation-koa/test/utils.test.ts @@ -58,4 +58,47 @@ describe('Utils', () => { ); }); }); + describe('isLayerNameIgnored()', () => { + it('should not fail with invalid config', () => { + assert.strictEqual(utils.isLayerNameIgnored(''), false); + assert.strictEqual( + utils.isLayerNameIgnored('', {} as KoaInstrumentationConfig), + false + ); + assert.strictEqual( + utils.isLayerNameIgnored('', { + ignoreLayersName: {}, + } as KoaInstrumentationConfig), + false + ); + assert.strictEqual( + utils.isLayerNameIgnored('logger', { + ignoreLayersName: {}, + } as KoaInstrumentationConfig), + false + ); + assert.strictEqual(utils.isLayerNameIgnored('logger'), false); + assert.strictEqual( + utils.isLayerNameIgnored('', { + ignoreLayersName: [], + } as KoaInstrumentationConfig), + false + ); + }); + + it('should ignore based on type', () => { + assert.strictEqual( + utils.isLayerNameIgnored('logger', { + ignoreLayersName: ['logger'], + }), + true + ); + assert.strictEqual( + utils.isLayerNameIgnored('', { + ignoreLayersName: ['logger'], + }), + false + ); + }); + }); });