Skip to content

Commit 9f92c8b

Browse files
authored
feat(instrumentations-ioredis): support net.* and database semconv migration (#3266)
1 parent 289e735 commit 9f92c8b

File tree

6 files changed

+259
-75
lines changed

6 files changed

+259
-75
lines changed

package-lock.json

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

packages/instrumentation-ioredis/README.md

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,17 +100,27 @@ requestHook: function (
100100

101101
## Semantic Conventions
102102

103-
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)
103+
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:
104+
105+
1. Upgrade to the latest version of this instrumentation package.
106+
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.)
107+
3. Modify alerts, dashboards, metrics, and other processes in your Observability system to use the stable semantic conventions.
108+
4. Set `OTEL_SEMCONV_STABILITY_OPT_IN=http,database` to emit only the stable semantic conventions.
109+
110+
By default, if `OTEL_SEMCONV_STABILITY_OPT_IN` includes neither of the above tokens, the old v1.7.0 semconv is used.
111+
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.
112+
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.
104113

105114
Attributes collected:
106115

107-
| Attribute | Short Description |
108-
| ---------------------- | --------------------------------------------------------------------------- |
109-
| `db.connection_string` | The connection string used to connect to the database. |
110-
| `db.statement` | The database statement being executed. |
111-
| `db.system` | An identifier for the database management system (DBMS) product being used. |
112-
| `net.peer.name` | Remote hostname or similar. |
113-
| `net.peer.port` | Remote port number. |
116+
| Old semconv | Stable semconv | Description |
117+
| ---------------------- | ---------------- | ---------------------------------- |
118+
| `db.connection_string` | Removed | |
119+
| `db.system` | `db.system.name` | 'redis' |
120+
| `db.statement` | `db.query.text` | The database query being executed. |
121+
| `net.peer.port` | `server.port` | Remote port number. |
122+
| `net.peer.name` | `server.address` | Remote hostname or similar. |
123+
114124

115125
## Useful links
116126

packages/instrumentation-ioredis/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,13 @@
5656
"@opentelemetry/contrib-test-utils": "^0.55.0",
5757
"@opentelemetry/sdk-trace-base": "^2.0.0",
5858
"@opentelemetry/sdk-trace-node": "^2.0.0",
59-
"@opentelemetry/semantic-conventions": "^1.27.0",
6059
"@types/ioredis4": "npm:@types/[email protected]",
6160
"ioredis": "5.8.2"
6261
},
6362
"dependencies": {
6463
"@opentelemetry/instrumentation": "^0.208.0",
65-
"@opentelemetry/redis-common": "^0.38.2"
64+
"@opentelemetry/redis-common": "^0.38.2",
65+
"@opentelemetry/semantic-conventions": "^1.33.0"
6666
},
6767
"homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/packages/instrumentation-ioredis#readme"
6868
}

packages/instrumentation-ioredis/src/instrumentation.ts

Lines changed: 67 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,25 @@
1414
* limitations under the License.
1515
*/
1616

17-
import { diag, trace, context, SpanKind } from '@opentelemetry/api';
17+
import { diag, trace, context, SpanKind, type Attributes } from '@opentelemetry/api';
1818
import {
1919
InstrumentationBase,
2020
InstrumentationNodeModuleDefinition,
2121
isWrapped,
22+
SemconvStability,
23+
semconvStabilityFromStr,
2224
} from '@opentelemetry/instrumentation';
2325
import { IORedisInstrumentationConfig } from './types';
2426
import { IORedisCommand, RedisInterface } from './internal-types';
27+
import {
28+
ATTR_DB_QUERY_TEXT,
29+
ATTR_DB_SYSTEM_NAME,
30+
ATTR_SERVER_ADDRESS,
31+
ATTR_SERVER_PORT,
32+
} from '@opentelemetry/semantic-conventions';
2533
import {
2634
DB_SYSTEM_VALUE_REDIS,
35+
DB_SYSTEM_NAME_VALUE_REDIS,
2736
ATTR_DB_CONNECTION_STRING,
2837
ATTR_DB_STATEMENT,
2938
ATTR_DB_SYSTEM,
@@ -41,8 +50,24 @@ const DEFAULT_CONFIG: IORedisInstrumentationConfig = {
4150
};
4251

4352
export class IORedisInstrumentation extends InstrumentationBase<IORedisInstrumentationConfig> {
53+
private _netSemconvStability!: SemconvStability;
54+
private _dbSemconvStability!: SemconvStability;
55+
4456
constructor(config: IORedisInstrumentationConfig = {}) {
4557
super(PACKAGE_NAME, PACKAGE_VERSION, { ...DEFAULT_CONFIG, ...config });
58+
this._setSemconvStabilityFromEnv();
59+
}
60+
61+
// Used for testing.
62+
private _setSemconvStabilityFromEnv() {
63+
this._netSemconvStability = semconvStabilityFromStr(
64+
'http',
65+
process.env.OTEL_SEMCONV_STABILITY_OPT_IN
66+
);
67+
this._dbSemconvStability = semconvStabilityFromStr(
68+
'database',
69+
process.env.OTEL_SEMCONV_STABILITY_OPT_IN
70+
);
4671
}
4772

4873
override setConfig(config: IORedisInstrumentationConfig = {}) {
@@ -120,12 +145,29 @@ export class IORedisInstrumentation extends InstrumentationBase<IORedisInstrumen
120145
return original.apply(this, arguments);
121146
}
122147

148+
const attributes: Attributes = {};
149+
const { host, port } = this.options;
150+
const dbQueryText = dbStatementSerializer(cmd.name, cmd.args);
151+
if (instrumentation._dbSemconvStability & SemconvStability.OLD) {
152+
attributes[ATTR_DB_SYSTEM] = DB_SYSTEM_VALUE_REDIS;
153+
attributes[ATTR_DB_STATEMENT] = dbQueryText;
154+
attributes[ATTR_DB_CONNECTION_STRING] = `redis://${host}:${port}`;
155+
}
156+
if (instrumentation._dbSemconvStability & SemconvStability.STABLE) {
157+
attributes[ATTR_DB_SYSTEM_NAME] = DB_SYSTEM_NAME_VALUE_REDIS;
158+
attributes[ATTR_DB_QUERY_TEXT] = dbQueryText;
159+
}
160+
if (instrumentation._netSemconvStability & SemconvStability.OLD) {
161+
attributes[ATTR_NET_PEER_NAME] = host;
162+
attributes[ATTR_NET_PEER_PORT] = port;
163+
}
164+
if (instrumentation._netSemconvStability & SemconvStability.STABLE) {
165+
attributes[ATTR_SERVER_ADDRESS] = host;
166+
attributes[ATTR_SERVER_PORT] = port;
167+
}
123168
const span = instrumentation.tracer.startSpan(cmd.name, {
124169
kind: SpanKind.CLIENT,
125-
attributes: {
126-
[ATTR_DB_SYSTEM]: DB_SYSTEM_VALUE_REDIS,
127-
[ATTR_DB_STATEMENT]: dbStatementSerializer(cmd.name, cmd.args),
128-
},
170+
attributes,
129171
});
130172

131173
const { requestHook } = config;
@@ -146,13 +188,6 @@ export class IORedisInstrumentation extends InstrumentationBase<IORedisInstrumen
146188
);
147189
}
148190

149-
const { host, port } = this.options;
150-
151-
span.setAttributes({
152-
[ATTR_NET_PEER_NAME]: host,
153-
[ATTR_NET_PEER_PORT]: port,
154-
[ATTR_DB_CONNECTION_STRING]: `redis://${host}:${port}`,
155-
});
156191

157192
try {
158193
const result = original.apply(this, arguments);
@@ -199,20 +234,30 @@ export class IORedisInstrumentation extends InstrumentationBase<IORedisInstrumen
199234
return original.apply(this, arguments);
200235
}
201236

237+
const attributes: Attributes = {};
238+
const { host, port } = this.options;
239+
if (instrumentation._dbSemconvStability & SemconvStability.OLD) {
240+
attributes[ATTR_DB_SYSTEM] = DB_SYSTEM_VALUE_REDIS;
241+
attributes[ATTR_DB_STATEMENT] = 'connect';
242+
attributes[ATTR_DB_CONNECTION_STRING] = `redis://${host}:${port}`;
243+
}
244+
if (instrumentation._dbSemconvStability & SemconvStability.STABLE) {
245+
attributes[ATTR_DB_SYSTEM_NAME] = DB_SYSTEM_NAME_VALUE_REDIS;
246+
attributes[ATTR_DB_QUERY_TEXT] = 'connect';
247+
}
248+
if (instrumentation._netSemconvStability & SemconvStability.OLD) {
249+
attributes[ATTR_NET_PEER_NAME] = host;
250+
attributes[ATTR_NET_PEER_PORT] = port;
251+
}
252+
if (instrumentation._netSemconvStability & SemconvStability.STABLE) {
253+
attributes[ATTR_SERVER_ADDRESS] = host;
254+
attributes[ATTR_SERVER_PORT] = port;
255+
}
202256
const span = instrumentation.tracer.startSpan('connect', {
203257
kind: SpanKind.CLIENT,
204-
attributes: {
205-
[ATTR_DB_SYSTEM]: DB_SYSTEM_VALUE_REDIS,
206-
[ATTR_DB_STATEMENT]: 'connect',
207-
},
258+
attributes,
208259
});
209-
const { host, port } = this.options;
210260

211-
span.setAttributes({
212-
[ATTR_NET_PEER_NAME]: host,
213-
[ATTR_NET_PEER_PORT]: port,
214-
[ATTR_DB_CONNECTION_STRING]: `redis://${host}:${port}`,
215-
});
216261
try {
217262
const client = original.apply(this, arguments);
218263
endSpan(span, null);

packages/instrumentation-ioredis/src/semconv.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,15 @@ export const ATTR_NET_PEER_NAME = 'net.peer.name' as const;
7474
*/
7575
export const ATTR_NET_PEER_PORT = 'net.peer.port' as const;
7676

77+
/**
78+
* Enum value "redis" for attribute {@link ATTR_DB_SYSTEM_NAME}.
79+
*
80+
* [Redis](https://redis.io/)
81+
*
82+
* @experimental This enum value is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`.
83+
*/
84+
export const DB_SYSTEM_NAME_VALUE_REDIS = 'redis' as const;
85+
7786
/**
7887
* Enum value "redis" for attribute {@link ATTR_DB_SYSTEM}.
7988
*

0 commit comments

Comments
 (0)