diff --git a/package-lock.json b/package-lock.json index f5fda4f2..32cd8ba3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40,6 +40,7 @@ "@opentelemetry/instrumentation-kafkajs": "0.1.0", "@opentelemetry/instrumentation-knex": "0.37.0", "@opentelemetry/instrumentation-koa": "0.41.0", + "@opentelemetry/instrumentation-lru-memoizer": "0.39.0", "@opentelemetry/instrumentation-memcached": "0.37.0", "@opentelemetry/instrumentation-mongodb": "0.45.0", "@opentelemetry/instrumentation-mongoose": "0.39.0", @@ -53,7 +54,9 @@ "@opentelemetry/instrumentation-redis-4": "0.40.0", "@opentelemetry/instrumentation-restify": "0.39.0", "@opentelemetry/instrumentation-router": "0.38.0", + "@opentelemetry/instrumentation-socket.io": "0.41.0", "@opentelemetry/instrumentation-tedious": "0.11.0", + "@opentelemetry/instrumentation-undici": "0.4.0", "@opentelemetry/instrumentation-winston": "0.38.0", "@opentelemetry/propagator-b3": "1.25.1", "@opentelemetry/resources": "1.25.1", @@ -2532,6 +2535,20 @@ "@opentelemetry/api": "^1.3.0" } }, + "node_modules/@opentelemetry/instrumentation-lru-memoizer": { + "version": "0.39.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-lru-memoizer/-/instrumentation-lru-memoizer-0.39.0.tgz", + "integrity": "sha512-eU1Wx1RRTR/2wYXFzH9gcpB8EPmhYlNDIUHzUXjyUE0CAXEJhBLkYNlzdaVCoQDw2neDqS+Woshiia6+emWK9A==", + "dependencies": { + "@opentelemetry/instrumentation": "^0.52.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, "node_modules/@opentelemetry/instrumentation-memcached": { "version": "0.37.0", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-memcached/-/instrumentation-memcached-0.37.0.tgz", @@ -2737,6 +2754,21 @@ "@opentelemetry/api": "^1.3.0" } }, + "node_modules/@opentelemetry/instrumentation-socket.io": { + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-socket.io/-/instrumentation-socket.io-0.41.0.tgz", + "integrity": "sha512-7fzDe9/FpO6NFizC/wnzXXX7bF9oRchsD//wFqy5g5hVEgXZCQ70IhxjrKdBvgjyIejR9T9zTvfQ6PfVKfkCAw==", + "dependencies": { + "@opentelemetry/instrumentation": "^0.52.0", + "@opentelemetry/semantic-conventions": "^1.22.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, "node_modules/@opentelemetry/instrumentation-tedious": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.11.0.tgz", @@ -2753,6 +2785,21 @@ "@opentelemetry/api": "^1.3.0" } }, + "node_modules/@opentelemetry/instrumentation-undici": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.4.0.tgz", + "integrity": "sha512-UdMQBpz11SqtWlmDnk5SoqF5QDom4VmW8SVDt9Q2xuMWVh8lc0kVROfoo2pl7zU6H6gFR8eudb3eFXIdrFn0ew==", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.52.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.7.0" + } + }, "node_modules/@opentelemetry/instrumentation-winston": { "version": "0.38.0", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-winston/-/instrumentation-winston-0.38.0.tgz", @@ -11907,6 +11954,14 @@ "@types/koa__router": "12.0.3" } }, + "@opentelemetry/instrumentation-lru-memoizer": { + "version": "0.39.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-lru-memoizer/-/instrumentation-lru-memoizer-0.39.0.tgz", + "integrity": "sha512-eU1Wx1RRTR/2wYXFzH9gcpB8EPmhYlNDIUHzUXjyUE0CAXEJhBLkYNlzdaVCoQDw2neDqS+Woshiia6+emWK9A==", + "requires": { + "@opentelemetry/instrumentation": "^0.52.0" + } + }, "@opentelemetry/instrumentation-memcached": { "version": "0.37.0", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-memcached/-/instrumentation-memcached-0.37.0.tgz", @@ -12034,6 +12089,15 @@ "@opentelemetry/semantic-conventions": "^1.22.0" } }, + "@opentelemetry/instrumentation-socket.io": { + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-socket.io/-/instrumentation-socket.io-0.41.0.tgz", + "integrity": "sha512-7fzDe9/FpO6NFizC/wnzXXX7bF9oRchsD//wFqy5g5hVEgXZCQ70IhxjrKdBvgjyIejR9T9zTvfQ6PfVKfkCAw==", + "requires": { + "@opentelemetry/instrumentation": "^0.52.0", + "@opentelemetry/semantic-conventions": "^1.22.0" + } + }, "@opentelemetry/instrumentation-tedious": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.11.0.tgz", @@ -12044,6 +12108,15 @@ "@types/tedious": "^4.0.10" } }, + "@opentelemetry/instrumentation-undici": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.4.0.tgz", + "integrity": "sha512-UdMQBpz11SqtWlmDnk5SoqF5QDom4VmW8SVDt9Q2xuMWVh8lc0kVROfoo2pl7zU6H6gFR8eudb3eFXIdrFn0ew==", + "requires": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.52.0" + } + }, "@opentelemetry/instrumentation-winston": { "version": "0.38.0", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-winston/-/instrumentation-winston-0.38.0.tgz", diff --git a/package.json b/package.json index 8074c840..8b5f20e7 100644 --- a/package.json +++ b/package.json @@ -128,6 +128,7 @@ "@opentelemetry/instrumentation-kafkajs": "0.1.0", "@opentelemetry/instrumentation-knex": "0.37.0", "@opentelemetry/instrumentation-koa": "0.41.0", + "@opentelemetry/instrumentation-lru-memoizer": "0.39.0", "@opentelemetry/instrumentation-memcached": "0.37.0", "@opentelemetry/instrumentation-mongodb": "0.45.0", "@opentelemetry/instrumentation-mongoose": "0.39.0", @@ -141,7 +142,9 @@ "@opentelemetry/instrumentation-redis-4": "0.40.0", "@opentelemetry/instrumentation-restify": "0.39.0", "@opentelemetry/instrumentation-router": "0.38.0", + "@opentelemetry/instrumentation-socket.io": "0.41.0", "@opentelemetry/instrumentation-tedious": "0.11.0", + "@opentelemetry/instrumentation-undici": "0.4.0", "@opentelemetry/instrumentation-winston": "0.38.0", "@opentelemetry/propagator-b3": "1.25.1", "@opentelemetry/resources": "1.25.1", diff --git a/scripts/generate-metadata-yaml.js b/scripts/generate-metadata-yaml.js index 4d2d802a..cf4fd15f 100644 --- a/scripts/generate-metadata-yaml.js +++ b/scripts/generate-metadata-yaml.js @@ -16,7 +16,10 @@ const KNOWN_TARGET_LIBRARY_VERSIONS = new Map([ ["@opentelemetry/instrumentation-grpc", ["1.x"]], ["@opentelemetry/instrumentation-aws-sdk", ["2.x", "3.x"]], ["@opentelemetry/instrumentation-redis", ["^2.6.0", "3.x"]], - ["@opentelemetry/instrumentation-redis-4", ["4.x"]] + ["@opentelemetry/instrumentation-redis-4", ["4.x"]], + ["@opentelemetry/instrumentation-lru-memoizer", [">=1.3 <3"]], + ["@opentelemetry/instrumentation-socket.io", [">=2 <5"]], + ["@opentelemetry/instrumentation-undici", [">=5.12.0"]], ]); const INSTRUMENTATIONS = [ @@ -38,6 +41,7 @@ const INSTRUMENTATIONS = [ { name: "@opentelemetry/instrumentation-kafkajs", target: "kafkajs", }, { name: "@opentelemetry/instrumentation-knex", target: "knex", }, { name: "@opentelemetry/instrumentation-koa", target: "koa", }, + { name: "@opentelemetry/instrumentation-lru-memoizer", target: "lru-memoizer", }, { name: "@opentelemetry/instrumentation-memcached", target: "memcached", }, { name: "@opentelemetry/instrumentation-mongodb", target: "mongodb", }, { name: "@opentelemetry/instrumentation-mongoose", target: "mongoose", }, @@ -51,7 +55,9 @@ const INSTRUMENTATIONS = [ { name: "@opentelemetry/instrumentation-redis-4", target: "redis", }, { name: "@opentelemetry/instrumentation-restify", target: "restify", }, { name: "@opentelemetry/instrumentation-router", target: "router", }, + { name: "@opentelemetry/instrumentation-socket.io", target: "socket.io", }, { name: "@opentelemetry/instrumentation-tedious", target: "tedious", }, + { name: "@opentelemetry/instrumentation-undici", target: "undici", }, { name: "@opentelemetry/instrumentation-winston", target: "winston", }, { name: "splunk-opentelemetry-instrumentation-elasticsearch", target: "@elastic/elasticsearch", support: "supported", }, { name: "splunk-opentelemetry-instrumentation-sequelize", target: "sequelize", support: "supported", }, diff --git a/src/instrumentations/http.ts b/src/instrumentations/http.ts index df3d231b..855f7337 100644 --- a/src/instrumentations/http.ts +++ b/src/instrumentations/http.ts @@ -17,9 +17,9 @@ import { Options, CaptureHttpUriParameters } from '../tracing/options'; import { IncomingMessage, ServerResponse } from 'http'; import { - HttpInstrumentationConfig, HttpResponseCustomAttributeFunction, HttpRequestCustomAttributeFunction, + HttpInstrumentation, } from '@opentelemetry/instrumentation-http'; import { diag, isSpanContextValid, TraceFlags } from '@opentelemetry/api'; import { Span } from '@opentelemetry/api'; @@ -115,18 +115,26 @@ function createHttpRequestHook( } export function configureHttpInstrumentation( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - instrumentation: any, + instrumentation: HttpInstrumentation, options: Options ) { - if (!options.serverTimingEnabled) { - return; + const config = instrumentation.getConfig(); + + if (shouldAddRequestHook(options)) { + const requestHook = createHttpRequestHook(options); + if (config.requestHook === undefined) { + config.requestHook = requestHook; + } else { + const original = config.requestHook; + config.requestHook = function (this: unknown, span, request) { + requestHook(span, request); + original.call(this, span, request); + }; + } } - if ( - typeof instrumentation['setConfig'] !== 'function' || - typeof instrumentation['getConfig'] !== 'function' - ) { + if (!options.serverTimingEnabled) { + instrumentation.setConfig(config); return; } @@ -156,12 +164,6 @@ export function configureHttpInstrumentation( ); }; - let config = instrumentation.getConfig() as HttpInstrumentationConfig; - - if (config === undefined) { - config = {}; - } - if (config.responseHook === undefined) { config.responseHook = responseHook; } else { @@ -172,22 +174,8 @@ export function configureHttpInstrumentation( }; } - if (shouldAddRequestHook(options)) { - const requestHook = createHttpRequestHook(options); - if (config.requestHook === undefined) { - config.requestHook = requestHook; - } else { - const original = config.requestHook; - config.requestHook = function (this: unknown, span, request) { - requestHook(span, request); - original.call(this, span, request); - }; - } - } - instrumentation.setConfig(config); } - function appendHeader(response: ServerResponse, header: string, value: string) { const existing = response.getHeader(header); diff --git a/src/instrumentations/index.ts b/src/instrumentations/index.ts index 35357c06..1648f00c 100644 --- a/src/instrumentations/index.ts +++ b/src/instrumentations/index.ts @@ -34,6 +34,7 @@ import { IORedisInstrumentation } from '@opentelemetry/instrumentation-ioredis'; import { KafkaJsInstrumentation } from '@opentelemetry/instrumentation-kafkajs'; import { KnexInstrumentation } from '@opentelemetry/instrumentation-knex'; import { KoaInstrumentation } from '@opentelemetry/instrumentation-koa'; +import { LruMemoizerInstrumentation } from '@opentelemetry/instrumentation-lru-memoizer'; import { MemcachedInstrumentation } from '@opentelemetry/instrumentation-memcached'; import { MongoDBInstrumentation } from '@opentelemetry/instrumentation-mongodb'; import { MongooseInstrumentation } from '@opentelemetry/instrumentation-mongoose'; @@ -47,11 +48,13 @@ import { RedisInstrumentation } from '@opentelemetry/instrumentation-redis'; import { RedisInstrumentation as Redis4Instrumentation } from '@opentelemetry/instrumentation-redis-4'; import { RestifyInstrumentation } from '@opentelemetry/instrumentation-restify'; import { RouterInstrumentation } from '@opentelemetry/instrumentation-router'; +import { SocketIoInstrumentation } from '@opentelemetry/instrumentation-socket.io'; import { TediousInstrumentation } from '@opentelemetry/instrumentation-tedious'; import { WinstonInstrumentation } from '@opentelemetry/instrumentation-winston'; import { ElasticsearchInstrumentation } from './external/elasticsearch'; import { SequelizeInstrumentation } from './external/sequelize'; import { TypeormInstrumentation } from './external/typeorm'; +import { UndiciInstrumentation } from '@opentelemetry/instrumentation-undici'; import type { Instrumentation } from '@opentelemetry/instrumentation'; type InstrumentationInfo = { @@ -132,6 +135,10 @@ export const bundledInstrumentations: InstrumentationInfo[] = [ create: () => new KoaInstrumentation(), shortName: 'koa', }, + { + create: () => new LruMemoizerInstrumentation(), + shortName: 'lru_memoizer', + }, { create: () => new MemcachedInstrumentation(), shortName: 'memcached', @@ -184,6 +191,10 @@ export const bundledInstrumentations: InstrumentationInfo[] = [ create: () => new RouterInstrumentation(), shortName: 'router', }, + { + create: () => new SocketIoInstrumentation(), + shortName: 'socketio', + }, { create: () => new TediousInstrumentation(), shortName: 'tedious', @@ -204,6 +215,10 @@ export const bundledInstrumentations: InstrumentationInfo[] = [ create: () => new TypeormInstrumentation(), shortName: 'typeorm', }, + { + create: () => new UndiciInstrumentation(), + shortName: 'undici', + }, ]; function envKey(info: InstrumentationInfo) { diff --git a/src/tracing/index.ts b/src/tracing/index.ts index 8c3b0f50..d0d4ef52 100644 --- a/src/tracing/index.ts +++ b/src/tracing/index.ts @@ -49,6 +49,7 @@ import { parseEnvBooleanString, } from '../utils'; import { isProfilingContextManagerSet } from '../profiling'; +import { HttpInstrumentation } from '@opentelemetry/instrumentation-http'; /** * We disallow calling `startTracing` twice because: @@ -224,7 +225,7 @@ function configureInstrumentations(options: Options) { configureGraphQlInstrumentation(instr, options); break; case '@opentelemetry/instrumentation-http': - configureHttpInstrumentation(instr, options); + configureHttpInstrumentation(instr as HttpInstrumentation, options); break; case '@opentelemetry/instrumentation-redis': configureRedisInstrumentation(instr, options); diff --git a/test/instrumentations.test.ts b/test/instrumentations.test.ts index ee72cd46..fbf11fc4 100644 --- a/test/instrumentations.test.ts +++ b/test/instrumentations.test.ts @@ -30,7 +30,7 @@ describe('instrumentations', () => { it('loads instrumentations if they are installed', () => { const loadedInstrumentations = getInstrumentations(); - assert.equal(loadedInstrumentations.length, 36); + assert.equal(loadedInstrumentations.length, 39); }); it('does not load instrumentations if OTEL_INSTRUMENTATION_COMMON_DEFAULT_ENABLED is false', () => { @@ -47,10 +47,14 @@ describe('instrumentations', () => { const instrumentations = getInstrumentations(); assert.equal(instrumentations.length, 1); const instrumentation: Instrumentation = instrumentations[0]; + // Dots in the instrumentation name are removed in the short name, e.g. socket.io -> socketio + const instrumentationName = instrumentation.instrumentationName.replace( + '.', + '' + ); assert( - instrumentation.instrumentationName.includes( - bundled.shortName.replace('_', '-') - ) + instrumentationName.includes(bundled.shortName.replace('_', '-')), + instrumentation.instrumentationName ); cleanEnvironment(); } @@ -74,6 +78,6 @@ describe('instrumentations', () => { ), undefined ); - assert.equal(loadedInstrumentations.length, 35); + assert.equal(loadedInstrumentations.length, 38); }); });