diff --git a/package-lock.json b/package-lock.json index a1a7846d38..e7399912de 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", @@ -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", @@ -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", @@ -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", @@ -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", @@ -46599,7 +46599,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", @@ -46857,7 +46857,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", @@ -46882,7 +46882,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", @@ -46920,7 +46920,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", @@ -46969,7 +46969,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/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); }); 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)); }); }); 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(); 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'); } } ); 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();