From df341d3019899b2d9d301d0156e73bb1ed7b5c1a Mon Sep 17 00:00:00 2001 From: Siim Kallas Date: Tue, 30 Jul 2024 21:37:29 +0300 Subject: [PATCH] use explicit imports when loading instrumentations (#926) --- package-lock.json | 19 ---- package.json | 1 - src/instrumentations/index.ts | 158 ++++++++++++++++----------------- src/instrumentations/loader.ts | 34 ------- test/instrumentations.test.ts | 27 ------ 5 files changed, 77 insertions(+), 162 deletions(-) delete mode 100644 src/instrumentations/loader.ts diff --git a/package-lock.json b/package-lock.json index 57c08167..b0da215a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -96,7 +96,6 @@ "prebuildify": "^6.0.1", "prettier": "^3.3.2", "redis": "^3.1.2", - "rewire": "^7.0.0", "sequelize": "^6.32.1", "sinon": "^18.0.0", "ts-mocha": "^10.0.0", @@ -8701,15 +8700,6 @@ "node": ">=0.10.0" } }, - "node_modules/rewire": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/rewire/-/rewire-7.0.0.tgz", - "integrity": "sha512-DyyNyzwMtGYgu0Zl/ya0PR/oaunM+VuCuBxCuhYJHHaV0V+YvYa3bBGxb5OZ71vndgmp1pYY8F4YOwQo1siRGw==", - "dev": true, - "dependencies": { - "eslint": "^8.47.0" - } - }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -16500,15 +16490,6 @@ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true }, - "rewire": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/rewire/-/rewire-7.0.0.tgz", - "integrity": "sha512-DyyNyzwMtGYgu0Zl/ya0PR/oaunM+VuCuBxCuhYJHHaV0V+YvYa3bBGxb5OZ71vndgmp1pYY8F4YOwQo1siRGw==", - "dev": true, - "requires": { - "eslint": "^8.47.0" - } - }, "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", diff --git a/package.json b/package.json index 16d84b70..8dfa5c53 100644 --- a/package.json +++ b/package.json @@ -89,7 +89,6 @@ "prebuildify": "^6.0.1", "prettier": "^3.3.2", "redis": "^3.1.2", - "rewire": "^7.0.0", "sequelize": "^6.32.1", "sinon": "^18.0.0", "ts-mocha": "^10.0.0", diff --git a/src/instrumentations/index.ts b/src/instrumentations/index.ts index 7068da1f..35357c06 100644 --- a/src/instrumentations/index.ts +++ b/src/instrumentations/index.ts @@ -14,195 +14,194 @@ * limitations under the License. */ -import { load } from './loader'; import { getEnvBoolean } from '../utils'; import type { EnvVarKey } from '../types'; +import { AmqplibInstrumentation } from '@opentelemetry/instrumentation-amqplib'; +import { AwsInstrumentation } from '@opentelemetry/instrumentation-aws-sdk'; +import { BunyanInstrumentation } from '@opentelemetry/instrumentation-bunyan'; +import { CassandraDriverInstrumentation } from '@opentelemetry/instrumentation-cassandra-driver'; +import { ConnectInstrumentation } from '@opentelemetry/instrumentation-connect'; +import { DataloaderInstrumentation } from '@opentelemetry/instrumentation-dataloader'; +import { DnsInstrumentation } from '@opentelemetry/instrumentation-dns'; +import { ExpressInstrumentation } from '@opentelemetry/instrumentation-express'; +import { FastifyInstrumentation } from '@opentelemetry/instrumentation-fastify'; +import { GenericPoolInstrumentation } from '@opentelemetry/instrumentation-generic-pool'; +import { GraphQLInstrumentation } from '@opentelemetry/instrumentation-graphql'; +import { GrpcInstrumentation } from '@opentelemetry/instrumentation-grpc'; +import { HapiInstrumentation } from '@opentelemetry/instrumentation-hapi'; +import { HttpInstrumentation } from '@opentelemetry/instrumentation-http'; +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 { MemcachedInstrumentation } from '@opentelemetry/instrumentation-memcached'; +import { MongoDBInstrumentation } from '@opentelemetry/instrumentation-mongodb'; +import { MongooseInstrumentation } from '@opentelemetry/instrumentation-mongoose'; +import { MySQLInstrumentation } from '@opentelemetry/instrumentation-mysql'; +import { MySQL2Instrumentation } from '@opentelemetry/instrumentation-mysql2'; +import { NestInstrumentation } from '@opentelemetry/instrumentation-nestjs-core'; +import { NetInstrumentation } from '@opentelemetry/instrumentation-net'; +import { PgInstrumentation } from '@opentelemetry/instrumentation-pg'; +import { PinoInstrumentation } from '@opentelemetry/instrumentation-pino'; +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 { 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 type { Instrumentation } from '@opentelemetry/instrumentation'; type InstrumentationInfo = { - module: string; - name: string; shortName: string; + create: () => Instrumentation; }; export const bundledInstrumentations: InstrumentationInfo[] = [ { - module: '@opentelemetry/instrumentation-amqplib', - name: 'AmqplibInstrumentation', + create: () => new AmqplibInstrumentation(), shortName: 'amqplib', }, { - module: '@opentelemetry/instrumentation-aws-sdk', - name: 'AwsInstrumentation', + create: () => new AwsInstrumentation(), shortName: 'aws_sdk', }, { - module: '@opentelemetry/instrumentation-bunyan', - name: 'BunyanInstrumentation', + create: () => new BunyanInstrumentation(), shortName: 'bunyan', }, { - module: '@opentelemetry/instrumentation-cassandra-driver', - name: 'CassandraDriverInstrumentation', + create: () => new CassandraDriverInstrumentation(), shortName: 'cassandra_driver', }, { - module: '@opentelemetry/instrumentation-connect', - name: 'ConnectInstrumentation', + create: () => new ConnectInstrumentation(), shortName: 'connect', }, { - module: '@opentelemetry/instrumentation-dataloader', - name: 'DataloaderInstrumentation', + create: () => new DataloaderInstrumentation(), shortName: 'dataloader', }, { - module: '@opentelemetry/instrumentation-dns', - name: 'DnsInstrumentation', + create: () => new DnsInstrumentation(), shortName: 'dns', }, { - module: '@opentelemetry/instrumentation-express', - name: 'ExpressInstrumentation', + create: () => new ExpressInstrumentation(), shortName: 'express', }, { - module: '@opentelemetry/instrumentation-fastify', - name: 'FastifyInstrumentation', + create: () => new FastifyInstrumentation(), shortName: 'fastify', }, { - module: '@opentelemetry/instrumentation-generic-pool', - name: 'GenericPoolInstrumentation', + create: () => new GenericPoolInstrumentation(), shortName: 'generic_pool', }, { - module: '@opentelemetry/instrumentation-graphql', - name: 'GraphQLInstrumentation', + create: () => new GraphQLInstrumentation(), shortName: 'graphql', }, { - module: '@opentelemetry/instrumentation-grpc', - name: 'GrpcInstrumentation', + create: () => new GrpcInstrumentation(), shortName: 'grpc', }, { - module: '@opentelemetry/instrumentation-hapi', - name: 'HapiInstrumentation', + create: () => new HapiInstrumentation(), shortName: 'hapi', }, { - module: '@opentelemetry/instrumentation-http', - name: 'HttpInstrumentation', + create: () => new HttpInstrumentation(), shortName: 'http', }, { - module: '@opentelemetry/instrumentation-ioredis', - name: 'IORedisInstrumentation', + create: () => new IORedisInstrumentation(), shortName: 'ioredis', }, { - module: '@opentelemetry/instrumentation-kafkajs', - name: 'KafkaJsInstrumentation', + create: () => new KafkaJsInstrumentation(), shortName: 'kafkajs', }, { - module: '@opentelemetry/instrumentation-knex', - name: 'KnexInstrumentation', + create: () => new KnexInstrumentation(), shortName: 'knex', }, { - module: '@opentelemetry/instrumentation-koa', - name: 'KoaInstrumentation', + create: () => new KoaInstrumentation(), shortName: 'koa', }, { - module: '@opentelemetry/instrumentation-memcached', - name: 'MemcachedInstrumentation', + create: () => new MemcachedInstrumentation(), shortName: 'memcached', }, { - module: '@opentelemetry/instrumentation-mongodb', - name: 'MongoDBInstrumentation', + create: () => new MongoDBInstrumentation(), shortName: 'mongodb', }, { - module: '@opentelemetry/instrumentation-mongoose', - name: 'MongooseInstrumentation', + create: () => new MongooseInstrumentation(), shortName: 'mongoose', }, { - module: '@opentelemetry/instrumentation-mysql', - name: 'MySQLInstrumentation', + create: () => new MySQLInstrumentation(), shortName: 'mysql', }, { - module: '@opentelemetry/instrumentation-mysql2', - name: 'MySQL2Instrumentation', + create: () => new MySQL2Instrumentation(), shortName: 'mysql2', }, { - module: '@opentelemetry/instrumentation-nestjs-core', - name: 'NestInstrumentation', + create: () => new NestInstrumentation(), shortName: 'nestjs_core', }, { - module: '@opentelemetry/instrumentation-net', - name: 'NetInstrumentation', + create: () => new NetInstrumentation(), shortName: 'net', }, { - module: '@opentelemetry/instrumentation-pg', - name: 'PgInstrumentation', + create: () => new PgInstrumentation(), shortName: 'pg', }, { - module: '@opentelemetry/instrumentation-pino', - name: 'PinoInstrumentation', + create: () => new PinoInstrumentation(), shortName: 'pino', }, { - module: '@opentelemetry/instrumentation-redis', - name: 'RedisInstrumentation', + create: () => new RedisInstrumentation(), shortName: 'redis', }, { - module: '@opentelemetry/instrumentation-redis-4', - name: 'RedisInstrumentation', + create: () => new Redis4Instrumentation(), shortName: 'redis_4', }, { - module: '@opentelemetry/instrumentation-restify', - name: 'RestifyInstrumentation', + create: () => new RestifyInstrumentation(), shortName: 'restify', }, { - module: '@opentelemetry/instrumentation-router', - name: 'RouterInstrumentation', + create: () => new RouterInstrumentation(), shortName: 'router', }, { - module: '@opentelemetry/instrumentation-tedious', - name: 'TediousInstrumentation', + create: () => new TediousInstrumentation(), shortName: 'tedious', }, { - module: '@opentelemetry/instrumentation-winston', - name: 'WinstonInstrumentation', + create: () => new WinstonInstrumentation(), shortName: 'winston', }, { - module: './external/elasticsearch', - name: 'ElasticsearchInstrumentation', + create: () => new ElasticsearchInstrumentation(), shortName: 'elasticsearch', }, { - module: './external/sequelize', - name: 'SequelizeInstrumentation', + create: () => new SequelizeInstrumentation(), shortName: 'sequelize', }, { - module: './external/typeorm', - name: 'TypeormInstrumentation', + create: () => new TypeormInstrumentation(), shortName: 'typeorm', }, ]; @@ -222,14 +221,11 @@ function getInstrumentationsToLoad() { } export function getInstrumentations() { - const loaded = []; + const instrumentations = []; for (const desc of getInstrumentationsToLoad()) { - const Instrumentation = load(desc.module, desc.name); - if (typeof Instrumentation === 'function') { - loaded.push(new (Instrumentation as typeof Instrumentation)()); - } + instrumentations.push(desc.create()); } - return loaded; + return instrumentations; } diff --git a/src/instrumentations/loader.ts b/src/instrumentations/loader.ts deleted file mode 100644 index 22f2221d..00000000 --- a/src/instrumentations/loader.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright Splunk Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { diag } from '@opentelemetry/api'; -import { Instrumentation } from '@opentelemetry/instrumentation'; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -type InstrumentationConstructor = { new (config?: any): Instrumentation }; - -export function load( - module: string, - instrumentation: string -): InstrumentationConstructor | null { - try { - // eslint-disable-next-line @typescript-eslint/no-var-requires - return require(module)[instrumentation]; - } catch (e) { - diag.debug('cannot find instrumentation package: ' + instrumentation); - } - return null; -} diff --git a/test/instrumentations.test.ts b/test/instrumentations.test.ts index 61de144e..ee72cd46 100644 --- a/test/instrumentations.test.ts +++ b/test/instrumentations.test.ts @@ -15,13 +15,11 @@ */ import * as assert from 'assert'; -import * as rewire from 'rewire'; import { bundledInstrumentations, getInstrumentations, } from '../src/instrumentations'; -import * as loader from '../src/instrumentations/loader'; import { cleanEnvironment } from './utils'; import { Instrumentation } from '@opentelemetry/instrumentation'; @@ -35,31 +33,6 @@ describe('instrumentations', () => { assert.equal(loadedInstrumentations.length, 36); }); - it('loader silently fails when instrumentation is not installed', () => { - const loader = require('../src/instrumentations/loader'); - const result = loader.load( - '@opentelemetry/instrumentation-fs', - 'FsInstrumentation' - ); - assert.strictEqual(result, null); - }); - - it('loader imports and returns object when package is available', () => { - const HttpInstrumentation = function () {}; - const loader = rewire('../src/instrumentations/loader'); - const revert = loader.__set__('require', (module) => { - return { HttpInstrumentation }; - }); - - const got = loader.load( - '@opentelemetry/instrumentation-http', - 'HttpInstrumentation' - ); - assert.strictEqual(got, HttpInstrumentation); - - revert(); - }); - it('does not load instrumentations if OTEL_INSTRUMENTATION_COMMON_DEFAULT_ENABLED is false', () => { process.env.OTEL_INSTRUMENTATION_COMMON_DEFAULT_ENABLED = 'false'; assert.equal(getInstrumentations().length, 0);