@opentelemetry/instrumentation-tedious 0.27.0 → 0.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -42,19 +42,29 @@ registerInstrumentations({
42
42
 
43
43
  ## Semantic Conventions
44
44
 
45
- 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)
45
+ This instrumentation implements Semantic Conventions (semconv) v1.7.0. Since then, networking (in semconv v1.23.1) and database (in semconv v1.33.0) semantic conventions were stabilized. As of `@opentelemetry/instrumentation-tedious@0.28.0` support has been added for migrating to the stable semantic conventions using the `OTEL_SEMCONV_STABILITY_OPT_IN` environment variable as follows:
46
+
47
+ 1. Upgrade to the latest version of this instrumentation package.
48
+ 2. Set `OTEL_SEMCONV_STABILITY_OPT_IN=http/dup,database/dup` to emit both old and stable semantic conventions. (The `http` token is used to control the `net.*` attributes, the `database` token to control to `db.*` attributes.)
49
+ 3. Modify alerts, dashboards, metrics, and other processes in your Observability system to use the stable semantic conventions.
50
+ 4. Set `OTEL_SEMCONV_STABILITY_OPT_IN=http,database` to emit only the stable semantic conventions.
51
+
52
+ By default, if `OTEL_SEMCONV_STABILITY_OPT_IN` includes neither of the above tokens, the old v1.7.0 semconv is used.
53
+ The intent is to provide an approximate 6 month time window for users of this instrumentation to migrate to the new database and networking semconv, after which a new minor version will use the new semconv by default and drop support for the old semconv.
54
+ See [the HTTP migration guide](https://opentelemetry.io/docs/specs/semconv/non-normative/http-migration/) and the [database migration guide](https://opentelemetry.io/docs/specs/semconv/non-normative/db-migration/) for details.
46
55
 
47
56
  Attributes collected:
48
57
 
49
- | Attribute | Short Description |
50
- | ----------------------- | ------------------------------------------------------------------------------ |
51
- | `db.name` | This attribute is used to report the name of the database being accessed. |
52
- | `db.sql.table` | The name of the primary table that the operation is acting upon. |
53
- | `db.statement` | The database statement being executed. |
54
- | `db.system` | An identifier for the database management system (DBMS) product being used. |
55
- | `db.user` | Username for accessing the database. |
56
- | `net.peer.name` | Remote hostname or similar. |
57
- | `net.peer.port` | Remote port number. |
58
+ | Old semconv | Stable semconv | Description |
59
+ | --------------- | -------------------- | ---------------------------------- |
60
+ | `db.system` | `db.system.name` | 'mssql' (old), 'microsoft.sql_server' (stable) |
61
+ | `db.statement` | `db.query.text` | The database query being executed. |
62
+ | `db.user` | Removed | Username for accessing the database. |
63
+ | `db.name` | Removed | Integrated into new `db.namespace`. |
64
+ | (not included) | `db.namespace` | The database associated with the connection, qualified by the instance name. |
65
+ | `db.sql.table` | `db.collection.name` | The name of a collection (table, container) within the database. |
66
+ | `net.peer.name` | `server.address` | Remote hostname or similar. |
67
+ | `net.peer.port` | `server.port` | Remote port number. |
58
68
 
59
69
  ### Trace Context Propagation
60
70
 
@@ -3,7 +3,10 @@ import { TediousInstrumentationConfig } from './types';
3
3
  export declare const INJECTED_CTX: unique symbol;
4
4
  export declare class TediousInstrumentation extends InstrumentationBase<TediousInstrumentationConfig> {
5
5
  static readonly COMPONENT = "tedious";
6
+ private _netSemconvStability;
7
+ private _dbSemconvStability;
6
8
  constructor(config?: TediousInstrumentationConfig);
9
+ private _setSemconvStabilityFromEnv;
7
10
  protected init(): InstrumentationNodeModuleDefinition[];
8
11
  private _patchConnect;
9
12
  private _buildTraceparent;
@@ -19,6 +19,7 @@ exports.TediousInstrumentation = exports.INJECTED_CTX = void 0;
19
19
  const api = require("@opentelemetry/api");
20
20
  const events_1 = require("events");
21
21
  const instrumentation_1 = require("@opentelemetry/instrumentation");
22
+ const semantic_conventions_1 = require("@opentelemetry/semantic-conventions");
22
23
  const semconv_1 = require("./semconv");
23
24
  const utils_1 = require("./utils");
24
25
  /** @knipignore */
@@ -41,8 +42,16 @@ function setDatabase(databaseName) {
41
42
  }
42
43
  class TediousInstrumentation extends instrumentation_1.InstrumentationBase {
43
44
  static COMPONENT = 'tedious';
45
+ _netSemconvStability;
46
+ _dbSemconvStability;
44
47
  constructor(config = {}) {
45
48
  super(version_1.PACKAGE_NAME, version_1.PACKAGE_VERSION, config);
49
+ this._setSemconvStabilityFromEnv();
50
+ }
51
+ // Used for testing.
52
+ _setSemconvStabilityFromEnv() {
53
+ this._netSemconvStability = (0, instrumentation_1.semconvStabilityFromStr)('http', process.env.OTEL_SEMCONV_STABILITY_OPT_IN);
54
+ this._dbSemconvStability = (0, instrumentation_1.semconvStabilityFromStr)('database', process.env.OTEL_SEMCONV_STABILITY_OPT_IN);
46
55
  }
47
56
  init() {
48
57
  return [
@@ -138,19 +147,43 @@ class TediousInstrumentation extends instrumentation_1.InstrumentationBase {
138
147
  }
139
148
  return request.sqlTextOrProcedure;
140
149
  })(request);
150
+ const attributes = {};
151
+ if (thisPlugin._dbSemconvStability & instrumentation_1.SemconvStability.OLD) {
152
+ attributes[semconv_1.ATTR_DB_SYSTEM] = semconv_1.DB_SYSTEM_VALUE_MSSQL;
153
+ attributes[semconv_1.ATTR_DB_NAME] = databaseName;
154
+ // >=4 uses `authentication` object; older versions just userName and password pair
155
+ attributes[semconv_1.ATTR_DB_USER] =
156
+ this.config?.userName ??
157
+ this.config?.authentication?.options?.userName;
158
+ attributes[semconv_1.ATTR_DB_STATEMENT] = sql;
159
+ attributes[semconv_1.ATTR_DB_SQL_TABLE] = request.table;
160
+ }
161
+ if (thisPlugin._dbSemconvStability & instrumentation_1.SemconvStability.STABLE) {
162
+ // The OTel spec for "db.namespace" discusses handling for connection
163
+ // to MSSQL "named instances". This isn't currently supported.
164
+ // https://opentelemetry.io/docs/specs/semconv/database/sql-server/#:~:text=%5B1%5D%20db%2Enamespace
165
+ attributes[semantic_conventions_1.ATTR_DB_NAMESPACE] = databaseName;
166
+ attributes[semantic_conventions_1.ATTR_DB_SYSTEM_NAME] =
167
+ semantic_conventions_1.DB_SYSTEM_NAME_VALUE_MICROSOFT_SQL_SERVER;
168
+ attributes[semantic_conventions_1.ATTR_DB_QUERY_TEXT] = sql;
169
+ attributes[semantic_conventions_1.ATTR_DB_COLLECTION_NAME] = request.table;
170
+ // See https://opentelemetry.io/docs/specs/semconv/database/sql-server/#spans
171
+ // TODO(3290): can `db.response.status_code` be added?
172
+ // TODO(3290): is `operation` correct for `db.operation.name`
173
+ // TODO(3290): can `db.query.summary` reliably be calculated?
174
+ // TODO(3290): `db.stored_procedure.name`
175
+ }
176
+ if (thisPlugin._netSemconvStability & instrumentation_1.SemconvStability.OLD) {
177
+ attributes[semconv_1.ATTR_NET_PEER_NAME] = this.config?.server;
178
+ attributes[semconv_1.ATTR_NET_PEER_PORT] = this.config?.options?.port;
179
+ }
180
+ if (thisPlugin._netSemconvStability & instrumentation_1.SemconvStability.STABLE) {
181
+ attributes[semantic_conventions_1.ATTR_SERVER_ADDRESS] = this.config?.server;
182
+ attributes[semantic_conventions_1.ATTR_SERVER_PORT] = this.config?.options?.port;
183
+ }
141
184
  const span = thisPlugin.tracer.startSpan((0, utils_1.getSpanName)(operation, databaseName, sql, request.table), {
142
185
  kind: api.SpanKind.CLIENT,
143
- attributes: {
144
- [semconv_1.ATTR_DB_SYSTEM]: semconv_1.DB_SYSTEM_VALUE_MSSQL,
145
- [semconv_1.ATTR_DB_NAME]: databaseName,
146
- [semconv_1.ATTR_NET_PEER_PORT]: this.config?.options?.port,
147
- [semconv_1.ATTR_NET_PEER_NAME]: this.config?.server,
148
- // >=4 uses `authentication` object, older versions just userName and password pair
149
- [semconv_1.ATTR_DB_USER]: this.config?.userName ??
150
- this.config?.authentication?.options?.userName,
151
- [semconv_1.ATTR_DB_STATEMENT]: sql,
152
- [semconv_1.ATTR_DB_SQL_TABLE]: request.table,
153
- },
186
+ attributes,
154
187
  });
155
188
  const endSpan = (0, utils_1.once)((err) => {
156
189
  request.removeListener('done', incrementStatementCount);
@@ -165,6 +198,7 @@ class TediousInstrumentation extends instrumentation_1.InstrumentationBase {
165
198
  code: api.SpanStatusCode.ERROR,
166
199
  message: err.message,
167
200
  });
201
+ // TODO(3290): set `error.type` attribute?
168
202
  }
169
203
  span.end();
170
204
  });
@@ -1 +1 @@
1
- {"version":3,"file":"instrumentation.js","sourceRoot":"","sources":["../../src/instrumentation.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as api from '@opentelemetry/api';\nimport { EventEmitter } from 'events';\nimport {\n InstrumentationBase,\n InstrumentationNodeModuleDefinition,\n isWrapped,\n} from '@opentelemetry/instrumentation';\nimport {\n DB_SYSTEM_VALUE_MSSQL,\n ATTR_DB_NAME,\n ATTR_DB_SQL_TABLE,\n ATTR_DB_STATEMENT,\n ATTR_DB_SYSTEM,\n ATTR_DB_USER,\n ATTR_NET_PEER_NAME,\n ATTR_NET_PEER_PORT,\n} from './semconv';\nimport type * as tedious from 'tedious';\nimport { TediousInstrumentationConfig } from './types';\nimport { getSpanName, once } from './utils';\n/** @knipignore */\nimport { PACKAGE_NAME, PACKAGE_VERSION } from './version';\n\nconst CURRENT_DATABASE = Symbol(\n 'opentelemetry.instrumentation-tedious.current-database'\n);\n\nexport const INJECTED_CTX = Symbol(\n 'opentelemetry.instrumentation-tedious.context-info-injected'\n);\n\nconst PATCHED_METHODS = [\n 'callProcedure',\n 'execSql',\n 'execSqlBatch',\n 'execBulkLoad',\n 'prepare',\n 'execute',\n];\n\ntype UnknownFunction = (...args: any[]) => any;\ntype ApproxConnection = EventEmitter & {\n [CURRENT_DATABASE]: string;\n config: any;\n};\ntype ApproxRequest = EventEmitter & {\n sqlTextOrProcedure: string | undefined;\n callback: any;\n table: string | undefined;\n parametersByName: any;\n};\n\nfunction setDatabase(this: ApproxConnection, databaseName: string) {\n Object.defineProperty(this, CURRENT_DATABASE, {\n value: databaseName,\n writable: true,\n });\n}\n\nexport class TediousInstrumentation extends InstrumentationBase<TediousInstrumentationConfig> {\n static readonly COMPONENT = 'tedious';\n\n constructor(config: TediousInstrumentationConfig = {}) {\n super(PACKAGE_NAME, PACKAGE_VERSION, config);\n }\n\n protected init() {\n return [\n new InstrumentationNodeModuleDefinition(\n TediousInstrumentation.COMPONENT,\n ['>=1.11.0 <20'],\n (moduleExports: typeof tedious) => {\n const ConnectionPrototype: any = moduleExports.Connection.prototype;\n for (const method of PATCHED_METHODS) {\n if (isWrapped(ConnectionPrototype[method])) {\n this._unwrap(ConnectionPrototype, method);\n }\n this._wrap(\n ConnectionPrototype,\n method,\n this._patchQuery(method, moduleExports) as any\n );\n }\n\n if (isWrapped(ConnectionPrototype.connect)) {\n this._unwrap(ConnectionPrototype, 'connect');\n }\n this._wrap(ConnectionPrototype, 'connect', this._patchConnect);\n\n return moduleExports;\n },\n (moduleExports: typeof tedious) => {\n if (moduleExports === undefined) return;\n const ConnectionPrototype: any = moduleExports.Connection.prototype;\n for (const method of PATCHED_METHODS) {\n this._unwrap(ConnectionPrototype, method);\n }\n this._unwrap(ConnectionPrototype, 'connect');\n }\n ),\n ];\n }\n\n private _patchConnect(original: UnknownFunction): UnknownFunction {\n return function patchedConnect(this: ApproxConnection) {\n setDatabase.call(this, this.config?.options?.database);\n\n // remove the listener first in case it's already added\n this.removeListener('databaseChange', setDatabase);\n this.on('databaseChange', setDatabase);\n\n this.once('end', () => {\n this.removeListener('databaseChange', setDatabase);\n });\n return original.apply(this, arguments as unknown as any[]);\n };\n }\n\n private _buildTraceparent(span: api.Span): string {\n const sc = span.spanContext();\n return `00-${sc.traceId}-${sc.spanId}-0${Number(sc.traceFlags || api.TraceFlags.NONE).toString(16)}`;\n }\n\n /**\n * Fire a one-off `SET CONTEXT_INFO @opentelemetry_traceparent` on the same\n * connection. Marks the request with INJECTED_CTX so our patch skips it.\n */\n private _injectContextInfo(\n connection: any,\n tediousModule: typeof tedious,\n traceparent: string\n ): Promise<void> {\n return new Promise(resolve => {\n try {\n const sql = 'set context_info @opentelemetry_traceparent';\n const req = new tediousModule.Request(sql, (_err: any) => {\n resolve();\n });\n Object.defineProperty(req, INJECTED_CTX, { value: true });\n const buf = Buffer.from(traceparent, 'utf8');\n req.addParameter(\n 'opentelemetry_traceparent',\n (tediousModule as any).TYPES.VarBinary,\n buf,\n { length: buf.length }\n );\n\n connection.execSql(req);\n } catch {\n resolve();\n }\n });\n }\n\n private _shouldInjectFor(operation: string): boolean {\n return (\n operation === 'execSql' ||\n operation === 'execSqlBatch' ||\n operation === 'callProcedure' ||\n operation === 'execute'\n );\n }\n\n private _patchQuery(operation: string, tediousModule: typeof tedious) {\n return (originalMethod: UnknownFunction): UnknownFunction => {\n const thisPlugin = this;\n\n function patchedMethod(this: ApproxConnection, request: ApproxRequest) {\n // Skip our own injected request\n if ((request as any)?.[INJECTED_CTX]) {\n return originalMethod.apply(this, arguments as unknown as any[]);\n }\n\n if (!(request instanceof EventEmitter)) {\n thisPlugin._diag.warn(\n `Unexpected invocation of patched ${operation} method. Span not recorded`\n );\n return originalMethod.apply(this, arguments as unknown as any[]);\n }\n let procCount = 0;\n let statementCount = 0;\n const incrementStatementCount = () => statementCount++;\n const incrementProcCount = () => procCount++;\n const databaseName = this[CURRENT_DATABASE];\n const sql = (request => {\n // Required for <11.0.9\n if (\n request.sqlTextOrProcedure === 'sp_prepare' &&\n request.parametersByName?.stmt?.value\n ) {\n return request.parametersByName.stmt.value;\n }\n return request.sqlTextOrProcedure;\n })(request);\n\n const span = thisPlugin.tracer.startSpan(\n getSpanName(operation, databaseName, sql, request.table),\n {\n kind: api.SpanKind.CLIENT,\n attributes: {\n [ATTR_DB_SYSTEM]: DB_SYSTEM_VALUE_MSSQL,\n [ATTR_DB_NAME]: databaseName,\n [ATTR_NET_PEER_PORT]: this.config?.options?.port,\n [ATTR_NET_PEER_NAME]: this.config?.server,\n // >=4 uses `authentication` object, older versions just userName and password pair\n [ATTR_DB_USER]:\n this.config?.userName ??\n this.config?.authentication?.options?.userName,\n [ATTR_DB_STATEMENT]: sql,\n [ATTR_DB_SQL_TABLE]: request.table,\n },\n }\n );\n\n const endSpan = once((err?: any) => {\n request.removeListener('done', incrementStatementCount);\n request.removeListener('doneInProc', incrementStatementCount);\n request.removeListener('doneProc', incrementProcCount);\n request.removeListener('error', endSpan);\n this.removeListener('end', endSpan);\n\n span.setAttribute('tedious.procedure_count', procCount);\n span.setAttribute('tedious.statement_count', statementCount);\n if (err) {\n span.setStatus({\n code: api.SpanStatusCode.ERROR,\n message: err.message,\n });\n }\n span.end();\n });\n\n request.on('done', incrementStatementCount);\n request.on('doneInProc', incrementStatementCount);\n request.on('doneProc', incrementProcCount);\n request.once('error', endSpan);\n this.on('end', endSpan);\n\n if (typeof request.callback === 'function') {\n thisPlugin._wrap(\n request,\n 'callback',\n thisPlugin._patchCallbackQuery(endSpan)\n );\n } else {\n thisPlugin._diag.error('Expected request.callback to be a function');\n }\n\n const runUserRequest = () => {\n return api.context.with(\n api.trace.setSpan(api.context.active(), span),\n originalMethod,\n this,\n ...arguments\n );\n };\n\n const cfg = thisPlugin.getConfig();\n const shouldInject =\n cfg.enableTraceContextPropagation &&\n thisPlugin._shouldInjectFor(operation);\n\n if (!shouldInject) return runUserRequest();\n\n const traceparent = thisPlugin._buildTraceparent(span);\n \n void thisPlugin\n ._injectContextInfo(this, tediousModule, traceparent)\n .finally(runUserRequest);\n }\n\n Object.defineProperty(patchedMethod, 'length', {\n value: originalMethod.length,\n writable: false,\n });\n\n return patchedMethod;\n };\n }\n\n private _patchCallbackQuery(endSpan: Function) {\n return (originalCallback: Function) => {\n return function (\n this: any,\n err: Error | undefined | null,\n rowCount?: number,\n rows?: any\n ) {\n endSpan(err);\n return originalCallback.apply(this, arguments);\n };\n };\n }\n}\n"]}
1
+ {"version":3,"file":"instrumentation.js","sourceRoot":"","sources":["../../src/instrumentation.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as api from '@opentelemetry/api';\nimport { EventEmitter } from 'events';\nimport {\n InstrumentationBase,\n InstrumentationNodeModuleDefinition,\n isWrapped,\n SemconvStability,\n semconvStabilityFromStr,\n} from '@opentelemetry/instrumentation';\nimport {\n ATTR_DB_COLLECTION_NAME,\n ATTR_DB_NAMESPACE,\n ATTR_DB_QUERY_TEXT,\n ATTR_DB_SYSTEM_NAME,\n ATTR_SERVER_ADDRESS,\n ATTR_SERVER_PORT,\n DB_SYSTEM_NAME_VALUE_MICROSOFT_SQL_SERVER,\n} from '@opentelemetry/semantic-conventions';\nimport {\n DB_SYSTEM_VALUE_MSSQL,\n ATTR_DB_NAME,\n ATTR_DB_SQL_TABLE,\n ATTR_DB_STATEMENT,\n ATTR_DB_SYSTEM,\n ATTR_DB_USER,\n ATTR_NET_PEER_NAME,\n ATTR_NET_PEER_PORT,\n} from './semconv';\nimport type * as tedious from 'tedious';\nimport { TediousInstrumentationConfig } from './types';\nimport { getSpanName, once } from './utils';\n/** @knipignore */\nimport { PACKAGE_NAME, PACKAGE_VERSION } from './version';\n\nconst CURRENT_DATABASE = Symbol(\n 'opentelemetry.instrumentation-tedious.current-database'\n);\n\nexport const INJECTED_CTX = Symbol(\n 'opentelemetry.instrumentation-tedious.context-info-injected'\n);\n\nconst PATCHED_METHODS = [\n 'callProcedure',\n 'execSql',\n 'execSqlBatch',\n 'execBulkLoad',\n 'prepare',\n 'execute',\n];\n\ntype UnknownFunction = (...args: any[]) => any;\ntype ApproxConnection = EventEmitter & {\n [CURRENT_DATABASE]: string;\n config: any;\n};\ntype ApproxRequest = EventEmitter & {\n sqlTextOrProcedure: string | undefined;\n callback: any;\n table: string | undefined;\n parametersByName: any;\n};\n\nfunction setDatabase(this: ApproxConnection, databaseName: string) {\n Object.defineProperty(this, CURRENT_DATABASE, {\n value: databaseName,\n writable: true,\n });\n}\n\nexport class TediousInstrumentation extends InstrumentationBase<TediousInstrumentationConfig> {\n static readonly COMPONENT = 'tedious';\n private _netSemconvStability!: SemconvStability;\n private _dbSemconvStability!: SemconvStability;\n\n constructor(config: TediousInstrumentationConfig = {}) {\n super(PACKAGE_NAME, PACKAGE_VERSION, config);\n this._setSemconvStabilityFromEnv();\n }\n\n // Used for testing.\n private _setSemconvStabilityFromEnv() {\n this._netSemconvStability = semconvStabilityFromStr(\n 'http',\n process.env.OTEL_SEMCONV_STABILITY_OPT_IN\n );\n this._dbSemconvStability = semconvStabilityFromStr(\n 'database',\n process.env.OTEL_SEMCONV_STABILITY_OPT_IN\n );\n }\n\n protected init() {\n return [\n new InstrumentationNodeModuleDefinition(\n TediousInstrumentation.COMPONENT,\n ['>=1.11.0 <20'],\n (moduleExports: typeof tedious) => {\n const ConnectionPrototype: any = moduleExports.Connection.prototype;\n for (const method of PATCHED_METHODS) {\n if (isWrapped(ConnectionPrototype[method])) {\n this._unwrap(ConnectionPrototype, method);\n }\n this._wrap(\n ConnectionPrototype,\n method,\n this._patchQuery(method, moduleExports) as any\n );\n }\n\n if (isWrapped(ConnectionPrototype.connect)) {\n this._unwrap(ConnectionPrototype, 'connect');\n }\n this._wrap(ConnectionPrototype, 'connect', this._patchConnect);\n\n return moduleExports;\n },\n (moduleExports: typeof tedious) => {\n if (moduleExports === undefined) return;\n const ConnectionPrototype: any = moduleExports.Connection.prototype;\n for (const method of PATCHED_METHODS) {\n this._unwrap(ConnectionPrototype, method);\n }\n this._unwrap(ConnectionPrototype, 'connect');\n }\n ),\n ];\n }\n\n private _patchConnect(original: UnknownFunction): UnknownFunction {\n return function patchedConnect(this: ApproxConnection) {\n setDatabase.call(this, this.config?.options?.database);\n\n // remove the listener first in case it's already added\n this.removeListener('databaseChange', setDatabase);\n this.on('databaseChange', setDatabase);\n\n this.once('end', () => {\n this.removeListener('databaseChange', setDatabase);\n });\n return original.apply(this, arguments as unknown as any[]);\n };\n }\n\n private _buildTraceparent(span: api.Span): string {\n const sc = span.spanContext();\n return `00-${sc.traceId}-${sc.spanId}-0${Number(sc.traceFlags || api.TraceFlags.NONE).toString(16)}`;\n }\n\n /**\n * Fire a one-off `SET CONTEXT_INFO @opentelemetry_traceparent` on the same\n * connection. Marks the request with INJECTED_CTX so our patch skips it.\n */\n private _injectContextInfo(\n connection: any,\n tediousModule: typeof tedious,\n traceparent: string\n ): Promise<void> {\n return new Promise(resolve => {\n try {\n const sql = 'set context_info @opentelemetry_traceparent';\n const req = new tediousModule.Request(sql, (_err: any) => {\n resolve();\n });\n Object.defineProperty(req, INJECTED_CTX, { value: true });\n const buf = Buffer.from(traceparent, 'utf8');\n req.addParameter(\n 'opentelemetry_traceparent',\n (tediousModule as any).TYPES.VarBinary,\n buf,\n { length: buf.length }\n );\n\n connection.execSql(req);\n } catch {\n resolve();\n }\n });\n }\n\n private _shouldInjectFor(operation: string): boolean {\n return (\n operation === 'execSql' ||\n operation === 'execSqlBatch' ||\n operation === 'callProcedure' ||\n operation === 'execute'\n );\n }\n\n private _patchQuery(operation: string, tediousModule: typeof tedious) {\n return (originalMethod: UnknownFunction): UnknownFunction => {\n const thisPlugin = this;\n\n function patchedMethod(this: ApproxConnection, request: ApproxRequest) {\n // Skip our own injected request\n if ((request as any)?.[INJECTED_CTX]) {\n return originalMethod.apply(this, arguments as unknown as any[]);\n }\n\n if (!(request instanceof EventEmitter)) {\n thisPlugin._diag.warn(\n `Unexpected invocation of patched ${operation} method. Span not recorded`\n );\n return originalMethod.apply(this, arguments as unknown as any[]);\n }\n let procCount = 0;\n let statementCount = 0;\n const incrementStatementCount = () => statementCount++;\n const incrementProcCount = () => procCount++;\n const databaseName = this[CURRENT_DATABASE];\n const sql = (request => {\n // Required for <11.0.9\n if (\n request.sqlTextOrProcedure === 'sp_prepare' &&\n request.parametersByName?.stmt?.value\n ) {\n return request.parametersByName.stmt.value;\n }\n return request.sqlTextOrProcedure;\n })(request);\n\n const attributes: api.Attributes = {};\n if (thisPlugin._dbSemconvStability & SemconvStability.OLD) {\n attributes[ATTR_DB_SYSTEM] = DB_SYSTEM_VALUE_MSSQL;\n attributes[ATTR_DB_NAME] = databaseName;\n // >=4 uses `authentication` object; older versions just userName and password pair\n attributes[ATTR_DB_USER] =\n this.config?.userName ??\n this.config?.authentication?.options?.userName;\n attributes[ATTR_DB_STATEMENT] = sql;\n attributes[ATTR_DB_SQL_TABLE] = request.table;\n }\n if (thisPlugin._dbSemconvStability & SemconvStability.STABLE) {\n // The OTel spec for \"db.namespace\" discusses handling for connection\n // to MSSQL \"named instances\". This isn't currently supported.\n // https://opentelemetry.io/docs/specs/semconv/database/sql-server/#:~:text=%5B1%5D%20db%2Enamespace\n attributes[ATTR_DB_NAMESPACE] = databaseName;\n attributes[ATTR_DB_SYSTEM_NAME] =\n DB_SYSTEM_NAME_VALUE_MICROSOFT_SQL_SERVER;\n attributes[ATTR_DB_QUERY_TEXT] = sql;\n attributes[ATTR_DB_COLLECTION_NAME] = request.table;\n // See https://opentelemetry.io/docs/specs/semconv/database/sql-server/#spans\n // TODO(3290): can `db.response.status_code` be added?\n // TODO(3290): is `operation` correct for `db.operation.name`\n // TODO(3290): can `db.query.summary` reliably be calculated?\n // TODO(3290): `db.stored_procedure.name`\n }\n if (thisPlugin._netSemconvStability & SemconvStability.OLD) {\n attributes[ATTR_NET_PEER_NAME] = this.config?.server;\n attributes[ATTR_NET_PEER_PORT] = this.config?.options?.port;\n }\n if (thisPlugin._netSemconvStability & SemconvStability.STABLE) {\n attributes[ATTR_SERVER_ADDRESS] = this.config?.server;\n attributes[ATTR_SERVER_PORT] = this.config?.options?.port;\n }\n const span = thisPlugin.tracer.startSpan(\n getSpanName(operation, databaseName, sql, request.table),\n {\n kind: api.SpanKind.CLIENT,\n attributes,\n }\n );\n\n const endSpan = once((err?: any) => {\n request.removeListener('done', incrementStatementCount);\n request.removeListener('doneInProc', incrementStatementCount);\n request.removeListener('doneProc', incrementProcCount);\n request.removeListener('error', endSpan);\n this.removeListener('end', endSpan);\n\n span.setAttribute('tedious.procedure_count', procCount);\n span.setAttribute('tedious.statement_count', statementCount);\n if (err) {\n span.setStatus({\n code: api.SpanStatusCode.ERROR,\n message: err.message,\n });\n // TODO(3290): set `error.type` attribute?\n }\n span.end();\n });\n\n request.on('done', incrementStatementCount);\n request.on('doneInProc', incrementStatementCount);\n request.on('doneProc', incrementProcCount);\n request.once('error', endSpan);\n this.on('end', endSpan);\n\n if (typeof request.callback === 'function') {\n thisPlugin._wrap(\n request,\n 'callback',\n thisPlugin._patchCallbackQuery(endSpan)\n );\n } else {\n thisPlugin._diag.error('Expected request.callback to be a function');\n }\n\n const runUserRequest = () => {\n return api.context.with(\n api.trace.setSpan(api.context.active(), span),\n originalMethod,\n this,\n ...arguments\n );\n };\n\n const cfg = thisPlugin.getConfig();\n const shouldInject =\n cfg.enableTraceContextPropagation &&\n thisPlugin._shouldInjectFor(operation);\n\n if (!shouldInject) return runUserRequest();\n\n const traceparent = thisPlugin._buildTraceparent(span);\n\n void thisPlugin\n ._injectContextInfo(this, tediousModule, traceparent)\n .finally(runUserRequest);\n }\n\n Object.defineProperty(patchedMethod, 'length', {\n value: originalMethod.length,\n writable: false,\n });\n\n return patchedMethod;\n };\n }\n\n private _patchCallbackQuery(endSpan: Function) {\n return (originalCallback: Function) => {\n return function (\n this: any,\n err: Error | undefined | null,\n rowCount?: number,\n rows?: any\n ) {\n endSpan(err);\n return originalCallback.apply(this, arguments);\n };\n };\n }\n}\n"]}
@@ -1,3 +1,3 @@
1
- export declare const PACKAGE_VERSION = "0.27.0";
1
+ export declare const PACKAGE_VERSION = "0.29.0";
2
2
  export declare const PACKAGE_NAME = "@opentelemetry/instrumentation-tedious";
3
3
  //# sourceMappingURL=version.d.ts.map
@@ -17,6 +17,6 @@
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.PACKAGE_NAME = exports.PACKAGE_VERSION = void 0;
19
19
  // this is autogenerated file, see scripts/version-update.js
20
- exports.PACKAGE_VERSION = '0.27.0';
20
+ exports.PACKAGE_VERSION = '0.29.0';
21
21
  exports.PACKAGE_NAME = '@opentelemetry/instrumentation-tedious';
22
22
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;;AAEH,4DAA4D;AAC/C,QAAA,eAAe,GAAG,QAAQ,CAAC;AAC3B,QAAA,YAAY,GAAG,wCAAwC,CAAC","sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// this is autogenerated file, see scripts/version-update.js\nexport const PACKAGE_VERSION = '0.27.0';\nexport const PACKAGE_NAME = '@opentelemetry/instrumentation-tedious';\n"]}
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;;AAEH,4DAA4D;AAC/C,QAAA,eAAe,GAAG,QAAQ,CAAC;AAC3B,QAAA,YAAY,GAAG,wCAAwC,CAAC","sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// this is autogenerated file, see scripts/version-update.js\nexport const PACKAGE_VERSION = '0.29.0';\nexport const PACKAGE_NAME = '@opentelemetry/instrumentation-tedious';\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opentelemetry/instrumentation-tedious",
3
- "version": "0.27.0",
3
+ "version": "0.29.0",
4
4
  "description": "OpenTelemetry instrumentation for `tedious` database client for Microsoft SQL Server",
5
5
  "main": "build/src/index.js",
6
6
  "types": "build/src/index.d.ts",
@@ -54,22 +54,15 @@
54
54
  "devDependencies": {
55
55
  "@opentelemetry/api": "^1.3.0",
56
56
  "@opentelemetry/context-async-hooks": "^2.0.0",
57
- "@opentelemetry/contrib-test-utils": "^0.55.0",
57
+ "@opentelemetry/contrib-test-utils": "^0.57.0",
58
58
  "@opentelemetry/sdk-trace-base": "^2.0.0",
59
- "@types/mocha": "10.0.10",
60
- "@types/node": "18.18.14",
61
- "cross-env": "7.0.3",
62
- "nyc": "17.1.0",
63
- "rimraf": "5.0.10",
64
- "semver": "7.7.3",
65
- "tedious": "17.0.0",
66
- "test-all-versions": "6.1.0",
67
- "typescript": "5.0.4"
59
+ "tedious": "17.0.0"
68
60
  },
69
61
  "dependencies": {
70
- "@opentelemetry/instrumentation": "^0.208.0",
62
+ "@opentelemetry/instrumentation": "^0.210.0",
63
+ "@opentelemetry/semantic-conventions": "^1.33.0",
71
64
  "@types/tedious": "^4.0.14"
72
65
  },
73
66
  "homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/packages/instrumentation-tedious#readme",
74
- "gitHead": "94e5b7da4500459e38e8d4dfda93542f22159600"
67
+ "gitHead": "c84212cca7f010b80747cccb9942474e0459df6e"
75
68
  }