From 245d7ee199ab75407f6ef4269e634f09300add30 Mon Sep 17 00:00:00 2001 From: Amir Blum Date: Wed, 7 Apr 2021 16:49:50 +0300 Subject: [PATCH 01/13] feat(instrumentation-ioredis): add moduleVersionAttributeName config options --- .../README.md | 1 + .../src/ioredis.ts | 13 ++++++--- .../src/types.ts | 6 ++++ .../src/utils.ts | 7 ++++- .../test/ioredis.test.ts | 29 +++++++++++++++++++ 5 files changed, 51 insertions(+), 5 deletions(-) diff --git a/plugins/node/opentelemetry-instrumentation-ioredis/README.md b/plugins/node/opentelemetry-instrumentation-ioredis/README.md index 78eb4ba748..c6917e8ce7 100644 --- a/plugins/node/opentelemetry-instrumentation-ioredis/README.md +++ b/plugins/node/opentelemetry-instrumentation-ioredis/README.md @@ -58,6 +58,7 @@ IORedis instrumentation has few options available to choose from. You can set th | `dbStatementSerializer` | `DbStatementSerializer` | IORedis instrumentation will serialize db.statement using the specified function. | | `responseHook` | `RedisResponseCustomAttributeFunction` | Function for adding custom attributes on db response | | `requireParentSpan` | `boolean` | Require parent to create ioredis span, default when unset is true | +| `moduleVersionAttributeName` | `string` | If passed, a span attribute will be added to all spans with key of the provided "moduleVersionAttributeName" and value of the module version. | #### Custom db.statement Serializer The instrumentation serializes the whole command into a Span attribute called `db.statement`. The standard serialization format is `{cmdName} {cmdArgs.join(',')}`. diff --git a/plugins/node/opentelemetry-instrumentation-ioredis/src/ioredis.ts b/plugins/node/opentelemetry-instrumentation-ioredis/src/ioredis.ts index 62aaff2460..23f7ea18ea 100644 --- a/plugins/node/opentelemetry-instrumentation-ioredis/src/ioredis.ts +++ b/plugins/node/opentelemetry-instrumentation-ioredis/src/ioredis.ts @@ -48,7 +48,7 @@ export class IORedisInstrumentation extends InstrumentationBase< new InstrumentationNodeModuleDefinition( 'ioredis', this.supportedVersions, - moduleExports => { + (moduleExports, moduleVersion?: string | undefined) => { diag.debug('Applying patch for ioredis'); if (isWrapped(moduleExports.prototype.sendCommand)) { this._unwrap(moduleExports.prototype, 'sendCommand'); @@ -56,7 +56,7 @@ export class IORedisInstrumentation extends InstrumentationBase< this._wrap( moduleExports.prototype, 'sendCommand', - this._patchSendCommand() + this._patchSendCommand(moduleVersion) ); if (isWrapped(moduleExports.prototype.connect)) { this._unwrap(moduleExports.prototype, 'connect'); @@ -81,9 +81,14 @@ export class IORedisInstrumentation extends InstrumentationBase< /** * Patch send command internal to trace requests */ - private _patchSendCommand() { + private _patchSendCommand(moduleVersion?: string | undefined) { return (original: Function) => { - return traceSendCommand(this.tracer, original, this._config); + return traceSendCommand( + this.tracer, + original, + this._config, + moduleVersion + ); }; } diff --git a/plugins/node/opentelemetry-instrumentation-ioredis/src/types.ts b/plugins/node/opentelemetry-instrumentation-ioredis/src/types.ts index 4119c97415..9be4e7a5d5 100644 --- a/plugins/node/opentelemetry-instrumentation-ioredis/src/types.ts +++ b/plugins/node/opentelemetry-instrumentation-ioredis/src/types.ts @@ -71,4 +71,10 @@ export interface IORedisInstrumentationConfig extends InstrumentationConfig { /** Require parent to create ioredis span, default when unset is true */ requireParentSpan?: boolean; + + /** + * If passed, a span attribute will be added to all spans with key of the provided "moduleVersionAttributeName" + * and value of the module version. + */ + moduleVersionAttributeName?: string; } diff --git a/plugins/node/opentelemetry-instrumentation-ioredis/src/utils.ts b/plugins/node/opentelemetry-instrumentation-ioredis/src/utils.ts index c1db621a33..159a0fe9cf 100644 --- a/plugins/node/opentelemetry-instrumentation-ioredis/src/utils.ts +++ b/plugins/node/opentelemetry-instrumentation-ioredis/src/utils.ts @@ -85,7 +85,8 @@ const defaultDbStatementSerializer: DbStatementSerializer = ( export const traceSendCommand = ( tracer: Tracer, original: Function, - config?: IORedisInstrumentationConfig + config?: IORedisInstrumentationConfig, + moduleVersion?: string | undefined ) => { const dbStatementSerializer = config?.dbStatementSerializer || defaultDbStatementSerializer; @@ -110,6 +111,10 @@ export const traceSendCommand = ( }, }); + if (config?.moduleVersionAttributeName && moduleVersion) { + span.setAttribute(config?.moduleVersionAttributeName, moduleVersion); + } + const { host, port } = this.options; span.setAttributes({ diff --git a/plugins/node/opentelemetry-instrumentation-ioredis/test/ioredis.test.ts b/plugins/node/opentelemetry-instrumentation-ioredis/test/ioredis.test.ts index 841de12337..ce4ed8c8de 100644 --- a/plugins/node/opentelemetry-instrumentation-ioredis/test/ioredis.test.ts +++ b/plugins/node/opentelemetry-instrumentation-ioredis/test/ioredis.test.ts @@ -228,6 +228,13 @@ describe('ioredis', () => { }); describe('Instrumenting query operations', () => { + before(() => { + instrumentation.disable(); + instrumentation = new IORedisInstrumentation(); + instrumentation.setTracerProvider(provider); + require('ioredis'); + }); + IOREDIS_CALLBACK_OPERATIONS.forEach(command => { it(`should create a child span for cb style ${command.description}`, done => { const attributes = { @@ -762,6 +769,28 @@ describe('ioredis', () => { }); }); + it('moduleVersionAttributeName should capture ioredis version', async () => { + const VERSION_ATTR = 'instrumentedmodule.version'; + instrumentation.disable(); + const config: IORedisInstrumentationConfig = { + moduleVersionAttributeName: VERSION_ATTR, + }; + instrumentation = new IORedisInstrumentation(config); + instrumentation.setTracerProvider(provider); + require('ioredis'); + + const span = provider.getTracer('ioredis-test').startSpan('test span'); + await context.with(setSpan(context.active(), span), async () => { + await client.set(testKeyName, 'data'); + const endedSpans = memoryExporter.getFinishedSpans(); + assert.strictEqual(endedSpans.length, 1); + assert.match( + endedSpans[0].attributes[VERSION_ATTR] as string, + /\d{1,4}\.\d{1,4}\.\d{1,5}.*/ + ); + }); + }); + describe('Instrumenting with a custom responseHook', () => { it('should call responseHook when set in config', async () => { instrumentation.disable(); From 12ba869eb68d41e1bd20c3b15d694ea8d7e9e0e5 Mon Sep 17 00:00:00 2001 From: Amir Blum Date: Sun, 18 Apr 2021 14:18:23 +0300 Subject: [PATCH 02/13] chore(ioredis): type of moduleVersion --- plugins/node/opentelemetry-instrumentation-ioredis/src/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/node/opentelemetry-instrumentation-ioredis/src/utils.ts b/plugins/node/opentelemetry-instrumentation-ioredis/src/utils.ts index 159a0fe9cf..e8732a38e9 100644 --- a/plugins/node/opentelemetry-instrumentation-ioredis/src/utils.ts +++ b/plugins/node/opentelemetry-instrumentation-ioredis/src/utils.ts @@ -86,7 +86,7 @@ export const traceSendCommand = ( tracer: Tracer, original: Function, config?: IORedisInstrumentationConfig, - moduleVersion?: string | undefined + moduleVersion?: string ) => { const dbStatementSerializer = config?.dbStatementSerializer || defaultDbStatementSerializer; From ce35c7a82fdbd1168fb10f7b83042095d3bfb63c Mon Sep 17 00:00:00 2001 From: Amir Blum Date: Sun, 25 Apr 2021 14:39:45 +0300 Subject: [PATCH 03/13] feat(instrumentation-ioredis): convert module version capturing to hook --- .../README.md | 2 +- .../src/ioredis.ts | 38 +++---- .../src/types.ts | 19 +++- .../src/utils.ts | 19 +++- .../test/ioredis.test.ts | 107 +++++++++++++----- 5 files changed, 127 insertions(+), 58 deletions(-) diff --git a/plugins/node/opentelemetry-instrumentation-ioredis/README.md b/plugins/node/opentelemetry-instrumentation-ioredis/README.md index be2e8a1edb..dd1ff4b298 100644 --- a/plugins/node/opentelemetry-instrumentation-ioredis/README.md +++ b/plugins/node/opentelemetry-instrumentation-ioredis/README.md @@ -49,9 +49,9 @@ IORedis instrumentation has few options available to choose from. You can set th | Options | Type | Description | | ------- | ---- | ----------- | | `dbStatementSerializer` | `DbStatementSerializer` | IORedis instrumentation will serialize db.statement using the specified function. | +| `requestHook` | `RedisRequestCustomAttributeFunction` | Function for adding custom attributes on db request | | `responseHook` | `RedisResponseCustomAttributeFunction` | Function for adding custom attributes on db response | | `requireParentSpan` | `boolean` | Require parent to create ioredis span, default when unset is true | -| `moduleVersionAttributeName` | `string` | If passed, a span attribute will be added to all spans with key of the provided "moduleVersionAttributeName" and value of the module version. | #### Custom db.statement Serializer The instrumentation serializes the whole command into a Span attribute called `db.statement`. The standard serialization format is `{cmdName} {cmdArgs.join(',')}`. diff --git a/plugins/node/opentelemetry-instrumentation-ioredis/src/ioredis.ts b/plugins/node/opentelemetry-instrumentation-ioredis/src/ioredis.ts index cbd854df95..ee965e00b3 100644 --- a/plugins/node/opentelemetry-instrumentation-ioredis/src/ioredis.ts +++ b/plugins/node/opentelemetry-instrumentation-ioredis/src/ioredis.ts @@ -14,16 +14,16 @@ * limitations under the License. */ -import { diag } from "@opentelemetry/api"; -import type * as ioredisTypes from "ioredis"; +import { diag } from '@opentelemetry/api'; +import type * as ioredisTypes from 'ioredis'; import { InstrumentationBase, InstrumentationNodeModuleDefinition, isWrapped, -} from "@opentelemetry/instrumentation"; -import { IORedisInstrumentationConfig } from "./types"; -import { traceConnection, traceSendCommand } from "./utils"; -import { VERSION } from "./version"; +} from '@opentelemetry/instrumentation'; +import { IORedisInstrumentationConfig } from './types'; +import { traceConnection, traceSendCommand } from './utils'; +import { VERSION } from './version'; const DEFAULT_CONFIG: IORedisInstrumentationConfig = { requireParentSpan: true, @@ -32,11 +32,11 @@ const DEFAULT_CONFIG: IORedisInstrumentationConfig = { export class IORedisInstrumentation extends InstrumentationBase< typeof ioredisTypes > { - static readonly DB_SYSTEM = "redis"; + static readonly DB_SYSTEM = 'redis'; constructor(_config: IORedisInstrumentationConfig = {}) { super( - "@opentelemetry/instrumentation-ioredis", + '@opentelemetry/instrumentation-ioredis', VERSION, Object.assign({}, DEFAULT_CONFIG, _config) ); @@ -45,33 +45,33 @@ export class IORedisInstrumentation extends InstrumentationBase< init(): InstrumentationNodeModuleDefinition[] { return [ new InstrumentationNodeModuleDefinition( - "ioredis", - [">1 <5"], + 'ioredis', + ['>1 <5'], (moduleExports, moduleVersion?: string | undefined) => { - diag.debug("Applying patch for ioredis"); + diag.debug('Applying patch for ioredis'); if (isWrapped(moduleExports.prototype.sendCommand)) { - this._unwrap(moduleExports.prototype, "sendCommand"); + this._unwrap(moduleExports.prototype, 'sendCommand'); } this._wrap( moduleExports.prototype, - "sendCommand", + 'sendCommand', this._patchSendCommand(moduleVersion) ); if (isWrapped(moduleExports.prototype.connect)) { - this._unwrap(moduleExports.prototype, "connect"); + this._unwrap(moduleExports.prototype, 'connect'); } this._wrap( moduleExports.prototype, - "connect", + 'connect', this._patchConnection() ); return moduleExports; }, - (moduleExports) => { + moduleExports => { if (moduleExports === undefined) return; - diag.debug("Removing patch for ioredis"); - this._unwrap(moduleExports.prototype, "sendCommand"); - this._unwrap(moduleExports.prototype, "connect"); + diag.debug('Removing patch for ioredis'); + this._unwrap(moduleExports.prototype, 'sendCommand'); + this._unwrap(moduleExports.prototype, 'connect'); } ), ]; diff --git a/plugins/node/opentelemetry-instrumentation-ioredis/src/types.ts b/plugins/node/opentelemetry-instrumentation-ioredis/src/types.ts index 9be4e7a5d5..bb29a994c0 100644 --- a/plugins/node/opentelemetry-instrumentation-ioredis/src/types.ts +++ b/plugins/node/opentelemetry-instrumentation-ioredis/src/types.ts @@ -40,6 +40,16 @@ export type DbStatementSerializer = ( cmdArgs: IORedisCommand['args'] ) => string; +export interface IoRedisRequestHookInformation { + moduleVersion?: string; + cmdName: IORedisCommand['name']; + cmdArgs: IORedisCommand['args']; +} + +export interface RedisRequestCustomAttributeFunction { + (span: Span, requestInfo: IoRedisRequestHookInformation): void; +} + /** * Function that can be used to add custom attributes to span on response from redis server * @param span - The span created for the redis command, on which attributes can be set @@ -66,15 +76,12 @@ export interface IORedisInstrumentationConfig extends InstrumentationConfig { /** Custom serializer function for the db.statement tag */ dbStatementSerializer?: DbStatementSerializer; + /** Function for adding custom attributes on db request */ + requestHook?: RedisRequestCustomAttributeFunction; + /** Function for adding custom attributes on db response */ responseHook?: RedisResponseCustomAttributeFunction; /** Require parent to create ioredis span, default when unset is true */ requireParentSpan?: boolean; - - /** - * If passed, a span attribute will be added to all spans with key of the provided "moduleVersionAttributeName" - * and value of the module version. - */ - moduleVersionAttributeName?: string; } diff --git a/plugins/node/opentelemetry-instrumentation-ioredis/src/utils.ts b/plugins/node/opentelemetry-instrumentation-ioredis/src/utils.ts index 6a42316ab8..6f101601f6 100644 --- a/plugins/node/opentelemetry-instrumentation-ioredis/src/utils.ts +++ b/plugins/node/opentelemetry-instrumentation-ioredis/src/utils.ts @@ -108,8 +108,21 @@ export const traceSendCommand = ( }, }); - if (config?.moduleVersionAttributeName && moduleVersion) { - span.setAttribute(config?.moduleVersionAttributeName, moduleVersion); + if (config?.requestHook) { + safeExecuteInTheMiddle( + () => + config?.requestHook!(span, { + moduleVersion, + cmdName: cmd.name, + cmdArgs: cmd.args, + }), + e => { + if (e) { + diag.error('ioredis instrumentation: request hook failed', e); + } + }, + true + ); } const { host, port } = this.options; @@ -130,7 +143,7 @@ export const traceSendCommand = ( () => config?.responseHook?.(span, cmd.name, cmd.args, result), e => { if (e) { - diag.error('ioredis response hook failed', e); + diag.error('ioredis instrumentation: response hook failed', e); } }, true diff --git a/plugins/node/opentelemetry-instrumentation-ioredis/test/ioredis.test.ts b/plugins/node/opentelemetry-instrumentation-ioredis/test/ioredis.test.ts index 04cd4c2600..887682810e 100644 --- a/plugins/node/opentelemetry-instrumentation-ioredis/test/ioredis.test.ts +++ b/plugins/node/opentelemetry-instrumentation-ioredis/test/ioredis.test.ts @@ -37,6 +37,7 @@ import { IORedisInstrumentation } from '../src'; import { IORedisInstrumentationConfig, DbStatementSerializer, + IoRedisRequestHookInformation, } from '../src/types'; import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; @@ -769,29 +770,73 @@ describe('ioredis', () => { }); }); - it('moduleVersionAttributeName should capture ioredis version', async () => { - const VERSION_ATTR = 'instrumentedmodule.version'; - instrumentation.disable(); - const config: IORedisInstrumentationConfig = { - moduleVersionAttributeName: VERSION_ATTR, - }; - instrumentation = new IORedisInstrumentation(config); - instrumentation.setTracerProvider(provider); - require('ioredis'); + describe('Instrumenting with a custom hooks', () => { + it('should call requestHook when set in config', async () => { + instrumentation.disable(); + const config: IORedisInstrumentationConfig = { + requestHook: ( + span: Span, + requestInfo: IoRedisRequestHookInformation + ) => { + assert.match( + requestInfo.moduleVersion as string, + /\d{1,4}\.\d{1,4}\.\d{1,5}.*/ + ); + assert.strictEqual(requestInfo.cmdName, 'incr'); + assert.deepStrictEqual(requestInfo.cmdArgs, ['request-hook-test']); - const span = provider.getTracer('ioredis-test').startSpan('test span'); - await context.with(setSpan(context.active(), span), async () => { - await client.set(testKeyName, 'data'); - const endedSpans = memoryExporter.getFinishedSpans(); - assert.strictEqual(endedSpans.length, 1); - assert.match( - endedSpans[0].attributes[VERSION_ATTR] as string, - /\d{1,4}\.\d{1,4}\.\d{1,5}.*/ - ); + span.setAttribute( + 'attribute key from request hook', + 'custom value from request hook' + ); + }, + }; + instrumentation = new IORedisInstrumentation(config); + instrumentation.setTracerProvider(provider); + require('ioredis'); + + const span = provider.getTracer('ioredis-test').startSpan('test span'); + await context.with(setSpan(context.active(), span), async () => { + await client.incr('request-hook-test'); + const endedSpans = memoryExporter.getFinishedSpans(); + assert.strictEqual(endedSpans.length, 1); + assert.strictEqual( + endedSpans[0].attributes['attribute key from request hook'], + 'custom value from request hook' + ); + }); + }); + + it('should ignore requestHook which throws exception', async () => { + instrumentation.disable(); + const config: IORedisInstrumentationConfig = { + requestHook: ( + span: Span, + _requestInfo: IoRedisRequestHookInformation + ) => { + span.setAttribute( + 'attribute key BEFORE exception', + 'this attribute is added to span BEFORE exception is thrown thus we can expect it' + ); + throw Error('error thrown in requestHook'); + }, + }; + instrumentation = new IORedisInstrumentation(config); + instrumentation.setTracerProvider(provider); + require('ioredis'); + + const span = provider.getTracer('ioredis-test').startSpan('test span'); + await context.with(setSpan(context.active(), span), async () => { + await client.incr('request-hook-throw-test'); + const endedSpans = memoryExporter.getFinishedSpans(); + assert.strictEqual(endedSpans.length, 1); + assert.strictEqual( + endedSpans[0].attributes['attribute key BEFORE exception'], + 'this attribute is added to span BEFORE exception is thrown thus we can expect it' + ); + }); }); - }); - describe('Instrumenting with a custom responseHook', () => { it('should call responseHook when set in config', async () => { instrumentation.disable(); const config: IORedisInstrumentationConfig = { @@ -801,13 +846,17 @@ describe('ioredis', () => { _cmdArgs: Array, response: unknown ) => { - assert.strictEqual(cmdName, 'incr'); - // the command is 'incr' on a key which does not exist, thus it increase 0 by 1 and respond 1 - assert.strictEqual(response, 1); - span.setAttribute( - 'attribute key from hook', - 'custom value from hook' - ); + try { + assert.strictEqual(cmdName, 'incr'); + // the command is 'incr' on a key which does not exist, thus it increase 0 by 1 and respond 1 + assert.strictEqual(response, 1); + span.setAttribute( + 'attribute key from hook', + 'custom value from hook' + ); + } catch (err) { + console.log(err); + } }, }; instrumentation = new IORedisInstrumentation(config); @@ -816,7 +865,7 @@ describe('ioredis', () => { const span = provider.getTracer('ioredis-test').startSpan('test span'); await context.with(setSpan(context.active(), span), async () => { - await client.incr('new-key'); + await client.incr('response-hook-test'); const endedSpans = memoryExporter.getFinishedSpans(); assert.strictEqual(endedSpans.length, 1); assert.strictEqual( @@ -844,7 +893,7 @@ describe('ioredis', () => { const span = provider.getTracer('ioredis-test').startSpan('test span'); await context.with(setSpan(context.active(), span), async () => { - await client.incr('some-key'); + await client.incr('response-hook-throw-test'); const endedSpans = memoryExporter.getFinishedSpans(); // hook throw exception, but span should not be affected From 077973e3913799e5d4c5911cccba71625eca6880 Mon Sep 17 00:00:00 2001 From: Amir Blum Date: Sun, 25 Apr 2021 14:42:51 +0300 Subject: [PATCH 04/13] style(instrumentation-ioredis): moduleVersion optional type --- .../node/opentelemetry-instrumentation-ioredis/src/ioredis.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/node/opentelemetry-instrumentation-ioredis/src/ioredis.ts b/plugins/node/opentelemetry-instrumentation-ioredis/src/ioredis.ts index ee965e00b3..7c74454c55 100644 --- a/plugins/node/opentelemetry-instrumentation-ioredis/src/ioredis.ts +++ b/plugins/node/opentelemetry-instrumentation-ioredis/src/ioredis.ts @@ -47,7 +47,7 @@ export class IORedisInstrumentation extends InstrumentationBase< new InstrumentationNodeModuleDefinition( 'ioredis', ['>1 <5'], - (moduleExports, moduleVersion?: string | undefined) => { + (moduleExports, moduleVersion?: string) => { diag.debug('Applying patch for ioredis'); if (isWrapped(moduleExports.prototype.sendCommand)) { this._unwrap(moduleExports.prototype, 'sendCommand'); @@ -80,7 +80,7 @@ export class IORedisInstrumentation extends InstrumentationBase< /** * Patch send command internal to trace requests */ - private _patchSendCommand(moduleVersion?: string | undefined) { + private _patchSendCommand(moduleVersion?: string) { return (original: Function) => { return traceSendCommand( this.tracer, From 3d06618108d4a15615bdaa367289104f3b6d9d24 Mon Sep 17 00:00:00 2001 From: Amir Blum Date: Sun, 25 Apr 2021 14:54:45 +0300 Subject: [PATCH 05/13] fix(instrumentation-ioredis): no assert.match in node 10 --- .../test/ioredis.test.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/node/opentelemetry-instrumentation-ioredis/test/ioredis.test.ts b/plugins/node/opentelemetry-instrumentation-ioredis/test/ioredis.test.ts index 887682810e..57f37dd7af 100644 --- a/plugins/node/opentelemetry-instrumentation-ioredis/test/ioredis.test.ts +++ b/plugins/node/opentelemetry-instrumentation-ioredis/test/ioredis.test.ts @@ -778,9 +778,10 @@ describe('ioredis', () => { span: Span, requestInfo: IoRedisRequestHookInformation ) => { - assert.match( - requestInfo.moduleVersion as string, - /\d{1,4}\.\d{1,4}\.\d{1,5}.*/ + assert.ok( + /\d{1,4}\.\d{1,4}\.\d{1,5}.*/.test( + requestInfo.moduleVersion as string + ) ); assert.strictEqual(requestInfo.cmdName, 'incr'); assert.deepStrictEqual(requestInfo.cmdArgs, ['request-hook-test']); From e7db198518c936de028f3b311128adf7e3923591 Mon Sep 17 00:00:00 2001 From: Amir Blum Date: Mon, 26 Apr 2021 10:36:45 +0300 Subject: [PATCH 06/13] docs(instrumentation-ioredis): add request hook signuature to README --- plugins/node/opentelemetry-instrumentation-ioredis/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/node/opentelemetry-instrumentation-ioredis/README.md b/plugins/node/opentelemetry-instrumentation-ioredis/README.md index dd1ff4b298..3504929cf4 100644 --- a/plugins/node/opentelemetry-instrumentation-ioredis/README.md +++ b/plugins/node/opentelemetry-instrumentation-ioredis/README.md @@ -49,8 +49,8 @@ IORedis instrumentation has few options available to choose from. You can set th | Options | Type | Description | | ------- | ---- | ----------- | | `dbStatementSerializer` | `DbStatementSerializer` | IORedis instrumentation will serialize db.statement using the specified function. | -| `requestHook` | `RedisRequestCustomAttributeFunction` | Function for adding custom attributes on db request | -| `responseHook` | `RedisResponseCustomAttributeFunction` | Function for adding custom attributes on db response | +| `requestHook` | `RedisRequestCustomAttributeFunction` (function) | Function for adding custom attributes on db request. Receives params: `(span: Span, { moduleVersion, cmdName, cmdArgs } : ExpressRequestHookInformation)` | +| `responseHook` | `RedisResponseCustomAttributeFunction` (function) | Function for adding custom attributes on db response | | `requireParentSpan` | `boolean` | Require parent to create ioredis span, default when unset is true | #### Custom db.statement Serializer From 5fbfa9379ab88545119430473752c215284d5eee Mon Sep 17 00:00:00 2001 From: Amir Blum Date: Mon, 26 Apr 2021 10:56:52 +0300 Subject: [PATCH 07/13] docs(instrumentation-ioredis): lighter hook params documentation --- plugins/node/opentelemetry-instrumentation-ioredis/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/node/opentelemetry-instrumentation-ioredis/README.md b/plugins/node/opentelemetry-instrumentation-ioredis/README.md index 3504929cf4..92ea1072a9 100644 --- a/plugins/node/opentelemetry-instrumentation-ioredis/README.md +++ b/plugins/node/opentelemetry-instrumentation-ioredis/README.md @@ -49,7 +49,7 @@ IORedis instrumentation has few options available to choose from. You can set th | Options | Type | Description | | ------- | ---- | ----------- | | `dbStatementSerializer` | `DbStatementSerializer` | IORedis instrumentation will serialize db.statement using the specified function. | -| `requestHook` | `RedisRequestCustomAttributeFunction` (function) | Function for adding custom attributes on db request. Receives params: `(span: Span, { moduleVersion, cmdName, cmdArgs } : ExpressRequestHookInformation)` | +| `requestHook` | `RedisRequestCustomAttributeFunction` (function) | Function for adding custom attributes on db request. Receives params: `span, { moduleVersion, cmdName, cmdArgs }` | | `responseHook` | `RedisResponseCustomAttributeFunction` (function) | Function for adding custom attributes on db response | | `requireParentSpan` | `boolean` | Require parent to create ioredis span, default when unset is true | From 04356440906250d0ff7363b708337463d1c9a0c6 Mon Sep 17 00:00:00 2001 From: Amir Blum Date: Mon, 26 Apr 2021 12:29:03 +0300 Subject: [PATCH 08/13] docs(instrumentation-ioredis): add request hook example --- .../README.md | 53 +++++++++++++------ 1 file changed, 38 insertions(+), 15 deletions(-) diff --git a/plugins/node/opentelemetry-instrumentation-ioredis/README.md b/plugins/node/opentelemetry-instrumentation-ioredis/README.md index 92ea1072a9..6a604c88de 100644 --- a/plugins/node/opentelemetry-instrumentation-ioredis/README.md +++ b/plugins/node/opentelemetry-instrumentation-ioredis/README.md @@ -2,7 +2,7 @@ [![NPM Published Version][npm-img]][npm-url] [![dependencies][dependencies-image]][dependencies-url] -[![devDependencies][devDependencies-image]][devDependencies-url] +[![devDependencies][devdependencies-image]][devdependencies-url] [![Apache License][license-image]][license-image] This module provides automatic instrumentation for [`ioredis`](https://github.com/luin/ioredis). @@ -25,9 +25,11 @@ npm install --save @opentelemetry/instrumentation-ioredis To load a specific instrumentation (**ioredis** in this case), specify it in the registerInstrumentations's configuration ```javascript -const { NodeTracerProvider } = require('@opentelemetry/node'); -const { IORedisInstrumentation } = require('@opentelemetry/instrumentation-ioredis'); -const { registerInstrumentations } = require('@opentelemetry/instrumentation'); +const { NodeTracerProvider } = require("@opentelemetry/node"); +const { + IORedisInstrumentation, +} = require("@opentelemetry/instrumentation-ioredis"); +const { registerInstrumentations } = require("@opentelemetry/instrumentation"); const provider = new NodeTracerProvider(); provider.register(); @@ -36,22 +38,22 @@ registerInstrumentations({ instrumentations: [ new IORedisInstrumentation({ // see under for available configuration - }) + }), ], tracerProvider: provider, -}) +}); ``` ### IORedis Instrumentation Options IORedis instrumentation has few options available to choose from. You can set the following: -| Options | Type | Description | -| ------- | ---- | ----------- | -| `dbStatementSerializer` | `DbStatementSerializer` | IORedis instrumentation will serialize db.statement using the specified function. | -| `requestHook` | `RedisRequestCustomAttributeFunction` (function) | Function for adding custom attributes on db request. Receives params: `span, { moduleVersion, cmdName, cmdArgs }` | -| `responseHook` | `RedisResponseCustomAttributeFunction` (function) | Function for adding custom attributes on db response | -| `requireParentSpan` | `boolean` | Require parent to create ioredis span, default when unset is true | +| Options | Type | Description | +| ----------------------- | ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | +| `dbStatementSerializer` | `DbStatementSerializer` | IORedis instrumentation will serialize db.statement using the specified function. | +| `requestHook` | `RedisRequestCustomAttributeFunction` (function) | Function for adding custom attributes on db request. Receives params: `span, { moduleVersion, cmdName, cmdArgs }` | +| `responseHook` | `RedisResponseCustomAttributeFunction` (function) | Function for adding custom attributes on db response | +| `requireParentSpan` | `boolean` | Require parent to create ioredis span, default when unset is true | #### Custom db.statement Serializer The instrumentation serializes the whole command into a Span attribute called `db.statement`. The standard serialization format is `{cmdName} {cmdArgs.join(',')}`. @@ -60,12 +62,33 @@ It is also possible to define a custom serialization function. The function will Here is a simple example to serialize the command name skipping arguments: ```javascript -const { IORedisInstrumentation } = require('@opentelemetry/instrumentation-ioredis'); +const { + IORedisInstrumentation, +} = require("@opentelemetry/instrumentation-ioredis"); const ioredisInstrumentation = new IORedisInstrumentation({ dbStatementSerializer: function (cmdName, cmdArgs) { return cmdName; - } + }, +}); +``` + +#### Using `requestHook` + +Instrumentation user can configure a custom "hook" function which will be called on every request with the relevant span and request information. User can then set custom attributes on the span or run any instrumentation extension logic per request. + +Here is a simple example that adds and attribute of `ioredis` instrumented version: + +```javascript +const { IORedisInstrumentation } = require('@opentelemetry/instrumentation-ioredis'); + +const ioredisInstrumentation = new IORedisInstrumentation({ + requestHook: function( + span: Span, + requestInfo: IoRedisRequestHookInformation + ) { + span.setAttribute('instrumented_library.version', requestInfo.moduleVersion) + }) }); ``` @@ -86,6 +109,6 @@ Apache 2.0 - See [LICENSE][license-url] for more information. [dependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js-contrib.svg?path=plugins%2Fnode%2Fopentelemetry-instrumentation-ioredis [dependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js-contrib?path=plugins%2Fnode%2Fopentelemetry-instrumentation-ioredis [devdependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js-contrib.svg?path=plugins%2Fnode%2Fopentelemetry-instrumentation-ioredis&type=dev -[devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js-contrib?path=plugins%2Fnode%2Fopentelemetry-instrumentation-ioredis&type=dev +[devdependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js-contrib?path=plugins%2Fnode%2Fopentelemetry-instrumentation-ioredis&type=dev [npm-url]: https://www.npmjs.com/package/@opentelemetry/instrumentation-ioredis [npm-img]: https://badge.fury.io/js/%40opentelemetry%2Finstrumentation-ioredis.svg From ea1d7b974414fc5630e5b1ca230cadadef2ce848 Mon Sep 17 00:00:00 2001 From: Amir Blum Date: Mon, 26 Apr 2021 12:31:27 +0300 Subject: [PATCH 09/13] docs(instrumentation-ioredis): improve request hook example --- .../README.md | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/plugins/node/opentelemetry-instrumentation-ioredis/README.md b/plugins/node/opentelemetry-instrumentation-ioredis/README.md index 6a604c88de..a6260ec628 100644 --- a/plugins/node/opentelemetry-instrumentation-ioredis/README.md +++ b/plugins/node/opentelemetry-instrumentation-ioredis/README.md @@ -75,20 +75,25 @@ const ioredisInstrumentation = new IORedisInstrumentation({ #### Using `requestHook` -Instrumentation user can configure a custom "hook" function which will be called on every request with the relevant span and request information. User can then set custom attributes on the span or run any instrumentation extension logic per request. +Instrumentation user can configure a custom "hook" function which will be called on every request with the relevant span and request information. User can then set custom attributes on the span or run any instrumentation-extension logic per request. -Here is a simple example that adds and attribute of `ioredis` instrumented version: +Here is a simple example that adds a span attribute of `ioredis` instrumented version on each request: ```javascript const { IORedisInstrumentation } = require('@opentelemetry/instrumentation-ioredis'); const ioredisInstrumentation = new IORedisInstrumentation({ - requestHook: function( - span: Span, - requestInfo: IoRedisRequestHookInformation - ) { - span.setAttribute('instrumented_library.version', requestInfo.moduleVersion) - }) +requestHook: function ( + span: Span, + requestInfo: IoRedisRequestHookInformation + ) { + if (requestInfo.moduleVersion) { + span.setAttribute( + "instrumented_library.version", + requestInfo.moduleVersion + ); + } + } }); ``` From acd178933f106f874d93ae5c67d2643b15283287 Mon Sep 17 00:00:00 2001 From: Amir Blum Date: Mon, 26 Apr 2021 21:10:35 +0300 Subject: [PATCH 10/13] Update plugins/node/opentelemetry-instrumentation-ioredis/src/types.ts Co-authored-by: Bartlomiej Obecny --- plugins/node/opentelemetry-instrumentation-ioredis/src/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/node/opentelemetry-instrumentation-ioredis/src/types.ts b/plugins/node/opentelemetry-instrumentation-ioredis/src/types.ts index bb29a994c0..ed1f7aada4 100644 --- a/plugins/node/opentelemetry-instrumentation-ioredis/src/types.ts +++ b/plugins/node/opentelemetry-instrumentation-ioredis/src/types.ts @@ -40,7 +40,7 @@ export type DbStatementSerializer = ( cmdArgs: IORedisCommand['args'] ) => string; -export interface IoRedisRequestHookInformation { +export interface IORedisRequestHookInformation { moduleVersion?: string; cmdName: IORedisCommand['name']; cmdArgs: IORedisCommand['args']; From 14ca036a6faf8c8de3f899cbb26feec2010e11e2 Mon Sep 17 00:00:00 2001 From: Amir Blum Date: Mon, 26 Apr 2021 21:26:17 +0300 Subject: [PATCH 11/13] docs(instrumentation-ioredis): double to single quotes --- .../node/opentelemetry-instrumentation-ioredis/README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/plugins/node/opentelemetry-instrumentation-ioredis/README.md b/plugins/node/opentelemetry-instrumentation-ioredis/README.md index a6260ec628..e776d1b1d2 100644 --- a/plugins/node/opentelemetry-instrumentation-ioredis/README.md +++ b/plugins/node/opentelemetry-instrumentation-ioredis/README.md @@ -62,9 +62,7 @@ It is also possible to define a custom serialization function. The function will Here is a simple example to serialize the command name skipping arguments: ```javascript -const { - IORedisInstrumentation, -} = require("@opentelemetry/instrumentation-ioredis"); +const { IORedisInstrumentation } = require('@opentelemetry/instrumentation-ioredis'); const ioredisInstrumentation = new IORedisInstrumentation({ dbStatementSerializer: function (cmdName, cmdArgs) { @@ -89,7 +87,7 @@ requestHook: function ( ) { if (requestInfo.moduleVersion) { span.setAttribute( - "instrumented_library.version", + 'instrumented_library.version', requestInfo.moduleVersion ); } From 4d0a1bebd99ab1a856fbb6a5b5eb6ed8fd0e4ddb Mon Sep 17 00:00:00 2001 From: Amir Blum Date: Mon, 26 Apr 2021 21:42:14 +0300 Subject: [PATCH 12/13] fix(instrumentation-ioredis): update changed interface name everywhere --- .../node/opentelemetry-instrumentation-ioredis/README.md | 2 +- .../node/opentelemetry-instrumentation-ioredis/src/types.ts | 2 +- .../test/ioredis.test.ts | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/node/opentelemetry-instrumentation-ioredis/README.md b/plugins/node/opentelemetry-instrumentation-ioredis/README.md index e776d1b1d2..621d0b3f0a 100644 --- a/plugins/node/opentelemetry-instrumentation-ioredis/README.md +++ b/plugins/node/opentelemetry-instrumentation-ioredis/README.md @@ -83,7 +83,7 @@ const { IORedisInstrumentation } = require('@opentelemetry/instrumentation-iored const ioredisInstrumentation = new IORedisInstrumentation({ requestHook: function ( span: Span, - requestInfo: IoRedisRequestHookInformation + requestInfo: IORedisRequestHookInformation ) { if (requestInfo.moduleVersion) { span.setAttribute( diff --git a/plugins/node/opentelemetry-instrumentation-ioredis/src/types.ts b/plugins/node/opentelemetry-instrumentation-ioredis/src/types.ts index 927e54f946..66f3137484 100644 --- a/plugins/node/opentelemetry-instrumentation-ioredis/src/types.ts +++ b/plugins/node/opentelemetry-instrumentation-ioredis/src/types.ts @@ -46,7 +46,7 @@ export interface IORedisRequestHookInformation { } export interface RedisRequestCustomAttributeFunction { - (span: Span, requestInfo: IoRedisRequestHookInformation): void; + (span: Span, requestInfo: IORedisRequestHookInformation): void; } /** diff --git a/plugins/node/opentelemetry-instrumentation-ioredis/test/ioredis.test.ts b/plugins/node/opentelemetry-instrumentation-ioredis/test/ioredis.test.ts index 57f37dd7af..55bb8e360b 100644 --- a/plugins/node/opentelemetry-instrumentation-ioredis/test/ioredis.test.ts +++ b/plugins/node/opentelemetry-instrumentation-ioredis/test/ioredis.test.ts @@ -37,7 +37,7 @@ import { IORedisInstrumentation } from '../src'; import { IORedisInstrumentationConfig, DbStatementSerializer, - IoRedisRequestHookInformation, + IORedisRequestHookInformation, } from '../src/types'; import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; @@ -776,7 +776,7 @@ describe('ioredis', () => { const config: IORedisInstrumentationConfig = { requestHook: ( span: Span, - requestInfo: IoRedisRequestHookInformation + requestInfo: IORedisRequestHookInformation ) => { assert.ok( /\d{1,4}\.\d{1,4}\.\d{1,5}.*/.test( @@ -813,7 +813,7 @@ describe('ioredis', () => { const config: IORedisInstrumentationConfig = { requestHook: ( span: Span, - _requestInfo: IoRedisRequestHookInformation + _requestInfo: IORedisRequestHookInformation ) => { span.setAttribute( 'attribute key BEFORE exception', From 2924b56ccf47fa956445fcbf3461c6464b12661d Mon Sep 17 00:00:00 2001 From: Amir Blum Date: Mon, 26 Apr 2021 21:58:04 +0300 Subject: [PATCH 13/13] docs(instrumentation-ioredis): revert change of badge --- plugins/node/opentelemetry-instrumentation-ioredis/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/node/opentelemetry-instrumentation-ioredis/README.md b/plugins/node/opentelemetry-instrumentation-ioredis/README.md index 621d0b3f0a..b7a2d22405 100644 --- a/plugins/node/opentelemetry-instrumentation-ioredis/README.md +++ b/plugins/node/opentelemetry-instrumentation-ioredis/README.md @@ -2,7 +2,7 @@ [![NPM Published Version][npm-img]][npm-url] [![dependencies][dependencies-image]][dependencies-url] -[![devDependencies][devdependencies-image]][devdependencies-url] +[![devDependencies][devDependencies-image]][devDependencies-url] [![Apache License][license-image]][license-image] This module provides automatic instrumentation for [`ioredis`](https://github.com/luin/ioredis). @@ -112,6 +112,6 @@ Apache 2.0 - See [LICENSE][license-url] for more information. [dependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js-contrib.svg?path=plugins%2Fnode%2Fopentelemetry-instrumentation-ioredis [dependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js-contrib?path=plugins%2Fnode%2Fopentelemetry-instrumentation-ioredis [devdependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js-contrib.svg?path=plugins%2Fnode%2Fopentelemetry-instrumentation-ioredis&type=dev -[devdependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js-contrib?path=plugins%2Fnode%2Fopentelemetry-instrumentation-ioredis&type=dev +[devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js-contrib?path=plugins%2Fnode%2Fopentelemetry-instrumentation-ioredis&type=dev [npm-url]: https://www.npmjs.com/package/@opentelemetry/instrumentation-ioredis [npm-img]: https://badge.fury.io/js/%40opentelemetry%2Finstrumentation-ioredis.svg