Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 20 additions & 10 deletions packages/instrumentation-tedious/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,29 @@ registerInstrumentations({

## 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)
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:

1. Upgrade to the latest version of this instrumentation package.
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.)
3. Modify alerts, dashboards, metrics, and other processes in your Observability system to use the stable semantic conventions.
4. Set `OTEL_SEMCONV_STABILITY_OPT_IN=http,database` to emit only the stable semantic conventions.

By default, if `OTEL_SEMCONV_STABILITY_OPT_IN` includes neither of the above tokens, the old v1.7.0 semconv is used.
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.
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.

Attributes collected:

| Attribute | Short Description |
| ----------------------- | ------------------------------------------------------------------------------ |
| `db.name` | This attribute is used to report the name of the database being accessed. |
| `db.sql.table` | The name of the primary table that the operation is acting upon. |
| `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. |
| Old semconv | Stable semconv | Description |
| --------------- | -------------------- | ---------------------------------- |
| `db.system` | `db.system.name` | 'mssql' (old), 'microsoft.sql_server' (stable) |
| `db.statement` | `db.query.text` | The database query being executed. |
| `db.user` | Removed | Username for accessing the database. |
| `db.name` | Removed | Integrated into new `db.namespace`. |
| (not included) | `db.namespace` | The database associated with the connection, qualified by the instance name. |
| `db.sql.table` | `db.collection.name` | The name of a collection (table, container) within the database. |
| `net.peer.name` | `server.address` | Remote hostname or similar. |
| `net.peer.port` | `server.port` | Remote port number. |

### Trace Context Propagation

Expand Down
1 change: 1 addition & 0 deletions packages/instrumentation-tedious/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
},
"dependencies": {
"@opentelemetry/instrumentation": "^0.208.0",
"@opentelemetry/semantic-conventions": "^1.33.0",
"@types/tedious": "^4.0.14"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/packages/instrumentation-tedious#readme"
Expand Down
74 changes: 62 additions & 12 deletions packages/instrumentation-tedious/src/instrumentation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,18 @@ import {
InstrumentationBase,
InstrumentationNodeModuleDefinition,
isWrapped,
SemconvStability,
semconvStabilityFromStr,
} from '@opentelemetry/instrumentation';
import {
ATTR_DB_COLLECTION_NAME,
ATTR_DB_NAMESPACE,
ATTR_DB_QUERY_TEXT,
ATTR_DB_SYSTEM_NAME,
ATTR_SERVER_ADDRESS,
ATTR_SERVER_PORT,
DB_SYSTEM_NAME_VALUE_MICROSOFT_SQL_SERVER,
} from '@opentelemetry/semantic-conventions';
import {
DB_SYSTEM_VALUE_MSSQL,
ATTR_DB_NAME,
Expand Down Expand Up @@ -75,9 +86,24 @@ function setDatabase(this: ApproxConnection, databaseName: string) {

export class TediousInstrumentation extends InstrumentationBase<TediousInstrumentationConfig> {
static readonly COMPONENT = 'tedious';
private _netSemconvStability!: SemconvStability;
private _dbSemconvStability!: SemconvStability;

constructor(config: TediousInstrumentationConfig = {}) {
super(PACKAGE_NAME, PACKAGE_VERSION, config);
this._setSemconvStabilityFromEnv();
}

// Used for testing.
private _setSemconvStabilityFromEnv() {
this._netSemconvStability = semconvStabilityFromStr(
'http',
process.env.OTEL_SEMCONV_STABILITY_OPT_IN
);
this._dbSemconvStability = semconvStabilityFromStr(
'database',
process.env.OTEL_SEMCONV_STABILITY_OPT_IN
);
}

protected init() {
Expand Down Expand Up @@ -209,22 +235,45 @@ export class TediousInstrumentation extends InstrumentationBase<TediousInstrumen
return request.sqlTextOrProcedure;
})(request);

const attributes: api.Attributes = {};
if (thisPlugin._dbSemconvStability & SemconvStability.OLD) {
attributes[ATTR_DB_SYSTEM] = DB_SYSTEM_VALUE_MSSQL;
attributes[ATTR_DB_NAME] = databaseName;
// >=4 uses `authentication` object; older versions just userName and password pair
attributes[ATTR_DB_USER] =
this.config?.userName ??
this.config?.authentication?.options?.userName;
attributes[ATTR_DB_STATEMENT] = sql;
attributes[ATTR_DB_SQL_TABLE] = request.table;
}
if (thisPlugin._dbSemconvStability & SemconvStability.STABLE) {
// The OTel spec for "db.namespace" discusses handling for connection
// to MSSQL "named instances". This isn't currently supported.
// https://opentelemetry.io/docs/specs/semconv/database/sql-server/#:~:text=%5B1%5D%20db%2Enamespace
attributes[ATTR_DB_NAMESPACE] = databaseName;
attributes[ATTR_DB_SYSTEM_NAME] =
DB_SYSTEM_NAME_VALUE_MICROSOFT_SQL_SERVER;
attributes[ATTR_DB_QUERY_TEXT] = sql;
attributes[ATTR_DB_COLLECTION_NAME] = request.table;
// See https://opentelemetry.io/docs/specs/semconv/database/sql-server/#spans
// TODO: can `db.response.status_code` be added?
// TODO: is `operation` correct for `db.operation.name`
// TODO: can `db.query.summary` reliably be calculated?
// TODO: `db.stored_procedure.name`
}
if (thisPlugin._netSemconvStability & SemconvStability.OLD) {
attributes[ATTR_NET_PEER_NAME] = this.config?.server;
attributes[ATTR_NET_PEER_PORT] = this.config?.options?.port;
}
if (thisPlugin._netSemconvStability & SemconvStability.STABLE) {
attributes[ATTR_SERVER_ADDRESS] = this.config?.server;
attributes[ATTR_SERVER_PORT] = this.config?.options?.port;
}
const span = thisPlugin.tracer.startSpan(
getSpanName(operation, databaseName, sql, request.table),
{
kind: api.SpanKind.CLIENT,
attributes: {
[ATTR_DB_SYSTEM]: DB_SYSTEM_VALUE_MSSQL,
[ATTR_DB_NAME]: databaseName,
[ATTR_NET_PEER_PORT]: this.config?.options?.port,
[ATTR_NET_PEER_NAME]: this.config?.server,
// >=4 uses `authentication` object, older versions just userName and password pair
[ATTR_DB_USER]:
this.config?.userName ??
this.config?.authentication?.options?.userName,
[ATTR_DB_STATEMENT]: sql,
[ATTR_DB_SQL_TABLE]: request.table,
},
attributes,
}
);

Expand All @@ -242,6 +291,7 @@ export class TediousInstrumentation extends InstrumentationBase<TediousInstrumen
code: api.SpanStatusCode.ERROR,
message: err.message,
});
// TODO: set `error.type` attribute?
}
span.end();
});
Expand Down
Loading
Loading