Skip to content

Commit 78df9f5

Browse files
authored
feat(instrumentations-tedious): support net.* and database semconv migration (#3273)
This adds support for using `OTEL_SEMCONV_STABILITY_OPT_IN` for controlled migration to stable `net.*` and `db.*` semconv. The `net.*` attributes are controlled by the `http[/dup]` token in `OTEL_SEMCONV_STABILITY_OPT_IN` (as [discussed here](open-telemetry/opentelemetry-js#5663 (comment))) and `db.*` with the `database[/dup]` token. Refs: open-telemetry/opentelemetry-js#5663 Refs: #2953
1 parent 9c1503f commit 78df9f5

File tree

5 files changed

+245
-65
lines changed

5 files changed

+245
-65
lines changed

package-lock.json

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/instrumentation-tedious/README.md

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,19 +42,29 @@ registerInstrumentations({
4242

4343
## Semantic Conventions
4444

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/[email protected]` 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.
4655

4756
Attributes collected:
4857

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. |
5868

5969
### Trace Context Propagation
6070

packages/instrumentation-tedious/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
},
6161
"dependencies": {
6262
"@opentelemetry/instrumentation": "^0.208.0",
63+
"@opentelemetry/semantic-conventions": "^1.33.0",
6364
"@types/tedious": "^4.0.14"
6465
},
6566
"homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/packages/instrumentation-tedious#readme"

packages/instrumentation-tedious/src/instrumentation.ts

Lines changed: 62 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,18 @@ import {
2020
InstrumentationBase,
2121
InstrumentationNodeModuleDefinition,
2222
isWrapped,
23+
SemconvStability,
24+
semconvStabilityFromStr,
2325
} from '@opentelemetry/instrumentation';
26+
import {
27+
ATTR_DB_COLLECTION_NAME,
28+
ATTR_DB_NAMESPACE,
29+
ATTR_DB_QUERY_TEXT,
30+
ATTR_DB_SYSTEM_NAME,
31+
ATTR_SERVER_ADDRESS,
32+
ATTR_SERVER_PORT,
33+
DB_SYSTEM_NAME_VALUE_MICROSOFT_SQL_SERVER,
34+
} from '@opentelemetry/semantic-conventions';
2435
import {
2536
DB_SYSTEM_VALUE_MSSQL,
2637
ATTR_DB_NAME,
@@ -75,9 +86,24 @@ function setDatabase(this: ApproxConnection, databaseName: string) {
7586

7687
export class TediousInstrumentation extends InstrumentationBase<TediousInstrumentationConfig> {
7788
static readonly COMPONENT = 'tedious';
89+
private _netSemconvStability!: SemconvStability;
90+
private _dbSemconvStability!: SemconvStability;
7891

7992
constructor(config: TediousInstrumentationConfig = {}) {
8093
super(PACKAGE_NAME, PACKAGE_VERSION, config);
94+
this._setSemconvStabilityFromEnv();
95+
}
96+
97+
// Used for testing.
98+
private _setSemconvStabilityFromEnv() {
99+
this._netSemconvStability = semconvStabilityFromStr(
100+
'http',
101+
process.env.OTEL_SEMCONV_STABILITY_OPT_IN
102+
);
103+
this._dbSemconvStability = semconvStabilityFromStr(
104+
'database',
105+
process.env.OTEL_SEMCONV_STABILITY_OPT_IN
106+
);
81107
}
82108

83109
protected init() {
@@ -209,22 +235,45 @@ export class TediousInstrumentation extends InstrumentationBase<TediousInstrumen
209235
return request.sqlTextOrProcedure;
210236
})(request);
211237

238+
const attributes: api.Attributes = {};
239+
if (thisPlugin._dbSemconvStability & SemconvStability.OLD) {
240+
attributes[ATTR_DB_SYSTEM] = DB_SYSTEM_VALUE_MSSQL;
241+
attributes[ATTR_DB_NAME] = databaseName;
242+
// >=4 uses `authentication` object; older versions just userName and password pair
243+
attributes[ATTR_DB_USER] =
244+
this.config?.userName ??
245+
this.config?.authentication?.options?.userName;
246+
attributes[ATTR_DB_STATEMENT] = sql;
247+
attributes[ATTR_DB_SQL_TABLE] = request.table;
248+
}
249+
if (thisPlugin._dbSemconvStability & SemconvStability.STABLE) {
250+
// The OTel spec for "db.namespace" discusses handling for connection
251+
// to MSSQL "named instances". This isn't currently supported.
252+
// https://opentelemetry.io/docs/specs/semconv/database/sql-server/#:~:text=%5B1%5D%20db%2Enamespace
253+
attributes[ATTR_DB_NAMESPACE] = databaseName;
254+
attributes[ATTR_DB_SYSTEM_NAME] =
255+
DB_SYSTEM_NAME_VALUE_MICROSOFT_SQL_SERVER;
256+
attributes[ATTR_DB_QUERY_TEXT] = sql;
257+
attributes[ATTR_DB_COLLECTION_NAME] = request.table;
258+
// See https://opentelemetry.io/docs/specs/semconv/database/sql-server/#spans
259+
// TODO(3290): can `db.response.status_code` be added?
260+
// TODO(3290): is `operation` correct for `db.operation.name`
261+
// TODO(3290): can `db.query.summary` reliably be calculated?
262+
// TODO(3290): `db.stored_procedure.name`
263+
}
264+
if (thisPlugin._netSemconvStability & SemconvStability.OLD) {
265+
attributes[ATTR_NET_PEER_NAME] = this.config?.server;
266+
attributes[ATTR_NET_PEER_PORT] = this.config?.options?.port;
267+
}
268+
if (thisPlugin._netSemconvStability & SemconvStability.STABLE) {
269+
attributes[ATTR_SERVER_ADDRESS] = this.config?.server;
270+
attributes[ATTR_SERVER_PORT] = this.config?.options?.port;
271+
}
212272
const span = thisPlugin.tracer.startSpan(
213273
getSpanName(operation, databaseName, sql, request.table),
214274
{
215275
kind: api.SpanKind.CLIENT,
216-
attributes: {
217-
[ATTR_DB_SYSTEM]: DB_SYSTEM_VALUE_MSSQL,
218-
[ATTR_DB_NAME]: databaseName,
219-
[ATTR_NET_PEER_PORT]: this.config?.options?.port,
220-
[ATTR_NET_PEER_NAME]: this.config?.server,
221-
// >=4 uses `authentication` object, older versions just userName and password pair
222-
[ATTR_DB_USER]:
223-
this.config?.userName ??
224-
this.config?.authentication?.options?.userName,
225-
[ATTR_DB_STATEMENT]: sql,
226-
[ATTR_DB_SQL_TABLE]: request.table,
227-
},
276+
attributes,
228277
}
229278
);
230279

@@ -242,6 +291,7 @@ export class TediousInstrumentation extends InstrumentationBase<TediousInstrumen
242291
code: api.SpanStatusCode.ERROR,
243292
message: err.message,
244293
});
294+
// TODO(3290): set `error.type` attribute?
245295
}
246296
span.end();
247297
});

0 commit comments

Comments
 (0)