From a00f390977a3091b068cf1485e7596b4133ea5d8 Mon Sep 17 00:00:00 2001 From: Rauno Viskus Date: Fri, 30 Sep 2022 14:32:24 +0300 Subject: [PATCH 1/4] feat: add new instrumentations into `auto-instrumentations-node` (#981) * feat: add new instrumentations into auto-instrumentations-node * test: test to make sure all installed instrumentations are added * fix: register the added instrumentations * test: remove the redundant test * fix: add fs instrumentation back I missed during conflict resolution * fix: add config argument to RouterInstrumentation * style: lint it --- .../auto-instrumentations-node/package.json | 3 ++ .../auto-instrumentations-node/src/utils.ts | 7 +++ .../test/utils.test.ts | 54 ++++--------------- .../src/instrumentation.ts | 9 +++- 4 files changed, 28 insertions(+), 45 deletions(-) diff --git a/metapackages/auto-instrumentations-node/package.json b/metapackages/auto-instrumentations-node/package.json index 112ac785ac..443e3badc9 100644 --- a/metapackages/auto-instrumentations-node/package.json +++ b/metapackages/auto-instrumentations-node/package.json @@ -56,6 +56,7 @@ "@opentelemetry/instrumentation-dataloader": "^0.2.0", "@opentelemetry/instrumentation-dns": "^0.30.0", "@opentelemetry/instrumentation-express": "^0.31.2", + "@opentelemetry/instrumentation-fs": "^0.5.0", "@opentelemetry/instrumentation-fastify": "^0.30.0", "@opentelemetry/instrumentation-generic-pool": "^0.30.0", "@opentelemetry/instrumentation-graphql": "^0.31.0", @@ -78,6 +79,8 @@ "@opentelemetry/instrumentation-redis": "^0.33.0", "@opentelemetry/instrumentation-redis-4": "^0.33.0", "@opentelemetry/instrumentation-restify": "^0.30.0", + "@opentelemetry/instrumentation-router": "^0.30.0", + "@opentelemetry/instrumentation-tedious": "^0.4.0", "@opentelemetry/instrumentation-winston": "^0.30.0" } } diff --git a/metapackages/auto-instrumentations-node/src/utils.ts b/metapackages/auto-instrumentations-node/src/utils.ts index 826dd30221..2daba2146d 100644 --- a/metapackages/auto-instrumentations-node/src/utils.ts +++ b/metapackages/auto-instrumentations-node/src/utils.ts @@ -16,6 +16,7 @@ import { diag } from '@opentelemetry/api'; import { Instrumentation } from '@opentelemetry/instrumentation'; + import { AmqplibInstrumentation } from '@opentelemetry/instrumentation-amqplib'; import { AwsLambdaInstrumentation } from '@opentelemetry/instrumentation-aws-lambda'; import { AwsInstrumentation } from '@opentelemetry/instrumentation-aws-sdk'; @@ -26,6 +27,7 @@ import { DataloaderInstrumentation } from '@opentelemetry/instrumentation-datalo import { DnsInstrumentation } from '@opentelemetry/instrumentation-dns'; import { ExpressInstrumentation } from '@opentelemetry/instrumentation-express'; import { FastifyInstrumentation } from '@opentelemetry/instrumentation-fastify'; +import { FsInstrumentation } from '@opentelemetry/instrumentation-fs'; import { GenericPoolInstrumentation } from '@opentelemetry/instrumentation-generic-pool'; import { GraphQLInstrumentation } from '@opentelemetry/instrumentation-graphql'; import { GrpcInstrumentation } from '@opentelemetry/instrumentation-grpc'; @@ -47,6 +49,8 @@ import { PinoInstrumentation } from '@opentelemetry/instrumentation-pino'; import { RedisInstrumentation as RedisInstrumentationV2 } from '@opentelemetry/instrumentation-redis'; import { RedisInstrumentation as RedisInstrumentationV4 } 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'; const InstrumentationMap = { @@ -61,6 +65,7 @@ const InstrumentationMap = { '@opentelemetry/instrumentation-dns': DnsInstrumentation, '@opentelemetry/instrumentation-express': ExpressInstrumentation, '@opentelemetry/instrumentation-fastify': FastifyInstrumentation, + '@opentelemetry/instrumentation-fs': FsInstrumentation, '@opentelemetry/instrumentation-generic-pool': GenericPoolInstrumentation, '@opentelemetry/instrumentation-graphql': GraphQLInstrumentation, '@opentelemetry/instrumentation-grpc': GrpcInstrumentation, @@ -82,6 +87,8 @@ const InstrumentationMap = { '@opentelemetry/instrumentation-redis': RedisInstrumentationV2, '@opentelemetry/instrumentation-redis-4': RedisInstrumentationV4, '@opentelemetry/instrumentation-restify': RestifyInstrumentation, + '@opentelemetry/instrumentation-router': RouterInstrumentation, + '@opentelemetry/instrumentation-tedious': TediousInstrumentation, '@opentelemetry/instrumentation-winston': WinstonInstrumentation, }; diff --git a/metapackages/auto-instrumentations-node/test/utils.test.ts b/metapackages/auto-instrumentations-node/test/utils.test.ts index aaef8784ee..5707eed8f3 100644 --- a/metapackages/auto-instrumentations-node/test/utils.test.ts +++ b/metapackages/auto-instrumentations-node/test/utils.test.ts @@ -22,50 +22,18 @@ import { getNodeAutoInstrumentations } from '../src'; describe('utils', () => { describe('getNodeAutoInstrumentations', () => { - it('should load default instrumentations', () => { + it('should include all installed instrumentations', () => { const instrumentations = getNodeAutoInstrumentations(); - const expectedInstrumentations = [ - '@opentelemetry/instrumentation-amqplib', - '@opentelemetry/instrumentation-aws-lambda', - '@opentelemetry/instrumentation-aws-sdk', - '@opentelemetry/instrumentation-bunyan', - '@opentelemetry/instrumentation-cassandra-driver', - '@opentelemetry/instrumentation-connect', - '@opentelemetry/instrumentation-dataloader', - '@opentelemetry/instrumentation-dns', - '@opentelemetry/instrumentation-express', - '@opentelemetry/instrumentation-fastify', - '@opentelemetry/instrumentation-generic-pool', - '@opentelemetry/instrumentation-graphql', - '@opentelemetry/instrumentation-grpc', - '@opentelemetry/instrumentation-hapi', - '@opentelemetry/instrumentation-http', - '@opentelemetry/instrumentation-ioredis', - '@opentelemetry/instrumentation-knex', - '@opentelemetry/instrumentation-koa', - '@opentelemetry/instrumentation-lru-memoizer', - '@opentelemetry/instrumentation-memcached', - '@opentelemetry/instrumentation-mongodb', - '@opentelemetry/instrumentation-mongoose', - '@opentelemetry/instrumentation-mysql2', - '@opentelemetry/instrumentation-mysql', - '@opentelemetry/instrumentation-nestjs-core', - '@opentelemetry/instrumentation-net', - '@opentelemetry/instrumentation-pg', - '@opentelemetry/instrumentation-pino', - '@opentelemetry/instrumentation-redis', - '@opentelemetry/instrumentation-redis-4', - '@opentelemetry/instrumentation-restify', - '@opentelemetry/instrumentation-winston', - ]; - assert.strictEqual(instrumentations.length, 32); - for (let i = 0, j = instrumentations.length; i < j; i++) { - assert.strictEqual( - instrumentations[i].instrumentationName, - expectedInstrumentations[i], - `Instrumentation ${expectedInstrumentations[i]}, not loaded` - ); - } + const installedInstrumentations = Object.keys( + require('../package.json').dependencies + ).filter(depName => { + return depName.startsWith('@opentelemetry/instrumentation-'); + }); + + assert.deepStrictEqual( + new Set(instrumentations.map(i => i.instrumentationName)), + new Set(installedInstrumentations) + ); }); it('should use user config', () => { diff --git a/plugins/node/opentelemetry-instrumentation-router/src/instrumentation.ts b/plugins/node/opentelemetry-instrumentation-router/src/instrumentation.ts index 125f2e28a8..7de5eeea61 100644 --- a/plugins/node/opentelemetry-instrumentation-router/src/instrumentation.ts +++ b/plugins/node/opentelemetry-instrumentation-router/src/instrumentation.ts @@ -16,6 +16,7 @@ import * as api from '@opentelemetry/api'; import { + InstrumentationConfig, InstrumentationBase, InstrumentationNodeModuleDefinition, InstrumentationNodeModuleFile, @@ -34,8 +35,12 @@ import AttributeNames from './enums/AttributeNames'; import LayerType from './enums/LayerType'; export default class RouterInstrumentation extends InstrumentationBase { - constructor() { - super(`@opentelemetry/instrumentation-${constants.MODULE_NAME}`, VERSION); + constructor(config?: InstrumentationConfig) { + super( + `@opentelemetry/instrumentation-${constants.MODULE_NAME}`, + VERSION, + config + ); } private _moduleVersion?: string; From 60a92c7dc404255294f5e166b08425b7ca3b247b Mon Sep 17 00:00:00 2001 From: Rauno Viskus Date: Fri, 30 Sep 2022 15:22:33 +0300 Subject: [PATCH 2/4] chore: implement CI job to validate Release Please's config and manifest (#1207) --- .../workflows/release-please-validate.yaml | 22 +++++ scripts/check-release-please.mjs | 83 +++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 .github/workflows/release-please-validate.yaml create mode 100644 scripts/check-release-please.mjs diff --git a/.github/workflows/release-please-validate.yaml b/.github/workflows/release-please-validate.yaml new file mode 100644 index 0000000000..ca2e86da77 --- /dev/null +++ b/.github/workflows/release-please-validate.yaml @@ -0,0 +1,22 @@ +name: Validate Release Please Config + +on: + push: + branches: + - main + pull_request: + +jobs: + rp-validate: + runs-on: ubuntu-latest + container: + image: node:14 + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Install lerna + run: npm install -g lerna + + - name: Ensure Release Please Config and Manifest are in sync with the repository + run: node scripts/check-release-please.mjs diff --git a/scripts/check-release-please.mjs b/scripts/check-release-please.mjs new file mode 100644 index 0000000000..0496533bcc --- /dev/null +++ b/scripts/check-release-please.mjs @@ -0,0 +1,83 @@ +import { strict as assert } from 'assert'; +import * as childProcess from 'child_process'; +import path from 'path'; +import { readFileSync } from 'fs'; + +/* + Enumerates through + + - lerna packages, + - release please's manifest, and + - release please's config, and + + makes sure all those lists are in sync. If not, guides you to do the correct thing +*/ + +const errors = []; +const logErrorIf = (condition, errorMessage) => { + if (condition) { + errors.push(errorMessage); + } +}; +const PROJECT_ROOT = process.cwd(); +const readJson = (filePath) => { + return JSON.parse(readFileSync(filePath)); +}; +const getProcessOutput = (cmd, args) => { + const result = childProcess.spawnSync(cmd, args); + assert(!result.error, result.error); + return result.stdout.toString('utf8'); +} + +const lernaList = JSON.parse( + getProcessOutput('lerna', ['list', '--json']) +); +const manifest = readJson('.release-please-manifest.json'); +const config = readJson('release-please-config.json'); + +const lernaPackages = new Set( + lernaList.map((pkg) => { + return path.relative(PROJECT_ROOT, pkg.location); + }) +); +const manifestPackages = new Set(Object.keys(manifest)); +const configPackages = new Set(Object.keys(config.packages)); + +console.log('lerna packages', lernaPackages); +console.log('manifest packages', manifestPackages); +console.log('config packages', configPackages); + +lernaPackages.forEach((relativeLocation) => { + logErrorIf( + !manifestPackages.has(relativeLocation), + `Could not find ${relativeLocation} in .release-please-manifest.json. If you are adding a new package. Add following + "${relativeLocation}": "0.0.1",`); + + logErrorIf( + !configPackages.has(relativeLocation), + `Could not find ${relativeLocation} in release-please-config.json. If you are adding a new package. Add following to "packages" object + "${relativeLocation}": {},`); + +}); + +manifestPackages.forEach((relativeLocation) => { + logErrorIf( + !lernaPackages.has(relativeLocation), + `Extraneous path ${relativeLocation} in .release-please-manifest.json` + ); +}); + +configPackages.forEach((relativeLocation) => { + logErrorIf( + !lernaPackages.has(relativeLocation), + `Extraneous path ${relativeLocation} in release-please-config.json` + ); +}); + +if (errors.length) { + console.error('Errors occured:\n'); + console.error(errors.join('\n\n')); + process.exit(1); +} else { + console.error('OK'); +} From 502caae17be17e20ee81189dbf79ca25121c7cfe Mon Sep 17 00:00:00 2001 From: Abhinav Mathur Date: Sat, 1 Oct 2022 04:19:03 -0400 Subject: [PATCH 3/4] feat: container ID detector for cgroup v2 (#1181) * added another block to test for v2 * feat: changing export name to reflect generic docker * feat: adding geenric naming and logic changes to support cgroup v2 * test: test file renamed * feat: adding hostname check * feat: adding hostname check- refactor * feat: fixed a test and fixed lint * feat: added another condition to check for length * test: added two more tests * feat: renamed docker to container and addressed pr comments * feat: renamed docker to container and addressed pr comments- 2 * feat: renamed docker to container and addressed pr comments-3 * feat: addressed pr comments-2 * feat: modified tests to take in multiple lines input * feat: merge resolution for manifest * feat: fixing release please manifest * feat: changing please-config to rename docker to container * feat: replaced >= check to == check --- .release-please-manifest.json | 3 +- .../.eslintignore | 0 .../.eslintrc.js | 0 .../.npmignore | 0 .../CHANGELOG.md | 0 .../LICENSE | 0 .../README.md | 15 +- .../package.json | 8 +- .../src/detectors/ContainerDetector.ts} | 57 +++++-- .../src/detectors/index.ts | 2 +- .../src/index.ts | 0 .../test/ContainerDetector.test.ts | 140 ++++++++++++++++++ .../tsconfig.json | 0 .../test/DockerCGroupv1Detector.test.ts | 91 ------------ release-please-config.json | 2 +- 15 files changed, 197 insertions(+), 121 deletions(-) rename detectors/node/{opentelemetry-resource-detector-docker => opentelemetry-resource-detector-container}/.eslintignore (100%) rename detectors/node/{opentelemetry-resource-detector-docker => opentelemetry-resource-detector-container}/.eslintrc.js (100%) rename detectors/node/{opentelemetry-resource-detector-docker => opentelemetry-resource-detector-container}/.npmignore (100%) rename detectors/node/{opentelemetry-resource-detector-docker => opentelemetry-resource-detector-container}/CHANGELOG.md (100%) rename detectors/node/{opentelemetry-resource-detector-docker => opentelemetry-resource-detector-container}/LICENSE (100%) rename detectors/node/{opentelemetry-resource-detector-docker => opentelemetry-resource-detector-container}/README.md (70%) rename detectors/node/{opentelemetry-resource-detector-docker => opentelemetry-resource-detector-container}/package.json (88%) rename detectors/node/{opentelemetry-resource-detector-docker/src/detectors/DockerCGroupV1Detector.ts => opentelemetry-resource-detector-container/src/detectors/ContainerDetector.ts} (51%) rename detectors/node/{opentelemetry-resource-detector-docker => opentelemetry-resource-detector-container}/src/detectors/index.ts (93%) rename detectors/node/{opentelemetry-resource-detector-docker => opentelemetry-resource-detector-container}/src/index.ts (100%) create mode 100644 detectors/node/opentelemetry-resource-detector-container/test/ContainerDetector.test.ts rename detectors/node/{opentelemetry-resource-detector-docker => opentelemetry-resource-detector-container}/tsconfig.json (100%) delete mode 100644 detectors/node/opentelemetry-resource-detector-docker/test/DockerCGroupv1Detector.test.ts diff --git a/.release-please-manifest.json b/.release-please-manifest.json index b83a2c5a43..583b4986b3 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1 +1,2 @@ -{"detectors/node/opentelemetry-resource-detector-alibaba-cloud":"0.27.2","detectors/node/opentelemetry-resource-detector-aws":"1.1.2","detectors/node/opentelemetry-resource-detector-docker":"0.1.2","detectors/node/opentelemetry-resource-detector-gcp":"0.27.2","detectors/node/opentelemetry-resource-detector-github":"0.27.0","detectors/node/opentelemetry-resource-detector-instana":"0.3.0","metapackages/auto-instrumentations-node":"0.33.1","metapackages/auto-instrumentations-web":"0.30.0","packages/opentelemetry-host-metrics":"0.30.1","packages/opentelemetry-id-generator-aws-xray":"1.1.0","packages/opentelemetry-propagation-utils":"0.29.0","packages/opentelemetry-test-utils":"0.32.0","plugins/node/instrumentation-amqplib":"0.31.0","plugins/node/instrumentation-dataloader":"0.2.0","plugins/node/instrumentation-fs":"0.5.0","plugins/node/instrumentation-lru-memoizer":"0.31.0","plugins/node/instrumentation-mongoose":"0.31.0","plugins/node/instrumentation-tedious":"0.4.0","plugins/node/opentelemetry-instrumentation-aws-lambda":"0.33.0","plugins/node/opentelemetry-instrumentation-aws-sdk":"0.9.2","plugins/node/opentelemetry-instrumentation-bunyan":"0.30.0","plugins/node/opentelemetry-instrumentation-cassandra":"0.30.0","plugins/node/opentelemetry-instrumentation-connect":"0.30.0","plugins/node/opentelemetry-instrumentation-dns":"0.30.0","plugins/node/opentelemetry-instrumentation-express":"0.31.2","plugins/node/opentelemetry-instrumentation-fastify":"0.30.0","plugins/node/opentelemetry-instrumentation-generic-pool":"0.30.0","plugins/node/opentelemetry-instrumentation-graphql":"0.31.0","plugins/node/opentelemetry-instrumentation-hapi":"0.30.0","plugins/node/opentelemetry-instrumentation-ioredis":"0.32.1","plugins/node/opentelemetry-instrumentation-knex":"0.30.0","plugins/node/opentelemetry-instrumentation-koa":"0.32.0","plugins/node/opentelemetry-instrumentation-memcached":"0.30.0","plugins/node/opentelemetry-instrumentation-mongodb":"0.32.1","plugins/node/opentelemetry-instrumentation-mysql":"0.31.1","plugins/node/opentelemetry-instrumentation-mysql2":"0.32.0","plugins/node/opentelemetry-instrumentation-nestjs-core":"0.31.0","plugins/node/opentelemetry-instrumentation-net":"0.30.1","plugins/node/opentelemetry-instrumentation-pg":"0.31.1","plugins/node/opentelemetry-instrumentation-pino":"0.32.0","plugins/node/opentelemetry-instrumentation-redis":"0.33.0","plugins/node/opentelemetry-instrumentation-redis-4":"0.33.0","plugins/node/opentelemetry-instrumentation-restify":"0.30.0","plugins/node/opentelemetry-instrumentation-router":"0.30.0","plugins/node/opentelemetry-instrumentation-winston":"0.30.0","plugins/web/opentelemetry-instrumentation-document-load":"0.30.0","plugins/web/opentelemetry-instrumentation-long-task":"0.31.0","plugins/web/opentelemetry-instrumentation-user-interaction":"0.31.0","plugins/web/opentelemetry-plugin-react-load":"0.28.0","propagators/opentelemetry-propagator-aws-xray":"1.1.0","propagators/opentelemetry-propagator-grpc-census-binary":"0.26.0","propagators/opentelemetry-propagator-instana":"0.2.0","propagators/opentelemetry-propagator-ot-trace":"0.26.1"} +{"detectors/node/opentelemetry-resource-detector-alibaba-cloud":"0.27.2","detectors/node/opentelemetry-resource-detector-aws":"1.1.2","detectors/node/opentelemetry-resource-detector-container":"0.1.2","detectors/node/opentelemetry-resource-detector-gcp":"0.27.2","detectors/node/opentelemetry-resource-detector-github":"0.27.0","detectors/node/opentelemetry-resource-detector-instana":"0.3.0","metapackages/auto-instrumentations-node":"0.33.1","metapackages/auto-instrumentations-web":"0.30.0","packages/opentelemetry-host-metrics":"0.30.1","packages/opentelemetry-id-generator-aws-xray":"1.1.0","packages/opentelemetry-propagation-utils":"0.29.0","packages/opentelemetry-test-utils":"0.32.0","plugins/node/instrumentation-amqplib":"0.31.0","plugins/node/instrumentation-dataloader":"0.2.0","plugins/node/instrumentation-fs":"0.5.0","plugins/node/instrumentation-lru-memoizer":"0.31.0","plugins/node/instrumentation-mongoose":"0.31.0","plugins/node/instrumentation-tedious":"0.4.0","plugins/node/opentelemetry-instrumentation-aws-lambda":"0.33.0","plugins/node/opentelemetry-instrumentation-aws-sdk":"0.9.2","plugins/node/opentelemetry-instrumentation-bunyan":"0.30.0","plugins/node/opentelemetry-instrumentation-cassandra":"0.30.0","plugins/node/opentelemetry-instrumentation-connect":"0.30.0","plugins/node/opentelemetry-instrumentation-dns":"0.30.0","plugins/node/opentelemetry-instrumentation-express":"0.31.2","plugins/node/opentelemetry-instrumentation-fastify":"0.30.0","plugins/node/opentelemetry-instrumentation-generic-pool":"0.30.0","plugins/node/opentelemetry-instrumentation-graphql":"0.31.0","plugins/node/opentelemetry-instrumentation-hapi":"0.30.0","plugins/node/opentelemetry-instrumentation-ioredis":"0.32.1","plugins/node/opentelemetry-instrumentation-knex":"0.30.0","plugins/node/opentelemetry-instrumentation-koa":"0.32.0","plugins/node/opentelemetry-instrumentation-memcached":"0.30.0","plugins/node/opentelemetry-instrumentation-mongodb":"0.32.1","plugins/node/opentelemetry-instrumentation-mysql":"0.31.1","plugins/node/opentelemetry-instrumentation-mysql2":"0.32.0","plugins/node/opentelemetry-instrumentation-nestjs-core":"0.31.0","plugins/node/opentelemetry-instrumentation-net":"0.30.1","plugins/node/opentelemetry-instrumentation-pg":"0.31.1","plugins/node/opentelemetry-instrumentation-pino":"0.32.0","plugins/node/opentelemetry-instrumentation-redis":"0.33.0","plugins/node/opentelemetry-instrumentation-redis-4":"0.33.0","plugins/node/opentelemetry-instrumentation-restify":"0.30.0","plugins/node/opentelemetry-instrumentation-router":"0.30.0","plugins/node/opentelemetry-instrumentation-winston":"0.30.0","plugins/web/opentelemetry-instrumentation-document-load":"0.30.0","plugins/web/opentelemetry-instrumentation-long-task":"0.31.0","plugins/web/opentelemetry-instrumentation-user-interaction":"0.31.0","plugins/web/opentelemetry-plugin-react-load":"0.28.0","propagators/opentelemetry-propagator-aws-xray":"1.1.0","propagators/opentelemetry-propagator-grpc-census-binary":"0.26.0","propagators/opentelemetry-propagator-instana":"0.2.0","propagators/opentelemetry-propagator-ot-trace":"0.26.1"} + diff --git a/detectors/node/opentelemetry-resource-detector-docker/.eslintignore b/detectors/node/opentelemetry-resource-detector-container/.eslintignore similarity index 100% rename from detectors/node/opentelemetry-resource-detector-docker/.eslintignore rename to detectors/node/opentelemetry-resource-detector-container/.eslintignore diff --git a/detectors/node/opentelemetry-resource-detector-docker/.eslintrc.js b/detectors/node/opentelemetry-resource-detector-container/.eslintrc.js similarity index 100% rename from detectors/node/opentelemetry-resource-detector-docker/.eslintrc.js rename to detectors/node/opentelemetry-resource-detector-container/.eslintrc.js diff --git a/detectors/node/opentelemetry-resource-detector-docker/.npmignore b/detectors/node/opentelemetry-resource-detector-container/.npmignore similarity index 100% rename from detectors/node/opentelemetry-resource-detector-docker/.npmignore rename to detectors/node/opentelemetry-resource-detector-container/.npmignore diff --git a/detectors/node/opentelemetry-resource-detector-docker/CHANGELOG.md b/detectors/node/opentelemetry-resource-detector-container/CHANGELOG.md similarity index 100% rename from detectors/node/opentelemetry-resource-detector-docker/CHANGELOG.md rename to detectors/node/opentelemetry-resource-detector-container/CHANGELOG.md diff --git a/detectors/node/opentelemetry-resource-detector-docker/LICENSE b/detectors/node/opentelemetry-resource-detector-container/LICENSE similarity index 100% rename from detectors/node/opentelemetry-resource-detector-docker/LICENSE rename to detectors/node/opentelemetry-resource-detector-container/LICENSE diff --git a/detectors/node/opentelemetry-resource-detector-docker/README.md b/detectors/node/opentelemetry-resource-detector-container/README.md similarity index 70% rename from detectors/node/opentelemetry-resource-detector-docker/README.md rename to detectors/node/opentelemetry-resource-detector-container/README.md index 56a884cff2..9e5709b82b 100644 --- a/detectors/node/opentelemetry-resource-detector-docker/README.md +++ b/detectors/node/opentelemetry-resource-detector-container/README.md @@ -1,29 +1,26 @@ -# OpenTelemetry Resource Detector for Docker +# OpenTelemetry Resource Detector for Container [![NPM Published Version][npm-img]][npm-url] -[![dependencies][dependencies-image]][dependencies-url] -[![devDependencies][devDependencies-image]][devDependencies-url] [![Apache License][license-image]][license-image] [component owners](https://github.com/open-telemetry/opentelemetry-js-contrib/blob/main/.github/component_owners.yml): @abhee11 -Resource detector for docker. - +Resource detector for container id. Compatible with OpenTelemetry JS API and SDK `1.0+`. ## Installation ```bash -npm install --save @opentelemetry/resource-detector-docker +npm install --save @opentelemetry/resource-detector-container ``` ## Usage ```typescript import { detectResources } from '@opentelemetry/resources'; -import { dockerCGroupV1Detector } from '@opentelemetry/resource-detector-docker' +import { containerDetector } from '@opentelemetry/resource-detector-container' const resource = await detectResources({ - detectors: [dockerCGroupV1Detector], + detectors: [containerDetector], }) const tracerProvider = new NodeTracerProvider({ resource }); @@ -31,7 +28,7 @@ const tracerProvider = new NodeTracerProvider({ resource }); ## Available detectors -- `dockerCGroupV1Detector`: Populates `container.id` for processes running on docker cgroup v1 +- `containerDetector`: Populates `container.id` for processes running on contianers supporting : docker( cgroup v1 or v2 ) or with containerd ## Useful links diff --git a/detectors/node/opentelemetry-resource-detector-docker/package.json b/detectors/node/opentelemetry-resource-detector-container/package.json similarity index 88% rename from detectors/node/opentelemetry-resource-detector-docker/package.json rename to detectors/node/opentelemetry-resource-detector-container/package.json index 7dd6ea54e1..6cbfb50119 100644 --- a/detectors/node/opentelemetry-resource-detector-docker/package.json +++ b/detectors/node/opentelemetry-resource-detector-container/package.json @@ -1,7 +1,7 @@ { - "name": "@opentelemetry/resource-detector-docker", + "name": "@opentelemetry/resource-detector-container", "version": "0.1.2", - "description": "Opentelemetry resource detector to get docker resource attributes", + "description": "Opentelemetry resource detector to get container resource attributes", "main": "build/src/index.js", "types": "build/src/index.d.ts", "repository": "open-telemetry/opentelemetry-js-contrib", @@ -11,7 +11,7 @@ "compile": "npm run version:update && tsc -p .", "lint": "eslint . --ext .ts", "lint:fix": "eslint . --ext .ts --fix", - "precompile": "tsc --version && lerna run version --scope @opentelemetry/resource-detector-docker --include-dependencies", + "precompile": "tsc --version && lerna run version --scope @opentelemetry/resource-detector-container --include-dependencies", "prewatch": "npm run precompile", "prepare": "npm run compile", "test": "nyc ts-mocha -p tsconfig.json 'test/**/*.test.ts'", @@ -57,5 +57,5 @@ "@opentelemetry/resources": "^1.0.0", "@opentelemetry/semantic-conventions": "^1.0.0" }, - "homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/detectors/node/opentelemetry-resource-detector-docker#readme" + "homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/detectors/node/opentelemetry-resource-detector-container#readme" } diff --git a/detectors/node/opentelemetry-resource-detector-docker/src/detectors/DockerCGroupV1Detector.ts b/detectors/node/opentelemetry-resource-detector-container/src/detectors/ContainerDetector.ts similarity index 51% rename from detectors/node/opentelemetry-resource-detector-docker/src/detectors/DockerCGroupV1Detector.ts rename to detectors/node/opentelemetry-resource-detector-container/src/detectors/ContainerDetector.ts index 8b2ee77fa2..e318c8bd4e 100644 --- a/detectors/node/opentelemetry-resource-detector-docker/src/detectors/DockerCGroupV1Detector.ts +++ b/detectors/node/opentelemetry-resource-detector-container/src/detectors/ContainerDetector.ts @@ -25,10 +25,12 @@ import * as fs from 'fs'; import * as util from 'util'; import { diag } from '@opentelemetry/api'; -export class DockerCGroupV1Detector implements Detector { +export class ContainerDetector implements Detector { readonly CONTAINER_ID_LENGTH = 64; - readonly DEFAULT_CGROUP_PATH = '/proc/self/cgroup'; + readonly DEFAULT_CGROUP_V1_PATH = '/proc/self/cgroup'; + readonly DEFAULT_CGROUP_V2_PATH = '/proc/self/mountinfo'; readonly UTF8_UNICODE = 'utf8'; + readonly HOSTNAME = 'hostname'; private static readFileAsync = util.promisify(fs.readFile); @@ -42,30 +44,57 @@ export class DockerCGroupV1Detector implements Detector { }); } catch (e) { diag.info( - 'Docker CGROUP V1 Detector did not identify running inside a supported docker container, no docker attributes will be added to resource: ', + 'Container Detector did not identify running inside a supported container, no container attributes will be added to resource: ', e ); return Resource.empty(); } } + private async _getContainerIdV1() { + const rawData = await ContainerDetector.readFileAsync( + this.DEFAULT_CGROUP_V1_PATH, + this.UTF8_UNICODE + ); + const splitData = rawData.trim().split('\n'); + for (const str of splitData) { + if (str.length >= this.CONTAINER_ID_LENGTH) { + return str.substring(str.length - this.CONTAINER_ID_LENGTH); + } + } + return undefined; + } + + private async _getContainerIdV2() { + const rawData = await ContainerDetector.readFileAsync( + this.DEFAULT_CGROUP_V2_PATH, + this.UTF8_UNICODE + ); + const str = rawData + .trim() + .split('\n') + .find(s => s.includes(this.HOSTNAME)); + const containerIdStr = str + ?.split('/') + .find(s => s.length === this.CONTAINER_ID_LENGTH); + return containerIdStr || ''; + } + + /* + cgroupv1 path would still exist in case of container running on v2 + but the cgroupv1 path would no longer have the container id and would + fallback on the cgroupv2 implementation. + */ private async _getContainerId(): Promise { try { - const rawData = await DockerCGroupV1Detector.readFileAsync( - this.DEFAULT_CGROUP_PATH, - this.UTF8_UNICODE + return ( + (await this._getContainerIdV1()) ?? (await this._getContainerIdV2()) ); - const splitData = rawData.trim().split('\n'); - for (const str of splitData) { - if (str.length >= this.CONTAINER_ID_LENGTH) { - return str.substring(str.length - this.CONTAINER_ID_LENGTH); - } - } } catch (e) { if (e instanceof Error) { const errorMessage = e.message; diag.info( - 'Docker CGROUP V1 Detector failed to read the Container ID: ', + 'Container Detector failed to read the Container ID: ', errorMessage ); } @@ -74,4 +103,4 @@ export class DockerCGroupV1Detector implements Detector { } } -export const dockerCGroupV1Detector = new DockerCGroupV1Detector(); +export const containerDetector = new ContainerDetector(); diff --git a/detectors/node/opentelemetry-resource-detector-docker/src/detectors/index.ts b/detectors/node/opentelemetry-resource-detector-container/src/detectors/index.ts similarity index 93% rename from detectors/node/opentelemetry-resource-detector-docker/src/detectors/index.ts rename to detectors/node/opentelemetry-resource-detector-container/src/detectors/index.ts index 25aa53ab9a..edd915f6aa 100644 --- a/detectors/node/opentelemetry-resource-detector-docker/src/detectors/index.ts +++ b/detectors/node/opentelemetry-resource-detector-container/src/detectors/index.ts @@ -13,4 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export * from './DockerCGroupV1Detector'; +export * from './ContainerDetector'; diff --git a/detectors/node/opentelemetry-resource-detector-docker/src/index.ts b/detectors/node/opentelemetry-resource-detector-container/src/index.ts similarity index 100% rename from detectors/node/opentelemetry-resource-detector-docker/src/index.ts rename to detectors/node/opentelemetry-resource-detector-container/src/index.ts diff --git a/detectors/node/opentelemetry-resource-detector-container/test/ContainerDetector.test.ts b/detectors/node/opentelemetry-resource-detector-container/test/ContainerDetector.test.ts new file mode 100644 index 0000000000..e9c5c3aaf4 --- /dev/null +++ b/detectors/node/opentelemetry-resource-detector-container/test/ContainerDetector.test.ts @@ -0,0 +1,140 @@ +/* + * Copyright The OpenTelemetry Authors + * + * 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 + * + * https://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 * as sinon from 'sinon'; +import * as assert from 'assert'; +import { Resource } from '@opentelemetry/resources'; +import { containerDetector } from '../src'; +import { + assertContainerResource, + assertEmptyResource, +} from '@opentelemetry/contrib-test-utils'; + +import { ContainerDetector } from '../src'; + +describe('ContainerDetector', () => { + let readStub; + const correctCgroupV1Data = + 'bcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklm'; + const correctCgroupV2Data = `tmhdefghijklmnopqrstuvwxyzafgrefghiugkmnopqrstuvwxyzabcdefghijkl/hostname + fhkjdshgfhsdfjhdsfkjhfkdshkjhfd/host + sahfhfjkhjhfhjdhfjkdhfkjdhfjkhhdsjfhdfhjdhfkj/somethingelse`; + + const wrongCgroupV2Data = + 'bcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklm/wrongkeyword'; + + afterEach(() => { + sinon.restore(); + }); + + describe('Supported container - Container ID ', () => { + it('should return a resource attributes without container id - docker cgroup v1 detector', async () => { + readStub = sinon + .stub(ContainerDetector, 'readFileAsync' as any) + .resolves(undefined); + + const resource: Resource = await containerDetector.detect(); + + assert.deepStrictEqual(resource.attributes, {}); + assert.ok(resource); + }); + + it('should return a resource with container ID with a valid container ID present', async () => { + readStub = sinon + .stub(ContainerDetector, 'readFileAsync' as any) + .resolves(correctCgroupV1Data); + + const resource: Resource = await containerDetector.detect(); + + sinon.assert.calledOnce(readStub); + + assert.ok(resource); + assertContainerResource(resource, { + id: 'bcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklm', + }); + }); + + it('should return a resource with container ID with a valid container ID present for v2', async () => { + readStub = sinon.stub(ContainerDetector, 'readFileAsync' as any); + + readStub.onFirstCall().resolves(''); + readStub.onSecondCall().resolves(correctCgroupV2Data); + + const resource: Resource = await containerDetector.detect(); + sinon.assert.calledTwice(readStub); + + assert.ok(resource); + assertContainerResource(resource, { + id: 'tmhdefghijklmnopqrstuvwxyzafgrefghiugkmnopqrstuvwxyzabcdefghijkl', + }); + }); + + it('should return a empty resource with failed hostname check for v2', async () => { + readStub = sinon.stub(ContainerDetector, 'readFileAsync' as any); + + readStub.onFirstCall().resolves(''); + readStub.onSecondCall().resolves(wrongCgroupV2Data); + + const resource: Resource = await containerDetector.detect(); + sinon.assert.calledTwice(readStub); + + assert.ok(resource); + }); + + it('should return a resource without attribute container.id when cgroup file does not contain valid Container ID', async () => { + readStub = sinon + .stub(ContainerDetector, 'readFileAsync' as any) + .resolves(''); + + const resource: Resource = await containerDetector.detect(); + assert.deepStrictEqual(resource.attributes, {}); + + sinon.assert.calledTwice(readStub); + assert.ok(resource); + }); + + it('should return an empty resource when containerId is not valid', async () => { + const errorMsg = { + fileNotFoundError: new Error('cannot find file in path'), + }; + + readStub = sinon + .stub(ContainerDetector, 'readFileAsync' as any) + .rejects(errorMsg.fileNotFoundError); + + const resource: Resource = await containerDetector.detect(); + + sinon.assert.calledOnce(readStub); + assertEmptyResource(resource); + }); + + //cgroup v2 and containerd test + + it('should return an empty resource when containerId is not valid', async () => { + const errorMsg = { + fileNotFoundError: new Error('cannot find file in path'), + }; + + readStub = sinon + .stub(ContainerDetector, 'readFileAsync' as any) + .rejects(errorMsg.fileNotFoundError); + + const resource: Resource = await containerDetector.detect(); + sinon.assert.calledOnce(readStub); + assertEmptyResource(resource); + }); + }); +}); diff --git a/detectors/node/opentelemetry-resource-detector-docker/tsconfig.json b/detectors/node/opentelemetry-resource-detector-container/tsconfig.json similarity index 100% rename from detectors/node/opentelemetry-resource-detector-docker/tsconfig.json rename to detectors/node/opentelemetry-resource-detector-container/tsconfig.json diff --git a/detectors/node/opentelemetry-resource-detector-docker/test/DockerCGroupv1Detector.test.ts b/detectors/node/opentelemetry-resource-detector-docker/test/DockerCGroupv1Detector.test.ts deleted file mode 100644 index 7911545427..0000000000 --- a/detectors/node/opentelemetry-resource-detector-docker/test/DockerCGroupv1Detector.test.ts +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * - * 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 - * - * https://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 * as sinon from 'sinon'; -import * as assert from 'assert'; -import { Resource } from '@opentelemetry/resources'; -import { dockerCGroupV1Detector } from '../src'; -import { - assertContainerResource, - assertEmptyResource, -} from '@opentelemetry/contrib-test-utils'; - -import { DockerCGroupV1Detector } from '../src'; - -describe('dockerCGroupV1Detector', () => { - let readStub; - const correctCgroupData = - 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklm'; - - afterEach(() => { - sinon.restore(); - }); - - describe('Supported docker - Container ID ', () => { - it('should return a resource attributes without container id - docker cgroup v1 detector', async () => { - readStub = sinon - .stub(DockerCGroupV1Detector, 'readFileAsync' as any) - .resolves(undefined); - - const resource: Resource = await dockerCGroupV1Detector.detect(); - - assert.deepStrictEqual(resource.attributes, {}); - assert.ok(resource); - }); - - it('should return a resource with container ID with a valid container ID present', async () => { - readStub = sinon - .stub(DockerCGroupV1Detector, 'readFileAsync' as any) - .resolves(correctCgroupData); - - const resource: Resource = await dockerCGroupV1Detector.detect(); - - sinon.assert.calledOnce(readStub); - - assert.ok(resource); - assertContainerResource(resource, { - id: 'bcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklm', - }); - }); - - it('should return a resource without attribute container.id when cgroup file does not contain valid Container ID', async () => { - readStub = sinon - .stub(DockerCGroupV1Detector, 'readFileAsync' as any) - .resolves(''); - - const resource: Resource = await dockerCGroupV1Detector.detect(); - assert.deepStrictEqual(resource.attributes, {}); - - sinon.assert.calledOnce(readStub); - assert.ok(resource); - }); - - it('should return an empty resource when containerId is not valid', async () => { - const errorMsg = { - fileNotFoundError: new Error('cannot find file in path'), - }; - - readStub = sinon - .stub(DockerCGroupV1Detector, 'readFileAsync' as any) - .rejects(errorMsg.fileNotFoundError); - - const resource: Resource = await dockerCGroupV1Detector.detect(); - - sinon.assert.calledOnce(readStub); - assertEmptyResource(resource); - }); - }); -}); diff --git a/release-please-config.json b/release-please-config.json index 00070fc0c4..76911a8653 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -8,7 +8,7 @@ "packages": { "detectors/node/opentelemetry-resource-detector-alibaba-cloud": {}, "detectors/node/opentelemetry-resource-detector-aws": {}, - "detectors/node/opentelemetry-resource-detector-docker": {}, + "detectors/node/opentelemetry-resource-detector-container": {}, "detectors/node/opentelemetry-resource-detector-gcp": {}, "detectors/node/opentelemetry-resource-detector-github": {}, "detectors/node/opentelemetry-resource-detector-instana": {}, From 5da46ef7a29bbc64f600d794b1e68bb6738a9f2e Mon Sep 17 00:00:00 2001 From: Dominic Chambers Date: Mon, 3 Oct 2022 10:20:49 +0100 Subject: [PATCH 4/4] feat: support `graphql` v16 (#998) Co-authored-by: Rauno Viskus Co-authored-by: Rauno Viskus --- .../.tav.yml | 4 +- .../package.json | 7 +-- .../src/instrumentation.ts | 8 +-- .../src/types.ts | 4 +- .../src/utils.ts | 10 +++- .../test/graphql-adaptor.ts | 52 +++++++++++++++++++ .../test/graphql.test.ts | 46 +++++++++------- 7 files changed, 99 insertions(+), 32 deletions(-) create mode 100644 plugins/node/opentelemetry-instrumentation-graphql/test/graphql-adaptor.ts diff --git a/plugins/node/opentelemetry-instrumentation-graphql/.tav.yml b/plugins/node/opentelemetry-instrumentation-graphql/.tav.yml index a80a1f590e..603ce40daf 100644 --- a/plugins/node/opentelemetry-instrumentation-graphql/.tav.yml +++ b/plugins/node/opentelemetry-instrumentation-graphql/.tav.yml @@ -1,4 +1,4 @@ graphql: - # Taking a sample from the most downloaded versions in the range "14 || 15" - versions: "^15.8.0 || 15.7.2 || 15.6.1 || 15.6.0 || 15.5.3 || 15.5.1 || 15.5.0 || 15.4.0 || 15.3.0 || 14.6.0 || 14.5.8 || 14.5.0 || 14.0.0" + # Taking a sample from the most downloaded versions in the range "14 || 15 || 16" + versions: "16.4.0 || 16.3.0 || 16.2.0 || 16.0.0 || ^15.8.0 || 15.7.2 || 15.6.1 || 15.6.0 || 15.5.3 || 15.5.1 || 15.5.0 || 15.4.0 || 15.3.0 || ^14.7.0 || 14.6.0 || 14.5.8 || 14.0.0" commands: npm run test diff --git a/plugins/node/opentelemetry-instrumentation-graphql/package.json b/plugins/node/opentelemetry-instrumentation-graphql/package.json index 414c70fb61..0777ea5682 100644 --- a/plugins/node/opentelemetry-instrumentation-graphql/package.json +++ b/plugins/node/opentelemetry-instrumentation-graphql/package.json @@ -44,13 +44,15 @@ "access": "public" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@opentelemetry/api": "^1.0.0", + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0" }, "devDependencies": { "@opentelemetry/api": "^1.0.0", "@opentelemetry/sdk-trace-base": "^1.3.1", "@types/mocha": "8.2.3", "@types/node": "16.11.21", + "graphql": "^16.5.0", "gts": "3.1.0", "mocha": "7.2.0", "nyc": "15.1.0", @@ -60,8 +62,7 @@ "typescript": "4.3.5" }, "dependencies": { - "@opentelemetry/instrumentation": "^0.32.0", - "graphql": "^15.5.1" + "@opentelemetry/instrumentation": "^0.32.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-graphql#readme" } diff --git a/plugins/node/opentelemetry-instrumentation-graphql/src/instrumentation.ts b/plugins/node/opentelemetry-instrumentation-graphql/src/instrumentation.ts index 52c7465a2f..efb54b6c87 100644 --- a/plugins/node/opentelemetry-instrumentation-graphql/src/instrumentation.ts +++ b/plugins/node/opentelemetry-instrumentation-graphql/src/instrumentation.ts @@ -307,8 +307,8 @@ export class GraphQLInstrumentation extends InstrumentationBase { schema: graphqlTypes.GraphQLSchema, documentAST: graphqlTypes.DocumentNode, rules?: ReadonlyArray, - typeInfo?: graphqlTypes.TypeInfo, - options?: { maxErrors?: number } + options?: { maxErrors?: number }, + typeInfo?: graphqlTypes.TypeInfo ): ReadonlyArray { return instrumentation._validate( this, @@ -373,8 +373,8 @@ export class GraphQLInstrumentation extends InstrumentationBase { schema, documentAST, rules, - typeInfo, - options + options, + typeInfo ); }, (err, errors) => { diff --git a/plugins/node/opentelemetry-instrumentation-graphql/src/types.ts b/plugins/node/opentelemetry-instrumentation-graphql/src/types.ts index 7f457dafcf..f783140bed 100644 --- a/plugins/node/opentelemetry-instrumentation-graphql/src/types.ts +++ b/plugins/node/opentelemetry-instrumentation-graphql/src/types.ts @@ -120,8 +120,8 @@ export type validateType = ( schema: graphqlTypes.GraphQLSchema, documentAST: graphqlTypes.DocumentNode, rules?: ReadonlyArray, - typeInfo?: graphqlTypes.TypeInfo, - options?: { maxErrors?: number } + options?: { maxErrors?: number }, + typeInfo?: graphqlTypes.TypeInfo ) => ReadonlyArray; export interface GraphQLField { diff --git a/plugins/node/opentelemetry-instrumentation-graphql/src/utils.ts b/plugins/node/opentelemetry-instrumentation-graphql/src/utils.ts index 052953a5e5..0a938dfb72 100644 --- a/plugins/node/opentelemetry-instrumentation-graphql/src/utils.ts +++ b/plugins/node/opentelemetry-instrumentation-graphql/src/utils.ts @@ -387,7 +387,13 @@ export function wrapFieldResolver( > >( () => { - return fieldResolver.call(this, source, args, contextValue, info); + return fieldResolver.call( + this, + source, + args, + contextValue, + info + ) as any; }, err => { if (shouldEndSpan) { @@ -421,7 +427,7 @@ async function safeExecuteInTheMiddleAsync( try { result = await execute(); } catch (e) { - error = e; + error = e as Error; } finally { onFinish(error, result); if (error && !preventThrowingError) { diff --git a/plugins/node/opentelemetry-instrumentation-graphql/test/graphql-adaptor.ts b/plugins/node/opentelemetry-instrumentation-graphql/test/graphql-adaptor.ts new file mode 100644 index 0000000000..c0ccac4848 --- /dev/null +++ b/plugins/node/opentelemetry-instrumentation-graphql/test/graphql-adaptor.ts @@ -0,0 +1,52 @@ +/* + * Copyright The OpenTelemetry Authors + * + * 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 + * + * https://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 type { + GraphQLFieldResolver, + GraphQLSchema, + GraphQLTypeResolver, + Source, +} from 'graphql'; +import { graphql as origGraphql, version } from 'graphql'; +import { Maybe } from 'graphql/jsutils/Maybe'; + +const variantGraphql = origGraphql as Function; + +interface GraphQLArgs { + schema: GraphQLSchema; + source: string | Source; + rootValue?: unknown; + contextValue?: unknown; + variableValues?: Maybe<{ + readonly [variable: string]: unknown; + }>; + operationName?: Maybe; + fieldResolver?: Maybe>; + typeResolver?: Maybe>; +} + +export const graphql = (args: GraphQLArgs) => + !version || version.startsWith('14.') || version.startsWith('15.') + ? variantGraphql( + args.schema, + args.source, + args.rootValue, + args.contextValue, + args.variableValues, + args.operationName, + args.fieldResolver, + args.typeResolver + ) + : variantGraphql(args); diff --git a/plugins/node/opentelemetry-instrumentation-graphql/test/graphql.test.ts b/plugins/node/opentelemetry-instrumentation-graphql/test/graphql.test.ts index 5d54744f2a..abdf338112 100644 --- a/plugins/node/opentelemetry-instrumentation-graphql/test/graphql.test.ts +++ b/plugins/node/opentelemetry-instrumentation-graphql/test/graphql.test.ts @@ -40,7 +40,7 @@ graphQLInstrumentation.disable(); // now graphql can be required import { buildSchema } from './schema'; -import { graphql } from 'graphql'; +import { graphql } from './graphql-adaptor'; // Construct a schema, using GraphQL schema language const schema = buildSchema(); @@ -107,7 +107,7 @@ describe('graphql', () => { let spans: ReadableSpan[]; beforeEach(async () => { create({}); - await graphql(schema, sourceList1); + await graphql({ schema, source: sourceList1 }); spans = exporter.getFinishedSpans(); }); @@ -235,7 +235,7 @@ describe('graphql', () => { beforeEach(async () => { create({}); - await graphql(schema, sourceBookById); + await graphql({ schema, source: sourceBookById }); spans = exporter.getFinishedSpans(); }); @@ -323,8 +323,12 @@ describe('graphql', () => { beforeEach(async () => { create({}); - await graphql(schema, sourceFindUsingVariable, null, null, { - id: 2, + await graphql({ + schema, + source: sourceFindUsingVariable, + variableValues: { + id: 2, + }, }); spans = exporter.getFinishedSpans(); }); @@ -421,7 +425,7 @@ describe('graphql', () => { create({ depth: 0, }); - await graphql(schema, sourceList1); + await graphql({ schema, source: sourceList1 }); spans = exporter.getFinishedSpans(); }); @@ -489,7 +493,7 @@ describe('graphql', () => { create({ mergeItems: true, }); - await graphql(schema, sourceList1); + await graphql({ schema, source: sourceList1 }); spans = exporter.getFinishedSpans(); }); @@ -556,7 +560,7 @@ describe('graphql', () => { mergeItems: true, depth: 0, }); - await graphql(schema, sourceList1); + await graphql({ schema, source: sourceList1 }); spans = exporter.getFinishedSpans(); }); @@ -580,7 +584,7 @@ describe('graphql', () => { create({ allowValues: true, }); - await graphql(schema, sourceBookById); + await graphql({ schema, source: sourceBookById }); spans = exporter.getFinishedSpans(); }); @@ -670,7 +674,7 @@ describe('graphql', () => { create({ allowValues: true, }); - await graphql(schema, sourceAddBook); + await graphql({ schema, source: sourceAddBook }); spans = exporter.getFinishedSpans(); }); @@ -764,8 +768,12 @@ describe('graphql', () => { create({ allowValues: true, }); - await graphql(schema, sourceFindUsingVariable, null, null, { - id: 2, + await graphql({ + schema, + source: sourceFindUsingVariable, + variableValues: { + id: 2, + }, }); spans = exporter.getFinishedSpans(); }); @@ -862,7 +870,7 @@ describe('graphql', () => { create({ // allowValues: true }); - await graphql(schema, sourceAddBook); + await graphql({ schema, source: sourceAddBook }); spans = exporter.getFinishedSpans(); }); @@ -955,7 +963,7 @@ describe('graphql', () => { beforeEach(async () => { create({}); - await graphql(schema, badQuery); + await graphql({ schema, source: badQuery }); spans = exporter.getFinishedSpans(); }); @@ -990,7 +998,7 @@ describe('graphql', () => { beforeEach(async () => { create({}); - await graphql(schema, queryInvalid); + await graphql({ schema, source: queryInvalid }); spans = exporter.getFinishedSpans(); }); @@ -1036,7 +1044,7 @@ describe('graphql', () => { describe('responseHook', () => { let spans: ReadableSpan[]; - let graphqlResult: graphqlTypes.ExecutionResult; + let graphqlResult: graphqlTypes.ExecutionResult<{ books: unknown[] }>; const dataAttributeName = 'graphql_data'; afterEach(() => { @@ -1052,7 +1060,7 @@ describe('graphql', () => { span.setAttribute(dataAttributeName, JSON.stringify(data)); }, }); - graphqlResult = await graphql(schema, sourceList1); + graphqlResult = await graphql({ schema, source: sourceList1 }); spans = exporter.getFinishedSpans(); }); @@ -1075,7 +1083,7 @@ describe('graphql', () => { throw 'some kind of failure!'; }, }); - graphqlResult = await graphql(schema, sourceList1); + graphqlResult = await graphql({ schema, source: sourceList1 }); spans = exporter.getFinishedSpans(); }); @@ -1092,7 +1100,7 @@ describe('graphql', () => { responseHook: invalidTypeHook as GraphQLInstrumentationExecutionResponseHook, }); - graphqlResult = await graphql(schema, sourceList1); + graphqlResult = await graphql({ schema, source: sourceList1 }); spans = exporter.getFinishedSpans(); });