From 2915c43357b853a87d7c763b7571060851ec619e Mon Sep 17 00:00:00 2001 From: Naseem Date: Tue, 1 Sep 2020 16:12:46 -0400 Subject: [PATCH] [mongodb] implement semantic db conventions (#187) * feat: implement semantic db conventions Signed-off-by: Naseem * refactor: set db name and collection constants before their use in setting attributes Signed-off-by: Naseem * fix: always coerce namespace to string It could be a string or an instance of MongoDBNamespace Signed-off-by: Naseem --- .../opentelemetry-plugin-mongodb/package.json | 1 + .../src/mongodb.ts | 27 ++++++++++++------- .../opentelemetry-plugin-mongodb/src/types.ts | 15 ----------- .../test/utils.ts | 14 +++++++--- 4 files changed, 28 insertions(+), 29 deletions(-) diff --git a/plugins/node/opentelemetry-plugin-mongodb/package.json b/plugins/node/opentelemetry-plugin-mongodb/package.json index 4e65b8c735..e05e524a92 100644 --- a/plugins/node/opentelemetry-plugin-mongodb/package.json +++ b/plugins/node/opentelemetry-plugin-mongodb/package.json @@ -43,6 +43,7 @@ "devDependencies": { "@opentelemetry/context-async-hooks": "0.10.2", "@opentelemetry/node": "0.10.2", + "@opentelemetry/semantic-conventions": "^0.10.2", "@opentelemetry/tracing": "0.10.2", "@types/mocha": "7.0.2", "@types/mongodb": "3.5.25", diff --git a/plugins/node/opentelemetry-plugin-mongodb/src/mongodb.ts b/plugins/node/opentelemetry-plugin-mongodb/src/mongodb.ts index 6183ca9f41..3fe3704754 100644 --- a/plugins/node/opentelemetry-plugin-mongodb/src/mongodb.ts +++ b/plugins/node/opentelemetry-plugin-mongodb/src/mongodb.ts @@ -16,16 +16,19 @@ import { BasePlugin } from '@opentelemetry/core'; import { CanonicalCode, Span, SpanKind } from '@opentelemetry/api'; -import * as mongodb from 'mongodb'; +import type * as mongodb from 'mongodb'; import * as shimmer from 'shimmer'; import { - AttributeNames, Func, MongodbCommandType, MongoInternalCommand, MongoInternalTopology, } from './types'; import { VERSION } from './version'; +import { + DatabaseAttribute, + GeneralAttribute, +} from '@opentelemetry/semantic-conventions'; /** MongoDBCore instrumentation plugin for OpenTelemetry */ export class MongoDBPlugin extends BasePlugin { @@ -33,9 +36,6 @@ export class MongoDBPlugin extends BasePlugin { private readonly _CURSOR_METHODS = ['_next', 'next']; private _hasPatched: boolean = false; - private readonly _COMPONENT = 'mongodb'; - private readonly _DB_TYPE = 'mongodb'; - readonly supportedVersions = ['>=2 <4']; constructor(readonly moduleName: string) { @@ -175,19 +175,26 @@ export class MongoDBPlugin extends BasePlugin { // add network attributes to determine the remote server if (topology && topology.s) { span.setAttributes({ - [AttributeNames.PEER_HOSTNAME]: `${ + [GeneralAttribute.NET_HOST_NAME]: `${ topology.s.options?.host ?? topology.s.host }`, - [AttributeNames.PEER_PORT]: `${ + [GeneralAttribute.NET_HOST_PORT]: `${ topology.s.options?.port ?? topology.s.port }`, }); } + + // The namespace is a combination of the database name and the name of the + // collection or index, like so: [database-name].[collection-or-index-name]. + // It could be a string or an instance of MongoDBNamespace, as such we + // always coerce to a string to extract db and collection. + const [dbName, dbCollection] = ns.toString().split('.'); + // add database related attributes span.setAttributes({ - [AttributeNames.DB_INSTANCE]: `${ns}`, - [AttributeNames.DB_TYPE]: this._DB_TYPE, - [AttributeNames.COMPONENT]: this._COMPONENT, + [DatabaseAttribute.DB_SYSTEM]: 'mongodb', + [DatabaseAttribute.DB_NAME]: dbName, + [DatabaseAttribute.DB_MONGODB_COLLECTION]: dbCollection, }); if (command === undefined) return; diff --git a/plugins/node/opentelemetry-plugin-mongodb/src/types.ts b/plugins/node/opentelemetry-plugin-mongodb/src/types.ts index c49ee4b3cb..928539c606 100644 --- a/plugins/node/opentelemetry-plugin-mongodb/src/types.ts +++ b/plugins/node/opentelemetry-plugin-mongodb/src/types.ts @@ -40,21 +40,6 @@ export type MongoInternalTopology = { }; }; -export enum AttributeNames { - // required by https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-semantic-conventions.md#databases-client-calls - COMPONENT = 'component', - DB_TYPE = 'db.type', - DB_INSTANCE = 'db.instance', - DB_STATEMENT = 'db.statement', - PEER_ADDRESS = 'peer.address', - PEER_HOSTNAME = 'peer.host', - - PEER_PORT = 'peer.port', - PEER_IPV4 = 'peer.ipv4', - PEER_IPV6 = 'peer.ipv6', - PEER_SERVICE = 'peer.service', -} - export enum MongodbCommandType { CREATE_INDEXES = 'createIndexes', FIND_AND_MODIFY = 'findAndModify', diff --git a/plugins/node/opentelemetry-plugin-mongodb/test/utils.ts b/plugins/node/opentelemetry-plugin-mongodb/test/utils.ts index e03aed6c68..cd8de27843 100644 --- a/plugins/node/opentelemetry-plugin-mongodb/test/utils.ts +++ b/plugins/node/opentelemetry-plugin-mongodb/test/utils.ts @@ -18,7 +18,10 @@ import { CanonicalCode, SpanKind } from '@opentelemetry/api'; import { ReadableSpan } from '@opentelemetry/tracing'; import * as assert from 'assert'; import * as mongodb from 'mongodb'; -import { AttributeNames } from '../src/types'; +import { + DatabaseAttribute, + GeneralAttribute, +} from '@opentelemetry/semantic-conventions'; export interface MongoDBAccess { client: mongodb.MongoClient; @@ -75,16 +78,19 @@ export function assertSpans( const [mongoSpan] = spans; assert.strictEqual(mongoSpan.name, expectedName); assert.strictEqual(mongoSpan.kind, expectedKind); - assert.strictEqual(mongoSpan.attributes[AttributeNames.COMPONENT], 'mongodb'); assert.strictEqual( - mongoSpan.attributes[AttributeNames.PEER_HOSTNAME], + mongoSpan.attributes[DatabaseAttribute.DB_SYSTEM], + 'mongodb' + ); + assert.strictEqual( + mongoSpan.attributes[GeneralAttribute.NET_HOST_NAME], process.env.MONGODB_HOST || 'localhost' ); assert.strictEqual(mongoSpan.status.code, CanonicalCode.OK); if (isEnhancedDatabaseReportingEnabled) { const dbStatement = mongoSpan.attributes[ - AttributeNames.DB_STATEMENT + DatabaseAttribute.DB_STATEMENT ] as any; for (const key in dbStatement) { assert.notStrictEqual(dbStatement[key], '?');