From 0a0b4dcac282eac90f8bf76b53e539d58200c772 Mon Sep 17 00:00:00 2001 From: Zirak Date: Wed, 17 Apr 2024 13:56:58 +0000 Subject: [PATCH 1/5] refactor(instrumentation-redis): Use exported semconv strings (#2075) * refactor(instrumentation-redis): Use exported semconv strings Part of #2025. * chore(instrumentation-redis): Update package-lock --------- Co-authored-by: Jamie Danielson Co-authored-by: Amir Blum Co-authored-by: Marc Pichler --- package-lock.json | 4 ++-- .../README.md | 14 +++++++++++++ .../package.json | 2 +- .../src/utils.ts | 21 ++++++++++--------- .../test/redis.test.ts | 20 +++++++++++------- 5 files changed, 40 insertions(+), 21 deletions(-) diff --git a/package-lock.json b/package-lock.json index f48f69eb25..fe110e001b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38497,7 +38497,7 @@ "dependencies": { "@opentelemetry/instrumentation": "^0.50.0", "@opentelemetry/redis-common": "^0.36.1", - "@opentelemetry/semantic-conventions": "^1.0.0" + "@opentelemetry/semantic-conventions": "^1.22.0" }, "devDependencies": { "@opentelemetry/api": "^1.3.0", @@ -46856,7 +46856,7 @@ "@opentelemetry/redis-common": "^0.36.1", "@opentelemetry/sdk-trace-base": "^1.8.0", "@opentelemetry/sdk-trace-node": "^1.8.0", - "@opentelemetry/semantic-conventions": "^1.0.0", + "@opentelemetry/semantic-conventions": "^1.22.0", "@types/mocha": "7.0.2", "@types/node": "18.6.5", "@types/redis": "2.8.32", diff --git a/plugins/node/opentelemetry-instrumentation-redis/README.md b/plugins/node/opentelemetry-instrumentation-redis/README.md index 693edfdd21..e93e4c7873 100644 --- a/plugins/node/opentelemetry-instrumentation-redis/README.md +++ b/plugins/node/opentelemetry-instrumentation-redis/README.md @@ -74,6 +74,20 @@ const redisInstrumentation = new RedisInstrumentation({ }); ``` +## Semantic Conventions + +This package uses `@opentelemetry/semantic-conventions` version `1.22+`, which implements Semantic Convention [Version 1.7.0](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.7.0/semantic_conventions/README.md) + +Attributes collected: + +| Attribute | Short Description | Notes | +|------------------------|--------------------------------------------------------------|--------------------------------------| +| `db.connection_string` | URL to Redis server address, of the form `redis://host:port` | Key: `SEMATTRS_DB_CONNECTION_STRING` | +| `db.statement` | Executed Redis statement | Key: `SEMATTRS_DB_STATEMENT` | +| `db.system` | Database identifier; always `redis` | Key: `SEMATTRS_DB_SYSTEM` | +| `net.peer.name` | Hostname or IP of the connected Redis server | Key: `SEMATTRS_NET_PEER_NAME` | +| `net.peer.port` | Port of the connected Redis server | Key: `SEMATTRS_NET_PORT_NAME` | + ## Useful links - For more information on OpenTelemetry, visit: diff --git a/plugins/node/opentelemetry-instrumentation-redis/package.json b/plugins/node/opentelemetry-instrumentation-redis/package.json index 67d8fc6c1a..7c52f2cb7b 100644 --- a/plugins/node/opentelemetry-instrumentation-redis/package.json +++ b/plugins/node/opentelemetry-instrumentation-redis/package.json @@ -68,7 +68,7 @@ "dependencies": { "@opentelemetry/instrumentation": "^0.50.0", "@opentelemetry/redis-common": "^0.36.1", - "@opentelemetry/semantic-conventions": "^1.0.0" + "@opentelemetry/semantic-conventions": "^1.22.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-redis#readme" } diff --git a/plugins/node/opentelemetry-instrumentation-redis/src/utils.ts b/plugins/node/opentelemetry-instrumentation-redis/src/utils.ts index 7575e51376..fed4f769f9 100644 --- a/plugins/node/opentelemetry-instrumentation-redis/src/utils.ts +++ b/plugins/node/opentelemetry-instrumentation-redis/src/utils.ts @@ -28,8 +28,12 @@ import { RedisCommand, RedisInstrumentationConfig } from './types'; import { EventEmitter } from 'events'; import { RedisInstrumentation } from './'; import { - DbSystemValues, - SemanticAttributes, + DBSYSTEMVALUES_REDIS, + SEMATTRS_DB_CONNECTION_STRING, + SEMATTRS_DB_STATEMENT, + SEMATTRS_DB_SYSTEM, + SEMATTRS_NET_PEER_NAME, + SEMATTRS_NET_PEER_PORT, } from '@opentelemetry/semantic-conventions'; import { safeExecuteInTheMiddle } from '@opentelemetry/instrumentation'; import { RedisPluginClientTypes } from './internal-types'; @@ -100,11 +104,8 @@ export const getTracedInternalSendCommand = ( { kind: SpanKind.CLIENT, attributes: { - [SemanticAttributes.DB_SYSTEM]: DbSystemValues.REDIS, - [SemanticAttributes.DB_STATEMENT]: dbStatementSerializer( - cmd.command, - cmd.args - ), + [SEMATTRS_DB_SYSTEM]: DBSYSTEMVALUES_REDIS, + [SEMATTRS_DB_STATEMENT]: dbStatementSerializer(cmd.command, cmd.args), }, } ); @@ -112,13 +113,13 @@ export const getTracedInternalSendCommand = ( // Set attributes for not explicitly typed RedisPluginClientTypes if (this.options) { span.setAttributes({ - [SemanticAttributes.NET_PEER_NAME]: this.options.host, - [SemanticAttributes.NET_PEER_PORT]: this.options.port, + [SEMATTRS_NET_PEER_NAME]: this.options.host, + [SEMATTRS_NET_PEER_PORT]: this.options.port, }); } if (this.address) { span.setAttribute( - SemanticAttributes.DB_CONNECTION_STRING, + SEMATTRS_DB_CONNECTION_STRING, `redis://${this.address}` ); } diff --git a/plugins/node/opentelemetry-instrumentation-redis/test/redis.test.ts b/plugins/node/opentelemetry-instrumentation-redis/test/redis.test.ts index 01d449a57e..63ab337e86 100644 --- a/plugins/node/opentelemetry-instrumentation-redis/test/redis.test.ts +++ b/plugins/node/opentelemetry-instrumentation-redis/test/redis.test.ts @@ -32,8 +32,12 @@ import { import * as assert from 'assert'; import { RedisInstrumentation } from '../src'; import { - DbSystemValues, - SemanticAttributes, + DBSYSTEMVALUES_REDIS, + SEMATTRS_DB_CONNECTION_STRING, + SEMATTRS_DB_STATEMENT, + SEMATTRS_DB_SYSTEM, + SEMATTRS_NET_PEER_NAME, + SEMATTRS_NET_PEER_PORT, } from '@opentelemetry/semantic-conventions'; const instrumentation = new RedisInstrumentation(); @@ -53,10 +57,10 @@ const CONFIG = { const URL = `redis://${CONFIG.host}:${CONFIG.port}`; const DEFAULT_ATTRIBUTES = { - [SemanticAttributes.DB_SYSTEM]: DbSystemValues.REDIS, - [SemanticAttributes.NET_PEER_NAME]: CONFIG.host, - [SemanticAttributes.NET_PEER_PORT]: CONFIG.port, - [SemanticAttributes.DB_CONNECTION_STRING]: URL, + [SEMATTRS_DB_SYSTEM]: DBSYSTEMVALUES_REDIS, + [SEMATTRS_NET_PEER_NAME]: CONFIG.host, + [SEMATTRS_NET_PEER_PORT]: CONFIG.port, + [SEMATTRS_DB_CONNECTION_STRING]: URL, }; const unsetStatus: SpanStatus = { @@ -192,7 +196,7 @@ describe('redis@2.x', () => { it(`should create a child span for ${operation.description}`, done => { const attributes = { ...DEFAULT_ATTRIBUTES, - [SemanticAttributes.DB_STATEMENT]: `${operation.command} ${operation.expectedDbStatement}`, + [SEMATTRS_DB_STATEMENT]: `${operation.command} ${operation.expectedDbStatement}`, }; const span = tracer.startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { @@ -281,7 +285,7 @@ describe('redis@2.x', () => { operation.args ); assert.strictEqual( - endedSpans[0].attributes[SemanticAttributes.DB_STATEMENT], + endedSpans[0].attributes[SEMATTRS_DB_STATEMENT], expectedStatement ); done(); From fae30104c6a8b93de54436e58f17fb9b53c0a573 Mon Sep 17 00:00:00 2001 From: David Luna Date: Wed, 17 Apr 2024 15:58:12 +0200 Subject: [PATCH 2/5] refactor(instr-redis-4): use exported strings for attributes (#2100) * refactor(instr-redis-4): use exported strings for attributes * chore(instr-redis-4): update README --------- Co-authored-by: Marc Pichler --- package-lock.json | 4 +- .../README.md | 14 +++ .../package.json | 2 +- .../src/instrumentation.ts | 4 +- .../src/utils.ts | 15 +-- .../test/redis.test.ts | 95 +++++++++---------- 6 files changed, 73 insertions(+), 61 deletions(-) diff --git a/package-lock.json b/package-lock.json index fe110e001b..1d7ceac08b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38531,7 +38531,7 @@ "dependencies": { "@opentelemetry/instrumentation": "^0.50.0", "@opentelemetry/redis-common": "^0.36.1", - "@opentelemetry/semantic-conventions": "^1.0.0" + "@opentelemetry/semantic-conventions": "^1.22.0" }, "devDependencies": { "@opentelemetry/api": "^1.3.0", @@ -46881,7 +46881,7 @@ "@opentelemetry/redis-common": "^0.36.1", "@opentelemetry/sdk-trace-base": "^1.8.0", "@opentelemetry/sdk-trace-node": "^1.8.0", - "@opentelemetry/semantic-conventions": "^1.0.0", + "@opentelemetry/semantic-conventions": "^1.22.0", "@types/mocha": "7.0.2", "@types/node": "18.6.5", "cross-env": "7.0.3", diff --git a/plugins/node/opentelemetry-instrumentation-redis-4/README.md b/plugins/node/opentelemetry-instrumentation-redis-4/README.md index dec67f105d..19eea1b33a 100644 --- a/plugins/node/opentelemetry-instrumentation-redis-4/README.md +++ b/plugins/node/opentelemetry-instrumentation-redis-4/README.md @@ -71,6 +71,20 @@ const redisInstrumentation = new RedisInstrumentation({ }); ``` +## Semantic Conventions + +This package uses `@opentelemetry/semantic-conventions` version `1.22+`, which implements Semantic Convention [Version 1.7.0](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.7.0/semantic_conventions/README.md) + +Attributes collected: + +| Attribute | Short Description | +| ---------------------- | ---------------------------------------------------------------------------- | +| `db.connection_string` | The connection string used to connect to the database (without credentials). | +| `db.statement` | The database statement being executed. | +| `db.system` | An identifier for the database management system (DBMS) product being used. | +| `net.peer.name` | Remote hostname or similar, see note below. | +| `net.peer.port` | Remote port number. | + ## Useful links - For more information on OpenTelemetry, visit: diff --git a/plugins/node/opentelemetry-instrumentation-redis-4/package.json b/plugins/node/opentelemetry-instrumentation-redis-4/package.json index 08077ae594..f6e0957832 100644 --- a/plugins/node/opentelemetry-instrumentation-redis-4/package.json +++ b/plugins/node/opentelemetry-instrumentation-redis-4/package.json @@ -68,7 +68,7 @@ "dependencies": { "@opentelemetry/instrumentation": "^0.50.0", "@opentelemetry/redis-common": "^0.36.1", - "@opentelemetry/semantic-conventions": "^1.0.0" + "@opentelemetry/semantic-conventions": "^1.22.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-redis-4#readme" } diff --git a/plugins/node/opentelemetry-instrumentation-redis-4/src/instrumentation.ts b/plugins/node/opentelemetry-instrumentation-redis-4/src/instrumentation.ts index e018845e2d..825defe5cf 100644 --- a/plugins/node/opentelemetry-instrumentation-redis-4/src/instrumentation.ts +++ b/plugins/node/opentelemetry-instrumentation-redis-4/src/instrumentation.ts @@ -32,7 +32,7 @@ import { getClientAttributes } from './utils'; import { defaultDbStatementSerializer } from '@opentelemetry/redis-common'; import { RedisInstrumentationConfig } from './types'; import { VERSION } from './version'; -import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; +import { SEMATTRS_DB_STATEMENT } from '@opentelemetry/semantic-conventions'; import type { MultiErrorReply } from './internal-types'; const OTEL_OPEN_SPANS = Symbol( @@ -405,7 +405,7 @@ export class RedisInstrumentation extends InstrumentationBase { try { const dbStatement = dbStatementSerializer(commandName, commandArgs); if (dbStatement != null) { - attributes[SemanticAttributes.DB_STATEMENT] = dbStatement; + attributes[SEMATTRS_DB_STATEMENT] = dbStatement; } } catch (e) { this._diag.error('dbStatementSerializer throw an exception', e, { diff --git a/plugins/node/opentelemetry-instrumentation-redis-4/src/utils.ts b/plugins/node/opentelemetry-instrumentation-redis-4/src/utils.ts index 4275f10175..7bdbf768ac 100644 --- a/plugins/node/opentelemetry-instrumentation-redis-4/src/utils.ts +++ b/plugins/node/opentelemetry-instrumentation-redis-4/src/utils.ts @@ -15,8 +15,11 @@ */ import { Attributes, DiagLogger } from '@opentelemetry/api'; import { - DbSystemValues, - SemanticAttributes, + SEMATTRS_DB_SYSTEM, + SEMATTRS_DB_CONNECTION_STRING, + SEMATTRS_NET_PEER_NAME, + SEMATTRS_NET_PEER_PORT, + DBSYSTEMVALUES_REDIS, } from '@opentelemetry/semantic-conventions'; export function getClientAttributes( @@ -24,10 +27,10 @@ export function getClientAttributes( options: any ): Attributes { return { - [SemanticAttributes.DB_SYSTEM]: DbSystemValues.REDIS, - [SemanticAttributes.NET_PEER_NAME]: options?.socket?.host, - [SemanticAttributes.NET_PEER_PORT]: options?.socket?.port, - [SemanticAttributes.DB_CONNECTION_STRING]: + [SEMATTRS_DB_SYSTEM]: DBSYSTEMVALUES_REDIS, + [SEMATTRS_NET_PEER_NAME]: options?.socket?.host, + [SEMATTRS_NET_PEER_PORT]: options?.socket?.port, + [SEMATTRS_DB_CONNECTION_STRING]: removeCredentialsFromDBConnectionStringAttribute(diag, options?.url), }; } diff --git a/plugins/node/opentelemetry-instrumentation-redis-4/test/redis.test.ts b/plugins/node/opentelemetry-instrumentation-redis-4/test/redis.test.ts index 713c2130fe..6200b4c1eb 100644 --- a/plugins/node/opentelemetry-instrumentation-redis-4/test/redis.test.ts +++ b/plugins/node/opentelemetry-instrumentation-redis-4/test/redis.test.ts @@ -41,7 +41,14 @@ import { trace, context, } from '@opentelemetry/api'; -import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; +import { + SEMATTRS_DB_CONNECTION_STRING, + SEMATTRS_DB_STATEMENT, + SEMATTRS_DB_SYSTEM, + SEMATTRS_EXCEPTION_MESSAGE, + SEMATTRS_NET_PEER_NAME, + SEMATTRS_NET_PEER_PORT, +} from '@opentelemetry/semantic-conventions'; import { RedisResponseCustomAttributeFunction } from '../src/types'; import { hrTimeToMilliseconds, suppressTracing } from '@opentelemetry/core'; @@ -94,24 +101,21 @@ describe('redis@^4.0.0', () => { assert.ok(setSpan); assert.strictEqual(setSpan?.kind, SpanKind.CLIENT); assert.strictEqual(setSpan?.name, 'redis-SET'); + assert.strictEqual(setSpan?.attributes[SEMATTRS_DB_SYSTEM], 'redis'); assert.strictEqual( - setSpan?.attributes[SemanticAttributes.DB_SYSTEM], - 'redis' - ); - assert.strictEqual( - setSpan?.attributes[SemanticAttributes.DB_STATEMENT], + setSpan?.attributes[SEMATTRS_DB_STATEMENT], 'SET key [1 other arguments]' ); assert.strictEqual( - setSpan?.attributes[SemanticAttributes.NET_PEER_NAME], + setSpan?.attributes[SEMATTRS_NET_PEER_NAME], redisTestConfig.host ); assert.strictEqual( - setSpan?.attributes[SemanticAttributes.NET_PEER_PORT], + setSpan?.attributes[SEMATTRS_NET_PEER_PORT], redisTestConfig.port ); assert.strictEqual( - setSpan?.attributes[SemanticAttributes.DB_CONNECTION_STRING], + setSpan?.attributes[SEMATTRS_DB_CONNECTION_STRING], redisTestUrl ); @@ -119,24 +123,18 @@ describe('redis@^4.0.0', () => { assert.ok(getSpan); assert.strictEqual(getSpan?.kind, SpanKind.CLIENT); assert.strictEqual(getSpan?.name, 'redis-GET'); + assert.strictEqual(getSpan?.attributes[SEMATTRS_DB_SYSTEM], 'redis'); + assert.strictEqual(getSpan?.attributes[SEMATTRS_DB_STATEMENT], 'GET key'); assert.strictEqual( - getSpan?.attributes[SemanticAttributes.DB_SYSTEM], - 'redis' - ); - assert.strictEqual( - getSpan?.attributes[SemanticAttributes.DB_STATEMENT], - 'GET key' - ); - assert.strictEqual( - getSpan?.attributes[SemanticAttributes.NET_PEER_NAME], + getSpan?.attributes[SEMATTRS_NET_PEER_NAME], redisTestConfig.host ); assert.strictEqual( - getSpan?.attributes[SemanticAttributes.NET_PEER_PORT], + getSpan?.attributes[SEMATTRS_NET_PEER_PORT], redisTestConfig.port ); assert.strictEqual( - getSpan?.attributes[SemanticAttributes.DB_CONNECTION_STRING], + getSpan?.attributes[SEMATTRS_DB_CONNECTION_STRING], redisTestUrl ); }); @@ -149,15 +147,15 @@ describe('redis@^4.0.0', () => { assert.ok(setSpan); assert.strictEqual( - setSpan?.attributes[SemanticAttributes.DB_STATEMENT], + setSpan?.attributes[SEMATTRS_DB_STATEMENT], 'SET key [1 other arguments]' ); assert.strictEqual( - setSpan?.attributes[SemanticAttributes.NET_PEER_NAME], + setSpan?.attributes[SEMATTRS_NET_PEER_NAME], redisTestConfig.host ); assert.strictEqual( - setSpan?.attributes[SemanticAttributes.NET_PEER_PORT], + setSpan?.attributes[SEMATTRS_NET_PEER_PORT], redisTestConfig.port ); }); @@ -180,7 +178,7 @@ describe('redis@^4.0.0', () => { ); assert.strictEqual(exceptions.length, 1); assert.strictEqual( - exceptions?.[0].attributes?.[SemanticAttributes.EXCEPTION_MESSAGE], + exceptions?.[0].attributes?.[SEMATTRS_EXCEPTION_MESSAGE], 'ERR value is not an integer or out of range' ); }); @@ -202,20 +200,17 @@ describe('redis@^4.0.0', () => { assert.strictEqual(span.name, 'redis-connect'); + assert.strictEqual(span.attributes[SEMATTRS_DB_SYSTEM], 'redis'); assert.strictEqual( - span.attributes[SemanticAttributes.DB_SYSTEM], - 'redis' - ); - assert.strictEqual( - span.attributes[SemanticAttributes.NET_PEER_NAME], + span.attributes[SEMATTRS_NET_PEER_NAME], redisTestConfig.host ); assert.strictEqual( - span.attributes[SemanticAttributes.NET_PEER_PORT], + span.attributes[SEMATTRS_NET_PEER_PORT], redisTestConfig.port ); assert.strictEqual( - span.attributes[SemanticAttributes.DB_CONNECTION_STRING], + span.attributes[SEMATTRS_DB_CONNECTION_STRING], redisTestUrl ); }); @@ -235,7 +230,7 @@ describe('redis@^4.0.0', () => { assert.strictEqual(span.name, 'redis-connect'); assert.strictEqual(span.status.code, SpanStatusCode.ERROR); assert.strictEqual( - span.attributes[SemanticAttributes.DB_CONNECTION_STRING], + span.attributes[SEMATTRS_DB_CONNECTION_STRING], redisURL ); }); @@ -258,11 +253,11 @@ describe('redis@^4.0.0', () => { assert.strictEqual(span.name, 'redis-connect'); assert.strictEqual(span.status.code, SpanStatusCode.ERROR); assert.strictEqual( - span.attributes[SemanticAttributes.NET_PEER_NAME], + span.attributes[SEMATTRS_NET_PEER_NAME], redisTestConfig.host ); assert.strictEqual( - span.attributes[SemanticAttributes.DB_CONNECTION_STRING], + span.attributes[SEMATTRS_DB_CONNECTION_STRING], expectAttributeConnString ); }); @@ -285,11 +280,11 @@ describe('redis@^4.0.0', () => { assert.strictEqual(span.name, 'redis-connect'); assert.strictEqual(span.status.code, SpanStatusCode.ERROR); assert.strictEqual( - span.attributes[SemanticAttributes.NET_PEER_NAME], + span.attributes[SEMATTRS_NET_PEER_NAME], redisTestConfig.host ); assert.strictEqual( - span.attributes[SemanticAttributes.DB_CONNECTION_STRING], + span.attributes[SEMATTRS_DB_CONNECTION_STRING], expectAttributeConnString ); }); @@ -314,38 +309,38 @@ describe('redis@^4.0.0', () => { assert.ok(multiSetSpan); assert.strictEqual(multiSetSpan.name, 'redis-SET'); assert.strictEqual( - multiSetSpan.attributes[SemanticAttributes.DB_STATEMENT], + multiSetSpan.attributes[SEMATTRS_DB_STATEMENT], 'SET key [1 other arguments]' ); assert.strictEqual( - multiSetSpan?.attributes[SemanticAttributes.NET_PEER_NAME], + multiSetSpan?.attributes[SEMATTRS_NET_PEER_NAME], redisTestConfig.host ); assert.strictEqual( - multiSetSpan?.attributes[SemanticAttributes.NET_PEER_PORT], + multiSetSpan?.attributes[SEMATTRS_NET_PEER_PORT], redisTestConfig.port ); assert.strictEqual( - multiSetSpan?.attributes[SemanticAttributes.DB_CONNECTION_STRING], + multiSetSpan?.attributes[SEMATTRS_DB_CONNECTION_STRING], redisTestUrl ); assert.ok(multiGetSpan); assert.strictEqual(multiGetSpan.name, 'redis-GET'); assert.strictEqual( - multiGetSpan.attributes[SemanticAttributes.DB_STATEMENT], + multiGetSpan.attributes[SEMATTRS_DB_STATEMENT], 'GET another-key' ); assert.strictEqual( - multiGetSpan?.attributes[SemanticAttributes.NET_PEER_NAME], + multiGetSpan?.attributes[SEMATTRS_NET_PEER_NAME], redisTestConfig.host ); assert.strictEqual( - multiGetSpan?.attributes[SemanticAttributes.NET_PEER_PORT], + multiGetSpan?.attributes[SEMATTRS_NET_PEER_PORT], redisTestConfig.port ); assert.strictEqual( - multiGetSpan?.attributes[SemanticAttributes.DB_CONNECTION_STRING], + multiGetSpan?.attributes[SEMATTRS_DB_CONNECTION_STRING], redisTestUrl ); }); @@ -360,19 +355,19 @@ describe('redis@^4.0.0', () => { const [multiSetSpan] = getTestSpans(); assert.ok(multiSetSpan); assert.strictEqual( - multiSetSpan.attributes[SemanticAttributes.DB_STATEMENT], + multiSetSpan.attributes[SEMATTRS_DB_STATEMENT], 'SET key [1 other arguments]' ); assert.strictEqual( - multiSetSpan?.attributes[SemanticAttributes.NET_PEER_NAME], + multiSetSpan?.attributes[SEMATTRS_NET_PEER_NAME], redisTestConfig.host ); assert.strictEqual( - multiSetSpan?.attributes[SemanticAttributes.NET_PEER_PORT], + multiSetSpan?.attributes[SEMATTRS_NET_PEER_PORT], redisTestConfig.port ); assert.strictEqual( - multiSetSpan?.attributes[SemanticAttributes.DB_CONNECTION_STRING], + multiSetSpan?.attributes[SEMATTRS_DB_CONNECTION_STRING], redisTestUrl ); }); @@ -513,7 +508,7 @@ describe('redis@^4.0.0', () => { await client.set('key', 'value'); const [span] = getTestSpans(); assert.strictEqual( - span.attributes[SemanticAttributes.DB_STATEMENT], + span.attributes[SEMATTRS_DB_STATEMENT], 'SET key value' ); }); @@ -527,7 +522,7 @@ describe('redis@^4.0.0', () => { await client.set('key', 'value'); const [span] = getTestSpans(); assert.ok(span); - assert.ok(!(SemanticAttributes.DB_STATEMENT in span.attributes)); + assert.ok(!(SEMATTRS_DB_STATEMENT in span.attributes)); }); }); From 34796e2a2f963a544acece8afcbaadab7b3f04cf Mon Sep 17 00:00:00 2001 From: David Luna Date: Wed, 17 Apr 2024 16:00:42 +0200 Subject: [PATCH 3/5] refactor(instr-router): use exported strings for attributes (#2099) Co-authored-by: Marc Pichler --- package-lock.json | 4 ++-- .../opentelemetry-instrumentation-router/README.md | 10 ++++++++++ .../opentelemetry-instrumentation-router/package.json | 2 +- .../src/instrumentation.ts | 4 ++-- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1d7ceac08b..080efc40e3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38645,7 +38645,7 @@ "license": "Apache-2.0", "dependencies": { "@opentelemetry/instrumentation": "^0.50.0", - "@opentelemetry/semantic-conventions": "^1.0.0" + "@opentelemetry/semantic-conventions": "^1.22.0" }, "devDependencies": { "@opentelemetry/api": "^1.3.0", @@ -46968,7 +46968,7 @@ "@opentelemetry/instrumentation": "^0.50.0", "@opentelemetry/sdk-trace-base": "^1.8.0", "@opentelemetry/sdk-trace-node": "^1.8.0", - "@opentelemetry/semantic-conventions": "^1.0.0", + "@opentelemetry/semantic-conventions": "^1.22.0", "@types/mocha": "7.0.2", "@types/node": "18.6.5", "mocha": "7.2.0", diff --git a/plugins/node/opentelemetry-instrumentation-router/README.md b/plugins/node/opentelemetry-instrumentation-router/README.md index 427dcc7a9f..152a9cf081 100644 --- a/plugins/node/opentelemetry-instrumentation-router/README.md +++ b/plugins/node/opentelemetry-instrumentation-router/README.md @@ -40,6 +40,16 @@ registerInstrumentations({ See [examples/router](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/examples/router) for a short example. +## Semantic Conventions + +This package uses `@opentelemetry/semantic-conventions` version `1.22+`, which implements Semantic Convention [Version 1.7.0](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.7.0/semantic_conventions/README.md) + +Attributes collected: + +| Attribute | Short Description | +| ------------ | ---------------------------------- | +| `http.route` | The matched route (path template). | + ## Useful links - For more information on OpenTelemetry, visit: diff --git a/plugins/node/opentelemetry-instrumentation-router/package.json b/plugins/node/opentelemetry-instrumentation-router/package.json index b57544e4de..48a8335379 100644 --- a/plugins/node/opentelemetry-instrumentation-router/package.json +++ b/plugins/node/opentelemetry-instrumentation-router/package.json @@ -57,7 +57,7 @@ }, "dependencies": { "@opentelemetry/instrumentation": "^0.50.0", - "@opentelemetry/semantic-conventions": "^1.0.0" + "@opentelemetry/semantic-conventions": "^1.22.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-router#readme" } diff --git a/plugins/node/opentelemetry-instrumentation-router/src/instrumentation.ts b/plugins/node/opentelemetry-instrumentation-router/src/instrumentation.ts index 8733daf1ab..46f6a84836 100644 --- a/plugins/node/opentelemetry-instrumentation-router/src/instrumentation.ts +++ b/plugins/node/opentelemetry-instrumentation-router/src/instrumentation.ts @@ -22,7 +22,7 @@ import { InstrumentationNodeModuleFile, isWrapped, } from '@opentelemetry/instrumentation'; -import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; +import { SEMATTRS_HTTP_ROUTE } from '@opentelemetry/semantic-conventions'; import * as http from 'http'; import type * as Router from 'router'; @@ -182,7 +182,7 @@ export default class RouterInstrumentation extends InstrumentationBase { [AttributeNames.NAME]: fnName, [AttributeNames.VERSION]: this._moduleVersion, [AttributeNames.TYPE]: type, - [SemanticAttributes.HTTP_ROUTE]: route, + [SEMATTRS_HTTP_ROUTE]: route, }; const parent = api.context.active(); From 5f42c51a9902b4d1a4172f10bfdc0a0a6166444f Mon Sep 17 00:00:00 2001 From: David Luna Date: Wed, 17 Apr 2024 17:25:53 +0200 Subject: [PATCH 4/5] refactor(instr-mongoose): use exported strings for attributes (#2103) Co-authored-by: Marc Pichler --- package-lock.json | 4 +- .../node/instrumentation-mongoose/README.md | 17 ++++ .../instrumentation-mongoose/package.json | 2 +- .../instrumentation-mongoose/src/mongoose.ts | 32 +++--- .../instrumentation-mongoose/src/utils.ts | 22 +++-- .../instrumentation-mongoose/test/asserts.ts | 23 +++-- .../test/mongoose.test.ts | 97 +++++++------------ 7 files changed, 97 insertions(+), 100 deletions(-) diff --git a/package-lock.json b/package-lock.json index 080efc40e3..0fb1ac4458 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37027,7 +37027,7 @@ "dependencies": { "@opentelemetry/core": "^1.8.0", "@opentelemetry/instrumentation": "^0.50.0", - "@opentelemetry/semantic-conventions": "^1.0.0" + "@opentelemetry/semantic-conventions": "^1.22.0" }, "devDependencies": { "@opentelemetry/api": "^1.3.0", @@ -46598,7 +46598,7 @@ "@opentelemetry/core": "^1.8.0", "@opentelemetry/instrumentation": "^0.50.0", "@opentelemetry/sdk-trace-base": "^1.8.0", - "@opentelemetry/semantic-conventions": "^1.0.0", + "@opentelemetry/semantic-conventions": "^1.22.0", "@types/mocha": "8.2.3", "@types/node": "18.6.5", "expect": "29.2.0", diff --git a/plugins/node/instrumentation-mongoose/README.md b/plugins/node/instrumentation-mongoose/README.md index 22a600e07e..159e01568b 100644 --- a/plugins/node/instrumentation-mongoose/README.md +++ b/plugins/node/instrumentation-mongoose/README.md @@ -52,6 +52,23 @@ The instrumentation's config `responseHook` functions signature changed, so the The `moduleVersionAttributeName` config option is removed. To add the mongoose package version to spans, use the `moduleVersion` attribute in hook info for `responseHook` function. +## Semantic Conventions + +This package uses `@opentelemetry/semantic-conventions` version `1.22+`, which implements Semantic Convention [Version 1.7.0](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.7.0/semantic_conventions/README.md) + +Attributes collected: + +| Attribute | Short Description | +| ----------------------- | --------------------------------------------------------------------------- | +| `db.mongodb.collection` | The collection being accessed within the database stated in `db.name`. | +| `db.name` | This attribute is used to report the name of the database being accessed. | +| `db.operation` | The name of the operation being executed, or the SQL keyword. | +| `db.statement` | The database statement being executed. | +| `db.system` | An identifier for the database management system (DBMS) product being used. | +| `db.user` | Username for accessing the database. | +| `net.peer.name` | Remote hostname or similar. | +| `net.peer.port` | Remote port number. | + ## Useful links - For more information on OpenTelemetry, visit: diff --git a/plugins/node/instrumentation-mongoose/package.json b/plugins/node/instrumentation-mongoose/package.json index 1a3d149543..dbafc9af61 100644 --- a/plugins/node/instrumentation-mongoose/package.json +++ b/plugins/node/instrumentation-mongoose/package.json @@ -62,7 +62,7 @@ "dependencies": { "@opentelemetry/core": "^1.8.0", "@opentelemetry/instrumentation": "^0.50.0", - "@opentelemetry/semantic-conventions": "^1.0.0" + "@opentelemetry/semantic-conventions": "^1.22.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/instrumentation-mongoose#readme" } diff --git a/plugins/node/instrumentation-mongoose/src/mongoose.ts b/plugins/node/instrumentation-mongoose/src/mongoose.ts index 77c8dbee0d..96bf8f3734 100644 --- a/plugins/node/instrumentation-mongoose/src/mongoose.ts +++ b/plugins/node/instrumentation-mongoose/src/mongoose.ts @@ -13,13 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { - context, - Span, - trace, - SpanAttributes, - SpanKind, -} from '@opentelemetry/api'; +import { context, Span, trace, Attributes, SpanKind } from '@opentelemetry/api'; import { suppressTracing } from '@opentelemetry/core'; import type * as mongoose from 'mongoose'; import { MongooseInstrumentationConfig, SerializerPayload } from './types'; @@ -34,7 +28,11 @@ import { InstrumentationNodeModuleDefinition, } from '@opentelemetry/instrumentation'; import { VERSION } from './version'; -import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; +import { + SEMATTRS_DB_OPERATION, + SEMATTRS_DB_STATEMENT, + SEMATTRS_DB_SYSTEM, +} from '@opentelemetry/semantic-conventions'; const contextCaptureFunctions = [ 'remove', @@ -155,9 +153,9 @@ export class MongooseInstrumentation extends InstrumentationBase { } const parentSpan = this[_STORED_PARENT_SPAN]; - const attributes: SpanAttributes = {}; + const attributes: Attributes = {}; if (self._config.dbStatementSerializer) { - attributes[SemanticAttributes.DB_STATEMENT] = + attributes[SEMATTRS_DB_STATEMENT] = self._config.dbStatementSerializer('aggregate', { options: this.options, aggregatePipeline: this._pipeline, @@ -197,9 +195,9 @@ export class MongooseInstrumentation extends InstrumentationBase { } const parentSpan = this[_STORED_PARENT_SPAN]; - const attributes: SpanAttributes = {}; + const attributes: Attributes = {}; if (self._config.dbStatementSerializer) { - attributes[SemanticAttributes.DB_STATEMENT] = + attributes[SEMATTRS_DB_STATEMENT] = self._config.dbStatementSerializer(this.op, { condition: this._conditions, updates: this._update, @@ -243,9 +241,9 @@ export class MongooseInstrumentation extends InstrumentationBase { if (options && !(options instanceof Function)) { serializePayload.options = options; } - const attributes: SpanAttributes = {}; + const attributes: Attributes = {}; if (self._config.dbStatementSerializer) { - attributes[SemanticAttributes.DB_STATEMENT] = + attributes[SEMATTRS_DB_STATEMENT] = self._config.dbStatementSerializer(op, serializePayload); } const span = self._startSpan( @@ -308,7 +306,7 @@ export class MongooseInstrumentation extends InstrumentationBase { collection: mongoose.Collection, modelName: string, operation: string, - attributes: SpanAttributes, + attributes: Attributes, parentSpan?: Span ): Span { return this.tracer.startSpan( @@ -318,8 +316,8 @@ export class MongooseInstrumentation extends InstrumentationBase { attributes: { ...attributes, ...getAttributesFromCollection(collection), - [SemanticAttributes.DB_OPERATION]: operation, - [SemanticAttributes.DB_SYSTEM]: 'mongoose', + [SEMATTRS_DB_OPERATION]: operation, + [SEMATTRS_DB_SYSTEM]: 'mongoose', }, }, parentSpan ? trace.setSpan(context.active(), parentSpan) : undefined diff --git a/plugins/node/instrumentation-mongoose/src/utils.ts b/plugins/node/instrumentation-mongoose/src/utils.ts index 2c44c87dae..f556218c87 100644 --- a/plugins/node/instrumentation-mongoose/src/utils.ts +++ b/plugins/node/instrumentation-mongoose/src/utils.ts @@ -13,21 +13,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { SpanAttributes, SpanStatusCode, diag, Span } from '@opentelemetry/api'; +import { Attributes, SpanStatusCode, diag, Span } from '@opentelemetry/api'; import type { Collection } from 'mongoose'; import { MongooseResponseCustomAttributesFunction } from './types'; import { safeExecuteInTheMiddle } from '@opentelemetry/instrumentation'; -import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; +import { + SEMATTRS_DB_MONGODB_COLLECTION, + SEMATTRS_DB_NAME, + SEMATTRS_DB_USER, + SEMATTRS_NET_PEER_NAME, + SEMATTRS_NET_PEER_PORT, +} from '@opentelemetry/semantic-conventions'; export function getAttributesFromCollection( collection: Collection -): SpanAttributes { +): Attributes { return { - [SemanticAttributes.DB_MONGODB_COLLECTION]: collection.name, - [SemanticAttributes.DB_NAME]: collection.conn.name, - [SemanticAttributes.DB_USER]: collection.conn.user, - [SemanticAttributes.NET_PEER_NAME]: collection.conn.host, - [SemanticAttributes.NET_PEER_PORT]: collection.conn.port, + [SEMATTRS_DB_MONGODB_COLLECTION]: collection.name, + [SEMATTRS_DB_NAME]: collection.conn.name, + [SEMATTRS_DB_USER]: collection.conn.user, + [SEMATTRS_NET_PEER_NAME]: collection.conn.host, + [SEMATTRS_NET_PEER_PORT]: collection.conn.port, }; } diff --git a/plugins/node/instrumentation-mongoose/test/asserts.ts b/plugins/node/instrumentation-mongoose/test/asserts.ts index ad21f9a716..0cf109c80e 100644 --- a/plugins/node/instrumentation-mongoose/test/asserts.ts +++ b/plugins/node/instrumentation-mongoose/test/asserts.ts @@ -15,21 +15,26 @@ */ import { expect } from 'expect'; import { ReadableSpan } from '@opentelemetry/sdk-trace-base'; -import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; +import { + SEMATTRS_DB_MONGODB_COLLECTION, + SEMATTRS_DB_NAME, + SEMATTRS_DB_STATEMENT, + SEMATTRS_DB_SYSTEM, + SEMATTRS_NET_PEER_NAME, + SEMATTRS_NET_PEER_PORT, +} from '@opentelemetry/semantic-conventions'; import { SpanStatusCode } from '@opentelemetry/api'; import { SerializerPayload } from '../src'; import { DB_NAME, MONGO_HOST, MONGO_PORT } from './config'; export const assertSpan = (span: ReadableSpan) => { expect(span.status.code).toBe(SpanStatusCode.UNSET); - expect(span.attributes[SemanticAttributes.DB_SYSTEM]).toEqual('mongoose'); - expect(span.attributes[SemanticAttributes.DB_MONGODB_COLLECTION]).toEqual( - 'users' - ); - expect(span.attributes[SemanticAttributes.DB_NAME]).toEqual(DB_NAME); - expect(span.attributes[SemanticAttributes.NET_PEER_NAME]).toEqual(MONGO_HOST); - expect(span.attributes[SemanticAttributes.NET_PEER_PORT]).toEqual(MONGO_PORT); + expect(span.attributes[SEMATTRS_DB_SYSTEM]).toEqual('mongoose'); + expect(span.attributes[SEMATTRS_DB_MONGODB_COLLECTION]).toEqual('users'); + expect(span.attributes[SEMATTRS_DB_NAME]).toEqual(DB_NAME); + expect(span.attributes[SEMATTRS_NET_PEER_NAME]).toEqual(MONGO_HOST); + expect(span.attributes[SEMATTRS_NET_PEER_PORT]).toEqual(MONGO_PORT); }; export const getStatement = (span: ReadableSpan): SerializerPayload => - JSON.parse(span.attributes[SemanticAttributes.DB_STATEMENT] as string); + JSON.parse(span.attributes[SEMATTRS_DB_STATEMENT] as string); diff --git a/plugins/node/instrumentation-mongoose/test/mongoose.test.ts b/plugins/node/instrumentation-mongoose/test/mongoose.test.ts index 37ce6c70ec..b907300b69 100644 --- a/plugins/node/instrumentation-mongoose/test/mongoose.test.ts +++ b/plugins/node/instrumentation-mongoose/test/mongoose.test.ts @@ -16,7 +16,10 @@ import 'mocha'; import { expect } from 'expect'; import { context, ROOT_CONTEXT } from '@opentelemetry/api'; -import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; +import { + SEMATTRS_DB_OPERATION, + SEMATTRS_DB_STATEMENT, +} from '@opentelemetry/semantic-conventions'; import { MongooseInstrumentation } from '../src'; import { getTestSpans, @@ -89,7 +92,7 @@ describe('mongoose instrumentation', () => { const spans = getTestSpans(); expect(spans.length).toBe(1); assertSpan(spans[0] as ReadableSpan); - expect(spans[0].attributes[SemanticAttributes.DB_OPERATION]).toBe('save'); + expect(spans[0].attributes[SEMATTRS_DB_OPERATION]).toBe('save'); const statement = getStatement(spans[0] as ReadableSpan); expect(statement.document).toEqual(expect.objectContaining(document)); }); @@ -107,7 +110,7 @@ describe('mongoose instrumentation', () => { expect(spans.length).toBe(1); assertSpan(spans[0] as ReadableSpan); - expect(spans[0].attributes[SemanticAttributes.DB_OPERATION]).toBe('save'); + expect(spans[0].attributes[SEMATTRS_DB_OPERATION]).toBe('save'); const statement = getStatement(spans[0] as ReadableSpan); expect(statement.document).toEqual(expect.objectContaining(document)); done(); @@ -120,7 +123,7 @@ describe('mongoose instrumentation', () => { const spans = getTestSpans(); expect(spans.length).toBe(1); assertSpan(spans[0] as ReadableSpan); - expect(spans[0].attributes[SemanticAttributes.DB_OPERATION]).toBe('find'); + expect(spans[0].attributes[SEMATTRS_DB_OPERATION]).toBe('find'); const statement = getStatement(spans[0] as ReadableSpan); expect(statement.condition).toEqual({ id: '_test' }); }); @@ -135,12 +138,12 @@ describe('mongoose instrumentation', () => { expect(spans.length).toBe(2); assertSpan(spans[0] as ReadableSpan); assertSpan(spans[1] as ReadableSpan); - expect(spans[0].attributes[SemanticAttributes.DB_OPERATION]).toBe('find'); - expect(spans[0].attributes[SemanticAttributes.DB_STATEMENT]).toMatch( + expect(spans[0].attributes[SEMATTRS_DB_OPERATION]).toBe('find'); + expect(spans[0].attributes[SEMATTRS_DB_STATEMENT]).toMatch( /.*{"id":"_test[1-2]"}.*/g ); - expect(spans[1].attributes[SemanticAttributes.DB_OPERATION]).toBe('find'); - expect(spans[1].attributes[SemanticAttributes.DB_STATEMENT]).toMatch( + expect(spans[1].attributes[SEMATTRS_DB_OPERATION]).toBe('find'); + expect(spans[1].attributes[SEMATTRS_DB_STATEMENT]).toMatch( /.*{"id":"_test[1-2]"}.*/g ); }); @@ -151,7 +154,7 @@ describe('mongoose instrumentation', () => { const spans = getTestSpans(); expect(spans.length).toBe(1); assertSpan(spans[0] as ReadableSpan); - expect(spans[0].attributes[SemanticAttributes.DB_OPERATION]).toBe('find'); + expect(spans[0].attributes[SEMATTRS_DB_OPERATION]).toBe('find'); const statement = getStatement(spans[0] as ReadableSpan); expect(statement.condition).toEqual({ id: '_test' }); expect(statement.options).toEqual({ @@ -168,7 +171,7 @@ describe('mongoose instrumentation', () => { const spans = getTestSpans(); expect(spans.length).toBe(2); assertSpan(spans[1] as ReadableSpan); - expect(spans[1].attributes[SemanticAttributes.DB_OPERATION]).toBe('remove'); + expect(spans[1].attributes[SEMATTRS_DB_OPERATION]).toBe('remove'); }); it('instrumenting remove operation with callbacks [deprecated]', done => { @@ -177,9 +180,7 @@ describe('mongoose instrumentation', () => { const spans = getTestSpans(); expect(spans.length).toBe(2); assertSpan(spans[1] as ReadableSpan); - expect(spans[1].attributes[SemanticAttributes.DB_OPERATION]).toBe( - 'remove' - ); + expect(spans[1].attributes[SEMATTRS_DB_OPERATION]).toBe('remove'); expect(getStatement(spans[1] as ReadableSpan).options).toEqual({ overwrite: true, }); @@ -194,9 +195,7 @@ describe('mongoose instrumentation', () => { const spans = getTestSpans(); expect(spans.length).toBe(1); assertSpan(spans[0] as ReadableSpan); - expect(spans[0].attributes[SemanticAttributes.DB_OPERATION]).toBe( - 'deleteOne' - ); + expect(spans[0].attributes[SEMATTRS_DB_OPERATION]).toBe('deleteOne'); }); it('instrumenting updateOne operation on models', async () => { @@ -206,9 +205,7 @@ describe('mongoose instrumentation', () => { const spans = getTestSpans(); expect(spans.length).toBe(2); assertSpan(spans[1] as ReadableSpan); - expect(spans[1].attributes[SemanticAttributes.DB_OPERATION]).toBe( - 'updateOne' - ); + expect(spans[1].attributes[SEMATTRS_DB_OPERATION]).toBe('updateOne'); const statement = getStatement(spans[1] as ReadableSpan); expect(statement.options).toEqual({ skip: 0 }); @@ -226,9 +223,7 @@ describe('mongoose instrumentation', () => { const spans = getTestSpans(); expect(spans.length).toBe(1); assertSpan(spans[0] as ReadableSpan); - expect(spans[0].attributes[SemanticAttributes.DB_OPERATION]).toBe( - 'updateOne' - ); + expect(spans[0].attributes[SEMATTRS_DB_OPERATION]).toBe('updateOne'); const statement = getStatement(spans[0] as ReadableSpan); expect(statement.options).toEqual({ skip: 0 }); @@ -242,7 +237,7 @@ describe('mongoose instrumentation', () => { const spans = getTestSpans(); expect(spans.length).toBe(1); assertSpan(spans[0] as ReadableSpan); - expect(spans[0].attributes[SemanticAttributes.DB_OPERATION]).toBe('count'); + expect(spans[0].attributes[SEMATTRS_DB_OPERATION]).toBe('count'); const statement = getStatement(spans[0] as ReadableSpan); expect(statement.options).toEqual({}); expect(statement.condition).toEqual({}); @@ -254,9 +249,7 @@ describe('mongoose instrumentation', () => { const spans = getTestSpans(); expect(spans.length).toBe(1); assertSpan(spans[0] as ReadableSpan); - expect(spans[0].attributes[SemanticAttributes.DB_OPERATION]).toBe( - 'countDocuments' - ); + expect(spans[0].attributes[SEMATTRS_DB_OPERATION]).toBe('countDocuments'); const statement = getStatement(spans[0] as ReadableSpan); expect(statement.options).toEqual({}); expect(statement.condition).toEqual({ email: 'john.doe@example.com' }); @@ -268,7 +261,7 @@ describe('mongoose instrumentation', () => { const spans = getTestSpans(); expect(spans.length).toBe(1); assertSpan(spans[0] as ReadableSpan); - expect(spans[0].attributes[SemanticAttributes.DB_OPERATION]).toBe( + expect(spans[0].attributes[SEMATTRS_DB_OPERATION]).toBe( 'estimatedDocumentCount' ); const statement = getStatement(spans[0] as ReadableSpan); @@ -282,9 +275,7 @@ describe('mongoose instrumentation', () => { const spans = getTestSpans(); expect(spans.length).toBe(1); assertSpan(spans[0] as ReadableSpan); - expect(spans[0].attributes[SemanticAttributes.DB_OPERATION]).toBe( - 'deleteMany' - ); + expect(spans[0].attributes[SEMATTRS_DB_OPERATION]).toBe('deleteMany'); const statement = getStatement(spans[0] as ReadableSpan); expect(statement.options).toEqual({}); expect(statement.condition).toEqual({}); @@ -296,9 +287,7 @@ describe('mongoose instrumentation', () => { const spans = getTestSpans(); expect(spans.length).toBe(1); assertSpan(spans[0] as ReadableSpan); - expect(spans[0].attributes[SemanticAttributes.DB_OPERATION]).toBe( - 'findOne' - ); + expect(spans[0].attributes[SEMATTRS_DB_OPERATION]).toBe('findOne'); const statement = getStatement(spans[0] as ReadableSpan); expect(statement.options).toEqual({}); expect(statement.condition).toEqual({ email: 'john.doe@example.com' }); @@ -313,7 +302,7 @@ describe('mongoose instrumentation', () => { const spans = getTestSpans(); expect(spans.length).toBe(1); assertSpan(spans[0] as ReadableSpan); - expect(spans[0].attributes[SemanticAttributes.DB_OPERATION]).toBe('update'); + expect(spans[0].attributes[SEMATTRS_DB_OPERATION]).toBe('update'); const statement = getStatement(spans[0] as ReadableSpan); expect(statement.options).toEqual({}); expect(statement.condition).toEqual({ email: 'john.doe@example.com' }); @@ -326,9 +315,7 @@ describe('mongoose instrumentation', () => { const spans = getTestSpans(); expect(spans.length).toBe(1); assertSpan(spans[0] as ReadableSpan); - expect(spans[0].attributes[SemanticAttributes.DB_OPERATION]).toBe( - 'updateOne' - ); + expect(spans[0].attributes[SEMATTRS_DB_OPERATION]).toBe('updateOne'); const statement = getStatement(spans[0] as ReadableSpan); expect(statement.options).toEqual({}); expect(statement.condition).toEqual({ email: 'john.doe@example.com' }); @@ -341,9 +328,7 @@ describe('mongoose instrumentation', () => { const spans = getTestSpans(); expect(spans.length).toBe(1); assertSpan(spans[0] as ReadableSpan); - expect(spans[0].attributes[SemanticAttributes.DB_OPERATION]).toBe( - 'updateMany' - ); + expect(spans[0].attributes[SEMATTRS_DB_OPERATION]).toBe('updateMany'); const statement = getStatement(spans[0] as ReadableSpan); expect(statement.options).toEqual({}); expect(statement.condition).toEqual({ age: 18 }); @@ -356,9 +341,7 @@ describe('mongoose instrumentation', () => { const spans = getTestSpans(); expect(spans.length).toBe(1); assertSpan(spans[0] as ReadableSpan); - expect(spans[0].attributes[SemanticAttributes.DB_OPERATION]).toBe( - 'findOneAndDelete' - ); + expect(spans[0].attributes[SEMATTRS_DB_OPERATION]).toBe('findOneAndDelete'); const statement = getStatement(spans[0] as ReadableSpan); expect(statement.options).toEqual({}); expect(statement.condition).toEqual({ email: 'john.doe@example.com' }); @@ -374,12 +357,8 @@ describe('mongoose instrumentation', () => { expect(spans.length).toBe(2); assertSpan(spans[0] as ReadableSpan); assertSpan(spans[1] as ReadableSpan); - expect(spans[0].attributes[SemanticAttributes.DB_OPERATION]).toBe( - 'findOne' - ); - expect(spans[1].attributes[SemanticAttributes.DB_OPERATION]).toBe( - 'findOneAndUpdate' - ); + expect(spans[0].attributes[SEMATTRS_DB_OPERATION]).toBe('findOne'); + expect(spans[1].attributes[SEMATTRS_DB_OPERATION]).toBe('findOneAndUpdate'); const statement = getStatement(spans[1] as ReadableSpan); expect(statement.options).toEqual({}); expect(statement.condition).toEqual({ email: 'john.doe@example.com' }); @@ -392,9 +371,7 @@ describe('mongoose instrumentation', () => { const spans = getTestSpans(); expect(spans.length).toBe(1); assertSpan(spans[0] as ReadableSpan); - expect(spans[0].attributes[SemanticAttributes.DB_OPERATION]).toBe( - 'findOneAndRemove' - ); + expect(spans[0].attributes[SEMATTRS_DB_OPERATION]).toBe('findOneAndRemove'); const statement = getStatement(spans[0] as ReadableSpan); expect(statement.options).toEqual({}); expect(statement.condition).toEqual({ email: 'john.doe@example.com' }); @@ -411,7 +388,7 @@ describe('mongoose instrumentation', () => { const spans = getTestSpans(); expect(spans.length).toBe(1); assertSpan(spans[0] as ReadableSpan); - expect(spans[0].attributes[SemanticAttributes.DB_OPERATION]).toBe('save'); + expect(spans[0].attributes[SEMATTRS_DB_OPERATION]).toBe('save'); const statement = getStatement(spans[0] as ReadableSpan); expect(statement.options).toEqual({}); expect(statement.document).toEqual(expect.objectContaining(document)); @@ -426,9 +403,7 @@ describe('mongoose instrumentation', () => { const spans = getTestSpans(); expect(spans.length).toBe(1); assertSpan(spans[0] as ReadableSpan); - expect(spans[0].attributes[SemanticAttributes.DB_OPERATION]).toBe( - 'aggregate' - ); + expect(spans[0].attributes[SEMATTRS_DB_OPERATION]).toBe('aggregate'); const statement = getStatement(spans[0] as ReadableSpan); expect(statement.aggregatePipeline).toEqual([ { $match: { firstName: 'John' } }, @@ -446,9 +421,7 @@ describe('mongoose instrumentation', () => { const spans = getTestSpans(); expect(spans.length).toBe(1); assertSpan(spans[0] as ReadableSpan); - expect(spans[0].attributes[SemanticAttributes.DB_OPERATION]).toBe( - 'aggregate' - ); + expect(spans[0].attributes[SEMATTRS_DB_OPERATION]).toBe('aggregate'); const statement = getStatement(spans[0] as ReadableSpan); expect(statement.aggregatePipeline).toEqual([ { $match: { firstName: 'John' } }, @@ -483,9 +456,7 @@ describe('mongoose instrumentation', () => { const spans = getTestSpans(); expect(spans.length).toBe(1); assertSpan(spans[0] as ReadableSpan); - expect(spans[0].attributes[SemanticAttributes.DB_STATEMENT]).toBe( - undefined - ); + expect(spans[0].attributes[SEMATTRS_DB_STATEMENT]).toBe(undefined); }); it('projection is sent to serializer', async () => { @@ -503,7 +474,7 @@ describe('mongoose instrumentation', () => { expect(spans.length).toBe(1); assertSpan(spans[0] as ReadableSpan); const reqPayload = JSON.parse( - spans[0].attributes[SemanticAttributes.DB_STATEMENT] as string + spans[0].attributes[SEMATTRS_DB_STATEMENT] as string ); expect(reqPayload.fields).toStrictEqual(projection); }); From 9f5a86712f1614026ad1a232d2923d85e69823e0 Mon Sep 17 00:00:00 2001 From: David Luna Date: Wed, 17 Apr 2024 17:31:17 +0200 Subject: [PATCH 5/5] refactor(instr-restify): use exported strings for attributes (#2098) * refactor(instr-restify): use exported strings for attributes * chore(instr-restify): fix lint issues --------- Co-authored-by: Marc Pichler --- package-lock.json | 4 ++-- .../README.md | 10 +++++++++ .../package.json | 2 +- .../src/instrumentation.ts | 14 ++++++------ .../test/restify.test.ts | 22 +++++-------------- 5 files changed, 25 insertions(+), 27 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0fb1ac4458..b25cf160bb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38579,7 +38579,7 @@ "dependencies": { "@opentelemetry/core": "^1.8.0", "@opentelemetry/instrumentation": "^0.50.0", - "@opentelemetry/semantic-conventions": "^1.0.0" + "@opentelemetry/semantic-conventions": "^1.22.0" }, "devDependencies": { "@opentelemetry/api": "^1.3.0", @@ -46919,7 +46919,7 @@ "@opentelemetry/instrumentation": "^0.50.0", "@opentelemetry/sdk-trace-base": "^1.8.0", "@opentelemetry/sdk-trace-node": "^1.8.0", - "@opentelemetry/semantic-conventions": "^1.0.0", + "@opentelemetry/semantic-conventions": "^1.22.0", "@types/mocha": "7.0.2", "@types/node": "18.6.5", "@types/restify": "4.3.10", diff --git a/plugins/node/opentelemetry-instrumentation-restify/README.md b/plugins/node/opentelemetry-instrumentation-restify/README.md index 2e16ea7490..fd9b7fc7cd 100644 --- a/plugins/node/opentelemetry-instrumentation-restify/README.md +++ b/plugins/node/opentelemetry-instrumentation-restify/README.md @@ -62,6 +62,16 @@ const restifyInstrumentation = new RestifyInstrumentation({ }); ``` +## Semantic Conventions + +This package uses `@opentelemetry/semantic-conventions` version `1.22+`, which implements Semantic Convention [Version 1.7.0](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.7.0/semantic_conventions/README.md) + +Attributes collected: + +| Attribute | Short Description | +| ------------ | ---------------------------------- | +| `http.route` | The matched route (path template). | + ## Useful links - For more information on OpenTelemetry, visit: diff --git a/plugins/node/opentelemetry-instrumentation-restify/package.json b/plugins/node/opentelemetry-instrumentation-restify/package.json index ddd13d9b97..dbe6fa86ed 100644 --- a/plugins/node/opentelemetry-instrumentation-restify/package.json +++ b/plugins/node/opentelemetry-instrumentation-restify/package.json @@ -63,7 +63,7 @@ "dependencies": { "@opentelemetry/core": "^1.8.0", "@opentelemetry/instrumentation": "^0.50.0", - "@opentelemetry/semantic-conventions": "^1.0.0" + "@opentelemetry/semantic-conventions": "^1.22.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-restify#readme" } diff --git a/plugins/node/opentelemetry-instrumentation-restify/src/instrumentation.ts b/plugins/node/opentelemetry-instrumentation-restify/src/instrumentation.ts index 9efe444502..a29679f6ba 100644 --- a/plugins/node/opentelemetry-instrumentation-restify/src/instrumentation.ts +++ b/plugins/node/opentelemetry-instrumentation-restify/src/instrumentation.ts @@ -20,7 +20,7 @@ import type * as restify from 'restify'; import * as api from '@opentelemetry/api'; import type { Server } from 'restify'; import { LayerType } from './types'; -import * as AttributeNames from './enums/AttributeNames'; +import { AttributeNames } from './enums/AttributeNames'; import { VERSION } from './version'; import * as constants from './constants'; import { @@ -30,7 +30,7 @@ import { isWrapped, safeExecuteInTheMiddle, } from '@opentelemetry/instrumentation'; -import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; +import { SEMATTRS_HTTP_ROUTE } from '@opentelemetry/semantic-conventions'; import { isPromise, isAsyncFunction } from './utils'; import { getRPCMetadata, RPCType } from '@opentelemetry/core'; import type { RestifyInstrumentationConfig } from './types'; @@ -185,11 +185,11 @@ export class RestifyInstrumentation extends InstrumentationBase { ? `request handler - ${route}` : `middleware - ${fnName || 'anonymous'}`; const attributes = { - [AttributeNames.AttributeNames.NAME]: fnName, - [AttributeNames.AttributeNames.VERSION]: this._moduleVersion || 'n/a', - [AttributeNames.AttributeNames.TYPE]: metadata.type, - [AttributeNames.AttributeNames.METHOD]: metadata.methodName, - [SemanticAttributes.HTTP_ROUTE]: route, + [AttributeNames.NAME]: fnName, + [AttributeNames.VERSION]: this._moduleVersion || 'n/a', + [AttributeNames.TYPE]: metadata.type, + [AttributeNames.METHOD]: metadata.methodName, + [SEMATTRS_HTTP_ROUTE]: route, }; const span = this.tracer.startSpan( spanName, diff --git a/plugins/node/opentelemetry-instrumentation-restify/test/restify.test.ts b/plugins/node/opentelemetry-instrumentation-restify/test/restify.test.ts index 6af016aed0..bea8b196a0 100644 --- a/plugins/node/opentelemetry-instrumentation-restify/test/restify.test.ts +++ b/plugins/node/opentelemetry-instrumentation-restify/test/restify.test.ts @@ -15,7 +15,7 @@ */ import { context, trace, Span } from '@opentelemetry/api'; -import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; +import { SEMATTRS_HTTP_METHOD } from '@opentelemetry/semantic-conventions'; import { RPCMetadata, RPCType, setRPCMetadata } from '@opentelemetry/core'; import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node'; import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks'; @@ -493,10 +493,7 @@ describe('Restify Instrumentation', () => { describe('using requestHook in config', () => { it('calls requestHook provided function when set in config', async () => { const requestHook = (span: Span, info: RestifyRequestInfo) => { - span.setAttribute( - SemanticAttributes.HTTP_METHOD, - info.request.method - ); + span.setAttribute(SEMATTRS_HTTP_METHOD, info.request.method); span.setAttribute('restify.layer', info.layerType); }; @@ -518,10 +515,7 @@ describe('Restify Instrumentation', () => { // span from get const span = memoryExporter.getFinishedSpans()[2]; assert.notStrictEqual(span, undefined); - assert.strictEqual( - span.attributes[SemanticAttributes.HTTP_METHOD], - 'GET' - ); + assert.strictEqual(span.attributes[SEMATTRS_HTTP_METHOD], 'GET'); assert.strictEqual( span.attributes['restify.layer'], 'request_handler' @@ -533,10 +527,7 @@ describe('Restify Instrumentation', () => { it('does not propagate an error from a requestHook that throws exception', async () => { const requestHook = (span: Span, info: RestifyRequestInfo) => { - span.setAttribute( - SemanticAttributes.HTTP_METHOD, - info.request.method - ); + span.setAttribute(SEMATTRS_HTTP_METHOD, info.request.method); throw Error('error thrown in requestHook'); }; @@ -559,10 +550,7 @@ describe('Restify Instrumentation', () => { // span from get const span = memoryExporter.getFinishedSpans()[2]; assert.notStrictEqual(span, undefined); - assert.strictEqual( - span.attributes[SemanticAttributes.HTTP_METHOD], - 'GET' - ); + assert.strictEqual(span.attributes[SEMATTRS_HTTP_METHOD], 'GET'); } } );