diff --git a/.github/component_owners.yml b/.github/component_owners.yml index cb8d103404..d0dbb99e9d 100644 --- a/.github/component_owners.yml +++ b/.github/component_owners.yml @@ -3,9 +3,12 @@ components: detectors/node/opentelemetry-resource-detector-alibaba-cloud: - legendecas detectors/node/opentelemetry-resource-detector-aws: - - willarmiros - detectors/node/opentelemetry-resource-detector-docker: + - carolabadeer + detectors/node/opentelemetry-resource-detector-container: - abhee11 + detectors/node/opentelemetry-resource-detector-instana: + - basti1302 + - kirrg001 metapackages/auto-instrumentations-node: - obecny metapackages/auto-instrumentations-web: @@ -15,7 +18,9 @@ components: packages/opentelemetry-host-metrics: - legendecas packages/opentelemetry-id-generator-aws-xray: - - willarmiros + - carolabadeer + packages/opentelemetry-redis-common: + - haddasbronfman plugins/node/instrumentation-amqplib: - blumamir plugins/node/instrumentation-dataloader: @@ -25,9 +30,9 @@ components: plugins/node/instrumentation-tedious: - rauno56 plugins/node/opentelemetry-instrumentation-aws-lambda: - - willarmiros + - carolabadeer plugins/node/opentelemetry-instrumentation-aws-sdk: - - willarmiros + - carolabadeer - blumamir plugins/node/opentelemetry-instrumentation-generic-pool: - rauno56 @@ -46,6 +51,8 @@ components: - osherv plugins/node/opentelemetry-instrumentation-mongoose: - blumamir + plugins/node/opentelemetry-instrumentation-mysql: + - haddasbronfman plugins/node/opentelemetry-instrumentation-nestjs-core: - rauno56 plugins/node/opentelemetry-instrumentation-redis: @@ -58,6 +65,9 @@ components: - rauno56 plugins/node/opentelemetry-instrumentation-pg: - rauno56 + plugins/node/opentelemetry-instrumentation-socket.io: + - mottibec + - rauno56 plugins/web/opentelemetry-instrumentation-document-load: - obecny plugins/web/opentelemetry-instrumentation-long-task: @@ -66,7 +76,7 @@ components: plugins/web/opentelemetry-instrumentation-user-interaction: - obecny propagators/opentelemetry-propagator-aws-xray: - - willarmiros + - carolabadeer propagators/opentelemetry-propagator-instana: - basti1302 - kirrg001 diff --git a/.github/workflows/close-stale.yml b/.github/workflows/close-stale.yml index 01b92f2366..2d098a0068 100644 --- a/.github/workflows/close-stale.yml +++ b/.github/workflows/close-stale.yml @@ -7,7 +7,7 @@ jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@v6 + - uses: actions/stale@v8 with: days-before-stale: 60 days-before-close: 14 diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index 0b79e7feb9..6cd76a49ea 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -8,13 +8,6 @@ jobs: release-please: runs-on: ubuntu-latest steps: - - uses: google-github-actions/release-please-action@v3 - id: release - with: - command: manifest - token: ${{secrets.RELEASE_PR_TOKEN}} - default-branch: main - # The logic below handles the npm publication: - name: Checkout Repository uses: actions/checkout@v3 @@ -46,6 +39,13 @@ jobs: npm install npx lerna bootstrap --no-ci + - uses: google-github-actions/release-please-action@v3 + id: release + with: + command: manifest + token: ${{secrets.RELEASE_PR_TOKEN}} + default-branch: main + # Release Please has already incremented versions and published tags, so we just # need to publish all unpublished versions to npm here # See: https://github.com/lerna/lerna/tree/main/commands/publish#bump-from-package diff --git a/.github/workflows/test-all-versions.pr.yml b/.github/workflows/test-all-versions.pr.yml index d0f9528d31..95271fa495 100644 --- a/.github/workflows/test-all-versions.pr.yml +++ b/.github/workflows/test-all-versions.pr.yml @@ -27,7 +27,7 @@ jobs: id: lerna-args run: | OUTPUT=`node scripts/parse-lerna-scopes.mjs "$PR_LABELS"` - echo "::set-output name=args::$OUTPUT" + echo "args=$OUTPUT" >> $GITHUB_OUTPUT tav: uses: ./.github/workflows/test-all-versions.yml diff --git a/.husky/commit-msg b/.husky/commit-msg deleted file mode 100755 index e8511eaeaf..0000000000 --- a/.husky/commit-msg +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" - -npx --no-install commitlint --edit $1 diff --git a/.release-please-manifest.json b/.release-please-manifest.json index ec840c24d3..67946c3423 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,2 +1 @@ -{"detectors/node/opentelemetry-resource-detector-alibaba-cloud":"0.27.2","detectors/node/opentelemetry-resource-detector-aws":"1.2.0","detectors/node/opentelemetry-resource-detector-container":"0.2.0","detectors/node/opentelemetry-resource-detector-gcp":"0.27.3","detectors/node/opentelemetry-resource-detector-github":"0.27.0","detectors/node/opentelemetry-resource-detector-instana":"0.3.0","metapackages/auto-instrumentations-node":"0.34.0","metapackages/auto-instrumentations-web":"0.30.1","packages/opentelemetry-host-metrics":"0.30.1","packages/opentelemetry-id-generator-aws-xray":"1.1.1","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.1","plugins/node/instrumentation-fs":"0.5.1","plugins/node/instrumentation-lru-memoizer":"0.31.0","plugins/node/instrumentation-mongoose":"0.31.1","plugins/node/instrumentation-tedious":"0.4.1","plugins/node/opentelemetry-instrumentation-aws-lambda":"0.33.1","plugins/node/opentelemetry-instrumentation-aws-sdk":"0.9.3","plugins/node/opentelemetry-instrumentation-bunyan":"0.30.1","plugins/node/opentelemetry-instrumentation-cassandra":"0.31.0","plugins/node/opentelemetry-instrumentation-connect":"0.30.1","plugins/node/opentelemetry-instrumentation-dns":"0.30.1","plugins/node/opentelemetry-instrumentation-express":"0.31.3","plugins/node/opentelemetry-instrumentation-fastify":"0.30.1","plugins/node/opentelemetry-instrumentation-generic-pool":"0.30.0","plugins/node/opentelemetry-instrumentation-graphql":"0.32.0","plugins/node/opentelemetry-instrumentation-hapi":"0.30.1","plugins/node/opentelemetry-instrumentation-ioredis":"0.32.2","plugins/node/opentelemetry-instrumentation-knex":"0.30.1","plugins/node/opentelemetry-instrumentation-koa":"0.33.0","plugins/node/opentelemetry-instrumentation-memcached":"0.30.1","plugins/node/opentelemetry-instrumentation-mongodb":"0.32.2","plugins/node/opentelemetry-instrumentation-mysql":"0.31.2","plugins/node/opentelemetry-instrumentation-mysql2":"0.32.1","plugins/node/opentelemetry-instrumentation-nestjs-core":"0.31.1","plugins/node/opentelemetry-instrumentation-net":"0.30.2","plugins/node/opentelemetry-instrumentation-pg":"0.32.0","plugins/node/opentelemetry-instrumentation-pino":"0.32.1","plugins/node/opentelemetry-instrumentation-redis":"0.33.1","plugins/node/opentelemetry-instrumentation-redis-4":"0.33.1","plugins/node/opentelemetry-instrumentation-restify":"0.30.1","plugins/node/opentelemetry-instrumentation-router":"0.31.0","plugins/node/opentelemetry-instrumentation-winston":"0.30.1","plugins/web/opentelemetry-instrumentation-document-load":"0.30.1","plugins/web/opentelemetry-instrumentation-long-task":"0.31.1","plugins/web/opentelemetry-instrumentation-user-interaction":"0.31.1","plugins/web/opentelemetry-plugin-react-load":"0.28.1","propagators/opentelemetry-propagator-aws-xray":"1.1.1","propagators/opentelemetry-propagator-grpc-census-binary":"0.26.0","propagators/opentelemetry-propagator-instana":"0.2.1","propagators/opentelemetry-propagator-ot-trace":"0.26.2"} - +{"detectors/node/opentelemetry-resource-detector-alibaba-cloud":"0.27.5","detectors/node/opentelemetry-resource-detector-aws":"1.2.3","detectors/node/opentelemetry-resource-detector-container":"0.2.3","detectors/node/opentelemetry-resource-detector-gcp":"0.28.1","detectors/node/opentelemetry-resource-detector-github":"0.27.0","detectors/node/opentelemetry-resource-detector-instana":"0.4.2","metapackages/auto-instrumentations-node":"0.36.6","metapackages/auto-instrumentations-web":"0.32.1","packages/opentelemetry-host-metrics":"0.32.1","packages/opentelemetry-id-generator-aws-xray":"1.1.1","packages/opentelemetry-propagation-utils":"0.29.3","packages/opentelemetry-redis-common":"0.35.0","packages/opentelemetry-test-utils":"0.33.2","plugins/node/instrumentation-amqplib":"0.32.3","plugins/node/instrumentation-dataloader":"0.4.1","plugins/node/instrumentation-fs":"0.7.2","plugins/node/instrumentation-lru-memoizer":"0.32.2","plugins/node/instrumentation-mongoose":"0.32.2","plugins/node/instrumentation-socket.io":"0.33.2","plugins/node/instrumentation-tedious":"0.5.2","plugins/node/opentelemetry-instrumentation-aws-lambda":"0.35.1","plugins/node/opentelemetry-instrumentation-aws-sdk":"0.34.1","plugins/node/opentelemetry-instrumentation-bunyan":"0.31.2","plugins/node/opentelemetry-instrumentation-cassandra":"0.32.2","plugins/node/opentelemetry-instrumentation-connect":"0.31.2","plugins/node/opentelemetry-instrumentation-dns":"0.31.3","plugins/node/opentelemetry-instrumentation-express":"0.32.2","plugins/node/opentelemetry-instrumentation-fastify":"0.31.2","plugins/node/opentelemetry-instrumentation-generic-pool":"0.31.2","plugins/node/opentelemetry-instrumentation-graphql":"0.34.1","plugins/node/opentelemetry-instrumentation-hapi":"0.31.2","plugins/node/opentelemetry-instrumentation-ioredis":"0.34.1","plugins/node/opentelemetry-instrumentation-knex":"0.31.2","plugins/node/opentelemetry-instrumentation-koa":"0.34.4","plugins/node/opentelemetry-instrumentation-memcached":"0.31.2","plugins/node/opentelemetry-instrumentation-mongodb":"0.34.2","plugins/node/opentelemetry-instrumentation-mysql":"0.33.1","plugins/node/opentelemetry-instrumentation-mysql2":"0.33.2","plugins/node/opentelemetry-instrumentation-nestjs-core":"0.32.3","plugins/node/opentelemetry-instrumentation-net":"0.31.2","plugins/node/opentelemetry-instrumentation-pg":"0.35.1","plugins/node/opentelemetry-instrumentation-pino":"0.33.2","plugins/node/opentelemetry-instrumentation-redis":"0.34.5","plugins/node/opentelemetry-instrumentation-redis-4":"0.34.4","plugins/node/opentelemetry-instrumentation-restify":"0.32.2","plugins/node/opentelemetry-instrumentation-router":"0.32.2","plugins/node/opentelemetry-instrumentation-winston":"0.31.2","plugins/web/opentelemetry-instrumentation-document-load":"0.32.1","plugins/web/opentelemetry-instrumentation-long-task":"0.32.3","plugins/web/opentelemetry-instrumentation-user-interaction":"0.32.2","plugins/web/opentelemetry-plugin-react-load":"0.28.1","propagators/opentelemetry-propagator-aws-xray":"1.2.0","propagators/opentelemetry-propagator-grpc-census-binary":"0.26.0","propagators/opentelemetry-propagator-instana":"0.2.1","propagators/opentelemetry-propagator-ot-trace":"0.26.2"} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 692d82b780..3c2b7513bc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,6 +2,27 @@ We'd love your help! +- [Report a bug or requesting feature](#report-a-bug-or-requesting-feature) +- [How to contribute](#how-to-contribute) + - [Before you start](#before-you-start) + - [Conventional commit](#conventional-commit) + - [Fork](#fork) + - [Running the tests](#running-the-tests) + - [Generating API documentation](#generating-api-documentation) + - [Generating CHANGELOG documentation](#generating-changelog-documentation) + - [Benchmarks](#benchmarks) +- [Component Ownership](#component-ownership) +- [Component Lifecycle](#component-lifecycle) + - [Unreleased](#unreleased) + - [Experimental](#experimental) + - [Beta](#beta) + - [Stable](#stable) + - [Unmaintained](#unmaintained) + - [Deprecated](#deprecated) +- [Contributing Vendor Components](#contributing-vendor-components) + - [Adding a New Vendor Component](#adding-a-new-vendor-component) + - [Removing Vendor Components](#removing-vendor-components) + ## Report a bug or requesting feature Reporting bugs is an important contribution. Please make sure to include: @@ -80,6 +101,67 @@ When two or more approaches must be compared, please write a benchmark in the be - `npm run bench` to run your benchmark. +## Component Ownership + +This repository contains many components which are maintained by more than the typical set of JS maintainers and approvers. +Each component in this repository SHOULD have a component owner who is responsible for maintaining it. +The README.md for each component SHOULD contain its owner, but the source of truth for component ownership is in [.github/component_owners.yml](.github/component_owners.yml). +Component owners are generally given authority to make decisions relating to implementation and feature requests for their components, provided they follow the best practices set out by the maintainers. +Component owners MUST do their best to maintain a high level of quality, security, performance, and specification compliance within their components. +Maintainers may override the decisions of component owners, but should only do so when they feel one or more of these traits is compromised. + +## Component Lifecycle + +This repository contains many components in various stages of the component lifecycle. +A component may be **unreleased**, **experimental**, **beta**, **stable**, **unmaintained**, or **deprecated**; see the below definitions for each stability level. +With the exception of the stable status, it is up to each individual [component owner](#component-ownership) to determine the status of a component. +A component may only be marked stable with the approval of a member of @open-telemetry/javascript-maintainers; see the definition of stable below for more details. + +### Unreleased + +Unreleased components are in active development and have not yet been released to NPM. +Unreleased packages should have the property `private` in their `package.json` set to `true`. + +### Experimental + +Experimental packages are in active development. +They should be considered unstable and potentially unsuitable for production use. +They are released to NPM for developers and early adopters. +Experimental components MUST have their major version set to `0`. +If a component does not have an explicit status in its README.md file, it should be considered to be experimental. + +### Beta + +Beta packages are not yet considered stable, but an effort should be made to preserve stability across versions if possible. +They may be ready for production use, but users should understand that their APIs or the telemetry they output MAY change if required. +Beta components MUST have their major version set to `0`. + +### Stable + +This is the highest level of quality and maintainership guarantee provided in this repository. +Stable packages should be considered stable and ready for production use. +In order for a package to be marked stable, it must meet the following requirements: + +- It MUST have a component owner that the JS maintainers feel confident will be responsive to issues and pull requests and will fulfill their responsibility competently. + If a component owner is not responsive to issues and PRs, the maintainers may assign a new owner or change the status of the component to unmaintained. +- All relevant specification relating to the component MUST be stable. For example, telemetry emitted by an instrumentation library should rely on a stable semantic convention. +- It MUST be reviewed and approved by a member of @open-telemetry/javascript-maintainers. + +Stable components MUST have their major version set to `1` or greater. + +### Unmaintained + +A component which does not have an assigned component owner, or has a component owner who has been unresponsive to issues and pull requests may be marked as unmaintained. +Unmaintained components may continue to work and receive updates and fixes from contributors, but may not receive immediate attention if there is a problem or feature request. +A component which is unmaintained may be deprecated if there is a problem that is not fixed in a timely manner. + +### Deprecated + +Deprecated components are no longer maintained and there are not currently plans to maintain them. +They may not work and there are no guarantees for fixes or new features. +Their source files may be deleted from the repository. +Any packages released from their source will be marked as deprecated in NPM. + ## Contributing Vendor Components This repo is generally meant for hosting components that work with popular open-source frameworks and tools. However, it is also possible to contribute components specific to a 3rd party vendor in this repo. diff --git a/GUIDELINES.md b/GUIDELINES.md index 42e4478421..42a1c4900b 100644 --- a/GUIDELINES.md +++ b/GUIDELINES.md @@ -39,3 +39,96 @@ This file MUST NOT be exported publicly from instrumentation package, not direct #### Changes Since the declarations in this file are not exported in the public instrumentation api, it is allowed to apply any refactors to this file, and they will not be breaking changes to users. + +## Dependencies + +This section refers to the "dependencies" and "peerDependencies" entries in instrumentation's `package.json` file. + +Since instrumentations will install all their dependencies into the end user `node_modules` application, they should be examined to guarantee only small-size-required packages are added. + +### OpenTelemetry API + +Instrumentation SHOULD NOT add a dependency on `@opentelemetry/api`, as using multiple instrumentations might install multiple api versions into the user node_modules directory. It SHOULD add an entry in `"peerDependencies"` in `package.json` with the **minimum** api version it requires, as caret range (for example: `^1.0.0`). + +Users and distributions need to install a version of `@opentelemetry/api` that is compatible with the instrumentation to use it. + +### OpenTelemetry Core packages + +Most instrumentations will depend on `@opentelemetry/instrumentation` and `@opentelemetry/semantic-conventions`. If needed, instrumentations can also depend on `@opentelemetry/core` for use of handy utils. + +Instrumentations SHOULD specify these dependencies as caret range (`^1.0.0`), with minimum supported version (and not latest version). If a specific feature or bug fix is required for instrumentation to function correctly, it SHOULD specify the minimum version that includes this feature. + +### Instrumented Package Dependency + +Instrumentations SHOULD NOT add a `"dependency"` or `"peerDependencies"` on the package it is instrumenting as it can end up installing this package into users' applications, adding large overhead. + +This means that the instrumentation code SHOULD NOT `import` anywhere from the instrumented package. e.g. `@opentelemetry/instrumentation-foo` cannot `import 'foo'` as it will fail for applications that installed the instrumentation but not the `foo` package itself, which is a valid and supported use case for OpenTelemetry distributions and end users. + +It is allowed, however, to import `types` from the instrumented package with the [`import type`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export) syntax, as long as this type is not used in the public api: + +```js +// instrumentation.ts +import type { Bar } from 'foo'; // OK +``` + +Since the instrumented package is installed as a dev dependency, types are available during compiling. Since they are not part of the public api, typescript removes these imports from the build artifacts during transpilation. + +### Types Public API + +When users install an instrumentation package into their typescript application, and `import * from '@opentelemetry/instrumentation-foo'` in their code, typescript compiler will look for the instrumentation package ["types"](https://www.typescriptlang.org/docs/handbook/declaration-files/publishing.html#including-declarations-in-your-npm-package) file `index.d.ts` and use it. If this file reference other type files such as `export * from './instrumentation';`, typescript will then import and transpile these files (and other transitive files they might use) as well. We will call these files "public" as they are exposed to the package consumers and processed by their typescript compiler when transpiling their applications. + +If one of these files `import`s from a package that is not in users' `node_module` directory, the instrumentation package will fail transpilation for the end users' application which should be avoided. A common problem is "leaking" the types from the instrumented package (which we cannot assume to be found in end-user `node_module`) in one of these public modules ".d.ts" files. + +When invoking `npm run compile` on the instrumentation package, typescript will generate the `.d.ts` types files in the `build` directory and will only include in them "public" types - those that can be consumed by the user of the module. These may include: + +- Types that are `export`ed from the module, or types that are transitively used in other types that are `export`ed from the module. +- Types in `public` functions of exported classes such as `class InstrumentationFoo`. +- Types used as [`Generic Type Varibles`] on exported generic types/classes/functions. + +Note that types that are used in non-public files (like `internal-types.ts` or `utils.ts`), or that are not somehow `export`ed from a module (for example - used in private function implementations), can safely use types from a "devDependency" package. + +### Adding Types in Public API + +Sometimes, instrumented package types are needed in an instrumentation's public api. These are mostly found in `types.ts` file on instrumentation config hooks that include data from the package and want to type it for consumers. + +To support this use case, you can choose one of the following options: + +1. Some packages do not distribute types. The types are alternatively available in the [Definitely Typed Project](https://github.com/DefinitelyTyped/DefinitelyTyped) as `@types/foo` (for a package named `foo`). Since @type package is mostly small in size, instrumentation MAY add dependency on the types package, and then use type-only import `import type from 'foo'` in `types.ts`. + + ```js + // package.json + { + ... + "dependencies": { + "@types/foo": "1.2.3" + }, + ... + } + + // types.ts + import type { Bar } from 'foo'; + + export interface FooRequestInfo { + bar: Bar; + } + + ... + ``` + + If possible, this is the prefered option, as it uses types from a maintained package. + + Notice that types may introduce breaking changes in major semver releases, and instrumentation should choose a `@types/` package that is compatible with the version range it supports. + +2. Copy the relevant type declarations into the instrumentation. You may choose to copy only a subset of the type that is relevant to the need. + + A type can transitively reference other types which in turn need to be copied as well. + + This option requires maintaining the types in the instrumentation codebase, which is not ideal. On the other end, it offers instrumentation users typing on its public API which is convenient. + + It is recommended to use this option when the types involved are simple and short. + +3. Use `any` type, and add a comment to guide users on what type they should expect, with a link to its definition. + + This option will offer no typing aid to the instrumentation consumer, which will move the burden and risk of checking type correctness to the user. + + It is recommended to implement it only if the previous options are not feasible or are too complex to use. diff --git a/README.md b/README.md index 6168d94a79..06cf359193 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,10 @@ This project includes: **Resource Detectors**: OpenTelemetry can collect resource attributes of the entity that producing telemetry. For example, a process producing telemetry that is running in a container on Kubernetes has a Pod name, it is in a namespace and possibly is part of a Deployment which also has a name. All three of these attributes can be included in the `Resource`. +## Stability levels + +Stability level for components in this repository follow the definitions in [CONTRIBUTING.md](./CONTRIBUTING.md). + ## Supported Runtimes Packages in this repository have a variable range of support for Node.JS and browser versions which for each package depend on diff --git a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/CHANGELOG.md b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/CHANGELOG.md index 008ddfc8fe..875df530e8 100644 --- a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/CHANGELOG.md +++ b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/CHANGELOG.md @@ -12,6 +12,24 @@ * devDependencies * @opentelemetry/contrib-test-utils bumped from ^0.31.0 to ^0.32.0 +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.32.0 to ^0.33.0 + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.0 to ^0.33.1 + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.1 to ^0.33.2 + ## [0.27.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/resource-detector-alibaba-cloud-v0.26.2...resource-detector-alibaba-cloud-v0.27.0) (2022-05-14) diff --git a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/package.json b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/package.json index 88cb6fd8f5..960f3c28ac 100644 --- a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/package.json +++ b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/resource-detector-alibaba-cloud", - "version": "0.27.2", + "version": "0.27.5", "description": "OpenTelemetry resource detector for Alibaba Cloud", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -43,18 +43,17 @@ }, "devDependencies": { "@opentelemetry/api": "^1.0.0", - "@opentelemetry/contrib-test-utils": "^0.32.0", + "@opentelemetry/contrib-test-utils": "^0.33.2", "@types/mocha": "8.2.3", "@types/node": "18.11.7", "@types/sinon": "10.0.2", - "gts": "3.1.0", "mocha": "7.2.0", "nock": "12.0.3", "nyc": "15.1.0", - "rimraf": "3.0.2", - "sinon": "14.0.0", + "rimraf": "4.2.0", + "sinon": "15.0.1", "ts-mocha": "10.0.0", - "typescript": "4.3.5" + "typescript": "4.4.4" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0" diff --git a/detectors/node/opentelemetry-resource-detector-aws/CHANGELOG.md b/detectors/node/opentelemetry-resource-detector-aws/CHANGELOG.md index a23c22bb39..1ee8654d58 100644 --- a/detectors/node/opentelemetry-resource-detector-aws/CHANGELOG.md +++ b/detectors/node/opentelemetry-resource-detector-aws/CHANGELOG.md @@ -12,6 +12,24 @@ * devDependencies * @opentelemetry/contrib-test-utils bumped from ^0.31.0 to ^0.32.0 +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.32.0 to ^0.33.0 + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.0 to ^0.33.1 + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.1 to ^0.33.2 + ## [1.2.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/resource-detector-aws-v1.1.2...resource-detector-aws-v1.2.0) (2022-11-02) diff --git a/detectors/node/opentelemetry-resource-detector-aws/README.md b/detectors/node/opentelemetry-resource-detector-aws/README.md index 7522b32ae5..690c25700d 100644 --- a/detectors/node/opentelemetry-resource-detector-aws/README.md +++ b/detectors/node/opentelemetry-resource-detector-aws/README.md @@ -3,11 +3,15 @@ [![NPM Published Version][npm-img]][npm-url] [![Apache License][license-image]][license-image] -[component owners](https://github.com/open-telemetry/opentelemetry-js-contrib/blob/main/.github/component_owners.yml): @willarmiros +[component owners](https://github.com/open-telemetry/opentelemetry-js-contrib/blob/main/.github/component_owners.yml): @carolabadeer Resource detector for Amazon Web Services. -Compatible with OpenTelemetry JS API and SDK `1.0+`. +## Status + +| Maturity | [Component Owner](../../.github/component_owners.yml) | Compatibility | +| ----------------------------------------- | ----------------------------------------------------- | --------------------- | +| [Stable](../../../CONTRIBUTING.md#stable) | @carolabadeer | API 1.0+
SDK 1.0+ | ## Installation diff --git a/detectors/node/opentelemetry-resource-detector-aws/package.json b/detectors/node/opentelemetry-resource-detector-aws/package.json index 05abb595d9..f99a6d42c6 100644 --- a/detectors/node/opentelemetry-resource-detector-aws/package.json +++ b/detectors/node/opentelemetry-resource-detector-aws/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/resource-detector-aws", - "version": "1.2.0", + "version": "1.2.3", "description": "OpenTelemetry SDK resource detector for AWS", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -42,18 +42,17 @@ }, "devDependencies": { "@opentelemetry/api": "^1.0.0", - "@opentelemetry/contrib-test-utils": "^0.32.0", + "@opentelemetry/contrib-test-utils": "^0.33.2", "@types/mocha": "8.2.3", "@types/node": "18.11.7", "@types/sinon": "10.0.2", - "gts": "3.1.0", "mocha": "7.2.0", "nock": "12.0.3", "nyc": "15.1.0", - "rimraf": "3.0.2", - "sinon": "14.0.0", + "rimraf": "4.2.0", + "sinon": "15.0.1", "ts-mocha": "10.0.0", - "typescript": "4.3.5" + "typescript": "4.4.4" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0" diff --git a/detectors/node/opentelemetry-resource-detector-aws/src/detectors/AwsBeanstalkDetector.ts b/detectors/node/opentelemetry-resource-detector-aws/src/detectors/AwsBeanstalkDetector.ts index 8f9964d2e5..44028c6ff6 100644 --- a/detectors/node/opentelemetry-resource-detector-aws/src/detectors/AwsBeanstalkDetector.ts +++ b/detectors/node/opentelemetry-resource-detector-aws/src/detectors/AwsBeanstalkDetector.ts @@ -80,7 +80,7 @@ export class AwsBeanstalkDetector implements Detector { [SemanticResourceAttributes.SERVICE_INSTANCE_ID]: parsedData.deployment_id, }); - } catch (e) { + } catch (e: any) { diag.debug(`AwsBeanstalkDetector failed: ${e.message}`); return Resource.empty(); } diff --git a/detectors/node/opentelemetry-resource-detector-aws/src/detectors/AwsEksDetector.ts b/detectors/node/opentelemetry-resource-detector-aws/src/detectors/AwsEksDetector.ts index 196e2a1cc0..d85deb558e 100644 --- a/detectors/node/opentelemetry-resource-detector-aws/src/detectors/AwsEksDetector.ts +++ b/detectors/node/opentelemetry-resource-detector-aws/src/detectors/AwsEksDetector.ts @@ -180,7 +180,7 @@ export class AwsEksDetector implements Detector { return str.substring(str.length - this.CONTAINER_ID_LENGTH); } } - } catch (e) { + } catch (e: any) { diag.warn(`AwsEksDetector failed to read container ID: ${e.message}`); } return undefined; diff --git a/detectors/node/opentelemetry-resource-detector-container/CHANGELOG.md b/detectors/node/opentelemetry-resource-detector-container/CHANGELOG.md index 1cc86f0097..ba00ad3ac9 100644 --- a/detectors/node/opentelemetry-resource-detector-container/CHANGELOG.md +++ b/detectors/node/opentelemetry-resource-detector-container/CHANGELOG.md @@ -6,6 +6,24 @@ * devDependencies * @opentelemetry/contrib-test-utils bumped from ^0.30.0 to ^0.31.0 +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.32.0 to ^0.33.0 + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.0 to ^0.33.1 + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.1 to ^0.33.2 + ## [0.2.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/resource-detector-container-v0.1.2...resource-detector-container-v0.2.0) (2022-11-02) diff --git a/detectors/node/opentelemetry-resource-detector-container/package.json b/detectors/node/opentelemetry-resource-detector-container/package.json index af32bb9d80..c64a07b822 100644 --- a/detectors/node/opentelemetry-resource-detector-container/package.json +++ b/detectors/node/opentelemetry-resource-detector-container/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/resource-detector-container", - "version": "0.2.0", + "version": "0.2.3", "description": "Opentelemetry resource detector to get container resource attributes", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -36,19 +36,18 @@ }, "devDependencies": { "@opentelemetry/api": "^1.0.0", - "@opentelemetry/contrib-test-utils": "^0.32.0", + "@opentelemetry/contrib-test-utils": "^0.33.2", "@types/mocha": "8.2.3", "@types/node": "^18.0.0", "@types/sinon": "10.0.2", "eslint-plugin-header": "^3.1.1", - "gts": "^3.1.0", "mocha": "7.2.0", "nock": "12.0.3", "nyc": "15.1.0", - "rimraf": "3.0.2", - "sinon": "14.0.0", + "rimraf": "4.2.0", + "sinon": "15.0.1", "ts-mocha": "10.0.0", - "typescript": "4.3.5" + "typescript": "4.4.4" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0" diff --git a/detectors/node/opentelemetry-resource-detector-gcp/CHANGELOG.md b/detectors/node/opentelemetry-resource-detector-gcp/CHANGELOG.md index 58b25bfbc6..5e228b0e0f 100644 --- a/detectors/node/opentelemetry-resource-detector-gcp/CHANGELOG.md +++ b/detectors/node/opentelemetry-resource-detector-gcp/CHANGELOG.md @@ -12,6 +12,31 @@ * devDependencies * @opentelemetry/contrib-test-utils bumped from ^0.31.0 to ^0.32.0 +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.32.0 to ^0.33.0 + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.0 to ^0.33.1 + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.1 to ^0.33.2 + +## [0.28.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/resource-detector-gcp-v0.27.5...resource-detector-gcp-v0.28.0) (2023-02-08) + + +### Features + +* **detector-gcp:** collect hostname resource attribute from GCP Metadata API ([#1364](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1364)) ([33c57cc](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/33c57cc84a8b87ad3a58dde2014738deab1c375b)) + ## [0.27.3](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/resource-detector-gcp-v0.27.2...resource-detector-gcp-v0.27.3) (2022-11-02) diff --git a/detectors/node/opentelemetry-resource-detector-gcp/package.json b/detectors/node/opentelemetry-resource-detector-gcp/package.json index bb5aade21d..fc7c6460a7 100644 --- a/detectors/node/opentelemetry-resource-detector-gcp/package.json +++ b/detectors/node/opentelemetry-resource-detector-gcp/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/resource-detector-gcp", - "version": "0.27.3", + "version": "0.28.1", "description": "OpenTelemetry SDK resource detector for GCP", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -42,17 +42,16 @@ }, "devDependencies": { "@opentelemetry/api": "^1.0.0", - "@opentelemetry/contrib-test-utils": "^0.32.0", + "@opentelemetry/contrib-test-utils": "^0.33.2", "@types/mocha": "8.2.3", "@types/node": "18.11.7", "@types/semver": "7.3.8", - "gts": "3.1.0", "mocha": "7.2.0", "nock": "12.0.3", "nyc": "15.1.0", - "rimraf": "3.0.2", + "rimraf": "4.2.0", "ts-mocha": "10.0.0", - "typescript": "4.3.5" + "typescript": "4.4.4" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0" @@ -61,8 +60,7 @@ "@opentelemetry/core": "^1.0.0", "@opentelemetry/resources": "^1.0.0", "@opentelemetry/semantic-conventions": "^1.0.0", - "gcp-metadata": "^5.0.0", - "semver": "7.3.5" + "gcp-metadata": "^5.0.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/detectors/node/opentelemetry-resource-detector-gcp#readme" } diff --git a/detectors/node/opentelemetry-resource-detector-gcp/src/detectors/GcpDetector.ts b/detectors/node/opentelemetry-resource-detector-gcp/src/detectors/GcpDetector.ts index 1d4139d70c..206bb4d1d3 100644 --- a/detectors/node/opentelemetry-resource-detector-gcp/src/detectors/GcpDetector.ts +++ b/detectors/node/opentelemetry-resource-detector-gcp/src/detectors/GcpDetector.ts @@ -14,7 +14,6 @@ * limitations under the License. */ -import * as semver from 'semver'; import * as gcpMetadata from 'gcp-metadata'; import { diag } from '@opentelemetry/api'; import { @@ -44,24 +43,24 @@ class GcpDetector implements Detector { * @param config The resource detection config */ async detect(_config?: ResourceDetectionConfig): Promise { - if ( - !semver.satisfies(process.version, '>=10') || - !(await gcpMetadata.isAvailable()) - ) { + if (!(await gcpMetadata.isAvailable())) { diag.debug('GcpDetector failed: GCP Metadata unavailable.'); return Resource.empty(); } - const [projectId, instanceId, zoneId, clusterName] = await Promise.all([ - this._getProjectId(), - this._getInstanceId(), - this._getZone(), - this._getClusterName(), - ]); + const [projectId, instanceId, zoneId, clusterName, hostname] = + await Promise.all([ + this._getProjectId(), + this._getInstanceId(), + this._getZone(), + this._getClusterName(), + this._getHostname(), + ]); const attributes: ResourceAttributes = {}; attributes[SemanticResourceAttributes.CLOUD_ACCOUNT_ID] = projectId; attributes[SemanticResourceAttributes.HOST_ID] = instanceId; + attributes[SemanticResourceAttributes.HOST_NAME] = hostname; attributes[SemanticResourceAttributes.CLOUD_AVAILABILITY_ZONE] = zoneId; attributes[SemanticResourceAttributes.CLOUD_PROVIDER] = CloudProviderValues.GCP; @@ -125,6 +124,15 @@ class GcpDetector implements Detector { return ''; } } + + /** Gets hostname from GCP instance metadata. */ + private async _getHostname(): Promise { + try { + return await gcpMetadata.instance('hostname'); + } catch { + return ''; + } + } } export const gcpDetector = new GcpDetector(); diff --git a/detectors/node/opentelemetry-resource-detector-gcp/test/detectors/GcpDetector.test.ts b/detectors/node/opentelemetry-resource-detector-gcp/test/detectors/GcpDetector.test.ts index ee1b59b4e6..85f40e413f 100644 --- a/detectors/node/opentelemetry-resource-detector-gcp/test/detectors/GcpDetector.test.ts +++ b/detectors/node/opentelemetry-resource-detector-gcp/test/detectors/GcpDetector.test.ts @@ -23,7 +23,6 @@ import { resetIsAvailableCache, } from 'gcp-metadata'; import * as nock from 'nock'; -import * as semver from 'semver'; import { gcpDetector } from '../../src'; import { assertCloudResource, @@ -42,127 +41,134 @@ const INSTANCE_ID_PATH = BASE_PATH + '/instance/id'; const PROJECT_ID_PATH = BASE_PATH + '/project/project-id'; const ZONE_PATH = BASE_PATH + '/instance/zone'; const CLUSTER_NAME_PATH = BASE_PATH + '/instance/attributes/cluster-name'; +const HOSTNAME_PATH = BASE_PATH + '/instance/hostname'; -(semver.satisfies(process.version, '>=10') ? describe : describe.skip)( - 'gcpDetector', - () => { - describe('.detect', () => { - before(() => { - nock.disableNetConnect(); - }); +describe('gcpDetector', () => { + describe('.detect', () => { + before(() => { + nock.disableNetConnect(); + }); - after(() => { - nock.enableNetConnect(); - delete process.env.KUBERNETES_SERVICE_HOST; - delete process.env.NAMESPACE; - delete process.env.CONTAINER_NAME; - delete process.env.HOSTNAME; - }); + after(() => { + nock.enableNetConnect(); + delete process.env.KUBERNETES_SERVICE_HOST; + delete process.env.NAMESPACE; + delete process.env.CONTAINER_NAME; + delete process.env.HOSTNAME; + }); - beforeEach(() => { - resetIsAvailableCache(); - nock.cleanAll(); - delete process.env.KUBERNETES_SERVICE_HOST; - delete process.env.NAMESPACE; - delete process.env.CONTAINER_NAME; - delete process.env.HOSTNAME; - }); + beforeEach(() => { + resetIsAvailableCache(); + nock.cleanAll(); + delete process.env.KUBERNETES_SERVICE_HOST; + delete process.env.NAMESPACE; + delete process.env.CONTAINER_NAME; + delete process.env.HOSTNAME; + }); - it('should return resource with GCP metadata', async () => { - const scope = nock(HOST_ADDRESS) - .get(INSTANCE_PATH) - .reply(200, {}, HEADERS) - .get(INSTANCE_ID_PATH) - // This number is too large to be safely represented by a JS number - // See https://github.com/googleapis/gcp-metadata/tree/fc2f0778138b36285643b2f716c485bf9614611f#take-care-with-large-number-valued-properties - .reply(200, () => '4520031799277581759', HEADERS) - .get(PROJECT_ID_PATH) - .reply(200, () => 'my-project-id', HEADERS) - .get(ZONE_PATH) - .reply(200, () => 'project/zone/my-zone', HEADERS) - .get(CLUSTER_NAME_PATH) - .reply(404); - const secondaryScope = nock(SECONDARY_HOST_ADDRESS) - .get(INSTANCE_PATH) - .reply(200, {}, HEADERS); - const resource: Resource = await gcpDetector.detect(); - secondaryScope.done(); - scope.done(); + it('should return resource with GCP metadata', async () => { + const scope = nock(HOST_ADDRESS) + .get(INSTANCE_PATH) + .reply(200, {}, HEADERS) + .get(INSTANCE_ID_PATH) + // This number is too large to be safely represented by a JS number + // See https://github.com/googleapis/gcp-metadata/tree/fc2f0778138b36285643b2f716c485bf9614611f#take-care-with-large-number-valued-properties + .reply(200, () => '4520031799277581759', HEADERS) + .get(PROJECT_ID_PATH) + .reply(200, () => 'my-project-id', HEADERS) + .get(ZONE_PATH) + .reply(200, () => 'project/zone/my-zone', HEADERS) + .get(CLUSTER_NAME_PATH) + .reply(404) + .get(HOSTNAME_PATH) + .reply(200, () => 'dev.my-project.local', HEADERS); + const secondaryScope = nock(SECONDARY_HOST_ADDRESS) + .get(INSTANCE_PATH) + .reply(200, {}, HEADERS); + const resource: Resource = await gcpDetector.detect(); + secondaryScope.done(); + scope.done(); - assertCloudResource(resource, { - provider: 'gcp', - accountId: 'my-project-id', - zone: 'my-zone', - }); - assertHostResource(resource, { id: '4520031799277581759' }); + assertCloudResource(resource, { + provider: 'gcp', + accountId: 'my-project-id', + zone: 'my-zone', }); + assertHostResource(resource, { + id: '4520031799277581759', + name: 'dev.my-project.local', + }); + }); - it('should populate K8s attributes when KUBERNETES_SERVICE_HOST is set', async () => { - process.env.KUBERNETES_SERVICE_HOST = 'my-host'; - process.env.NAMESPACE = 'my-namespace'; - process.env.HOSTNAME = 'my-hostname'; - process.env.CONTAINER_NAME = 'my-container-name'; - const scope = nock(HOST_ADDRESS) - .get(INSTANCE_PATH) - .reply(200, {}, HEADERS) - .get(INSTANCE_ID_PATH) - .reply(200, () => '4520031799277581759', HEADERS) - .get(CLUSTER_NAME_PATH) - .reply(200, () => 'my-cluster', HEADERS) - .get(PROJECT_ID_PATH) - .reply(200, () => 'my-project-id', HEADERS) - .get(ZONE_PATH) - .reply(200, () => 'project/zone/my-zone', HEADERS); - const secondaryScope = nock(SECONDARY_HOST_ADDRESS) - .get(INSTANCE_PATH) - .reply(200, {}, HEADERS); - const resource = await gcpDetector.detect(); - secondaryScope.done(); - scope.done(); + it('should populate K8s attributes when KUBERNETES_SERVICE_HOST is set', async () => { + process.env.KUBERNETES_SERVICE_HOST = 'my-host'; + process.env.NAMESPACE = 'my-namespace'; + process.env.HOSTNAME = 'my-hostname'; + process.env.CONTAINER_NAME = 'my-container-name'; + const scope = nock(HOST_ADDRESS) + .get(INSTANCE_PATH) + .reply(200, {}, HEADERS) + .get(INSTANCE_ID_PATH) + .reply(200, () => '4520031799277581759', HEADERS) + .get(CLUSTER_NAME_PATH) + .reply(200, () => 'my-cluster', HEADERS) + .get(PROJECT_ID_PATH) + .reply(200, () => 'my-project-id', HEADERS) + .get(ZONE_PATH) + .reply(200, () => 'project/zone/my-zone', HEADERS) + .get(HOSTNAME_PATH) + .reply(200, () => 'dev.my-project.local', HEADERS); + const secondaryScope = nock(SECONDARY_HOST_ADDRESS) + .get(INSTANCE_PATH) + .reply(200, {}, HEADERS); + const resource = await gcpDetector.detect(); + secondaryScope.done(); + scope.done(); - assertCloudResource(resource, { - provider: 'gcp', - accountId: 'my-project-id', - zone: 'my-zone', - }); - assertK8sResource(resource, { - clusterName: 'my-cluster', - podName: 'my-hostname', - namespaceName: 'my-namespace', - }); - assertContainerResource(resource, { name: 'my-container-name' }); + assertCloudResource(resource, { + provider: 'gcp', + accountId: 'my-project-id', + zone: 'my-zone', + }); + assertK8sResource(resource, { + clusterName: 'my-cluster', + podName: 'my-hostname', + namespaceName: 'my-namespace', }); + assertContainerResource(resource, { name: 'my-container-name' }); + }); - it('should return resource and empty data for non-available metadata attributes', async () => { - const scope = nock(HOST_ADDRESS) - .get(INSTANCE_PATH) - .reply(200, {}, HEADERS) - .get(PROJECT_ID_PATH) - .reply(200, () => 'my-project-id', HEADERS) - .get(ZONE_PATH) - .reply(413) - .get(INSTANCE_ID_PATH) - .reply(400, undefined, HEADERS) - .get(CLUSTER_NAME_PATH) - .reply(413); - const secondaryScope = nock(SECONDARY_HOST_ADDRESS) - .get(INSTANCE_PATH) - .reply(200, {}, HEADERS); - const resource = await gcpDetector.detect(); - secondaryScope.done(); - scope.done(); + it('should return resource and empty data for non-available metadata attributes', async () => { + const scope = nock(HOST_ADDRESS) + .get(INSTANCE_PATH) + .reply(200, {}, HEADERS) + .get(PROJECT_ID_PATH) + .reply(200, () => 'my-project-id', HEADERS) + .get(ZONE_PATH) + .reply(413) + .get(INSTANCE_ID_PATH) + .reply(400, undefined, HEADERS) + .get(CLUSTER_NAME_PATH) + .reply(413) + .get(HOSTNAME_PATH) + .reply(400, undefined, HEADERS); + const secondaryScope = nock(SECONDARY_HOST_ADDRESS) + .get(INSTANCE_PATH) + .reply(200, {}, HEADERS); + const resource = await gcpDetector.detect(); + secondaryScope.done(); + scope.done(); - assertCloudResource(resource, { - provider: 'gcp', - accountId: 'my-project-id', - zone: '', - }); + assertCloudResource(resource, { + provider: 'gcp', + accountId: 'my-project-id', + zone: '', }); + }); - it('returns empty resource if not detected', async () => { - const resource = await gcpDetector.detect(); - assertEmptyResource(resource); - }); + it('returns empty resource if not detected', async () => { + const resource = await gcpDetector.detect(); + assertEmptyResource(resource); }); - } -); + }); +}); diff --git a/detectors/node/opentelemetry-resource-detector-github/package.json b/detectors/node/opentelemetry-resource-detector-github/package.json index e0227a18d5..68516384f2 100644 --- a/detectors/node/opentelemetry-resource-detector-github/package.json +++ b/detectors/node/opentelemetry-resource-detector-github/package.json @@ -49,13 +49,12 @@ "@types/mocha": "8.2.3", "@types/node": "18.11.7", "@types/sinon": "10.0.2", - "gts": "3.1.0", "mocha": "7.2.0", "nyc": "15.1.0", - "rimraf": "3.0.2", - "sinon": "14.0.0", + "rimraf": "4.2.0", + "sinon": "15.0.1", "ts-mocha": "10.0.0", - "typescript": "4.3.5" + "typescript": "4.4.4" }, "dependencies": { "@opentelemetry/resources": "^1.0.0" diff --git a/detectors/node/opentelemetry-resource-detector-instana/CHANGELOG.md b/detectors/node/opentelemetry-resource-detector-instana/CHANGELOG.md index e9132a489d..7b8c167dfd 100644 --- a/detectors/node/opentelemetry-resource-detector-instana/CHANGELOG.md +++ b/detectors/node/opentelemetry-resource-detector-instana/CHANGELOG.md @@ -1,5 +1,47 @@ # Changelog +## [0.4.2](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/resource-detector-instana-v0.4.1...resource-detector-instana-v0.4.2) (2023-04-25) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.38.0 ([#1468](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1468)) ([565a2b2](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/565a2b2c6fde88af3f5401ef6a5a9643d0d66349)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.1 to ^0.33.2 + +## [0.4.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/resource-detector-instana-v0.4.0...resource-detector-instana-v0.4.1) (2023-02-07) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.35.1 ([#1358](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1358)) ([ff109b7](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/ff109b77928cc9a139a21c63d6b54399bb017fa4)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.0 to ^0.33.1 + +## [0.4.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/resource-detector-instana-v0.3.0...resource-detector-instana-v0.4.0) (2022-11-16) + + +### Features + +* update experimental deps to `^0.34.0`, core deps to `^1.8.0`, api to `^1.3.0` ([#1278](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1278)) ([e9fe8e1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/e9fe8e13e34f54e96c50525cadeb74ac048c5624)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.32.0 to ^0.33.0 + ## [0.3.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/resource-detector-instana-v0.2.0...resource-detector-instana-v0.3.0) (2022-09-02) diff --git a/detectors/node/opentelemetry-resource-detector-instana/README.md b/detectors/node/opentelemetry-resource-detector-instana/README.md index 427f00a259..fef7b05bbd 100644 --- a/detectors/node/opentelemetry-resource-detector-instana/README.md +++ b/detectors/node/opentelemetry-resource-detector-instana/README.md @@ -35,17 +35,11 @@ const globalResource = new Resource({ }); const sdk = new NodeSDK({ - autoDetectResources: false, + resourceDetectors: [envDetector, processDetector, instanaAgentDetector], resource: globalResource, }); -(async () => { - await sdk.detectResources({ - detectors: [envDetector, processDetector, instanaAgentDetector], - }); - - await sdk.start(); -}()); +sdk.start() ``` ## Useful links diff --git a/detectors/node/opentelemetry-resource-detector-instana/package.json b/detectors/node/opentelemetry-resource-detector-instana/package.json index f9d0a4973e..f9275e4488 100644 --- a/detectors/node/opentelemetry-resource-detector-instana/package.json +++ b/detectors/node/opentelemetry-resource-detector-instana/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/resource-detector-instana", - "version": "0.3.0", + "version": "0.4.2", "description": "OpenTelemetry SDK resource detector for Instana", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -39,26 +39,25 @@ "access": "public" }, "devDependencies": { - "@opentelemetry/api": "^1.0.0", - "@opentelemetry/contrib-test-utils": "^0.32.0", - "@opentelemetry/sdk-node": "^0.32.0", + "@opentelemetry/api": "^1.3.0", + "@opentelemetry/contrib-test-utils": "^0.33.2", + "@opentelemetry/sdk-node": "^0.38.0", "@types/mocha": "8.2.3", "@types/node": "18.11.7", "@types/semver": "7.3.8", "mocha": "7.2.0", "nock": "12.0.3", - "gts": "3.1.0", "nyc": "15.1.0", - "rimraf": "3.0.2", + "rimraf": "4.2.0", "ts-mocha": "10.0.0", - "typescript": "4.3.5" + "typescript": "4.4.4" }, "dependencies": { "@opentelemetry/resources": "^1.0.0", "@opentelemetry/semantic-conventions": "^1.0.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@opentelemetry/api": "^1.3.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/detectors/node/opentelemetry-resource-detector-instana#readme" } diff --git a/detectors/node/opentelemetry-resource-detector-instana/src/detectors/InstanaAgentDetector.ts b/detectors/node/opentelemetry-resource-detector-instana/src/detectors/InstanaAgentDetector.ts index 64968ad0fb..e036523240 100644 --- a/detectors/node/opentelemetry-resource-detector-instana/src/detectors/InstanaAgentDetector.ts +++ b/detectors/node/opentelemetry-resource-detector-instana/src/detectors/InstanaAgentDetector.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Detector, Resource } from '@opentelemetry/resources'; +import { Detector, Resource, IResource } from '@opentelemetry/resources'; import { diag } from '@opentelemetry/api'; import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions'; import * as http from 'http'; @@ -22,7 +22,7 @@ class InstanaAgentDetector implements Detector { readonly INSTANA_AGENT_DEFAULT_HOST = 'localhost'; readonly INSTANA_AGENT_DEFAULT_PORT = 42699; - async detect(): Promise { + async detect(): Promise { const host = process.env.INSTANA_AGENT_HOST || this.INSTANA_AGENT_DEFAULT_HOST; const port = Number( @@ -112,7 +112,6 @@ class InstanaAgentDetector implements Detector { try { const data = JSON.parse(rawData); - if (data.pid && data.agentUuid) { return resolve(data); } diff --git a/detectors/node/opentelemetry-resource-detector-instana/test/InstanaAgentDetectorIntegrationTest.test.ts b/detectors/node/opentelemetry-resource-detector-instana/test/InstanaAgentDetectorIntegrationTest.test.ts index 92ee31bf55..ee8124f3cc 100644 --- a/detectors/node/opentelemetry-resource-detector-instana/test/InstanaAgentDetectorIntegrationTest.test.ts +++ b/detectors/node/opentelemetry-resource-detector-instana/test/InstanaAgentDetectorIntegrationTest.test.ts @@ -25,6 +25,11 @@ import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions' import { NodeSDK } from '@opentelemetry/sdk-node'; import { instanaAgentDetector } from '../src'; +const delay = (ms: number) => + new Promise(resolve => { + setTimeout(resolve, ms); + }); + describe('[Integration] instanaAgentDetector', () => { beforeEach(() => { nock.disableNetConnect(); @@ -36,7 +41,7 @@ describe('[Integration] instanaAgentDetector', () => { nock.cleanAll(); }); - it('should return merged resource', async () => { + it('#1 should return merged resource', async () => { const mockedReply = { pid: 123, agentUuid: '14:7d:da:ff:fe:e4:08:d5', @@ -53,17 +58,54 @@ describe('[Integration] instanaAgentDetector', () => { }); const sdk = new NodeSDK({ - autoDetectResources: false, + resourceDetectors: [envDetector, processDetector, instanaAgentDetector], resource: globalResource, }); - // attributes are automatically merged! - await sdk.detectResources({ - detectors: [envDetector, processDetector, instanaAgentDetector], + sdk.start(); + + const resource = sdk['_resource']; + // await sdk.detectResources(); [< @opentelemetry/sdk-node@0.37.0] + // await resource.waitForAsyncAttributes?.(); [>= @opentelemetry/sdk-node@0.37.0] + await resource.waitForAsyncAttributes?.(); + + assert.equal(resource.attributes['process.pid'], 123); + assert.equal(resource.attributes['process.runtime.name'], 'nodejs'); + assert.equal(resource.attributes['service.name'], 'TestService'); + assert.equal( + resource.attributes['service.instance.id'], + '14:7d:da:ff:fe:e4:08:d5' + ); + + scope.done(); + }); + + it('#2 should return merged resource', async () => { + const mockedReply = { + pid: 123, + agentUuid: '14:7d:da:ff:fe:e4:08:d5', + }; + + const scope = nock('http://localhost:42699') + .persist() + .put('/com.instana.plugin.nodejs.discovery') + .reply(200, () => mockedReply); + + const serviceName = 'TestService'; + const globalResource = new Resource({ + [SemanticResourceAttributes.SERVICE_NAME]: serviceName, + }); + + const sdk = new NodeSDK({ + resourceDetectors: [envDetector, processDetector, instanaAgentDetector], + resource: globalResource, }); + sdk.start(); const resource = sdk['_resource']; + await delay(500); + assert.equal(resource.attributes['process.pid'], 123); assert.equal(resource.attributes['process.runtime.name'], 'nodejs'); assert.equal(resource.attributes['service.name'], 'TestService'); diff --git a/detectors/node/opentelemetry-resource-detector-instana/test/InstanaAgentDetectorUnitTest.test.ts b/detectors/node/opentelemetry-resource-detector-instana/test/InstanaAgentDetectorUnitTest.test.ts index d95c4f85c5..6799d96013 100644 --- a/detectors/node/opentelemetry-resource-detector-instana/test/InstanaAgentDetectorUnitTest.test.ts +++ b/detectors/node/opentelemetry-resource-detector-instana/test/InstanaAgentDetectorUnitTest.test.ts @@ -138,7 +138,7 @@ describe('[UNIT] instanaAgentDetector', () => { try { await instanaAgentDetector.detect(); assert.ok(false, 'Expected to throw'); - } catch (err) { + } catch (err: any) { assert.equal(err.code, 'ECONNREFUSED'); } }); diff --git a/eslint.config.js b/eslint.config.js index 1b57d26fd1..2ebc6dc369 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -2,50 +2,64 @@ module.exports = { plugins: [ "@typescript-eslint", "header", - "import" - ], - extends: [ - "./node_modules/gts", + "node", + "prettier" ], + extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:prettier/recommended"], parser: "@typescript-eslint/parser", parserOptions: { - "project": "./tsconfig.json" + "project": "./tsconfig.json" }, rules: { - "quotes": [2, "single", { "avoidEscape": true }], - "@typescript-eslint/no-this-alias": "off", + "quotes": ["error", "single", { "avoidEscape": true }], "eqeqeq": "off", "prefer-rest-params": "off", - "@typescript-eslint/naming-convention": [ - "error", - { - "selector": "memberLike", - "modifiers": ["private", "protected"], - "format": ["camelCase"], - "leadingUnderscore": "require" - } - ], - "@typescript-eslint/no-inferrable-types": ["error", { ignoreProperties: true }], - "arrow-parens": ["error", "as-needed"], - "prettier/prettier": ["error", { "singleQuote": true, "arrowParens": "avoid" }], + "no-shadow": "off", "node/no-deprecated-api": ["warn"], - "header/header": [2, "block", [{ - pattern: / \* Copyright The OpenTelemetry Authors[\r\n]+ \*[\r\n]+ \* Licensed under the Apache License, Version 2\.0 \(the \"License\"\);[\r\n]+ \* you may not use this file except in compliance with the License\.[\r\n]+ \* You may obtain a copy of the License at[\r\n]+ \*[\r\n]+ \* https:\/\/www\.apache\.org\/licenses\/LICENSE-2\.0[\r\n]+ \*[\r\n]+ \* Unless required by applicable law or agreed to in writing, software[\r\n]+ \* distributed under the License is distributed on an \"AS IS\" BASIS,[\r\n]+ \* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied\.[\r\n]+ \* See the License for the specific language governing permissions and[\r\n]+ \* limitations under the License\./gm, - template: + "header/header": ["error", "block", [{ + pattern: / \* Copyright The OpenTelemetry Authors[\r\n]+ \*[\r\n]+ \* Licensed under the Apache License, Version 2\.0 \(the \"License\"\);[\r\n]+ \* you may not use this file except in compliance with the License\.[\r\n]+ \* You may obtain a copy of the License at[\r\n]+ \*[\r\n]+ \* https:\/\/www\.apache\.org\/licenses\/LICENSE-2\.0[\r\n]+ \*[\r\n]+ \* Unless required by applicable law or agreed to in writing, software[\r\n]+ \* distributed under the License is distributed on an \"AS IS\" BASIS,[\r\n]+ \* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied\.[\r\n]+ \* See the License for the specific language governing permissions and[\r\n]+ \* limitations under the License\./gm, + template: `\n * Copyright The OpenTelemetry Authors\n *\n * Licensed under the Apache License, Version 2.0 (the "License");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n ` - }]], - "import/no-extraneous-dependencies": ["error", { devDependencies: ["test/**/*.ts"] }], + }]] }, overrides: [ { - "files": ["test/**/*.ts"], - "rules": { + files: ['*.ts'], + rules: { + "@typescript-eslint/no-this-alias": "off", + "@typescript-eslint/naming-convention": [ + "error", + { + "selector": "memberLike", + "modifiers": ["private", "protected"], + "format": ["camelCase"], + "leadingUnderscore": "require" + } + ], + "@typescript-eslint/no-var-requires": "off", + "@typescript-eslint/no-inferrable-types": ["error", { ignoreProperties: true }], + "@typescript-eslint/no-empty-function": ["off"], + "@typescript-eslint/ban-types": ["warn", { + "types": { + "Function": null, + } + }], + "@typescript-eslint/no-shadow": ["warn"], + } + }, + { + files: ["test/**/*.ts"], + rules: { "no-empty": "off", "@typescript-eslint/ban-ts-ignore": "off", "@typescript-eslint/no-empty-function": "off", "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-unused-vars": "off", - "@typescript-eslint/no-var-requires": "off" + "@typescript-eslint/no-var-requires": "off", + "@typescript-eslint/no-shadow": ["off"], + "@typescript-eslint/no-floating-promises": ["off"], + "@typescript-eslint/no-non-null-assertion": ["off"], + "@typescript-eslint/explicit-module-boundary-types": ["off"] } } ] diff --git a/examples/connect/package.json b/examples/connect/package.json index 0f1ec2f1cf..eb58fc2299 100644 --- a/examples/connect/package.json +++ b/examples/connect/package.json @@ -1,7 +1,7 @@ { "name": "connect-example", "private": true, - "version": "0.24.0", + "version": "0.25.0", "description": "Example of Connect integration with OpenTelemetry", "main": "index.js", "scripts": { @@ -41,7 +41,7 @@ "@opentelemetry/exporter-zipkin": "^0.25.0", "@opentelemetry/exporter-collector": "^0.25.0", "@opentelemetry/instrumentation": "^0.25.0", - "@opentelemetry/instrumentation-connect": "^0.24.0", + "@opentelemetry/instrumentation-connect": "^0.25.0", "@opentelemetry/instrumentation-http": "^0.25.0", "@opentelemetry/sdk-trace-node": "^0.25.0", "@opentelemetry/resources": "^0.25.0", diff --git a/examples/fastify/README.md b/examples/fastify/README.md index 844b20a32c..378a46cf13 100644 --- a/examples/fastify/README.md +++ b/examples/fastify/README.md @@ -9,6 +9,12 @@ This is a simple example that demonstrates tracing calls made to Fastify API. Th - Span Events - Span Attributes +## Prerequisites + +Install [Docker Desktop](https://docs.docker.com/desktop), version 4.12.0 or later. + +If you have an existing Docker Engine installation, you can [install the docker-compose plugin](https://docs.docker.com/compose/install) instead. + ## Installation ```sh @@ -22,26 +28,26 @@ npm install - Run docker container with collector - ```sh - # from this directory - $ npm run docker:start - ``` + ```sh + # from this directory + $ npm run docker:start + ``` ### Server - Run the server - ```sh - # from this directory - $ npm run server - ``` + ```sh + # from this directory + $ npm run server + ``` - Run the client - ```sh - # from this directory - npm run client - ``` + ```sh + # from this directory + npm run client + ``` #### Zipkin UI diff --git a/examples/fastify/package.json b/examples/fastify/package.json index 1cae7b7aa9..f4d2a07c6b 100644 --- a/examples/fastify/package.json +++ b/examples/fastify/package.json @@ -6,8 +6,8 @@ "main": "index.js", "scripts": { "client": "node ./client.js", - "docker:start": "cd ./docker && docker-compose down && docker-compose up", - "docker:stop": "cd ./docker && docker-compose down", + "docker:start": "cd ./docker && docker compose down && docker compose up", + "docker:stop": "cd ./docker && docker compose down", "server": "node ./server.js" }, "repository": { diff --git a/examples/ioredis/tracer.js b/examples/ioredis/tracer.js index dec989fec2..6d18533d9a 100644 --- a/examples/ioredis/tracer.js +++ b/examples/ioredis/tracer.js @@ -20,6 +20,7 @@ registerInstrumentations({ instrumentations: [ new IORedisInstrumentation(), ], + tracerProvider: provider, }); module.exports = opentelemetry.trace.getTracer('ioredis-example'); diff --git a/examples/react-load/preact/docker/collector-config.yaml b/examples/react-load/preact/docker/collector-config.yaml index 2f64d8b4fc..377986bf2d 100644 --- a/examples/react-load/preact/docker/collector-config.yaml +++ b/examples/react-load/preact/docker/collector-config.yaml @@ -1,18 +1,25 @@ receivers: otlp: - endpoint: 0.0.0.0:55678 + protocols: + http: + cors: + allowed_origins: + - http://* + - https://* exporters: zipkin: - url: "http://zipkin-all-in-one:9411/api/v2/spans" + endpoint: "http://zipkin-all-in-one:9411/api/v2/spans" processors: batch: - queued_retry: service: pipelines: traces: receivers: [otlp] exporters: [zipkin] - processors: [batch, queued_retry] + processors: [batch] + telemetry: + logs: + level: "debug" diff --git a/examples/react-load/preact/docker/docker-compose.yaml b/examples/react-load/preact/docker/docker-compose.yaml index fee8f1aca0..ab8fead390 100644 --- a/examples/react-load/preact/docker/docker-compose.yaml +++ b/examples/react-load/preact/docker/docker-compose.yaml @@ -3,12 +3,12 @@ services: # Collector collector: - image: omnition/opentelemetry-collector-contrib:0.2.8 - command: ["--config=/conf/collector-config.yaml", "--log-level=DEBUG"] + image: otel/opentelemetry-collector-contrib:0.75.0 + command: ["--config=/conf/collector-config.yaml"] volumes: - ./collector-config.yaml:/conf/collector-config.yaml ports: - - "55678:55678" + - "4318:4318" depends_on: - zipkin-all-in-one diff --git a/examples/react-load/preact/package.json b/examples/react-load/preact/package.json index 63719c9754..4d72912152 100644 --- a/examples/react-load/preact/package.json +++ b/examples/react-load/preact/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "react-load-preact-example", - "version": "0.23.0", + "version": "0.24.0", "description": "Example of using @opentelemetry/plugin-react-load in browser with Preact", "main": "index.js", "scripts": { @@ -23,7 +23,7 @@ "tracing" ], "engines": { - "node": ">=8" + "node": ">=14" }, "author": "OpenTelemetry Authors", "license": "Apache-2.0", @@ -33,15 +33,14 @@ "devDependencies": { "identity-obj-proxy": "^3.0.0", "preact-cli": "^3.0.0", - "preact-render-spy": "^1.2.1", "sirv-cli": "1.0.3" }, "dependencies": { - "@opentelemetry/context-zone": "^0.25.0", - "@opentelemetry/exporter-collector": "^0.25.0", - "@opentelemetry/plugin-react-load": "^0.23.0", - "@opentelemetry/sdk-trace-base": "^0.25.0", - "@opentelemetry/sdk-trace-web": "^0.25.0", + "@opentelemetry/context-zone": "^1.11.0", + "@opentelemetry/exporter-trace-otlp-http": "^0.37.0", + "@opentelemetry/plugin-react-load": "^0.28.1", + "@opentelemetry/sdk-trace-base": "^1.11.0", + "@opentelemetry/sdk-trace-web": "^1.11.0", "preact": "^10.3.2", "preact-render-to-string": "^5.1.4", "preact-router": "^3.2.1" diff --git a/examples/react-load/preact/src/web-tracer.js b/examples/react-load/preact/src/web-tracer.js index 984374bfbe..b52d436e0a 100644 --- a/examples/react-load/preact/src/web-tracer.js +++ b/examples/react-load/preact/src/web-tracer.js @@ -1,14 +1,15 @@ import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base'; +import { diag, DiagConsoleLogger, DiagLogLevel } from '@opentelemetry/api'; import { WebTracerProvider } from '@opentelemetry/sdk-trace-web'; import { BaseOpenTelemetryComponent } from '@opentelemetry/plugin-react-load'; import { ZoneContextManager } from '@opentelemetry/context-zone'; -import { CollectorTraceExporter } from '@opentelemetry/exporter-collector'; +import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'; export default (serviceName) => { + diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.DEBUG); const provider = new WebTracerProvider(); - - const exporter = new CollectorTraceExporter({ - url: 'http://localhost:55678/v1/trace', + const exporter = new OTLPTraceExporter({ + url: 'http://localhost:4318/v1/traces', }); provider.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter())); @@ -21,7 +22,6 @@ export default (serviceName) => { const tracer = provider.getTracer(serviceName); BaseOpenTelemetryComponent.setTracer(serviceName) - BaseOpenTelemetryComponent.setLogger(provider.logger) return tracer; } diff --git a/karma.webpack.js b/karma.webpack.js index 158e61c32e..546704817a 100644 --- a/karma.webpack.js +++ b/karma.webpack.js @@ -32,7 +32,10 @@ module.exports = { test: /\.ts$/, use: { loader: '@jsdevtools/coverage-istanbul-loader', - options: { esModules: true } + options: { + produceSourceMap: false, + esModules: true + } } }, // This setting configures Node polyfills for the browser that will be diff --git a/metapackages/auto-instrumentations-node/CHANGELOG.md b/metapackages/auto-instrumentations-node/CHANGELOG.md index 709535cb7f..9e86e111e1 100644 --- a/metapackages/auto-instrumentations-node/CHANGELOG.md +++ b/metapackages/auto-instrumentations-node/CHANGELOG.md @@ -52,6 +52,201 @@ * dependencies * @opentelemetry/instrumentation-express bumped from ^0.31.1 to ^0.31.2 +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @opentelemetry/instrumentation-aws-lambda bumped from ^0.34.1 to ^0.35.0 + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @opentelemetry/instrumentation-amqplib bumped from ^0.32.1 to ^0.32.2 + * @opentelemetry/instrumentation-dataloader bumped from ^0.3.1 to ^0.4.0 + * @opentelemetry/instrumentation-dns bumped from ^0.31.1 to ^0.31.2 + * @opentelemetry/instrumentation-nestjs-core bumped from ^0.32.1 to ^0.32.2 + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @opentelemetry/instrumentation-fs bumped from ^0.7.0 to ^0.7.1 + * @opentelemetry/instrumentation-graphql bumped from ^0.33.1 to ^0.33.2 + * @opentelemetry/instrumentation-ioredis bumped from ^0.33.2 to ^0.34.0 + * @opentelemetry/instrumentation-koa bumped from ^0.34.1 to ^0.34.2 + * @opentelemetry/instrumentation-pg bumped from ^0.34.1 to ^0.35.0 + * @opentelemetry/instrumentation-redis bumped from ^0.34.2 to ^0.34.3 + * @opentelemetry/instrumentation-redis-4 bumped from ^0.34.2 to ^0.34.3 + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @opentelemetry/instrumentation-graphql bumped from ^0.33.2 to ^0.34.0 + * @opentelemetry/instrumentation-koa bumped from ^0.34.2 to ^0.34.3 + * @opentelemetry/instrumentation-redis bumped from ^0.34.3 to ^0.34.4 + +## [0.36.6](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/auto-instrumentations-node-v0.36.5...auto-instrumentations-node-v0.36.6) (2023-04-25) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.38.0 ([#1468](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1468)) ([565a2b2](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/565a2b2c6fde88af3f5401ef6a5a9643d0d66349)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @opentelemetry/instrumentation-amqplib bumped from ^0.32.2 to ^0.32.3 + * @opentelemetry/instrumentation-aws-lambda bumped from ^0.35.0 to ^0.35.1 + * @opentelemetry/instrumentation-aws-sdk bumped from ^0.34.0 to ^0.34.1 + * @opentelemetry/instrumentation-bunyan bumped from ^0.31.1 to ^0.31.2 + * @opentelemetry/instrumentation-cassandra-driver bumped from ^0.32.1 to ^0.32.2 + * @opentelemetry/instrumentation-connect bumped from ^0.31.1 to ^0.31.2 + * @opentelemetry/instrumentation-dataloader bumped from ^0.4.0 to ^0.4.1 + * @opentelemetry/instrumentation-dns bumped from ^0.31.2 to ^0.31.3 + * @opentelemetry/instrumentation-express bumped from ^0.32.1 to ^0.32.2 + * @opentelemetry/instrumentation-fs bumped from ^0.7.1 to ^0.7.2 + * @opentelemetry/instrumentation-fastify bumped from ^0.31.1 to ^0.31.2 + * @opentelemetry/instrumentation-generic-pool bumped from ^0.31.1 to ^0.31.2 + * @opentelemetry/instrumentation-graphql bumped from ^0.34.0 to ^0.34.1 + * @opentelemetry/instrumentation-hapi bumped from ^0.31.1 to ^0.31.2 + * @opentelemetry/instrumentation-ioredis bumped from ^0.34.0 to ^0.34.1 + * @opentelemetry/instrumentation-knex bumped from ^0.31.1 to ^0.31.2 + * @opentelemetry/instrumentation-koa bumped from ^0.34.3 to ^0.34.4 + * @opentelemetry/instrumentation-lru-memoizer bumped from ^0.32.1 to ^0.32.2 + * @opentelemetry/instrumentation-memcached bumped from ^0.31.1 to ^0.31.2 + * @opentelemetry/instrumentation-mongodb bumped from ^0.34.1 to ^0.34.2 + * @opentelemetry/instrumentation-mongoose bumped from ^0.32.1 to ^0.32.2 + * @opentelemetry/instrumentation-mysql bumped from ^0.33.0 to ^0.33.1 + * @opentelemetry/instrumentation-mysql2 bumped from ^0.33.1 to ^0.33.2 + * @opentelemetry/instrumentation-nestjs-core bumped from ^0.32.2 to ^0.32.3 + * @opentelemetry/instrumentation-net bumped from ^0.31.1 to ^0.31.2 + * @opentelemetry/instrumentation-pg bumped from ^0.35.0 to ^0.35.1 + * @opentelemetry/instrumentation-pino bumped from ^0.33.1 to ^0.33.2 + * @opentelemetry/instrumentation-redis bumped from ^0.34.4 to ^0.34.5 + * @opentelemetry/instrumentation-redis-4 bumped from ^0.34.3 to ^0.34.4 + * @opentelemetry/instrumentation-restify bumped from ^0.32.1 to ^0.32.2 + * @opentelemetry/instrumentation-router bumped from ^0.32.1 to ^0.32.2 + * @opentelemetry/instrumentation-socket.io bumped from ^0.33.1 to ^0.33.2 + * @opentelemetry/instrumentation-tedious bumped from ^0.5.1 to ^0.5.2 + * @opentelemetry/instrumentation-winston bumped from ^0.31.1 to ^0.31.2 + +## [0.36.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/auto-instrumentations-node-v0.36.0...auto-instrumentations-node-v0.36.1) (2023-02-07) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.35.1 ([#1358](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1358)) ([ff109b7](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/ff109b77928cc9a139a21c63d6b54399bb017fa4)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @opentelemetry/instrumentation-amqplib bumped from ^0.32.0 to ^0.32.1 + * @opentelemetry/instrumentation-aws-lambda bumped from ^0.34.0 to ^0.34.1 + * @opentelemetry/instrumentation-aws-sdk bumped from ^0.33.0 to ^0.34.0 + * @opentelemetry/instrumentation-bunyan bumped from ^0.31.0 to ^0.31.1 + * @opentelemetry/instrumentation-cassandra-driver bumped from ^0.32.0 to ^0.32.1 + * @opentelemetry/instrumentation-connect bumped from ^0.31.0 to ^0.31.1 + * @opentelemetry/instrumentation-dataloader bumped from ^0.3.0 to ^0.3.1 + * @opentelemetry/instrumentation-dns bumped from ^0.31.0 to ^0.31.1 + * @opentelemetry/instrumentation-express bumped from ^0.32.0 to ^0.32.1 + * @opentelemetry/instrumentation-fs bumped from ^0.6.0 to ^0.7.0 + * @opentelemetry/instrumentation-fastify bumped from ^0.31.0 to ^0.31.1 + * @opentelemetry/instrumentation-generic-pool bumped from ^0.31.0 to ^0.31.1 + * @opentelemetry/instrumentation-graphql bumped from ^0.33.0 to ^0.33.1 + * @opentelemetry/instrumentation-hapi bumped from ^0.31.0 to ^0.31.1 + * @opentelemetry/instrumentation-ioredis bumped from ^0.33.1 to ^0.33.2 + * @opentelemetry/instrumentation-knex bumped from ^0.31.0 to ^0.31.1 + * @opentelemetry/instrumentation-koa bumped from ^0.34.0 to ^0.34.1 + * @opentelemetry/instrumentation-lru-memoizer bumped from ^0.32.0 to ^0.32.1 + * @opentelemetry/instrumentation-memcached bumped from ^0.31.0 to ^0.31.1 + * @opentelemetry/instrumentation-mongodb bumped from ^0.34.0 to ^0.34.1 + * @opentelemetry/instrumentation-mongoose bumped from ^0.32.0 to ^0.32.1 + * @opentelemetry/instrumentation-mysql bumped from ^0.32.0 to ^0.33.0 + * @opentelemetry/instrumentation-mysql2 bumped from ^0.33.0 to ^0.33.1 + * @opentelemetry/instrumentation-nestjs-core bumped from ^0.32.0 to ^0.32.1 + * @opentelemetry/instrumentation-net bumped from ^0.31.0 to ^0.31.1 + * @opentelemetry/instrumentation-pg bumped from ^0.34.0 to ^0.34.1 + * @opentelemetry/instrumentation-pino bumped from ^0.33.0 to ^0.33.1 + * @opentelemetry/instrumentation-redis bumped from ^0.34.1 to ^0.34.2 + * @opentelemetry/instrumentation-redis-4 bumped from ^0.34.1 to ^0.34.2 + * @opentelemetry/instrumentation-restify bumped from ^0.32.0 to ^0.32.1 + * @opentelemetry/instrumentation-router bumped from ^0.32.0 to ^0.32.1 + * @opentelemetry/instrumentation-socket.io bumped from ^0.33.0 to ^0.33.1 + * @opentelemetry/instrumentation-tedious bumped from ^0.5.0 to ^0.5.1 + * @opentelemetry/instrumentation-winston bumped from ^0.31.0 to ^0.31.1 + +## [0.36.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/auto-instrumentations-node-v0.35.0...auto-instrumentations-node-v0.36.0) (2022-12-20) + + +### Features + +* add socket.io instrumentation ([#1284](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1284)) ([f865143](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/f865143d9042c41ebed6adbe906097ad7622f2c7)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @opentelemetry/instrumentation-ioredis bumped from ^0.33.0 to ^0.33.1 + * @opentelemetry/instrumentation-mongodb bumped from ^0.33.0 to ^0.34.0 + * @opentelemetry/instrumentation-pg bumped from ^0.33.0 to ^0.34.0 + * @opentelemetry/instrumentation-redis bumped from ^0.34.0 to ^0.34.1 + * @opentelemetry/instrumentation-redis-4 bumped from ^0.34.0 to ^0.34.1 + * @opentelemetry/instrumentation-restify bumped from ^0.31.0 to ^0.32.0 + * @opentelemetry/instrumentation-socket.io bumped from ^0.32.0 to ^0.33.0 + +## [0.35.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/auto-instrumentations-node-v0.34.0...auto-instrumentations-node-v0.35.0) (2022-11-16) + + +### Features + +* update experimental deps to `^0.34.0`, core deps to `^1.8.0`, api to `^1.3.0` ([#1278](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1278)) ([e9fe8e1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/e9fe8e13e34f54e96c50525cadeb74ac048c5624)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @opentelemetry/instrumentation-amqplib bumped from ^0.31.0 to ^0.32.0 + * @opentelemetry/instrumentation-aws-lambda bumped from ^0.33.1 to ^0.34.0 + * @opentelemetry/instrumentation-aws-sdk bumped from ^0.9.3 to ^0.10.0 + * @opentelemetry/instrumentation-bunyan bumped from ^0.30.1 to ^0.31.0 + * @opentelemetry/instrumentation-cassandra-driver bumped from ^0.31.0 to ^0.32.0 + * @opentelemetry/instrumentation-connect bumped from ^0.30.1 to ^0.31.0 + * @opentelemetry/instrumentation-dataloader bumped from ^0.2.1 to ^0.3.0 + * @opentelemetry/instrumentation-dns bumped from ^0.30.1 to ^0.31.0 + * @opentelemetry/instrumentation-express bumped from ^0.31.3 to ^0.32.0 + * @opentelemetry/instrumentation-fs bumped from ^0.5.1 to ^0.6.0 + * @opentelemetry/instrumentation-fastify bumped from ^0.30.1 to ^0.31.0 + * @opentelemetry/instrumentation-generic-pool bumped from ^0.30.0 to ^0.31.0 + * @opentelemetry/instrumentation-graphql bumped from ^0.32.0 to ^0.33.0 + * @opentelemetry/instrumentation-hapi bumped from ^0.30.1 to ^0.31.0 + * @opentelemetry/instrumentation-ioredis bumped from ^0.32.2 to ^0.33.0 + * @opentelemetry/instrumentation-knex bumped from ^0.30.1 to ^0.31.0 + * @opentelemetry/instrumentation-koa bumped from ^0.33.0 to ^0.34.0 + * @opentelemetry/instrumentation-lru-memoizer bumped from ^0.31.0 to ^0.32.0 + * @opentelemetry/instrumentation-memcached bumped from ^0.30.1 to ^0.31.0 + * @opentelemetry/instrumentation-mongodb bumped from ^0.32.2 to ^0.33.0 + * @opentelemetry/instrumentation-mongoose bumped from ^0.31.1 to ^0.32.0 + * @opentelemetry/instrumentation-mysql bumped from ^0.31.2 to ^0.32.0 + * @opentelemetry/instrumentation-mysql2 bumped from ^0.32.1 to ^0.33.0 + * @opentelemetry/instrumentation-nestjs-core bumped from ^0.31.1 to ^0.32.0 + * @opentelemetry/instrumentation-net bumped from ^0.30.2 to ^0.31.0 + * @opentelemetry/instrumentation-pg bumped from ^0.32.0 to ^0.33.0 + * @opentelemetry/instrumentation-pino bumped from ^0.32.1 to ^0.33.0 + * @opentelemetry/instrumentation-redis bumped from ^0.33.1 to ^0.34.0 + * @opentelemetry/instrumentation-redis-4 bumped from ^0.33.1 to ^0.34.0 + * @opentelemetry/instrumentation-restify bumped from ^0.30.1 to ^0.31.0 + * @opentelemetry/instrumentation-router bumped from ^0.31.0 to ^0.32.0 + * @opentelemetry/instrumentation-tedious bumped from ^0.4.1 to ^0.5.0 + * @opentelemetry/instrumentation-winston bumped from ^0.30.1 to ^0.31.0 + ## [0.34.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/auto-instrumentations-node-v0.33.1...auto-instrumentations-node-v0.34.0) (2022-11-02) diff --git a/metapackages/auto-instrumentations-node/README.md b/metapackages/auto-instrumentations-node/README.md index 21b7c9c8d3..0795f15b77 100644 --- a/metapackages/auto-instrumentations-node/README.md +++ b/metapackages/auto-instrumentations-node/README.md @@ -3,17 +3,97 @@ [![NPM Published Version][npm-img]][npm-url] [![Apache License][license-image]][license-url] -This module provides a simple way to initialize multiple Node instrumentations. +## About + +This module provides a way to auto instrument any Node application to capture telemetry from a number of popular libraries and frameworks. +You can export the telemetry data in a variety of formats. Exporters, samplers, and more can be configured via [environment variables][env-var-url]. +The net result is the ability to gather telemetry data from a Node application without any code changes. + +This module also provides a simple way to manually initialize multiple Node instrumentations for use with the OpenTelemetry SDK. Compatible with OpenTelemetry JS API and SDK `1.0+`. ## Installation ```bash +npm install --save @opentelemetry/api npm install --save @opentelemetry/auto-instrumentations-node ``` -## Usage +## Usage: Auto Instrumentation + +This module includes auto instrumentation for all supported instrumentations and [all available data exporters][exporter-url]. +It provides a completely automatic, out-of-the-box experience. +Please see the [Supported Instrumentations](#supported-instrumentations) section for more information. + +Enable auto instrumentation by requiring this module using the [--require flag][require-url]: + +```shell +node --require '@opentelemetry/auto-instrumentations-node/register' app.js +``` + +If your Node application is encapsulated in a complex run script, you can also set it via an environment variable before running Node. + +```shell +env NODE_OPTIONS="--require @opentelemetry/auto-instrumentations-node/register" +``` + +The module is highly configurable using environment variables. +Many aspects of the auto instrumentation's behavior can be configured for your needs, such as resource detectors, exporter choice, exporter configuration, trace context propagation headers, and much more. +Instrumentation configuration is not yet supported through environment variables. Users that require instrumentation configuration must initialize OpenTelemetry programmatically. + +```shell +export OTEL_TRACES_EXPORTER="otlp" +export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf" +export OTEL_EXPORTER_OTLP_COMPRESSION="gzip" +export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="https://your-endpoint" +export OTEL_EXPORTER_OTLP_HEADERS="x-api-key=your-api-key" +export OTEL_EXPORTER_OTLP_TRACES_HEADERS="x-api-key=your-api-key" +export OTEL_RESOURCE_ATTRIBUTES="service.namespace=my-namespace" +export OTEL_NODE_RESOURCE_DETECTORS="env,host,os" +export OTEL_SERVICE_NAME="client" +export NODE_OPTIONS="--require @opentelemetry/auto-instrumentations-node/register" +node app.js +``` + +By default, all SDK resource detectors are used, but you can use the environment variable OTEL_NODE_RESOURCE_DETECTORS to enable only certain detectors, or completely disable them: + +- `env` +- `host` +- `os` +- `process` +- `container` +- `alibaba` +- `aws` +- `gcp` +- `all` - enable all resource detectors +- `none` - disable resource detection + +For example, to enable only the `env`, `host` detectors: + +```shell +export OTEL_NODE_RESOURCE_DETECTORS="env,host" +``` + +To enable logging for troubleshooting, set the log level by setting the `OTEL_LOG_LEVEL` environment variable to one of the following: + +- `none` +- `error` +- `warn` +- `info` +- `debug` +- `verbose` +- `all` + +The default level is `info`. + +Notes: + +- In a production environment, it is recommended to set `OTEL_LOG_LEVEL`to `info`. +- Logs are always sent to console, no matter the environment, or debug level. +- Debug logs are extremely verbose. Enable debug logging only when needed. Debug logging negatively impacts the performance of your application. + +## Usage: Instrumentation Initialization OpenTelemetry Meta Packages for Node automatically loads instrumentations for Node builtin modules and common packages. @@ -62,32 +142,29 @@ registerInstrumentations({ - [@opentelemetry/instrumentation-connect](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-connect) - [@opentelemetry/instrumentation-dataloader](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/instrumentation-dataloader) - [@opentelemetry/instrumentation-dns](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-dns) -- [@opentelemetry/instrumentation-http](https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation-http) -- [@opentelemetry/instrumentation-grpc](https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation-grpc) - [@opentelemetry/instrumentation-express](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-express) -- [@opentelemetry/instrumentation-koa](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-koa) -- [@opentelemetry/instrumentation-lru-memoizer](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/instrumentation-lru-memoizer) - [@opentelemetry/instrumentation-fastify](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-fastify) - [@opentelemetry/instrumentation-generic-pool](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-generic-pool) - [@opentelemetry/instrumentation-graphql](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-graphql) +- [@opentelemetry/instrumentation-grpc](https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation-grpc) - [@opentelemetry/instrumentation-hapi](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-hapi) - [@opentelemetry/instrumentation-http](https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-instrumentation-http) - [@opentelemetry/instrumentation-ioredis](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-ioredis) -- [@opentelemetry/instrumentation-redis](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-redis) -- [@opentelemetry/instrumentation-pg](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-pg) - [@opentelemetry/instrumentation-knex](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-knex) - [@opentelemetry/instrumentation-koa](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-koa) +- [@opentelemetry/instrumentation-lru-memoizer](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/instrumentation-lru-memoizer) - [@opentelemetry/instrumentation-memcached](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-memcached) - [@opentelemetry/instrumentation-mongodb](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-mongodb) - [@opentelemetry/instrumentation-mongoose](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/instrumentation-mongoose) -- [@opentelemetry/instrumentation-mysql2](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-mysql2) - [@opentelemetry/instrumentation-mysql](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-mysql) +- [@opentelemetry/instrumentation-mysql2](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-mysql2) - [@opentelemetry/instrumentation-nestjs-core](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-nestjs-core) - [@opentelemetry/instrumentation-net](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-net) - [@opentelemetry/instrumentation-pg](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-pg) - [@opentelemetry/instrumentation-pino](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-pino) - [@opentelemetry/instrumentation-redis](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-redis) - [@opentelemetry/instrumentation-restify](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-restify) +- [@opentelemetry/instrumentation-socket.io](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/instrumentation-socket.io) - [@opentelemetry/instrumentation-winston](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-winston) ## Useful links @@ -103,3 +180,6 @@ APACHE 2.0 - See [LICENSE][license-url] for more information. [license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat [npm-url]: https://www.npmjs.com/package/@opentelemetry/auto-instrumentations-node [npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fauto-instrumentations-node.svg +[env-var-url]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#general-sdk-configuration +[exporter-url]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#otlp-exporter +[require-url]: https://nodejs.org/api/cli.html#-r---require-module diff --git a/metapackages/auto-instrumentations-node/package.json b/metapackages/auto-instrumentations-node/package.json index 625f4c0397..49a91d7696 100644 --- a/metapackages/auto-instrumentations-node/package.json +++ b/metapackages/auto-instrumentations-node/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/auto-instrumentations-node", - "version": "0.34.0", + "version": "0.36.6", "description": "Metapackage which bundles opentelemetry node core and contrib instrumentations", "author": "OpenTelemetry Authors", "homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/metapackages/auto-instrumentations-node#readme", @@ -13,6 +13,10 @@ }, "main": "build/src/index.js", "types": "build/src/index.d.ts", + "exports": { + ".": "./build/src/index.js", + "./register": "./build/src/register.js" + }, "repository": "open-telemetry/opentelemetry-js-contrib", "scripts": { "clean": "rimraf build/*", @@ -30,57 +34,63 @@ "url": "https://github.com/open-telemetry/opentelemetry-js-contrib/issues" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@opentelemetry/api": "^1.4.1" }, "devDependencies": { - "@opentelemetry/api": "^1.0.0", + "@opentelemetry/api": "^1.4.1", "@types/mocha": "7.0.2", "@types/node": "18.11.7", "@types/sinon": "10.0.2", - "gts": "3.1.0", "mocha": "7.2.0", "nyc": "15.1.0", - "rimraf": "3.0.2", - "sinon": "14.0.0", + "rimraf": "4.2.0", + "sinon": "15.0.1", "ts-mocha": "10.0.0", - "typescript": "4.3.5" + "typescript": "4.4.4" }, "dependencies": { - "@opentelemetry/instrumentation": "^0.32.0", - "@opentelemetry/instrumentation-amqplib": "^0.31.0", - "@opentelemetry/instrumentation-aws-lambda": "^0.33.1", - "@opentelemetry/instrumentation-aws-sdk": "^0.9.3", - "@opentelemetry/instrumentation-bunyan": "^0.30.1", - "@opentelemetry/instrumentation-cassandra-driver": "^0.31.0", - "@opentelemetry/instrumentation-connect": "^0.30.1", - "@opentelemetry/instrumentation-dataloader": "^0.2.1", - "@opentelemetry/instrumentation-dns": "^0.30.1", - "@opentelemetry/instrumentation-express": "^0.31.3", - "@opentelemetry/instrumentation-fs": "^0.5.1", - "@opentelemetry/instrumentation-fastify": "^0.30.1", - "@opentelemetry/instrumentation-generic-pool": "^0.30.0", - "@opentelemetry/instrumentation-graphql": "^0.32.0", - "@opentelemetry/instrumentation-grpc": "^0.32.0", - "@opentelemetry/instrumentation-hapi": "^0.30.1", - "@opentelemetry/instrumentation-http": "^0.32.0", - "@opentelemetry/instrumentation-ioredis": "^0.32.2", - "@opentelemetry/instrumentation-knex": "^0.30.1", - "@opentelemetry/instrumentation-koa": "^0.33.0", - "@opentelemetry/instrumentation-lru-memoizer": "^0.31.0", - "@opentelemetry/instrumentation-memcached": "^0.30.1", - "@opentelemetry/instrumentation-mongodb": "^0.32.2", - "@opentelemetry/instrumentation-mongoose": "^0.31.1", - "@opentelemetry/instrumentation-mysql": "^0.31.2", - "@opentelemetry/instrumentation-mysql2": "^0.32.1", - "@opentelemetry/instrumentation-nestjs-core": "^0.31.1", - "@opentelemetry/instrumentation-net": "^0.30.2", - "@opentelemetry/instrumentation-pg": "^0.32.0", - "@opentelemetry/instrumentation-pino": "^0.32.1", - "@opentelemetry/instrumentation-redis": "^0.33.1", - "@opentelemetry/instrumentation-redis-4": "^0.33.1", - "@opentelemetry/instrumentation-restify": "^0.30.1", - "@opentelemetry/instrumentation-router": "^0.31.0", - "@opentelemetry/instrumentation-tedious": "^0.4.1", - "@opentelemetry/instrumentation-winston": "^0.30.1" + "@opentelemetry/instrumentation": "^0.38.0", + "@opentelemetry/instrumentation-amqplib": "^0.32.3", + "@opentelemetry/instrumentation-aws-lambda": "^0.35.1", + "@opentelemetry/instrumentation-aws-sdk": "^0.34.1", + "@opentelemetry/instrumentation-bunyan": "^0.31.2", + "@opentelemetry/instrumentation-cassandra-driver": "^0.32.2", + "@opentelemetry/instrumentation-connect": "^0.31.2", + "@opentelemetry/instrumentation-dataloader": "^0.4.1", + "@opentelemetry/instrumentation-dns": "^0.31.3", + "@opentelemetry/instrumentation-express": "^0.32.2", + "@opentelemetry/instrumentation-fs": "^0.7.2", + "@opentelemetry/instrumentation-fastify": "^0.31.2", + "@opentelemetry/instrumentation-generic-pool": "^0.31.2", + "@opentelemetry/instrumentation-graphql": "^0.34.1", + "@opentelemetry/instrumentation-grpc": "^0.38.0", + "@opentelemetry/instrumentation-hapi": "^0.31.2", + "@opentelemetry/instrumentation-http": "^0.38.0", + "@opentelemetry/instrumentation-ioredis": "^0.34.1", + "@opentelemetry/instrumentation-knex": "^0.31.2", + "@opentelemetry/instrumentation-koa": "^0.34.4", + "@opentelemetry/instrumentation-lru-memoizer": "^0.32.2", + "@opentelemetry/instrumentation-memcached": "^0.31.2", + "@opentelemetry/instrumentation-mongodb": "^0.34.2", + "@opentelemetry/instrumentation-mongoose": "^0.32.2", + "@opentelemetry/instrumentation-mysql": "^0.33.1", + "@opentelemetry/instrumentation-mysql2": "^0.33.2", + "@opentelemetry/instrumentation-nestjs-core": "^0.32.3", + "@opentelemetry/instrumentation-net": "^0.31.2", + "@opentelemetry/instrumentation-pg": "^0.35.1", + "@opentelemetry/instrumentation-pino": "^0.33.2", + "@opentelemetry/instrumentation-redis": "^0.34.5", + "@opentelemetry/instrumentation-redis-4": "^0.34.4", + "@opentelemetry/instrumentation-restify": "^0.32.2", + "@opentelemetry/instrumentation-router": "^0.32.2", + "@opentelemetry/instrumentation-socket.io": "^0.33.2", + "@opentelemetry/instrumentation-tedious": "^0.5.2", + "@opentelemetry/instrumentation-winston": "^0.31.2", + "@opentelemetry/resource-detector-alibaba-cloud": "^0.27.4", + "@opentelemetry/resource-detector-aws": "^1.2.2", + "@opentelemetry/resource-detector-container": "^0.2.2", + "@opentelemetry/resource-detector-gcp": "^0.28.0", + "@opentelemetry/resources": "^1.12.0", + "@opentelemetry/sdk-node": "^0.38.0" } } diff --git a/metapackages/auto-instrumentations-node/src/register.ts b/metapackages/auto-instrumentations-node/src/register.ts new file mode 100644 index 0000000000..a14538da66 --- /dev/null +++ b/metapackages/auto-instrumentations-node/src/register.ts @@ -0,0 +1,48 @@ +/* + * 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 opentelemetry from '@opentelemetry/sdk-node'; +import { diag, DiagConsoleLogger } from '@opentelemetry/api'; +import { + getNodeAutoInstrumentations, + getResourceDetectorsFromEnv, +} from './utils'; + +diag.setLogger( + new DiagConsoleLogger(), + opentelemetry.core.getEnv().OTEL_LOG_LEVEL +); + +const sdk = new opentelemetry.NodeSDK({ + instrumentations: getNodeAutoInstrumentations(), + resourceDetectors: getResourceDetectorsFromEnv(), +}); + +try { + sdk.start(); + diag.info('OpenTelemetry automatic instrumentation started successfully'); +} catch (error) { + diag.error( + 'Error initializing OpenTelemetry SDK. Your application is not instrumented and will not produce telemetry', + error + ); +} + +process.on('SIGTERM', () => { + sdk + .shutdown() + .then(() => diag.debug('OpenTelemetry SDK terminated')) + .catch(error => diag.error('Error terminating OpenTelemetry SDK', error)); +}); diff --git a/metapackages/auto-instrumentations-node/src/utils.ts b/metapackages/auto-instrumentations-node/src/utils.ts index 2daba2146d..0c194f7a30 100644 --- a/metapackages/auto-instrumentations-node/src/utils.ts +++ b/metapackages/auto-instrumentations-node/src/utils.ts @@ -50,9 +50,38 @@ import { RedisInstrumentation as RedisInstrumentationV2 } from '@opentelemetry/i import { RedisInstrumentation as RedisInstrumentationV4 } 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 { alibabaCloudEcsDetector } from '@opentelemetry/resource-detector-alibaba-cloud'; +import { + awsBeanstalkDetector, + awsEc2Detector, + awsEcsDetector, + awsEksDetector, + awsLambdaDetector, +} from '@opentelemetry/resource-detector-aws'; +import { containerDetector } from '@opentelemetry/resource-detector-container'; +import { gcpDetector } from '@opentelemetry/resource-detector-gcp'; +import { + Detector, + DetectorSync, + envDetectorSync, + hostDetectorSync, + osDetectorSync, + processDetectorSync, +} from '@opentelemetry/resources'; + +const RESOURCE_DETECTOR_CONTAINER = 'container'; +const RESOURCE_DETECTOR_ENVIRONMENT = 'env'; +const RESOURCE_DETECTOR_HOST = 'host'; +const RESOURCE_DETECTOR_OS = 'os'; +const RESOURCE_DETECTOR_PROCESS = 'process'; +const RESOURCE_DETECTOR_ALIBABA = 'alibaba'; +const RESOURCE_DETECTOR_AWS = 'aws'; +const RESOURCE_DETECTOR_GCP = 'gcp'; + const InstrumentationMap = { '@opentelemetry/instrumentation-amqplib': AmqplibInstrumentation, '@opentelemetry/instrumentation-aws-lambda': AwsLambdaInstrumentation, @@ -88,6 +117,7 @@ const InstrumentationMap = { '@opentelemetry/instrumentation-redis-4': RedisInstrumentationV4, '@opentelemetry/instrumentation-restify': RestifyInstrumentation, '@opentelemetry/instrumentation-router': RouterInstrumentation, + '@opentelemetry/instrumentation-socket.io': SocketIoInstrumentation, '@opentelemetry/instrumentation-tedious': TediousInstrumentation, '@opentelemetry/instrumentation-winston': WinstonInstrumentation, }; @@ -96,7 +126,7 @@ const InstrumentationMap = { type ConfigArg = T extends new (...args: infer U) => unknown ? U[0] : never; export type InstrumentationConfigMap = { [Name in keyof typeof InstrumentationMap]?: ConfigArg< - typeof InstrumentationMap[Name] + (typeof InstrumentationMap)[Name] >; }; @@ -117,7 +147,7 @@ export function getNodeAutoInstrumentations( >) { const Instance = InstrumentationMap[name]; // Defaults are defined by the instrumentation itself - const userConfig = inputConfigs[name] ?? {}; + const userConfig: any = inputConfigs[name] ?? {}; if (userConfig.enabled === false) { diag.debug(`Disabling instrumentation for ${name}`); @@ -127,10 +157,56 @@ export function getNodeAutoInstrumentations( try { diag.debug(`Loading instrumentation for ${name}`); instrumentations.push(new Instance(userConfig)); - } catch (e) { + } catch (e: any) { diag.error(e); } } return instrumentations; } + +export function getResourceDetectorsFromEnv(): Array { + const resourceDetectors = new Map< + string, + Detector | DetectorSync | Detector[] + >([ + [RESOURCE_DETECTOR_CONTAINER, containerDetector], + [RESOURCE_DETECTOR_ENVIRONMENT, envDetectorSync], + [RESOURCE_DETECTOR_HOST, hostDetectorSync], + [RESOURCE_DETECTOR_OS, osDetectorSync], + [RESOURCE_DETECTOR_PROCESS, processDetectorSync], + [RESOURCE_DETECTOR_ALIBABA, alibabaCloudEcsDetector], + [RESOURCE_DETECTOR_GCP, gcpDetector], + [ + RESOURCE_DETECTOR_AWS, + [ + awsEc2Detector, + awsEcsDetector, + awsEksDetector, + awsBeanstalkDetector, + awsLambdaDetector, + ], + ], + ]); + + const resourceDetectorsFromEnv = + process.env.OTEL_NODE_RESOURCE_DETECTORS?.split(',') ?? ['all']; + + if (resourceDetectorsFromEnv.includes('all')) { + return [...resourceDetectors.values()].flat(); + } + + if (resourceDetectorsFromEnv.includes('none')) { + return []; + } + + return resourceDetectorsFromEnv.flatMap(detector => { + const resourceDetector = resourceDetectors.get(detector); + if (!resourceDetector) { + diag.error( + `Invalid resource detector "${detector}" specified in the environment variable OTEL_NODE_RESOURCE_DETECTORS` + ); + } + return resourceDetector || []; + }); +} diff --git a/metapackages/auto-instrumentations-node/test/register.test.ts b/metapackages/auto-instrumentations-node/test/register.test.ts new file mode 100644 index 0000000000..b3c0381274 --- /dev/null +++ b/metapackages/auto-instrumentations-node/test/register.test.ts @@ -0,0 +1,44 @@ +/* + * 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 { promisify } from 'util'; +import * as childProcess from 'child_process'; +import * as assert from 'assert'; + +const exec = promisify(childProcess.exec); + +describe('Register', function () { + this.timeout(5000); + it('can load auto instrumentation from command line', async () => { + process.env.OTEL_NODE_RESOURCE_DETECTORS = 'none'; + process.env.OTEL_TRACES_EXPORTER = 'console'; + + const { stdout } = await exec( + 'node --require ./build/src/register.js ./test/test-app/app.js' + ); + + assert.ok( + stdout.includes( + 'OpenTelemetry automatic instrumentation started successfully' + ) + ); + + //Check a span has been generated for the GET request done in app.js + assert.ok(stdout.includes("name: 'GET'")); + + delete process.env.OTEL_NODE_RESOURCE_DETECTORS; + delete process.env.OTEL_TRACES_EXPORTER; + }); +}); diff --git a/metapackages/auto-instrumentations-node/test/test-app/app.js b/metapackages/auto-instrumentations-node/test/test-app/app.js new file mode 100644 index 0000000000..1057acbce3 --- /dev/null +++ b/metapackages/auto-instrumentations-node/test/test-app/app.js @@ -0,0 +1,29 @@ +/* + * 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. + */ + +//Used in register.test.ts to mimic a JS app. +const http = require('http'); + +const options = { + hostname: 'example.com', + port: 80, + path: '/', + method: 'GET' +}; + +const req = http.request(options); + +req.end(); diff --git a/metapackages/auto-instrumentations-node/test/utils.test.ts b/metapackages/auto-instrumentations-node/test/utils.test.ts index 5707eed8f3..f295668d4f 100644 --- a/metapackages/auto-instrumentations-node/test/utils.test.ts +++ b/metapackages/auto-instrumentations-node/test/utils.test.ts @@ -19,6 +19,7 @@ import { HttpInstrumentationConfig } from '@opentelemetry/instrumentation-http'; import * as assert from 'assert'; import * as sinon from 'sinon'; import { getNodeAutoInstrumentations } from '../src'; +import { getResourceDetectorsFromEnv } from '../src/utils'; describe('utils', () => { describe('getNodeAutoInstrumentations', () => { @@ -87,6 +88,55 @@ describe('utils', () => { spy.args[0][0], `Provided instrumentation name "${name}" not found` ); + + spy.restore(); + }); + }); + + describe('getResourceDetectorsFromEnv', () => { + it('should return all resource detectors by default', () => { + assert.equal(getResourceDetectorsFromEnv().length, 12); + }); + + it('should return all resource detectors when OTEL_NODE_RESOURCE_DETECTORS contains "all"', () => { + process.env.OTEL_NODE_RESOURCE_DETECTORS = 'all'; + + assert.equal(getResourceDetectorsFromEnv().length, 12); + + delete process.env.OTEL_NODE_RESOURCE_DETECTORS; + }); + + it('should return specific resource detectors depending on OTEL_NODE_RESOURCE_DETECTORS', () => { + process.env.OTEL_NODE_RESOURCE_DETECTORS = 'env,host'; + + const resourceDetectors = getResourceDetectorsFromEnv(); + + assert.equal(resourceDetectors.length, 2); + assert.equal(resourceDetectors[0].constructor.name, 'EnvDetectorSync'); + assert.equal(resourceDetectors[1].constructor.name, 'HostDetectorSync'); + + delete process.env.OTEL_NODE_RESOURCE_DETECTORS; + }); + + it('should return no resource detectors when OTEL_NODE_RESOURCE_DETECTORS contains "none" or a typo', () => { + const spy = sinon.stub(diag, 'error'); + process.env.OTEL_NODE_RESOURCE_DETECTORS = 'none'; + + assert.equal(getResourceDetectorsFromEnv().length, 0); + + assert.strictEqual(spy.callCount, 0); + + process.env.OTEL_NODE_RESOURCE_DETECTORS = 'test'; + + assert.equal(getResourceDetectorsFromEnv().length, 0); + + assert.strictEqual( + spy.args[0][0], + 'Invalid resource detector "test" specified in the environment variable OTEL_NODE_RESOURCE_DETECTORS' + ); + + spy.restore(); + delete process.env.OTEL_NODE_RESOURCE_DETECTORS; }); }); }); diff --git a/metapackages/auto-instrumentations-web/CHANGELOG.md b/metapackages/auto-instrumentations-web/CHANGELOG.md index 18b471391f..a15dda040d 100644 --- a/metapackages/auto-instrumentations-web/CHANGELOG.md +++ b/metapackages/auto-instrumentations-web/CHANGELOG.md @@ -6,6 +6,71 @@ * dependencies * @opentelemetry/instrumentation-user-interaction bumped from ^0.30.0 to ^0.30.1 +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @opentelemetry/instrumentation-document-load bumped from ^0.31.1 to ^0.31.2 + +## [0.32.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/auto-instrumentations-web-v0.32.0...auto-instrumentations-web-v0.32.1) (2023-04-25) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.38.0 ([#1468](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1468)) ([565a2b2](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/565a2b2c6fde88af3f5401ef6a5a9643d0d66349)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @opentelemetry/instrumentation-document-load bumped from ^0.32.0 to ^0.32.1 + * @opentelemetry/instrumentation-user-interaction bumped from ^0.32.1 to ^0.32.2 + +## [0.32.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/auto-instrumentations-web-v0.31.2...auto-instrumentations-web-v0.32.0) (2023-04-06) + + +### Features + +* **instrumenation-document-load:** Add custom attributes to document load ([#1414](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1414)) ([98609c6](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/98609c69d951951edcaa3234914d04d7ae87e9b5)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @opentelemetry/instrumentation-document-load bumped from ^0.31.2 to ^0.32.0 + +## [0.31.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/auto-instrumentations-web-v0.31.0...auto-instrumentations-web-v0.31.1) (2023-02-07) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.35.1 ([#1358](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1358)) ([ff109b7](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/ff109b77928cc9a139a21c63d6b54399bb017fa4)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @opentelemetry/instrumentation-document-load bumped from ^0.31.0 to ^0.31.1 + * @opentelemetry/instrumentation-user-interaction bumped from ^0.32.0 to ^0.32.1 + +## [0.31.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/auto-instrumentations-web-v0.30.1...auto-instrumentations-web-v0.31.0) (2022-11-16) + + +### Features + +* update experimental deps to `^0.34.0`, core deps to `^1.8.0`, api to `^1.3.0` ([#1278](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1278)) ([e9fe8e1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/e9fe8e13e34f54e96c50525cadeb74ac048c5624)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @opentelemetry/instrumentation-document-load bumped from ^0.30.1 to ^0.31.0 + * @opentelemetry/instrumentation-user-interaction bumped from ^0.31.1 to ^0.32.0 + ## [0.30.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/auto-instrumentations-web-v0.30.0...auto-instrumentations-web-v0.30.1) (2022-11-02) diff --git a/metapackages/auto-instrumentations-web/package.json b/metapackages/auto-instrumentations-web/package.json index a096d7a444..a8fddc2392 100644 --- a/metapackages/auto-instrumentations-web/package.json +++ b/metapackages/auto-instrumentations-web/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/auto-instrumentations-web", - "version": "0.30.1", + "version": "0.32.1", "description": "Metapackage which bundles opentelemetry node core and contrib instrumentations", "author": "OpenTelemetry Authors", "homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/metapackages/auto-instrumentations-web#readme", @@ -30,17 +30,16 @@ "url": "https://github.com/open-telemetry/opentelemetry-js-contrib/issues" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@opentelemetry/api": "^1.3.0" }, "devDependencies": { "@babel/core": "7.15.0", - "@opentelemetry/api": "^1.0.0", + "@opentelemetry/api": "^1.3.0", "@types/mocha": "8.2.3", "@types/node": "18.11.7", "@types/sinon": "10.0.2", "@types/webpack-env": "1.16.2", "babel-loader": "8.2.2", - "gts": "3.1.0", "@jsdevtools/coverage-istanbul-loader": "3.0.5", "karma": "6.3.16", "karma-chrome-launcher": "^3.1.1", @@ -50,20 +49,20 @@ "karma-webpack": "4.0.2", "mocha": "7.2.0", "nyc": "15.1.0", - "rimraf": "3.0.2", - "sinon": "14.0.0", + "rimraf": "4.2.0", + "sinon": "15.0.1", "ts-loader": "8.3.0", "ts-mocha": "10.0.0", - "typescript": "4.3.5", + "typescript": "4.4.4", "webpack": "4.46.0", "webpack-cli": "4.7.2", "webpack-merge": "5.8.0" }, "dependencies": { - "@opentelemetry/instrumentation": "^0.32.0", - "@opentelemetry/instrumentation-document-load": "^0.30.1", - "@opentelemetry/instrumentation-fetch": "^0.32.0", - "@opentelemetry/instrumentation-user-interaction": "^0.31.1", - "@opentelemetry/instrumentation-xml-http-request": "^0.32.0" + "@opentelemetry/instrumentation": "^0.38.0", + "@opentelemetry/instrumentation-document-load": "^0.32.1", + "@opentelemetry/instrumentation-fetch": "^0.38.0", + "@opentelemetry/instrumentation-user-interaction": "^0.32.2", + "@opentelemetry/instrumentation-xml-http-request": "^0.38.0" } } diff --git a/metapackages/auto-instrumentations-web/src/utils.ts b/metapackages/auto-instrumentations-web/src/utils.ts index ed0a4d98ec..1127c0f1f2 100644 --- a/metapackages/auto-instrumentations-web/src/utils.ts +++ b/metapackages/auto-instrumentations-web/src/utils.ts @@ -15,7 +15,10 @@ */ import { diag } from '@opentelemetry/api'; -import { Instrumentation } from '@opentelemetry/instrumentation'; +import { + Instrumentation, + InstrumentationConfig, +} from '@opentelemetry/instrumentation'; import { DocumentLoadInstrumentation } from '@opentelemetry/instrumentation-document-load'; import { FetchInstrumentation } from '@opentelemetry/instrumentation-fetch'; import { UserInteractionInstrumentation } from '@opentelemetry/instrumentation-user-interaction'; @@ -34,7 +37,7 @@ const InstrumentationMap = { type ConfigArg = T extends new (...args: infer U) => unknown ? U[0] : never; export type InstrumentationConfigMap = { [Name in keyof typeof InstrumentationMap]?: ConfigArg< - typeof InstrumentationMap[Name] + (typeof InstrumentationMap)[Name] >; }; @@ -55,7 +58,7 @@ export function getWebAutoInstrumentations( >) { const Instance = InstrumentationMap[name]; // Defaults are defined by the instrumentation itself - const userConfig = inputConfigs[name] ?? {}; + const userConfig: InstrumentationConfig = inputConfigs[name] ?? {}; if (userConfig.enabled === false) { diag.debug(`Disabling instrumentation for ${name}`); @@ -65,7 +68,7 @@ export function getWebAutoInstrumentations( try { diag.debug(`Loading instrumentation for ${name}`); instrumentations.push(new Instance(userConfig)); - } catch (e) { + } catch (e: any) { diag.error(e); } } diff --git a/package.json b/package.json index ea02aba526..24049e1ff7 100644 --- a/package.json +++ b/package.json @@ -50,13 +50,16 @@ "@typescript-eslint/parser": "5.8.1", "eslint": "8.7.0", "eslint-config-airbnb-base": "15.0.0", + "eslint-config-prettier": "8.8.0", "eslint-plugin-header": "3.1.1", - "eslint-plugin-import": "2.25.4", - "gts": "3.1.0", + "eslint-plugin-import": "2.27.5", + "eslint-plugin-node": "11.1.0", + "eslint-plugin-prettier": "4.2.1", "husky": "7.0.4", "lerna": "5.5.2", "lerna-changelog": "2.2.0", - "typescript": "4.3.5" + "prettier": "2.8.7", + "typescript": "4.4.4" }, "changelog": { "labels": { diff --git a/packages/opentelemetry-host-metrics/CHANGELOG.md b/packages/opentelemetry-host-metrics/CHANGELOG.md index c3b0717860..a5554b4787 100644 --- a/packages/opentelemetry-host-metrics/CHANGELOG.md +++ b/packages/opentelemetry-host-metrics/CHANGELOG.md @@ -1,5 +1,27 @@ # Changelog +## [0.32.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/host-metrics-v0.32.0...host-metrics-v0.32.1) (2023-04-25) + + +### Bug Fixes + +* **host-metrics:** fallback to process.memoryUsage() ([#1471](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1471)) ([4d11d61](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/4d11d61b709cf12d7d02d31960cd7ccb67404b14)) + +## [0.32.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/host-metrics-v0.31.0...host-metrics-v0.32.0) (2023-04-06) + + +### Features + +* **host-metrics:** Add process metrics ([#1449](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1449)) ([9268716](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/92687167f08ea7e3dec046ca7f2be86b337dd743)) +* **host-metrics:** update host metrics to collect metrics in batch ([#1450](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1450)) ([6c708d1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/6c708d116264e395cf5eab94f3ba3250a8585c87)) + +## [0.31.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/host-metrics-v0.30.1...host-metrics-v0.31.0) (2022-11-16) + + +### Features + +* use GA version of metrics ([#1281](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1281)) ([7f02de2](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/7f02de23c3cedd6198bfd838e6b63002c3341bd8)) + ## [0.30.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/host-metrics-v0.30.0...host-metrics-v0.30.1) (2022-09-27) diff --git a/packages/opentelemetry-host-metrics/package.json b/packages/opentelemetry-host-metrics/package.json index 374c7a6beb..2a5fd25c0b 100644 --- a/packages/opentelemetry-host-metrics/package.json +++ b/packages/opentelemetry-host-metrics/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/host-metrics", - "version": "0.30.1", + "version": "0.32.1", "description": "OpenTelemetry Host Metrics for Node.js", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -43,25 +43,22 @@ "access": "public" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@opentelemetry/api": "^1.3.0" }, "devDependencies": { - "@opentelemetry/api": "^1.0.0", + "@opentelemetry/api": "^1.3.0", "@types/mocha": "8.2.3", "@types/node": "18.11.7", "@types/sinon": "10.0.2", - "gts": "3.1.0", "mocha": "7.2.0", "nyc": "15.1.0", - "rimraf": "3.0.2", - "sinon": "14.0.0", + "rimraf": "4.2.0", + "sinon": "15.0.1", "ts-mocha": "10.0.0", - "typescript": "4.3.5" + "typescript": "4.4.4" }, "dependencies": { - "@opentelemetry/api-metrics": "^0.32.0", - "@opentelemetry/core": "^1.0.0", - "@opentelemetry/sdk-metrics": "^0.32.0", + "@opentelemetry/sdk-metrics": "^1.8.0", "systeminformation": "^5.0.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/packages/opentelemetry-host-metrics#readme" diff --git a/packages/opentelemetry-host-metrics/src/BaseMetrics.ts b/packages/opentelemetry-host-metrics/src/BaseMetrics.ts index 6bc4774f43..7066ed65d8 100644 --- a/packages/opentelemetry-host-metrics/src/BaseMetrics.ts +++ b/packages/opentelemetry-host-metrics/src/BaseMetrics.ts @@ -15,7 +15,6 @@ */ import * as api from '@opentelemetry/api'; -import * as apiMetrics from '@opentelemetry/api-metrics'; import * as metrics from '@opentelemetry/sdk-metrics'; import { VERSION } from './version'; @@ -24,8 +23,6 @@ import { VERSION } from './version'; * Metrics Collector Configuration */ export interface MetricsCollectorConfig { - // maximum timeout to wait for stats collection default is 500ms - maxTimeoutUpdateMS?: number; // Meter Provider meterProvider?: metrics.MeterProvider; // Character to be used to join metrics - default is "." @@ -36,7 +33,6 @@ export interface MetricsCollectorConfig { url?: string; } -export const DEFAULT_MAX_TIMEOUT_UPDATE_MS = 500; const DEFAULT_NAME = 'opentelemetry-host-metrics'; /** @@ -44,16 +40,13 @@ const DEFAULT_NAME = 'opentelemetry-host-metrics'; */ export abstract class BaseMetrics { protected _logger = api.diag; - protected _maxTimeoutUpdateMS: number; - protected _meter: apiMetrics.Meter; + protected _meter: api.Meter; private _name: string; constructor(config: MetricsCollectorConfig) { this._name = config.name || DEFAULT_NAME; - this._maxTimeoutUpdateMS = - config.maxTimeoutUpdateMS || DEFAULT_MAX_TIMEOUT_UPDATE_MS; const meterProvider = - config.meterProvider! || apiMetrics.metrics.getMeterProvider(); + config.meterProvider! || api.metrics.getMeterProvider(); if (!config.meterProvider) { this._logger.warn('No meter provider, using default'); } diff --git a/packages/opentelemetry-host-metrics/src/enum.ts b/packages/opentelemetry-host-metrics/src/enum.ts index e4d113afb7..a4ed9a637b 100644 --- a/packages/opentelemetry-host-metrics/src/enum.ts +++ b/packages/opentelemetry-host-metrics/src/enum.ts @@ -22,6 +22,9 @@ export enum METRIC_NAMES { NETWORK_DROPPED = 'system.network.dropped', NETWORK_ERRORS = 'system.network.errors', NETWORK_IO = 'system.network.io', + PROCESS_CPU_TIME = 'process.cpu.time', + PROCESS_CPU_UTILIZATION = 'process.cpu.utilization', + PROCESS_MEMORY_USAGE = 'process.memory.usage', } export enum CPU_LABELS { diff --git a/packages/opentelemetry-host-metrics/src/metric.ts b/packages/opentelemetry-host-metrics/src/metric.ts index 11ea1ed910..e89b69887b 100644 --- a/packages/opentelemetry-host-metrics/src/metric.ts +++ b/packages/opentelemetry-host-metrics/src/metric.ts @@ -15,145 +15,159 @@ */ import { BaseMetrics } from './BaseMetrics'; -import * as api from '@opentelemetry/api-metrics'; +import * as api from '@opentelemetry/api'; import * as enums from './enum'; -import { getCpuUsageData, getMemoryData } from './stats/common'; +import { + getCpuUsageData, + getMemoryData, + getProcessCpuUsageData, + getProcessMemoryData, +} from './stats/common'; import { getNetworkData } from './stats/si'; -import { CpuUsageData, MemoryData, NetworkData } from './types'; -import { throttle } from './util'; +import { + CpuUsageData, + MemoryData, + NetworkData, + ProcessCpuUsageData, +} from './types'; /** * Metrics Collector - collects metrics for CPU, Memory, Network */ export class HostMetrics extends BaseMetrics { - private _updateCpuTime( - observableResult: api.ObservableResult, + private _batchUpdateCpuUsages( + observableResult: api.BatchObservableResult, cpuUsages: CpuUsageData[] ): void { for (let i = 0, j = cpuUsages.length; i < j; i++) { const cpuUsage = cpuUsages[i]; - observableResult.observe(cpuUsage.user, { + observableResult.observe(this._cpuTime, cpuUsage.user, { state: enums.CPU_LABELS.USER, cpu: cpuUsage.cpuNumber, }); - observableResult.observe(cpuUsage.system, { + observableResult.observe(this._cpuTime, cpuUsage.system, { state: enums.CPU_LABELS.SYSTEM, cpu: cpuUsage.cpuNumber, }); - observableResult.observe(cpuUsage.idle, { + observableResult.observe(this._cpuTime, cpuUsage.idle, { state: enums.CPU_LABELS.IDLE, cpu: cpuUsage.cpuNumber, }); - observableResult.observe(cpuUsage.interrupt, { + observableResult.observe(this._cpuTime, cpuUsage.interrupt, { state: enums.CPU_LABELS.INTERRUPT, cpu: cpuUsage.cpuNumber, }); - observableResult.observe(cpuUsage.nice, { + observableResult.observe(this._cpuTime, cpuUsage.nice, { state: enums.CPU_LABELS.NICE, cpu: cpuUsage.cpuNumber, }); - } - } - private _updateCpuUtilisation( - observableResult: api.ObservableResult, - cpuUsages: CpuUsageData[] - ): void { - for (let i = 0, j = cpuUsages.length; i < j; i++) { - const cpuUsage = cpuUsages[i]; - observableResult.observe(cpuUsage.userP, { + observableResult.observe(this._cpuUtilization, cpuUsage.userP, { state: enums.CPU_LABELS.USER, cpu: cpuUsage.cpuNumber, }); - observableResult.observe(cpuUsage.systemP, { + observableResult.observe(this._cpuUtilization, cpuUsage.systemP, { state: enums.CPU_LABELS.SYSTEM, cpu: cpuUsage.cpuNumber, }); - observableResult.observe(cpuUsage.idleP, { + observableResult.observe(this._cpuUtilization, cpuUsage.idleP, { state: enums.CPU_LABELS.IDLE, cpu: cpuUsage.cpuNumber, }); - observableResult.observe(cpuUsage.interruptP, { + observableResult.observe(this._cpuUtilization, cpuUsage.interruptP, { state: enums.CPU_LABELS.INTERRUPT, cpu: cpuUsage.cpuNumber, }); - observableResult.observe(cpuUsage.niceP, { + observableResult.observe(this._cpuUtilization, cpuUsage.niceP, { state: enums.CPU_LABELS.NICE, cpu: cpuUsage.cpuNumber, }); } } - private _updateMemUsage( - observableResult: api.ObservableResult, - memUsage: MemoryData + private _batchUpdateProcessCpuUsages( + observableResult: api.BatchObservableResult, + processCpuUsage: ProcessCpuUsageData ): void { - observableResult.observe(memUsage.used, { - state: enums.MEMORY_LABELS.USED, + observableResult.observe(this._processCpuTime, processCpuUsage.user, { + state: enums.CPU_LABELS.USER, }); - observableResult.observe(memUsage.free, { - state: enums.MEMORY_LABELS.FREE, + observableResult.observe(this._processCpuTime, processCpuUsage.system, { + state: enums.CPU_LABELS.SYSTEM, }); + + observableResult.observe( + this._processCpuUtilization, + processCpuUsage.userP, + { + state: enums.CPU_LABELS.USER, + } + ); + observableResult.observe( + this._processCpuUtilization, + processCpuUsage.systemP, + { + state: enums.CPU_LABELS.SYSTEM, + } + ); } - private _updateMemUtilization( - observableResult: api.ObservableResult, + private _batchUpdateMemUsages( + observableResult: api.BatchObservableResult, memUsage: MemoryData ): void { - observableResult.observe(memUsage.usedP, { + observableResult.observe(this._memoryUsage, memUsage.used, { state: enums.MEMORY_LABELS.USED, }); - observableResult.observe(memUsage.freeP, { + observableResult.observe(this._memoryUsage, memUsage.free, { + state: enums.MEMORY_LABELS.FREE, + }); + + observableResult.observe(this._memoryUtilization, memUsage.usedP, { + state: enums.MEMORY_LABELS.USED, + }); + observableResult.observe(this._memoryUtilization, memUsage.freeP, { state: enums.MEMORY_LABELS.FREE, }); } - private _updateNetworkDropped( - observableResult: api.ObservableResult, + private _batchUpdateProcessMemUsage( + observableResult: api.BatchObservableResult, + memoryUsage: number + ): void { + observableResult.observe(this._processMemoryUsage, memoryUsage); + } + + private _batchUpdateNetworkData( + observableResult: api.BatchObservableResult, networkUsages: NetworkData[] ): void { for (let i = 0, j = networkUsages.length; i < j; i++) { const networkUsage = networkUsages[i]; - observableResult.observe(networkUsage.rx_dropped, { + observableResult.observe(this._networkDropped, networkUsage.rx_dropped, { [enums.NETWORK_LABELS.DEVICE]: networkUsage.iface, direction: enums.NETWORK_LABELS.RECEIVE, }); - observableResult.observe(networkUsage.tx_dropped, { + observableResult.observe(this._networkDropped, networkUsage.tx_dropped, { device: networkUsage.iface, direction: enums.NETWORK_LABELS.TRANSMIT, }); - } - } - private _updateNetworkErrors( - observableResult: api.ObservableResult, - networkUsages: NetworkData[] - ): void { - for (let i = 0, j = networkUsages.length; i < j; i++) { - const networkUsage = networkUsages[i]; - observableResult.observe(networkUsage.rx_errors, { + observableResult.observe(this._networkErrors, networkUsage.rx_errors, { device: networkUsage.iface, direction: enums.NETWORK_LABELS.RECEIVE, }); - observableResult.observe(networkUsage.tx_errors, { + observableResult.observe(this._networkErrors, networkUsage.tx_errors, { device: networkUsage.iface, direction: enums.NETWORK_LABELS.TRANSMIT, }); - } - } - private _updateNetworkIO( - observableResult: api.ObservableResult, - networkUsages: NetworkData[] - ): void { - for (let i = 0, j = networkUsages.length; i < j; i++) { - const networkUsage = networkUsages[i]; - observableResult.observe(networkUsage.rx_bytes, { + observableResult.observe(this._networkIo, networkUsage.rx_bytes, { device: networkUsage.iface, direction: enums.NETWORK_LABELS.RECEIVE, }); - observableResult.observe(networkUsage.tx_bytes, { + observableResult.observe(this._networkIo, networkUsage.tx_bytes, { device: networkUsage.iface, direction: enums.NETWORK_LABELS.TRANSMIT, }); @@ -164,63 +178,99 @@ export class HostMetrics extends BaseMetrics { * Creates metrics */ protected _createMetrics(): void { - this._meter - .createObservableCounter(enums.METRIC_NAMES.CPU_TIME, { + this._cpuTime = this._meter.createObservableCounter( + enums.METRIC_NAMES.CPU_TIME, + { description: 'Cpu time in seconds', unit: 's', - }) - .addCallback(observableResult => { - const cpuUsageData = this._getCpuUsageData(); - this._updateCpuTime(observableResult, cpuUsageData); - }); - this._meter - .createObservableGauge(enums.METRIC_NAMES.CPU_UTILIZATION, { + } + ); + this._cpuUtilization = this._meter.createObservableGauge( + enums.METRIC_NAMES.CPU_UTILIZATION, + { description: 'Cpu usage time 0-1', - }) - .addCallback(observableResult => { - const cpuUsageData = this._getCpuUsageData(); - this._updateCpuUtilisation(observableResult, cpuUsageData); - }); - this._meter - .createObservableGauge(enums.METRIC_NAMES.MEMORY_USAGE, { + } + ); + + this._memoryUsage = this._meter.createObservableGauge( + enums.METRIC_NAMES.MEMORY_USAGE, + { description: 'Memory usage in bytes', - }) - .addCallback(observableResult => { - const memoryUsageData = this._getMemoryData(); - this._updateMemUsage(observableResult, memoryUsageData); - }); - this._meter - .createObservableGauge(enums.METRIC_NAMES.MEMORY_UTILIZATION, { + } + ); + this._memoryUtilization = this._meter.createObservableGauge( + enums.METRIC_NAMES.MEMORY_UTILIZATION, + { description: 'Memory usage 0-1', - }) - .addCallback(observableResult => { - const memoryUsageData = this._getMemoryData(); - this._updateMemUtilization(observableResult, memoryUsageData); - }); - this._meter - .createObservableCounter(enums.METRIC_NAMES.NETWORK_DROPPED, { + } + ); + + this._networkDropped = this._meter.createObservableCounter( + enums.METRIC_NAMES.NETWORK_DROPPED, + { description: 'Network dropped packets', - }) - .addCallback(async observableResult => { - const networkData = await this._getNetworkData(); - this._updateNetworkDropped(observableResult, networkData); - }); - this._meter - .createObservableCounter(enums.METRIC_NAMES.NETWORK_ERRORS, { + } + ); + this._networkErrors = this._meter.createObservableCounter( + enums.METRIC_NAMES.NETWORK_ERRORS, + { description: 'Network errors counter', - }) - .addCallback(async observableResult => { - const networkData = await this._getNetworkData(); - this._updateNetworkErrors(observableResult, networkData); - }); - this._meter - .createObservableCounter(enums.METRIC_NAMES.NETWORK_IO, { + } + ); + this._networkIo = this._meter.createObservableCounter( + enums.METRIC_NAMES.NETWORK_IO, + { description: 'Network transmit and received bytes', - }) - .addCallback(async observableResult => { - const networkData = await this._getNetworkData(); - this._updateNetworkIO(observableResult, networkData); - }); + } + ); + + this._processCpuTime = this._meter.createObservableCounter( + enums.METRIC_NAMES.PROCESS_CPU_TIME, + { + description: 'Process Cpu time in seconds', + unit: 's', + } + ); + this._processCpuUtilization = this._meter.createObservableGauge( + enums.METRIC_NAMES.PROCESS_CPU_UTILIZATION, + { + description: 'Process Cpu usage time 0-1', + } + ); + this._processMemoryUsage = this._meter.createObservableGauge( + enums.METRIC_NAMES.PROCESS_MEMORY_USAGE, + { + description: 'Process Memory usage in bytes', + } + ); + + this._meter.addBatchObservableCallback( + async observableResult => { + const cpuUsages = getCpuUsageData(); + const memoryUsages = getMemoryData(); + const processCpuUsages = getProcessCpuUsageData(); + const processMemoryUsages = getProcessMemoryData(); + const networkData = await getNetworkData(); + + this._batchUpdateCpuUsages(observableResult, cpuUsages); + this._batchUpdateMemUsages(observableResult, memoryUsages); + this._batchUpdateProcessCpuUsages(observableResult, processCpuUsages); + this._batchUpdateProcessMemUsage(observableResult, processMemoryUsages); + this._batchUpdateNetworkData(observableResult, networkData); + }, + [ + this._cpuTime, + this._cpuUtilization, + this._memoryUsage, + this._memoryUtilization, + this._processCpuTime, + this._processCpuUtilization, + this._processMemoryUsage, + this._networkDropped, + this._networkErrors, + this._networkIo, + ] + ); } /** @@ -230,10 +280,15 @@ export class HostMetrics extends BaseMetrics { this._createMetrics(); } - private _getMemoryData = throttle(getMemoryData, this._maxTimeoutUpdateMS); - private _getCpuUsageData = throttle( - getCpuUsageData, - this._maxTimeoutUpdateMS - ); - private _getNetworkData = throttle(getNetworkData, this._maxTimeoutUpdateMS); + // The metrics are created in `_createMetrics`. + private _cpuTime!: api.ObservableCounter; + private _cpuUtilization!: api.ObservableGauge; + private _memoryUsage!: api.ObservableGauge; + private _memoryUtilization!: api.ObservableGauge; + private _processCpuTime!: api.ObservableCounter; + private _processCpuUtilization!: api.ObservableGauge; + private _processMemoryUsage!: api.ObservableGauge; + private _networkDropped!: api.ObservableCounter; + private _networkErrors!: api.ObservableCounter; + private _networkIo!: api.ObservableCounter; } diff --git a/packages/opentelemetry-host-metrics/src/stats/common.ts b/packages/opentelemetry-host-metrics/src/stats/common.ts index 28b73f09d2..b74522ae0d 100644 --- a/packages/opentelemetry-host-metrics/src/stats/common.ts +++ b/packages/opentelemetry-host-metrics/src/stats/common.ts @@ -16,7 +16,7 @@ import * as os from 'os'; -import { CpuUsageData, MemoryData } from '../types'; +import { CpuUsageData, MemoryData, ProcessCpuUsageData } from '../types'; const MILLISECOND = 1 / 1e3; let cpuUsageTime: number | undefined = undefined; @@ -61,6 +61,28 @@ export function getCpuUsageData(): CpuUsageData[] { }); } +/** + * It returns process cpu load delta from last time - to be used with SumObservers. + * When called first time it will return 0 and then delta will be calculated + */ +export function getProcessCpuUsageData(): ProcessCpuUsageData { + if (typeof cpuUsageTime !== 'number') { + cpuUsageTime = new Date().getTime() - process.uptime() * 1000; + } + const timeElapsed = (new Date().getTime() - cpuUsageTime) / 1000; + const cpuUsage: NodeJS.CpuUsage = process.cpuUsage(); + const user = cpuUsage.user * MILLISECOND; + const system = cpuUsage.system * MILLISECOND; + const userP = user / timeElapsed; + const systemP = system / timeElapsed; + return { + user, + system, + userP, + systemP, + }; +} + /** * Returns memory data as absolute values */ @@ -80,3 +102,17 @@ export function getMemoryData(): MemoryData { freeP: freeP, // this is frac part (0-1) }; } + +/** + * Returns process memory RSS + * The Resident Set Size, is the amount of space occupied in the main memory device (that is a subset of the total allocated memory) for the process, + * including all C++ and JavaScript objects and code. + */ +export function getProcessMemoryData(): number { + // `process.memoryUsage.rss` is a faster alternative introduced in v14.18.0. + // Prefer it if available. + if (process.memoryUsage.rss) { + return process.memoryUsage.rss(); + } + return process.memoryUsage().rss; +} diff --git a/packages/opentelemetry-host-metrics/src/types.ts b/packages/opentelemetry-host-metrics/src/types.ts index 0e1aed4eb5..91d945012e 100644 --- a/packages/opentelemetry-host-metrics/src/types.ts +++ b/packages/opentelemetry-host-metrics/src/types.ts @@ -44,6 +44,16 @@ export interface CpuUsageData { niceP: number; } +/** + * Process CPU usage data + */ +export interface ProcessCpuUsageData { + system: number; + user: number; + systemP: number; + userP: number; +} + /** * Memory data */ diff --git a/packages/opentelemetry-host-metrics/src/util.ts b/packages/opentelemetry-host-metrics/src/util.ts index 2ad6d6c819..e26b0f7610 100644 --- a/packages/opentelemetry-host-metrics/src/util.ts +++ b/packages/opentelemetry-host-metrics/src/util.ts @@ -17,18 +17,3 @@ export function ObjectKeys(t: T) { return Object.keys(t) as (keyof T)[]; } - -export function throttle(fn: () => T, ms: number): () => T { - let memoized: T | undefined = undefined; - let timeout: ReturnType | null = null; - return () => { - if (timeout !== null) { - return memoized!; - } - memoized = fn(); - timeout = setTimeout(() => { - timeout = null; - }, ms); - return memoized; - }; -} diff --git a/packages/opentelemetry-host-metrics/test/metric.test.ts b/packages/opentelemetry-host-metrics/test/metric.test.ts index 9c16815aac..39b4fdb8eb 100644 --- a/packages/opentelemetry-host-metrics/test/metric.test.ts +++ b/packages/opentelemetry-host-metrics/test/metric.test.ts @@ -15,7 +15,7 @@ */ const SI = require('systeminformation'); -import { MetricAttributes } from '@opentelemetry/api-metrics'; +import { Attributes } from '@opentelemetry/api'; import { AggregationTemporality, DataPoint, @@ -27,13 +27,13 @@ import { import * as assert from 'assert'; import * as os from 'os'; import * as sinon from 'sinon'; -import { DEFAULT_MAX_TIMEOUT_UPDATE_MS, HostMetrics } from '../src'; +import { HostMetrics } from '../src'; const cpuJson = require('./mocks/cpu.json'); const networkJson = require('./mocks/network.json'); class TestMetricReader extends MetricReader { - public selectAggregationTemporality(): AggregationTemporality { + public override selectAggregationTemporality(): AggregationTemporality { return AggregationTemporality.CUMULATIVE; } protected async onForceFlush(): Promise {} @@ -117,6 +117,15 @@ describe('Host Metrics', () => { sandbox.stub(SI, 'networkStats').callsFake(() => { return mockedSI.networkStats(); }); + sandbox.stub(process, 'cpuUsage').callsFake(() => { + return { + user: 90713560, + system: 63192630, + }; + }); + sandbox.stub(process.memoryUsage, 'rss').callsFake(() => { + return 123456; + }); reader = new TestMetricReader(); @@ -138,7 +147,6 @@ describe('Host Metrics', () => { dateStub.returns(process.uptime() * 1000 + INTERVAL); // invalidates throttles - sandbox.clock.tick(DEFAULT_MAX_TIMEOUT_UPDATE_MS); countSI = 0; }); afterEach(() => { @@ -211,6 +219,26 @@ describe('Host Metrics', () => { ensureValue(metric, { direction: 'receive', device: 'eth0' }, 123123); ensureValue(metric, { direction: 'transmit', device: 'eth0' }, 321321); }); + + it('should export Process CPU time metrics', async () => { + const metric = await getRecords(reader, 'process.cpu.time'); + + ensureValue(metric, { state: 'user' }, 90713.56); + ensureValue(metric, { state: 'system' }, 63192.630000000005); + }); + + it('should export Process CPU utilization metrics', async () => { + const metric = await getRecords(reader, 'process.cpu.utilization'); + + ensureValue(metric, { state: 'user' }, 30247.935978659552); + ensureValue(metric, { state: 'system' }, 21071.23374458153); + }); + + it('should export Process Memory usage metrics', async () => { + const metric = await getRecords(reader, 'process.memory.usage'); + + ensureValue(metric, {}, 123456); + }); }); }); @@ -231,7 +259,7 @@ async function getRecords( function ensureValue( metric: MetricData, - attributes: MetricAttributes, + attributes: Attributes, value: number ) { const attrHash = hashAttributes(attributes); @@ -247,7 +275,7 @@ function ensureValue( assert.strictEqual(aggValue, value); } -function hashAttributes(attributes: MetricAttributes) { +function hashAttributes(attributes: Attributes) { return Object.entries(attributes) .sort(([a], [b]) => { return a < b ? -1 : 1; diff --git a/packages/opentelemetry-host-metrics/test/util.test.ts b/packages/opentelemetry-host-metrics/test/util.test.ts deleted file mode 100644 index 573996c20a..0000000000 --- a/packages/opentelemetry-host-metrics/test/util.test.ts +++ /dev/null @@ -1,83 +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 { throttle } from '../src/util'; -import * as sinon from 'sinon'; -import * as assert from 'assert'; - -describe('util', () => { - describe('throttle', () => { - let sandbox: sinon.SinonSandbox; - beforeEach(() => { - sandbox = sinon.createSandbox(); - sandbox.useFakeTimers(); - }); - - afterEach(() => { - sandbox.restore(); - }); - - it('should call the fn', () => { - let retValue = '1'; - const stub = sinon.stub(); - const throttled = throttle(stub, 100); - - // no return value is memoized, calls the fn. - stub.returns(retValue); - assert.strictEqual(throttled(), retValue); - assert.strictEqual(throttled(), retValue); - - sandbox.clock.tick(50); - // the return value is memoized, does not call the fn. - assert.strictEqual(throttled(), retValue); - assert.strictEqual(stub.callCount, 1); - - retValue = '2'; - stub.returns(retValue); - sandbox.clock.tick(50); - // no return value is memoized, calls the fn. - assert.strictEqual(throttled(), retValue); - assert.strictEqual(stub.callCount, 2); - }); - - it('should call the fn with exceptions', () => { - const stub = sinon.stub(); - const throttled = throttle(stub, 100); - - const error = new Error('foobar'); - stub.throws(error); - // no return value is memoized, throws. - assert.throws(throttled, error); - assert.throws(throttled, error); - stub.returns('1'); - assert.strictEqual(throttled(), '1'); - - sandbox.clock.tick(50); - assert.strictEqual(throttled(), '1'); - assert.strictEqual(stub.callCount, 3); - - sandbox.clock.tick(50); - // no return value is memoized, calls the fn. - assert.strictEqual(throttled(), '1'); - assert.strictEqual(stub.callCount, 4); - - // the return value is memoized, does not throw. - stub.throws(error); - assert.strictEqual(throttled(), '1'); - assert.strictEqual(stub.callCount, 4); - }); - }); -}); diff --git a/packages/opentelemetry-id-generator-aws-xray/README.md b/packages/opentelemetry-id-generator-aws-xray/README.md index 5b252f0b6f..707cddadbb 100644 --- a/packages/opentelemetry-id-generator-aws-xray/README.md +++ b/packages/opentelemetry-id-generator-aws-xray/README.md @@ -3,20 +3,22 @@ [![NPM Published Version][npm-img]][npm-url] [![Apache License][license-image]][license-image] -[component owners](https://github.com/open-telemetry/opentelemetry-js-contrib/blob/main/.github/component_owners.yml): @willarmiros - The OpenTelemetry IdGenerator for AWS X-Ray generates trace IDs with its first four bytes set to the start time of the trace followed by a unique identifier consisting of 12 bytes of randomly generated numbers. OpenTelemetry offers an extension point which allows the usage of this custom IdGenerator as opposed to the out-of-the-box random IdGenerator, enabling compatibility with AWS X-Ray. -Compatible with OpenTelemetry JS API and SDK `1.0+`. +## Status + +| Maturity | [Component Owner](../../.github/component_owners.yml) | Compatibility | +| -------------------------------------- | ----------------------------------------------------- | --------------------- | +| [Stable](../../CONTRIBUTING.md#stable) | @carolabadeer | API 1.0+
SDK 1.0+ | ## Installation -` +```bash npm install --save @opentelemetry/id-generator-aws-xray -` +``` ## Usage diff --git a/packages/opentelemetry-id-generator-aws-xray/package.json b/packages/opentelemetry-id-generator-aws-xray/package.json index f0a317c4a1..2248ea5727 100644 --- a/packages/opentelemetry-id-generator-aws-xray/package.json +++ b/packages/opentelemetry-id-generator-aws-xray/package.json @@ -59,7 +59,6 @@ "@types/node": "18.11.7", "@types/sinon": "10.0.2", "@types/webpack-env": "1.16.2", - "gts": "3.1.0", "@jsdevtools/coverage-istanbul-loader": "3.0.5", "karma": "6.3.16", "karma-chrome-launcher": "^3.1.1", @@ -69,11 +68,11 @@ "karma-webpack": "4.0.2", "mocha": "7.2.0", "nyc": "15.1.0", - "rimraf": "3.0.2", - "sinon": "14.0.0", + "rimraf": "4.2.0", + "sinon": "15.0.1", "ts-loader": "8.3.0", "ts-mocha": "10.0.0", - "typescript": "4.3.5", + "typescript": "4.4.4", "webpack": "4.46.0" }, "dependencies": { diff --git a/packages/opentelemetry-propagation-utils/CHANGELOG.md b/packages/opentelemetry-propagation-utils/CHANGELOG.md index 52b4058a4f..1fdcd0a4d6 100644 --- a/packages/opentelemetry-propagation-utils/CHANGELOG.md +++ b/packages/opentelemetry-propagation-utils/CHANGELOG.md @@ -1,5 +1,23 @@ # Changelog +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.31.0 to ^0.33.0 + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.0 to ^0.33.1 + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.1 to ^0.33.2 + ## [0.29.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/propagation-utils-v0.28.0...propagation-utils-v0.29.0) (2022-09-27) diff --git a/packages/opentelemetry-propagation-utils/package.json b/packages/opentelemetry-propagation-utils/package.json index e35153d111..013c3123a4 100644 --- a/packages/opentelemetry-propagation-utils/package.json +++ b/packages/opentelemetry-propagation-utils/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/propagation-utils", - "version": "0.29.0", + "version": "0.29.3", "description": "Propagation utilities for opentelemetry instrumentations", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -45,16 +45,15 @@ }, "devDependencies": { "@opentelemetry/api": "^1.0.0", - "@opentelemetry/contrib-test-utils": "^0.31.0", + "@opentelemetry/contrib-test-utils": "^0.33.2", "@types/mocha": "^9.1.1", "@types/node": "18.11.7", "@types/sinon": "^10.0.11", - "expect": "27.4.2", - "gts": "3.1.0", + "expect": "29.2.0", "mocha": "7.2.0", "nyc": "15.1.0", - "sinon": "13.0.1", + "sinon": "15.0.1", "ts-mocha": "10.0.0", - "typescript": "4.3.5" + "typescript": "4.4.4" } } diff --git a/packages/opentelemetry-propagation-utils/test/pubsub-propagation.test.ts b/packages/opentelemetry-propagation-utils/test/pubsub-propagation.test.ts index 8c853b791f..62199d4f33 100644 --- a/packages/opentelemetry-propagation-utils/test/pubsub-propagation.test.ts +++ b/packages/opentelemetry-propagation-utils/test/pubsub-propagation.test.ts @@ -20,7 +20,7 @@ import { resetMemoryExporter, } from '@opentelemetry/contrib-test-utils'; import { ROOT_CONTEXT, trace } from '@opentelemetry/api'; -import * as expect from 'expect'; +import { expect } from 'expect'; registerInstrumentationTestingProvider(); diff --git a/packages/opentelemetry-redis-common/.eslintignore b/packages/opentelemetry-redis-common/.eslintignore new file mode 100644 index 0000000000..378eac25d3 --- /dev/null +++ b/packages/opentelemetry-redis-common/.eslintignore @@ -0,0 +1 @@ +build diff --git a/packages/opentelemetry-redis-common/.eslintrc.js b/packages/opentelemetry-redis-common/.eslintrc.js new file mode 100644 index 0000000000..f726f3becb --- /dev/null +++ b/packages/opentelemetry-redis-common/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + "env": { + "mocha": true, + "node": true + }, + ...require('../../eslint.config.js') +} diff --git a/packages/opentelemetry-redis-common/CHANGELOG.md b/packages/opentelemetry-redis-common/CHANGELOG.md new file mode 100644 index 0000000000..a1c1410417 --- /dev/null +++ b/packages/opentelemetry-redis-common/CHANGELOG.md @@ -0,0 +1,20 @@ +# Changelog + +## [0.35.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/redis-common-v0.34.0...redis-common-v0.35.0) (2023-03-03) + + +### Features + +* **ioredis:** Update instrumentation-ioredis to version 5.x.x ([#1121](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1121)) ([f5f7ac6](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/f5f7ac6196b5422e030a6913c491117a6a3a0690)) + +## [0.34.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/redis-common-v0.33.0...redis-common-v0.34.0) (2022-12-20) + + +### Features + +* upstream mocha instrumentation testing plugin from ext-js [#621](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/621) ([#669](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/669)) ([a5170c4](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/a5170c494706a2bec3ba51e59966d0ca8a41d00e)) + + +### Bug Fixes + +* **redis:** serialize non sensitive arguments into db.statement attribute ([#1299](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1299)) ([092a250](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/092a2509bcf884e1b997e0eaec3a6ca02cfd2058)) diff --git a/packages/opentelemetry-redis-common/LICENSE b/packages/opentelemetry-redis-common/LICENSE new file mode 100644 index 0000000000..e50e8c80f9 --- /dev/null +++ b/packages/opentelemetry-redis-common/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [2022] 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 + + 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. diff --git a/packages/opentelemetry-redis-common/README.md b/packages/opentelemetry-redis-common/README.md new file mode 100644 index 0000000000..bb8de2d704 --- /dev/null +++ b/packages/opentelemetry-redis-common/README.md @@ -0,0 +1,7 @@ +# Redis Common Utils for OpenTelemetry redis packages + +This is an internal utils package used for the different redis instrumentations: + +1. ioredis +2. redis +3. redis-4 diff --git a/packages/opentelemetry-redis-common/package.json b/packages/opentelemetry-redis-common/package.json new file mode 100644 index 0000000000..e8622926c3 --- /dev/null +++ b/packages/opentelemetry-redis-common/package.json @@ -0,0 +1,49 @@ +{ + "name": "@opentelemetry/redis-common", + "version": "0.35.0", + "description": "Redis utilities for redis instrumentations", + "main": "build/src/index.js", + "types": "build/src/index.d.ts", + "publishConfig": { + "access": "public" + }, + "scripts": { + "lint": "eslint . --ext .ts", + "lint:fix": "eslint . --ext .ts --fix", + "compile": "tsc --build tsconfig.json", + "precompile": "tsc --version && lerna run version:update --scope @opentelemetry/redis-common --include-dependencies", + "prewatch": "npm run precompile", + "prepare": "npm run compile", + "test": "nyc ts-mocha -p tsconfig.json 'test/**/*.test.ts'", + "watch": "tsc -w" + }, + "repository": "open-telemetry/opentelemetry-js-contrib", + "keywords": [ + "opentelemetry", + "redis-common" + ], + "files": [ + "build/**/*.js", + "build/**/*.js.map", + "build/**/*.d.ts", + "LICENSE", + "README.md" + ], + "author": "OpenTelemetry Authors", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + }, + "bugs": { + "url": "https://github.com/open-telemetry/opentelemetry-js-contrib/issues" + }, + "homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/packages/redis-common#readme", + "devDependencies": { + "@types/mocha": "^9.1.1", + "@types/node": "18.11.7", + "mocha": "7.2.0", + "nyc": "15.1.0", + "ts-mocha": "10.0.0", + "typescript": "4.4.4" + } +} diff --git a/packages/opentelemetry-redis-common/src/index.ts b/packages/opentelemetry-redis-common/src/index.ts new file mode 100644 index 0000000000..eb093cb773 --- /dev/null +++ b/packages/opentelemetry-redis-common/src/index.ts @@ -0,0 +1,76 @@ +/* + * 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. + */ + +/** + * List of regexes and the number of arguments that should be serialized for matching commands. + * For example, HSET should serialize which key and field it's operating on, but not its value. + * Setting the subset to -1 will serialize all arguments. + * Commands without a match will have their first argument serialized. + * + * Refer to https://redis.io/commands/ for the full list. + */ +const serializationSubsets = [ + { + regex: /^ECHO/i, + args: 0, + }, + { + regex: /^(LPUSH|MSET|PFA|PUBLISH|RPUSH|SADD|SET|SPUBLISH|XADD|ZADD)/i, + args: 1, + }, + { + regex: /^(HSET|HMSET|LSET|LINSERT)/i, + args: 2, + }, + { + regex: + /^(ACL|BIT|B[LRZ]|CLIENT|CLUSTER|CONFIG|COMMAND|DECR|DEL|EVAL|EX|FUNCTION|GEO|GET|HINCR|HMGET|HSCAN|INCR|L[TRLM]|MEMORY|P[EFISTU]|RPOP|S[CDIMORSU]|XACK|X[CDGILPRT]|Z[CDILMPRS])/i, + args: -1, + }, +]; + +export type DbStatementSerializer = ( + cmdName: string, + cmdArgs: Array +) => string; + +/** + * Given the redis command name and arguments, return a combination of the + * command name + the allowed arguments according to `serializationSubsets`. + * @param cmdName The redis command name + * @param cmdArgs The redis command arguments + * @returns a combination of the command name + args according to `serializationSubsets`. + */ +export const defaultDbStatementSerializer: DbStatementSerializer = ( + cmdName, + cmdArgs +) => { + if (Array.isArray(cmdArgs) && cmdArgs.length) { + const nArgsToSerialize = + serializationSubsets.find(({ regex }) => { + return regex.test(cmdName); + })?.args ?? 0; + const argsToSerialize = + nArgsToSerialize >= 0 ? cmdArgs.slice(0, nArgsToSerialize) : cmdArgs; + if (cmdArgs.length > argsToSerialize.length) { + argsToSerialize.push( + `[${cmdArgs.length - nArgsToSerialize} other arguments]` + ); + } + return `${cmdName} ${argsToSerialize.join(' ')}`; + } + return cmdName; +}; diff --git a/packages/opentelemetry-redis-common/test/redis-common.test.ts b/packages/opentelemetry-redis-common/test/redis-common.test.ts new file mode 100644 index 0000000000..874903fadd --- /dev/null +++ b/packages/opentelemetry-redis-common/test/redis-common.test.ts @@ -0,0 +1,54 @@ +/* + * 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 { defaultDbStatementSerializer } from '../src/index'; +import * as assert from 'assert'; + +describe('#defaultDbStatementSerializer()', () => { + [ + { + cmdName: 'UNKNOWN', + cmdArgs: ['something'], + expected: 'UNKNOWN [1 other arguments]', + }, + { + cmdName: 'ECHO', + cmdArgs: ['echo'], + expected: 'ECHO [1 other arguments]', + }, + { + cmdName: 'LPUSH', + cmdArgs: ['list', 'value'], + expected: 'LPUSH list [1 other arguments]', + }, + { + cmdName: 'HSET', + cmdArgs: ['hash', 'field', 'value'], + expected: 'HSET hash field [1 other arguments]', + }, + { + cmdName: 'INCRBY', + cmdArgs: ['key', 5], + expected: 'INCRBY key 5', + }, + ].forEach(({ cmdName, cmdArgs, expected }) => { + it(`should serialize the correct number of arguments for ${cmdName}`, () => { + assert.strictEqual( + defaultDbStatementSerializer(cmdName, cmdArgs), + expected + ); + }); + }); +}); diff --git a/packages/opentelemetry-redis-common/tsconfig.json b/packages/opentelemetry-redis-common/tsconfig.json new file mode 100644 index 0000000000..4078877ce6 --- /dev/null +++ b/packages/opentelemetry-redis-common/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.base", + "compilerOptions": { + "rootDir": ".", + "outDir": "build" + }, + "include": [ + "src/**/*.ts", + "test/**/*.ts" + ] +} diff --git a/packages/opentelemetry-test-utils/CHANGELOG.md b/packages/opentelemetry-test-utils/CHANGELOG.md index 172e54896a..c6215dafe8 100644 --- a/packages/opentelemetry-test-utils/CHANGELOG.md +++ b/packages/opentelemetry-test-utils/CHANGELOG.md @@ -1,5 +1,26 @@ # Changelog +## [0.33.2](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/contrib-test-utils-v0.33.1...contrib-test-utils-v0.33.2) (2023-04-25) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.38.0 ([#1468](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1468)) ([565a2b2](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/565a2b2c6fde88af3f5401ef6a5a9643d0d66349)) + +## [0.33.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/contrib-test-utils-v0.33.0...contrib-test-utils-v0.33.1) (2023-02-07) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.35.1 ([#1358](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1358)) ([ff109b7](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/ff109b77928cc9a139a21c63d6b54399bb017fa4)) + +## [0.33.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/contrib-test-utils-v0.32.0...contrib-test-utils-v0.33.0) (2022-11-16) + + +### Features + +* update experimental deps to `^0.34.0`, core deps to `^1.8.0`, api to `^1.3.0` ([#1278](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1278)) ([e9fe8e1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/e9fe8e13e34f54e96c50525cadeb74ac048c5624)) + ## [0.32.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/contrib-test-utils-v0.31.0...contrib-test-utils-v0.32.0) (2022-09-02) diff --git a/packages/opentelemetry-test-utils/package.json b/packages/opentelemetry-test-utils/package.json index 1b41eea269..c88aa12eea 100644 --- a/packages/opentelemetry-test-utils/package.json +++ b/packages/opentelemetry-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/contrib-test-utils", - "version": "0.32.0", + "version": "0.33.2", "description": "Test utilities for opentelemetry components", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -38,21 +38,20 @@ }, "homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/packages/opentelemetry-test-utils#readme", "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@opentelemetry/api": "^1.3.0" }, "devDependencies": { - "@opentelemetry/api": "^1.0.0", + "@opentelemetry/api": "^1.3.0", "@types/node": "18.11.7", - "gts": "3.1.0", - "typescript": "4.3.5" + "typescript": "4.4.4" }, "dependencies": { "@opentelemetry/core": "^1.0.0", "@opentelemetry/exporter-jaeger": "^1.3.1", - "@opentelemetry/instrumentation": "^0.32.0", - "@opentelemetry/sdk-trace-node": "^1.3.1", - "@opentelemetry/resources": "^1.3.1", - "@opentelemetry/sdk-trace-base": "^1.3.1", + "@opentelemetry/instrumentation": "^0.38.0", + "@opentelemetry/sdk-trace-node": "^1.8.0", + "@opentelemetry/resources": "^1.8.0", + "@opentelemetry/sdk-trace-base": "^1.8.0", "@opentelemetry/semantic-conventions": "^1.0.0" } } diff --git a/plugins/node/instrumentation-amqplib/CHANGELOG.md b/plugins/node/instrumentation-amqplib/CHANGELOG.md index a12aa4da92..d17f68af9e 100644 --- a/plugins/node/instrumentation-amqplib/CHANGELOG.md +++ b/plugins/node/instrumentation-amqplib/CHANGELOG.md @@ -1,5 +1,56 @@ # Changelog +## [0.32.3](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-amqplib-v0.32.2...instrumentation-amqplib-v0.32.3) (2023-04-25) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.38.0 ([#1468](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1468)) ([565a2b2](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/565a2b2c6fde88af3f5401ef6a5a9643d0d66349)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.1 to ^0.33.2 + +## [0.32.2](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-amqplib-v0.32.1...instrumentation-amqplib-v0.32.2) (2023-02-14) + + +### Bug Fixes + +* **amqplib:** stop importing from `amqplib` directly in compiled types ([#1394](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1394)) ([9d0198c](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/9d0198ca104a34726a7b41dd910df275e0c5336d)) + +## [0.32.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-amqplib-v0.32.0...instrumentation-amqplib-v0.32.1) (2023-02-07) + + +### Bug Fixes + +* **amqplib:** use extracted context for message consuming ([#1354](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1354)) ([ad92673](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/ad92673bd6dbf154b8c73968f34d1e836099dd35)) +* **deps:** update otel core experimental to ^0.35.1 ([#1358](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1358)) ([ff109b7](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/ff109b77928cc9a139a21c63d6b54399bb017fa4)) +* **instrumentation-amqplib:** move `@types/amqplib` into dev deps ([#1320](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1320)) ([52136d8](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/52136d85064b0d451b3cc67530ee96f8bb8128af)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.0 to ^0.33.1 + +## [0.32.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-amqplib-v0.31.0...instrumentation-amqplib-v0.32.0) (2022-11-16) + + +### Features + +* update experimental deps to `^0.34.0`, core deps to `^1.8.0`, api to `^1.3.0` ([#1278](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1278)) ([e9fe8e1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/e9fe8e13e34f54e96c50525cadeb74ac048c5624)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.32.0 to ^0.33.0 + ## [0.31.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-amqplib-v0.30.0...instrumentation-amqplib-v0.31.0) (2022-09-02) diff --git a/plugins/node/instrumentation-amqplib/package.json b/plugins/node/instrumentation-amqplib/package.json index 8e7d661da9..5c085d9bcb 100644 --- a/plugins/node/instrumentation-amqplib/package.json +++ b/plugins/node/instrumentation-amqplib/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/instrumentation-amqplib", - "version": "0.31.0", + "version": "0.32.3", "description": "OpenTelemetry automatic instrumentation for the `amqplib` package", "keywords": [ "amqplib", @@ -43,31 +43,30 @@ "test:docker:run": "docker run -d --hostname demo-amqplib-rabbit --name amqplib-unittests -p 22221:5672 --env RABBITMQ_DEFAULT_USER=username --env RABBITMQ_DEFAULT_PASS=password rabbitmq:3" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@opentelemetry/api": "^1.3.0" }, "dependencies": { - "@opentelemetry/core": "^1.0.0", - "@opentelemetry/instrumentation": "^0.32.0", - "@opentelemetry/semantic-conventions": "^1.0.0", - "@types/amqplib": "^0.5.17" + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.38.0", + "@opentelemetry/semantic-conventions": "^1.0.0" }, "devDependencies": { - "@opentelemetry/api": "^1.0.0", - "@opentelemetry/contrib-test-utils": "^0.32.0", + "@opentelemetry/api": "^1.3.0", + "@opentelemetry/contrib-test-utils": "^0.33.2", + "@types/amqplib": "^0.5.17", "@types/lodash": "4.14.178", "@types/mocha": "8.2.3", "@types/sinon": "10.0.2", "@types/node": "18.11.7", "amqplib": "0.8.0", - "expect": "27.4.2", + "expect": "29.2.0", "lodash": "4.17.21", "mocha": "7.2.0", "ts-mocha": "10.0.0", "nyc": "15.1.0", - "gts": "3.1.0", - "sinon": "14.0.0", + "sinon": "15.0.1", "test-all-versions": "5.0.1", - "typescript": "4.3.5" + "typescript": "4.4.4" }, "engines": { "node": ">=14" diff --git a/plugins/node/instrumentation-amqplib/src/amqplib.ts b/plugins/node/instrumentation-amqplib/src/amqplib.ts index 5d51a3dde5..17fd6e20b6 100644 --- a/plugins/node/instrumentation-amqplib/src/amqplib.ts +++ b/plugins/node/instrumentation-amqplib/src/amqplib.ts @@ -30,7 +30,6 @@ import { } from '@opentelemetry/core'; import { InstrumentationBase, - InstrumentationModuleDefinition, InstrumentationNodeModuleDefinition, InstrumentationNodeModuleFile, isWrapped, @@ -41,7 +40,13 @@ import { MessagingOperationValues, MessagingDestinationKindValues, } from '@opentelemetry/semantic-conventions'; -import type * as amqp from 'amqplib'; +import type { + Connection, + ConsumeMessage, + Message, + Options, + Replies, +} from 'amqplib'; import { AmqplibInstrumentationConfig, DEFAULT_CONFIG, @@ -64,7 +69,7 @@ import { } from './utils'; import { VERSION } from './version'; -export class AmqplibInstrumentation extends InstrumentationBase { +export class AmqplibInstrumentation extends InstrumentationBase { protected override _config!: AmqplibInstrumentationConfig; constructor(config?: AmqplibInstrumentationConfig) { @@ -79,31 +84,29 @@ export class AmqplibInstrumentation extends InstrumentationBase { this._config = Object.assign({}, DEFAULT_CONFIG, config); } - protected init(): InstrumentationModuleDefinition { - const channelModelModuleFile = - new InstrumentationNodeModuleFile( - 'amqplib/lib/channel_model.js', - ['>=0.5.5'], - this.patchChannelModel.bind(this), - this.unpatchChannelModel.bind(this) - ); + protected init() { + const channelModelModuleFile = new InstrumentationNodeModuleFile( + 'amqplib/lib/channel_model.js', + ['>=0.5.5'], + this.patchChannelModel.bind(this), + this.unpatchChannelModel.bind(this) + ); - const callbackModelModuleFile = - new InstrumentationNodeModuleFile( - 'amqplib/lib/callback_model.js', - ['>=0.5.5'], - this.patchChannelModel.bind(this), - this.unpatchChannelModel.bind(this) - ); + const callbackModelModuleFile = new InstrumentationNodeModuleFile( + 'amqplib/lib/callback_model.js', + ['>=0.5.5'], + this.patchChannelModel.bind(this), + this.unpatchChannelModel.bind(this) + ); - const connectModuleFile = new InstrumentationNodeModuleFile( + const connectModuleFile = new InstrumentationNodeModuleFile( 'amqplib/lib/connect.js', ['>=0.5.5'], this.patchConnect.bind(this), this.unpatchConnect.bind(this) ); - const module = new InstrumentationNodeModuleDefinition( + const module = new InstrumentationNodeModuleDefinition( 'amqplib', ['>=0.5.5'], undefined, @@ -231,14 +234,14 @@ export class AmqplibInstrumentation extends InstrumentationBase { private getConnectPatch( original: ( - url: string | amqp.Options.Connect, + url: string | Options.Connect, socketOptions: any, - openCallback: (err: any, connection: amqp.Connection) => void - ) => amqp.Connection + openCallback: (err: any, connection: Connection) => void + ) => Connection ) { return function patchedConnect( this: unknown, - url: string | amqp.Options.Connect, + url: string | Options.Connect, socketOptions: any, openCallback: Function ) { @@ -246,7 +249,7 @@ export class AmqplibInstrumentation extends InstrumentationBase { this, url, socketOptions, - function (this: unknown, err, conn: amqp.Connection) { + function (this: unknown, err, conn: Connection) { if (err == null) { const urlAttributes = getConnectionAttributesFromUrl(url); // the type of conn in @types/amqplib is amqp.Connection, but in practice the library send the @@ -321,7 +324,7 @@ export class AmqplibInstrumentation extends InstrumentationBase { const self = this; return function ack( this: InstrumentationConsumeChannel, - message: amqp.Message, + message: Message, allUpToOrRequeue?: boolean, requeue?: boolean ): void { @@ -330,7 +333,7 @@ export class AmqplibInstrumentation extends InstrumentationBase { const requeueResolved = endOperation === EndOperation.Reject ? allUpToOrRequeue : requeue; - const spansNotEnded: { msg: amqp.Message }[] = + const spansNotEnded: { msg: Message }[] = channel[CHANNEL_SPANS_NOT_ENDED] ?? []; const msgIndex = spansNotEnded.findIndex( msgDetails => msgDetails.msg === message @@ -367,7 +370,7 @@ export class AmqplibInstrumentation extends InstrumentationBase { }; } - protected getConsumePatch( + private getConsumePatch( moduleVersion: string | undefined, original: Function ) { @@ -375,9 +378,9 @@ export class AmqplibInstrumentation extends InstrumentationBase { return function consume( this: InstrumentationConsumeChannel, queue: string, - onMessage: (msg: amqp.ConsumeMessage | null) => void, - options?: amqp.Options.Consume - ): Promise { + onMessage: (msg: ConsumeMessage | null) => void, + options?: Options.Consume + ): Promise { const channel = this; if ( !Object.prototype.hasOwnProperty.call(channel, CHANNEL_SPANS_NOT_ENDED) @@ -451,7 +454,7 @@ export class AmqplibInstrumentation extends InstrumentationBase { msg[MESSAGE_STORED_SPAN] = span; } - context.with(trace.setSpan(context.active(), span), () => { + context.with(trace.setSpan(parentContext, span), () => { onMessage.call(this, msg); }); @@ -465,7 +468,7 @@ export class AmqplibInstrumentation extends InstrumentationBase { }; } - protected getConfirmedPublishPatch( + private getConfirmedPublishPatch( moduleVersion: string | undefined, original: Function ) { @@ -475,8 +478,8 @@ export class AmqplibInstrumentation extends InstrumentationBase { exchange: string, routingKey: string, content: Buffer, - options?: amqp.Options.Publish, - callback?: (err: any, ok: amqp.Replies.Empty) => void + options?: Options.Publish, + callback?: (err: any, ok: Replies.Empty) => void ): boolean { const channel = this; const { span, modifiedOptions } = self.createPublishSpan( @@ -510,7 +513,7 @@ export class AmqplibInstrumentation extends InstrumentationBase { const patchedOnConfirm = function ( this: unknown, err: any, - ok: amqp.Replies.Empty + ok: Replies.Empty ) { try { callback?.call(this, err, ok); @@ -562,7 +565,7 @@ export class AmqplibInstrumentation extends InstrumentationBase { }; } - protected getPublishPatch( + private getPublishPatch( moduleVersion: string | undefined, original: Function ) { @@ -572,7 +575,7 @@ export class AmqplibInstrumentation extends InstrumentationBase { exchange: string, routingKey: string, content: Buffer, - options?: amqp.Options.Publish + options?: Options.Publish ): boolean { if (isConfirmChannelTracing(context.active())) { // work already done @@ -623,7 +626,7 @@ export class AmqplibInstrumentation extends InstrumentationBase { exchange: string, routingKey: string, channel: InstrumentationPublishChannel, - options?: amqp.Options.Publish + options?: Options.Publish ) { const normalizedExchange = normalizeExchange(exchange); @@ -689,7 +692,7 @@ export class AmqplibInstrumentation extends InstrumentationBase { operation: EndOperation, requeue: boolean | undefined ) { - const spansNotEnded: { msg: amqp.Message }[] = + const spansNotEnded: { msg: Message }[] = channel[CHANNEL_SPANS_NOT_ENDED] ?? []; spansNotEnded.forEach(msgDetails => { this.endConsumerSpan(msgDetails.msg, isRejected, operation, requeue); @@ -699,7 +702,7 @@ export class AmqplibInstrumentation extends InstrumentationBase { private callConsumeEndHook( span: Span, - msg: amqp.ConsumeMessage, + msg: ConsumeMessage, rejected: boolean | null, endOperation: EndOperation ) { diff --git a/plugins/node/instrumentation-amqplib/src/types.ts b/plugins/node/instrumentation-amqplib/src/types.ts index 66c6140eeb..2e82b471b5 100644 --- a/plugins/node/instrumentation-amqplib/src/types.ts +++ b/plugins/node/instrumentation-amqplib/src/types.ts @@ -15,14 +15,13 @@ */ import { Span } from '@opentelemetry/api'; import { InstrumentationConfig } from '@opentelemetry/instrumentation'; -import type * as amqp from 'amqplib'; export interface PublishInfo { moduleVersion: string | undefined; exchange: string; routingKey: string; content: Buffer; - options?: amqp.Options.Publish; + options?: AmqplibPublishOptions; isConfirmChannel?: boolean; } @@ -32,11 +31,11 @@ export interface PublishConfirmedInfo extends PublishInfo { export interface ConsumeInfo { moduleVersion: string | undefined; - msg: amqp.ConsumeMessage; + msg: ConsumeMessage; } export interface ConsumeEndInfo { - msg: amqp.ConsumeMessage; + msg: ConsumeMessage; rejected: boolean | null; endOperation: EndOperation; } @@ -102,3 +101,74 @@ export interface AmqplibInstrumentationConfig extends InstrumentationConfig { export const DEFAULT_CONFIG: AmqplibInstrumentationConfig = { consumeTimeoutMs: 1000 * 60, // 1 minute }; + +// The following types are vendored from `@types/amqplib@0.10.1` - commit SHA: 4205e03127692a40b4871709a7134fe4e2ed5510 + +// Vendored from: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/4205e03127692a40b4871709a7134fe4e2ed5510/types/amqplib/properties.d.ts#L108 +// This exists in `@types/amqplib` as `Options.Publish`. We're renaming things +// here to avoid importing the whole Options namespace. +export interface AmqplibPublishOptions { + expiration?: string | number; + userId?: string; + CC?: string | string[]; + + mandatory?: boolean; + persistent?: boolean; + deliveryMode?: boolean | number; + BCC?: string | string[]; + + contentType?: string; + contentEncoding?: string; + headers?: any; + priority?: number; + correlationId?: string; + replyTo?: string; + messageId?: string; + timestamp?: number; + type?: string; + appId?: string; +} + +// Vendored from: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/4205e03127692a40b4871709a7134fe4e2ed5510/types/amqplib/properties.d.ts#L142 +export interface Message { + content: Buffer; + fields: MessageFields; + properties: MessageProperties; +} + +export interface ConsumeMessage extends Message { + fields: ConsumeMessageFields; +} + +export interface CommonMessageFields { + deliveryTag: number; + redelivered: boolean; + exchange: string; + routingKey: string; +} + +export interface MessageFields extends CommonMessageFields { + messageCount?: number; + consumerTag?: string; +} + +export interface ConsumeMessageFields extends CommonMessageFields { + deliveryTag: number; +} + +export interface MessageProperties { + contentType: any | undefined; + contentEncoding: any | undefined; + headers: any; + deliveryMode: any | undefined; + priority: any | undefined; + correlationId: any | undefined; + replyTo: any | undefined; + expiration: any | undefined; + messageId: any | undefined; + timestamp: any | undefined; + type: any | undefined; + userId: any | undefined; + appId: any | undefined; + clusterId: any | undefined; +} diff --git a/plugins/node/instrumentation-amqplib/test/amqplib-callbacks.test.ts b/plugins/node/instrumentation-amqplib/test/amqplib-callbacks.test.ts index 424554e4dd..9f2ab1d81e 100644 --- a/plugins/node/instrumentation-amqplib/test/amqplib-callbacks.test.ts +++ b/plugins/node/instrumentation-amqplib/test/amqplib-callbacks.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import 'mocha'; -import * as expect from 'expect'; +import { expect } from 'expect'; import { AmqplibInstrumentation } from '../src'; import { getTestSpans, @@ -28,7 +28,7 @@ import { MessagingDestinationKindValues, SemanticAttributes, } from '@opentelemetry/semantic-conventions'; -import { context, SpanKind } from '@opentelemetry/api'; +import { Baggage, context, propagation, SpanKind } from '@opentelemetry/api'; import { asyncConfirmSend, asyncConsume, shouldTest } from './utils'; import { censoredUrl, @@ -36,12 +36,27 @@ import { TEST_RABBITMQ_HOST, TEST_RABBITMQ_PORT, } from './config'; +import { + CompositePropagator, + W3CBaggagePropagator, + W3CTraceContextPropagator, +} from '@opentelemetry/core'; const msgPayload = 'payload from test'; const queueName = 'queue-name-from-unittest'; describe('amqplib instrumentation callback model', () => { let conn: amqpCallback.Connection; + before(() => { + propagation.setGlobalPropagator( + new CompositePropagator({ + propagators: [ + new W3CBaggagePropagator(), + new W3CTraceContextPropagator(), + ], + }) + ); + }); before(function (done) { if (!shouldTest) { this.skip(); @@ -186,6 +201,35 @@ describe('amqplib instrumentation callback model', () => { }); }); + it('baggage is available while consuming', done => { + const baggageContext = propagation.setBaggage( + context.active(), + propagation.createBaggage({ + key1: { value: 'value1' }, + }) + ); + context.with(baggageContext, () => { + channel.sendToQueue(queueName, Buffer.from(msgPayload)); + let extractedBaggage: Baggage | undefined; + asyncConsume( + channel, + queueName, + [ + msg => { + extractedBaggage = propagation.getActiveBaggage(); + }, + ], + { + noAck: true, + } + ).then(() => { + expect(extractedBaggage).toBeDefined(); + expect(extractedBaggage!.getEntry('key1')).toBeDefined(); + done(); + }); + }); + }); + it('end span with ack sync', done => { channel.sendToQueue(queueName, Buffer.from(msgPayload)); diff --git a/plugins/node/instrumentation-amqplib/test/amqplib-connection.test.ts b/plugins/node/instrumentation-amqplib/test/amqplib-connection.test.ts index 748f06c7ee..7ac3e686e5 100644 --- a/plugins/node/instrumentation-amqplib/test/amqplib-connection.test.ts +++ b/plugins/node/instrumentation-amqplib/test/amqplib-connection.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import 'mocha'; -import * as expect from 'expect'; +import { expect } from 'expect'; import { shouldTest } from './utils'; import { censoredUrl, diff --git a/plugins/node/instrumentation-amqplib/test/amqplib-promise.test.ts b/plugins/node/instrumentation-amqplib/test/amqplib-promise.test.ts index b343dc71ea..e130f5e942 100644 --- a/plugins/node/instrumentation-amqplib/test/amqplib-promise.test.ts +++ b/plugins/node/instrumentation-amqplib/test/amqplib-promise.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import 'mocha'; -import * as expect from 'expect'; +import { expect } from 'expect'; import * as sinon from 'sinon'; import * as lodash from 'lodash'; import { diff --git a/plugins/node/instrumentation-amqplib/test/utils.test.ts b/plugins/node/instrumentation-amqplib/test/utils.test.ts index efa69b5886..34e6fb7aa9 100644 --- a/plugins/node/instrumentation-amqplib/test/utils.test.ts +++ b/plugins/node/instrumentation-amqplib/test/utils.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import 'mocha'; -import * as expect from 'expect'; +import { expect } from 'expect'; import { getConnectionAttributesFromServer, getConnectionAttributesFromUrl, diff --git a/plugins/node/instrumentation-amqplib/test/utils.ts b/plugins/node/instrumentation-amqplib/test/utils.ts index f6297dfb66..d1e3a2e4ca 100644 --- a/plugins/node/instrumentation-amqplib/test/utils.ts +++ b/plugins/node/instrumentation-amqplib/test/utils.ts @@ -15,7 +15,7 @@ */ import type * as amqp from 'amqplib'; import type * as amqpCallback from 'amqplib/callback_api'; -import * as expect from 'expect'; +import { expect } from 'expect'; export const asyncConfirmSend = ( confirmChannel: amqp.ConfirmChannel | amqpCallback.ConfirmChannel, diff --git a/plugins/node/instrumentation-dataloader/CHANGELOG.md b/plugins/node/instrumentation-dataloader/CHANGELOG.md index acd6a4e565..e68c02a4e1 100644 --- a/plugins/node/instrumentation-dataloader/CHANGELOG.md +++ b/plugins/node/instrumentation-dataloader/CHANGELOG.md @@ -1,5 +1,33 @@ # Changelog +## [0.4.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-dataloader-v0.4.0...instrumentation-dataloader-v0.4.1) (2023-04-25) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.38.0 ([#1468](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1468)) ([565a2b2](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/565a2b2c6fde88af3f5401ef6a5a9643d0d66349)) + +## [0.4.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-dataloader-v0.3.1...instrumentation-dataloader-v0.4.0) (2023-02-14) + + +### Features + +* **instrumentation-dataloader:** add dataloader name to span names ([#1345](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1345)) ([712b559](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/712b559416e0d86ef29ed06d46c180ef8360b411)) + +## [0.3.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-dataloader-v0.3.0...instrumentation-dataloader-v0.3.1) (2023-02-07) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.35.1 ([#1358](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1358)) ([ff109b7](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/ff109b77928cc9a139a21c63d6b54399bb017fa4)) + +## [0.3.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-dataloader-v0.2.1...instrumentation-dataloader-v0.3.0) (2022-11-16) + + +### Features + +* update experimental deps to `^0.34.0`, core deps to `^1.8.0`, api to `^1.3.0` ([#1278](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1278)) ([e9fe8e1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/e9fe8e13e34f54e96c50525cadeb74ac048c5624)) + ## [0.2.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-dataloader-v0.2.0...instrumentation-dataloader-v0.2.1) (2022-11-02) diff --git a/plugins/node/instrumentation-dataloader/package.json b/plugins/node/instrumentation-dataloader/package.json index 39f7ae002a..06ced203ab 100644 --- a/plugins/node/instrumentation-dataloader/package.json +++ b/plugins/node/instrumentation-dataloader/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/instrumentation-dataloader", - "version": "0.2.1", + "version": "0.4.1", "description": "OpenTelemetry instrumentation for dataloader", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -43,26 +43,25 @@ "access": "public" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@opentelemetry/api": "^1.3.0" }, "devDependencies": { - "@opentelemetry/api": "^1.0.0", - "@opentelemetry/context-async-hooks": "^1.6.0", - "@opentelemetry/sdk-trace-base": "^1.6.0", - "@opentelemetry/sdk-trace-node": "^1.6.0", + "@opentelemetry/api": "^1.3.0", + "@opentelemetry/context-async-hooks": "^1.8.0", + "@opentelemetry/sdk-trace-base": "^1.8.0", + "@opentelemetry/sdk-trace-node": "^1.8.0", "@types/mocha": "7.0.2", "@types/node": "18.11.7", - "dataloader": "2.0.0", - "gts": "3.1.0", + "dataloader": "2.2.1", "mocha": "7.2.0", "nyc": "15.1.0", - "rimraf": "3.0.2", + "rimraf": "4.2.0", "test-all-versions": "5.0.1", "ts-mocha": "10.0.0", - "typescript": "4.3.5" + "typescript": "4.4.4" }, "dependencies": { - "@opentelemetry/instrumentation": "^0.32.0" + "@opentelemetry/instrumentation": "^0.38.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/instrumentation-dataloader#readme" } diff --git a/plugins/node/instrumentation-dataloader/src/instrumentation.ts b/plugins/node/instrumentation-dataloader/src/instrumentation.ts index 7103e3e641..7264d031ae 100644 --- a/plugins/node/instrumentation-dataloader/src/instrumentation.ts +++ b/plugins/node/instrumentation-dataloader/src/instrumentation.ts @@ -36,10 +36,13 @@ const MODULE_NAME = 'dataloader'; type DataloaderInternal = typeof Dataloader.prototype & { _batchLoadFn: Dataloader.BatchLoadFn; _batch: { spanLinks?: Link[] } | null; + + // TODO: Remove this once types on Dataloader get fixed https://github.com/graphql/dataloader/pull/334 + name?: string | null; }; -type LoadFn = typeof Dataloader.prototype['load']; -type LoadManyFn = typeof Dataloader.prototype['loadMany']; +type LoadFn = (typeof Dataloader.prototype)['load']; +type LoadManyFn = (typeof Dataloader.prototype)['loadMany']; export class DataloaderInstrumentation extends InstrumentationBase { constructor(config: DataloaderInstrumentationConfig = {}) { @@ -89,40 +92,53 @@ export class DataloaderInstrumentation extends InstrumentationBase { return hasParentSpan || !config.requireParentSpan; } + private getSpanName( + dataloader: DataloaderInternal, + operation: 'load' | 'loadMany' | 'batch' + ): string { + const dataloaderName = dataloader.name; + if (dataloaderName === undefined || dataloaderName === null) { + return `${MODULE_NAME}.${operation}`; + } + + return `${MODULE_NAME}.${operation} ${dataloaderName}`; + } + private _getPatchedConstructor( constructor: typeof Dataloader ): typeof Dataloader { const prototype = constructor.prototype; - const self = this; + const instrumentation = this; function PatchedDataloader( ...args: ConstructorParameters ) { const inst = new constructor(...args) as DataloaderInternal; - if (!self.isEnabled()) { + if (!instrumentation.isEnabled()) { return inst; } if (isWrapped(inst._batchLoadFn)) { - self._unwrap(inst, '_batchLoadFn'); + instrumentation._unwrap(inst, '_batchLoadFn'); } - self._wrap(inst, '_batchLoadFn', original => { + instrumentation._wrap(inst, '_batchLoadFn', original => { return function patchedBatchLoadFn( this: DataloaderInternal, ...args: Parameters> ) { - if (!self.isEnabled() || !self.shouldCreateSpans()) { + if ( + !instrumentation.isEnabled() || + !instrumentation.shouldCreateSpans() + ) { return original.call(this, ...args); } const parent = context.active(); - const span = self.tracer.startSpan( - `${MODULE_NAME}.batch`, - { - links: this._batch?.spanLinks as Link[] | undefined, - }, + const span = instrumentation.tracer.startSpan( + instrumentation.getSpanName(inst, 'batch'), + { links: this._batch?.spanLinks as Link[] | undefined }, parent ); @@ -164,7 +180,7 @@ export class DataloaderInstrumentation extends InstrumentationBase { const instrumentation = this; return function patchedLoad( - this: typeof Dataloader.prototype, + this: DataloaderInternal, ...args: Parameters ) { if (!instrumentation.shouldCreateSpans()) { @@ -173,7 +189,7 @@ export class DataloaderInstrumentation extends InstrumentationBase { const parent = context.active(); const span = instrumentation.tracer.startSpan( - `${MODULE_NAME}.load`, + instrumentation.getSpanName(this, 'load'), { kind: SpanKind.CLIENT }, parent ); @@ -222,7 +238,7 @@ export class DataloaderInstrumentation extends InstrumentationBase { const instrumentation = this; return function patchedLoadMany( - this: typeof Dataloader.prototype, + this: DataloaderInternal, ...args: Parameters ) { if (!instrumentation.shouldCreateSpans()) { @@ -231,7 +247,7 @@ export class DataloaderInstrumentation extends InstrumentationBase { const parent = context.active(); const span = instrumentation.tracer.startSpan( - `${MODULE_NAME}.loadMany`, + instrumentation.getSpanName(this, 'loadMany'), { kind: SpanKind.CLIENT }, parent ); diff --git a/plugins/node/instrumentation-dataloader/test/dataloader.test.ts b/plugins/node/instrumentation-dataloader/test/dataloader.test.ts index b7ca578a91..9686c21d2e 100644 --- a/plugins/node/instrumentation-dataloader/test/dataloader.test.ts +++ b/plugins/node/instrumentation-dataloader/test/dataloader.test.ts @@ -140,6 +140,29 @@ describe('DataloaderInstrumentation', () => { message: 'Error message', }); }); + + it('correctly uses dataloader name (if available)', async () => { + const namedDataloader = new Dataloader( + async keys => keys.map((_, idx) => idx), + { name: 'test-name' } + ); + + assert.strictEqual(await namedDataloader.load('test'), 0); + + // We should have exactly two spans (one for .load and one for the following batch) + assert.strictEqual(memoryExporter.getFinishedSpans().length, 2); + const [batchSpan, loadSpan] = memoryExporter.getFinishedSpans(); + + if ((namedDataloader as { name?: string | null }).name === undefined) { + // For versions of dataloader package that does not support name, we should + // not be adding anything to the names + assert.strictEqual(loadSpan.name, 'dataloader.load'); + assert.strictEqual(batchSpan.name, 'dataloader.batch'); + } else { + assert.strictEqual(loadSpan.name, 'dataloader.load test-name'); + assert.strictEqual(batchSpan.name, 'dataloader.batch test-name'); + } + }); }); describe('loadMany', () => { @@ -235,6 +258,33 @@ describe('DataloaderInstrumentation', () => { code: SpanStatusCode.UNSET, }); }); + + it('correctly uses a generated name in spans', async () => { + const namedDataloader = new Dataloader( + async keys => keys.map((_, idx) => idx), + { name: 'test-name' } + ); + + assert.deepStrictEqual(await namedDataloader.loadMany(['test']), [0]); + + // We should have exactly three spans (one for .loadMany, one for the underlying .load + // and one for the following batch) + assert.strictEqual(memoryExporter.getFinishedSpans().length, 3); + const [batchSpan, loadSpan, loadManySpan] = + memoryExporter.getFinishedSpans(); + + if ((namedDataloader as { name?: string | null }).name === undefined) { + // For versions of dataloader package that does not support name, we should + // not be adding anything to the names + assert.strictEqual(batchSpan.name, 'dataloader.batch'); + assert.strictEqual(loadManySpan.name, 'dataloader.loadMany'); + assert.strictEqual(loadSpan.name, 'dataloader.load'); + } else { + assert.strictEqual(batchSpan.name, 'dataloader.batch test-name'); + assert.strictEqual(loadManySpan.name, 'dataloader.loadMany test-name'); + assert.strictEqual(loadSpan.name, 'dataloader.load test-name'); + } + }); }); it('should not create anything if disabled', async () => { diff --git a/plugins/node/instrumentation-fs/CHANGELOG.md b/plugins/node/instrumentation-fs/CHANGELOG.md index fa190b2e17..70a5e3083a 100644 --- a/plugins/node/instrumentation-fs/CHANGELOG.md +++ b/plugins/node/instrumentation-fs/CHANGELOG.md @@ -1,5 +1,39 @@ # Changelog +## [0.7.2](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-fs-v0.7.1...instrumentation-fs-v0.7.2) (2023-04-25) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.38.0 ([#1468](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1468)) ([565a2b2](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/565a2b2c6fde88af3f5401ef6a5a9643d0d66349)) + +## [0.7.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-fs-v0.7.0...instrumentation-fs-v0.7.1) (2023-03-03) + + +### Bug Fixes + +* **instrumentation-fs:** allow realpath.native and realpathSync.native ([#1332](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1332)) ([ee0a59a](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/ee0a59a59e94743b9411e10c09720a82c6586eb4)) +* **instrumentation-fs:** fix instrumentation of `fs/promises` ([#1375](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1375)) ([3ca874e](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/3ca874e45ebf4623e76cbe9305e55e820b6e03fd)) + +## [0.7.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-fs-v0.6.0...instrumentation-fs-v0.7.0) (2023-02-07) + + +### Features + +* **instrumentation-fs:** require parent span ([#1335](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1335)) ([79b2d3f](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/79b2d3ff08904ce84c6bc48427cd98906c2f0d79)) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.35.1 ([#1358](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1358)) ([ff109b7](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/ff109b77928cc9a139a21c63d6b54399bb017fa4)) + +## [0.6.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-fs-v0.5.1...instrumentation-fs-v0.6.0) (2022-11-16) + + +### Features + +* update experimental deps to `^0.34.0`, core deps to `^1.8.0`, api to `^1.3.0` ([#1278](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1278)) ([e9fe8e1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/e9fe8e13e34f54e96c50525cadeb74ac048c5624)) + ## [0.5.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-fs-v0.5.0...instrumentation-fs-v0.5.1) (2022-11-02) diff --git a/plugins/node/instrumentation-fs/README.md b/plugins/node/instrumentation-fs/README.md index 29f545a15f..77718809da 100644 --- a/plugins/node/instrumentation-fs/README.md +++ b/plugins/node/instrumentation-fs/README.md @@ -40,10 +40,11 @@ registerInstrumentations({ You can set the following: -| Options | Type | Description | -| ------- | ---- | ----------- | -| `createHook` | `(functionName: FMember | FPMember, info: { args: ArrayLike }) => boolean` | Hook called before creating the span. If `false` is returned this and all the sibling calls will not be traced. | -| `endHook` | `( functionName: FMember | FPMember, info: { args: ArrayLike; span: api.Span } ) => void` | Function called just before the span is ended. Useful for adding attributes. | +| Options | Type | Description | +| ------------------- | --------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | +| `createHook` | `(functionName: FMember \| FPMember, info: { args: ArrayLike }) => boolean` | Hook called before creating the span. If `false` is returned this and all the sibling calls will not be traced. | +| `endHook` | `( functionName: FMember \| FPMember, info: { args: ArrayLike; span: api.Span } ) => void` | Function called just before the span is ended. Useful for adding attributes. | +| `requireParentSpan` | `boolean` | Require parent to create fs span, default when unset is `false`. | ## Useful links diff --git a/plugins/node/instrumentation-fs/package.json b/plugins/node/instrumentation-fs/package.json index e22dbbc439..c40cd51e89 100644 --- a/plugins/node/instrumentation-fs/package.json +++ b/plugins/node/instrumentation-fs/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/instrumentation-fs", - "version": "0.5.1", + "version": "0.7.2", "description": "OpenTelemetry automatic instrumentation package for fs", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -39,28 +39,27 @@ "access": "public" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@opentelemetry/api": "^1.3.0" }, "devDependencies": { - "@opentelemetry/api": "^1.0.0", - "@opentelemetry/context-async-hooks": "^1.3.1", - "@opentelemetry/resources": "^1.3.1", - "@opentelemetry/sdk-trace-base": "^1.3.1", - "@opentelemetry/sdk-trace-node": "^1.3.1", + "@opentelemetry/api": "^1.3.0", + "@opentelemetry/context-async-hooks": "^1.8.0", + "@opentelemetry/resources": "^1.8.0", + "@opentelemetry/sdk-trace-base": "^1.8.0", + "@opentelemetry/sdk-trace-node": "^1.8.0", "@types/mocha": "7.0.2", "@types/node": "18.11.7", "@types/sinon": "^10.0.11", - "gts": "3.1.0", "mocha": "7.2.0", "nyc": "15.1.0", - "rimraf": "3.0.2", - "sinon": "14.0.0", + "rimraf": "4.2.0", + "sinon": "15.0.1", "ts-mocha": "10.0.0", - "typescript": "4.3.5" + "typescript": "4.4.4" }, "dependencies": { - "@opentelemetry/core": "^1.0.0", - "@opentelemetry/instrumentation": "^0.32.0", + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.38.0", "@opentelemetry/semantic-conventions": "^1.0.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/instrumentation-fs#readme" diff --git a/plugins/node/instrumentation-fs/src/constants.ts b/plugins/node/instrumentation-fs/src/constants.ts index 4b2a8ac0fc..a8588aae8f 100644 --- a/plugins/node/instrumentation-fs/src/constants.ts +++ b/plugins/node/instrumentation-fs/src/constants.ts @@ -67,6 +67,7 @@ export const CALLBACK_FUNCTIONS: FMember[] = [ 'readFile', 'readlink', 'realpath', + 'realpath.native', 'rename', 'rm', // added in v14 'rmdir', @@ -111,6 +112,7 @@ export const SYNC_FUNCTIONS: FMember[] = [ 'readFileSync', 'readlinkSync', 'realpathSync', + 'realpathSync.native', 'renameSync', 'rmdirSync', 'rmSync', // added in v14 diff --git a/plugins/node/instrumentation-fs/src/instrumentation.ts b/plugins/node/instrumentation-fs/src/instrumentation.ts index 6bd778da83..048b8d7b34 100644 --- a/plugins/node/instrumentation-fs/src/instrumentation.ts +++ b/plugins/node/instrumentation-fs/src/instrumentation.ts @@ -36,17 +36,30 @@ import type { FsInstrumentationConfig, } from './types'; import { promisify } from 'util'; +import { indexFs } from './utils'; type FS = typeof fs; +type FSPromises = (typeof fs)['promises']; -const supportsPromises = parseInt(process.versions.node.split('.')[0], 10) > 8; +/** + * This is important for 2-level functions like `realpath.native` to retain the 2nd-level + * when patching the 1st-level. + */ +function patchedFunctionWithOriginalProperties< + T extends (...args: any[]) => ReturnType +>(patchedFunction: T, original: T): T { + return Object.assign(patchedFunction, original); +} export default class FsInstrumentation extends InstrumentationBase { constructor(config?: FsInstrumentationConfig) { super('@opentelemetry/instrumentation-fs', VERSION, config); } - init(): InstrumentationNodeModuleDefinition[] { + init(): ( + | InstrumentationNodeModuleDefinition + | InstrumentationNodeModuleDefinition + )[] { return [ new InstrumentationNodeModuleDefinition( 'fs', @@ -54,46 +67,47 @@ export default class FsInstrumentation extends InstrumentationBase { (fs: FS) => { this._diag.debug('Applying patch for fs'); for (const fName of SYNC_FUNCTIONS) { - if (isWrapped(fs[fName])) { - this._unwrap(fs, fName); + const { objectToPatch, functionNameToPatch } = indexFs(fs, fName); + + if (isWrapped(objectToPatch[functionNameToPatch])) { + this._unwrap(objectToPatch, functionNameToPatch); } this._wrap( - fs, - fName, + objectToPatch, + functionNameToPatch, this._patchSyncFunction.bind(this, fName) ); } for (const fName of CALLBACK_FUNCTIONS) { - if (isWrapped(fs[fName])) { - this._unwrap(fs, fName); + const { objectToPatch, functionNameToPatch } = indexFs(fs, fName); + if (isWrapped(objectToPatch[functionNameToPatch])) { + this._unwrap(objectToPatch, functionNameToPatch); } if (fName === 'exists') { // handling separately because of the inconsistent cb style: // `exists` doesn't have error as the first argument, but the result this._wrap( - fs, - fName, + objectToPatch, + functionNameToPatch, this._patchExistsCallbackFunction.bind(this, fName) ); continue; } this._wrap( - fs, - fName, + objectToPatch, + functionNameToPatch, this._patchCallbackFunction.bind(this, fName) ); } - if (supportsPromises) { - for (const fName of PROMISE_FUNCTIONS) { - if (isWrapped(fs.promises[fName])) { - this._unwrap(fs.promises, fName); - } - this._wrap( - fs.promises, - fName, - this._patchPromiseFunction.bind(this, fName) - ); + for (const fName of PROMISE_FUNCTIONS) { + if (isWrapped(fs.promises[fName])) { + this._unwrap(fs.promises, fName); } + this._wrap( + fs.promises, + fName, + this._patchPromiseFunction.bind(this, fName) + ); } return fs; }, @@ -101,20 +115,47 @@ export default class FsInstrumentation extends InstrumentationBase { if (fs === undefined) return; this._diag.debug('Removing patch for fs'); for (const fName of SYNC_FUNCTIONS) { - if (isWrapped(fs[fName])) { - this._unwrap(fs, fName); + const { objectToPatch, functionNameToPatch } = indexFs(fs, fName); + if (isWrapped(objectToPatch[functionNameToPatch])) { + this._unwrap(objectToPatch, functionNameToPatch); } } for (const fName of CALLBACK_FUNCTIONS) { - if (isWrapped(fs[fName])) { - this._unwrap(fs, fName); + const { objectToPatch, functionNameToPatch } = indexFs(fs, fName); + if (isWrapped(objectToPatch[functionNameToPatch])) { + this._unwrap(objectToPatch, functionNameToPatch); } } - if (supportsPromises) { - for (const fName of PROMISE_FUNCTIONS) { - if (isWrapped(fs.promises[fName])) { - this._unwrap(fs.promises, fName); - } + for (const fName of PROMISE_FUNCTIONS) { + if (isWrapped(fs.promises[fName])) { + this._unwrap(fs.promises, fName); + } + } + } + ), + new InstrumentationNodeModuleDefinition( + 'fs/promises', + ['*'], + (fsPromises: FSPromises) => { + this._diag.debug('Applying patch for fs/promises'); + for (const fName of PROMISE_FUNCTIONS) { + if (isWrapped(fsPromises[fName])) { + this._unwrap(fsPromises, fName); + } + this._wrap( + fsPromises, + fName, + this._patchPromiseFunction.bind(this, fName) + ); + } + return fsPromises; + }, + (fsPromises: FSPromises) => { + if (fsPromises === undefined) return; + this._diag.debug('Removing patch for fs/promises'); + for (const fName of PROMISE_FUNCTIONS) { + if (isWrapped(fsPromises[fName])) { + this._unwrap(fsPromises, fName); } } } @@ -127,10 +168,10 @@ export default class FsInstrumentation extends InstrumentationBase { original: T ): T { const instrumentation = this; - return function (this: any, ...args: any[]) { - if (isTracingSuppressed(api.context.active())) { - // Performance optimization. Avoid creating additional contexts and spans - // if we already know that the tracing is being suppressed. + const patchedFunction = function (this: any, ...args: any[]) { + const activeContext = api.context.active(); + + if (!instrumentation._shouldTrace(activeContext)) { return original.apply(this, args); } if ( @@ -139,7 +180,7 @@ export default class FsInstrumentation extends InstrumentationBase { }) === false ) { return api.context.with( - suppressTracing(api.context.active()), + suppressTracing(activeContext), original, this, ...args @@ -153,14 +194,14 @@ export default class FsInstrumentation extends InstrumentationBase { try { // Suppress tracing for internal fs calls const res = api.context.with( - suppressTracing(api.trace.setSpan(api.context.active(), span)), + suppressTracing(api.trace.setSpan(activeContext, span)), original, this, ...args ); instrumentation._runEndHook(functionName, { args: args, span }); return res; - } catch (error) { + } catch (error: any) { span.recordException(error); span.setStatus({ message: error.message, @@ -172,6 +213,7 @@ export default class FsInstrumentation extends InstrumentationBase { span.end(); } }; + return patchedFunctionWithOriginalProperties(patchedFunction, original); } protected _patchCallbackFunction ReturnType>( @@ -179,10 +221,10 @@ export default class FsInstrumentation extends InstrumentationBase { original: T ): T { const instrumentation = this; - return function (this: any, ...args: any[]) { - if (isTracingSuppressed(api.context.active())) { - // Performance optimization. Avoid creating additional contexts and spans - // if we already know that the tracing is being suppressed. + const patchedFunction = function (this: any, ...args: any[]) { + const activeContext = api.context.active(); + + if (!instrumentation._shouldTrace(activeContext)) { return original.apply(this, args); } if ( @@ -191,7 +233,7 @@ export default class FsInstrumentation extends InstrumentationBase { }) === false ) { return api.context.with( - suppressTracing(api.context.active()), + suppressTracing(activeContext), original, this, ...args @@ -207,7 +249,7 @@ export default class FsInstrumentation extends InstrumentationBase { // Return to the context active during the call in the callback args[lastIdx] = api.context.bind( - api.context.active(), + activeContext, function (this: unknown, error?: Error) { if (error) { span.recordException(error); @@ -229,12 +271,12 @@ export default class FsInstrumentation extends InstrumentationBase { try { // Suppress tracing for internal fs calls return api.context.with( - suppressTracing(api.trace.setSpan(api.context.active(), span)), + suppressTracing(api.trace.setSpan(activeContext, span)), original, this, ...args ); - } catch (error) { + } catch (error: any) { span.recordException(error); span.setStatus({ message: error.message, @@ -253,16 +295,17 @@ export default class FsInstrumentation extends InstrumentationBase { return original.apply(this, args); } }; + return patchedFunctionWithOriginalProperties(patchedFunction, original); } protected _patchExistsCallbackFunction< T extends (...args: any[]) => ReturnType - >(functionName: FMember, original: T): T { + >(functionName: 'exists', original: T): T { const instrumentation = this; const patchedFunction = function (this: any, ...args: any[]) { - if (isTracingSuppressed(api.context.active())) { - // Performance optimization. Avoid creating additional contexts and spans - // if we already know that the tracing is being suppressed. + const activeContext = api.context.active(); + + if (!instrumentation._shouldTrace(activeContext)) { return original.apply(this, args); } if ( @@ -271,7 +314,7 @@ export default class FsInstrumentation extends InstrumentationBase { }) === false ) { return api.context.with( - suppressTracing(api.context.active()), + suppressTracing(activeContext), original, this, ...args @@ -287,7 +330,7 @@ export default class FsInstrumentation extends InstrumentationBase { // Return to the context active during the call in the callback args[lastIdx] = api.context.bind( - api.context.active(), + activeContext, function (this: unknown) { // `exists` never calls the callback with an error instrumentation._runEndHook(functionName, { @@ -302,12 +345,12 @@ export default class FsInstrumentation extends InstrumentationBase { try { // Suppress tracing for internal fs calls return api.context.with( - suppressTracing(api.trace.setSpan(api.context.active(), span)), + suppressTracing(api.trace.setSpan(activeContext, span)), original, this, ...args ); - } catch (error) { + } catch (error: any) { span.recordException(error); span.setStatus({ message: error.message, @@ -325,18 +368,22 @@ export default class FsInstrumentation extends InstrumentationBase { return original.apply(this, args); } }; + const functionWithOriginalProperties = + patchedFunctionWithOriginalProperties(patchedFunction, original); // `exists` has a custom promisify function because of the inconsistent signature // replicating that on the patched function const promisified = function (path: unknown) { - return new Promise(resolve => patchedFunction(path, resolve)); + return new Promise(resolve => + functionWithOriginalProperties(path, resolve) + ); }; Object.defineProperty(promisified, 'name', { value: functionName }); - Object.defineProperty(patchedFunction, promisify.custom, { + Object.defineProperty(functionWithOriginalProperties, promisify.custom, { value: promisified, }); - return patchedFunction; + return functionWithOriginalProperties; } protected _patchPromiseFunction ReturnType>( @@ -344,10 +391,10 @@ export default class FsInstrumentation extends InstrumentationBase { original: T ): T { const instrumentation = this; - return async function (this: any, ...args: any[]) { - if (isTracingSuppressed(api.context.active())) { - // Performance optimization. Avoid creating additional contexts and spans - // if we already know that the tracing is being suppressed. + const patchedFunction = async function (this: any, ...args: any[]) { + const activeContext = api.context.active(); + + if (!instrumentation._shouldTrace(activeContext)) { return original.apply(this, args); } if ( @@ -356,7 +403,7 @@ export default class FsInstrumentation extends InstrumentationBase { }) === false ) { return api.context.with( - suppressTracing(api.context.active()), + suppressTracing(activeContext), original, this, ...args @@ -370,14 +417,14 @@ export default class FsInstrumentation extends InstrumentationBase { try { // Suppress tracing for internal fs calls const res = await api.context.with( - suppressTracing(api.trace.setSpan(api.context.active(), span)), + suppressTracing(api.trace.setSpan(activeContext, span)), original, this, ...args ); instrumentation._runEndHook(functionName, { args: args, span }); return res; - } catch (error) { + } catch (error: any) { span.recordException(error); span.setStatus({ message: error.message, @@ -389,6 +436,7 @@ export default class FsInstrumentation extends InstrumentationBase { span.end(); } }; + return patchedFunctionWithOriginalProperties(patchedFunction, original); } protected _runCreateHook( @@ -415,4 +463,22 @@ export default class FsInstrumentation extends InstrumentationBase { } } } + + protected _shouldTrace(context: api.Context): boolean { + if (isTracingSuppressed(context)) { + // Performance optimization. Avoid creating additional contexts and spans + // if we already know that the tracing is being suppressed. + return false; + } + + const { requireParentSpan } = this.getConfig() as FsInstrumentationConfig; + if (requireParentSpan) { + const parentSpan = api.trace.getSpan(context); + if (parentSpan == null) { + return false; + } + } + + return true; + } } diff --git a/plugins/node/instrumentation-fs/src/types.ts b/plugins/node/instrumentation-fs/src/types.ts index d531cae43c..fe0a4132c5 100644 --- a/plugins/node/instrumentation-fs/src/types.ts +++ b/plugins/node/instrumentation-fs/src/types.ts @@ -18,13 +18,40 @@ import type * as fs from 'fs'; import type * as api from '@opentelemetry/api'; import type { InstrumentationConfig } from '@opentelemetry/instrumentation'; -export type FunctionPropertyNames = { - [K in keyof T]: T[K] extends Function ? K : never; -}[keyof T]; +export type FunctionPropertyNames = Exclude< + { + [K in keyof T]: T[K] extends Function ? K : never; + }[keyof T], + undefined +>; export type FunctionProperties = Pick>; -export type FMember = FunctionPropertyNames; -export type FPMember = FunctionPropertyNames; +export type FunctionPropertyNamesTwoLevels = Exclude< + { + [K in keyof T]: { + [L in keyof T[K]]: L extends string + ? T[K][L] extends Function + ? K extends string + ? L extends string + ? `${K}.${L}` + : never + : never + : never + : never; + }[keyof T[K]]; + }[keyof T], + undefined +>; + +export type Member = + | FunctionPropertyNames + | FunctionPropertyNamesTwoLevels; +export type FMember = + | FunctionPropertyNames + | FunctionPropertyNamesTwoLevels; +export type FPMember = + | FunctionPropertyNames<(typeof fs)['promises']> + | FunctionPropertyNamesTwoLevels<(typeof fs)['promises']>; export type CreateHook = ( functionName: FMember | FPMember, @@ -38,4 +65,5 @@ export type EndHook = ( export interface FsInstrumentationConfig extends InstrumentationConfig { createHook?: CreateHook; endHook?: EndHook; + requireParentSpan?: boolean; } diff --git a/plugins/node/instrumentation-fs/src/utils.ts b/plugins/node/instrumentation-fs/src/utils.ts new file mode 100644 index 0000000000..3a8c37149f --- /dev/null +++ b/plugins/node/instrumentation-fs/src/utils.ts @@ -0,0 +1,53 @@ +/* + * 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 { FunctionPropertyNames, FMember } from './types'; +import type * as fs from 'fs'; +type FS = typeof fs; + +export function splitTwoLevels( + functionName: FMember +): + | [FunctionPropertyNames & string] + | [FunctionPropertyNames & string, string] { + const memberParts = functionName.split('.'); + if (memberParts.length > 1) { + if (memberParts.length !== 2) + throw Error(`Invalid member function name ${functionName}`); + return memberParts as [FunctionPropertyNames & string, string]; + } else { + return [functionName as FunctionPropertyNames & string]; + } +} + +export function indexFs( + fs: FSObject, + member: FMember +): { objectToPatch: any; functionNameToPatch: string } { + if (!member) throw new Error(JSON.stringify({ member })); + const splitResult = splitTwoLevels(member); + const [functionName1, functionName2] = splitResult; + if (functionName2) { + return { + objectToPatch: fs[functionName1], + functionNameToPatch: functionName2, + }; + } else { + return { + objectToPatch: fs, + functionNameToPatch: functionName1, + }; + } +} diff --git a/plugins/node/instrumentation-fs/test/definitions.ts b/plugins/node/instrumentation-fs/test/definitions.ts index 551f104986..ed4a0673bc 100644 --- a/plugins/node/instrumentation-fs/test/definitions.ts +++ b/plugins/node/instrumentation-fs/test/definitions.ts @@ -17,16 +17,21 @@ import { FMember, FPMember } from '../src/types'; import * as fs from 'fs'; -export type FsFunction = FPMember & FMember; +export type FsFunction = FMember; export type Opts = { sync?: boolean; callback?: boolean; promise?: boolean; }; -export type Result = { error?: RegExp; result?: any; resultAsError?: any }; +export type Result = { + error?: RegExp; + result?: any; + resultAsError?: any; + hasPromiseVersion?: boolean; +}; export type TestCase = [FsFunction, any[], Result, any[], Opts?]; -export type TestCreator = ( - name: FsFunction, +export type TestCreator = ( + name: Member, args: any[], result: Result, spans: any[] @@ -77,6 +82,13 @@ const tests: TestCase[] = [ { resultAsError: true }, [{ name: 'fs %NAME' }], ], + ['realpath', ['/./'], { result: '/' }, [{ name: 'fs %NAME' }]], + [ + 'realpath.native', + ['/./'], + { result: '/', hasPromiseVersion: false }, + [{ name: 'fs %NAME' }], + ], ]; export default tests; diff --git a/plugins/node/instrumentation-fs/test/index.test.ts b/plugins/node/instrumentation-fs/test/fs.test.ts similarity index 76% rename from plugins/node/instrumentation-fs/test/index.test.ts rename to plugins/node/instrumentation-fs/test/fs.test.ts index cb49a5f5d0..e8f97b6ab2 100644 --- a/plugins/node/instrumentation-fs/test/index.test.ts +++ b/plugins/node/instrumentation-fs/test/fs.test.ts @@ -13,12 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { context, trace, SpanStatusCode, SpanKind } from '@opentelemetry/api'; +import { context, trace } from '@opentelemetry/api'; import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks'; import { BasicTracerProvider, InMemorySpanExporter, - ReadableSpan, SimpleSpanProcessor, } from '@opentelemetry/sdk-trace-base'; import * as assert from 'assert'; @@ -28,8 +27,13 @@ import * as sinon from 'sinon'; import type * as FSType from 'fs'; import tests, { TestCase, TestCreator } from './definitions'; import type { FMember, FPMember, CreateHook, EndHook } from '../src/types'; - -const supportsPromises = parseInt(process.versions.node.split('.')[0], 10) > 8; +import { + CALLBACK_FUNCTIONS, + PROMISE_FUNCTIONS, + SYNC_FUNCTIONS, +} from '../src/constants'; +import { indexFs, splitTwoLevels } from '../src/utils'; +import { assertSpans, makeRootSpanName } from './utils'; const TEST_ATTRIBUTE = 'test.attr'; const TEST_VALUE = 'test.attr.value'; @@ -38,7 +42,7 @@ const createHook = sinon.spy( (fnName: FMember | FPMember, { args, span }) => { // `ts-node`, which we use via `ts-mocha` also patches module loading and creates // a lot of unrelated spans. Filter those out. - if (['readFileSync', 'existsSync'].includes(fnName)) { + if (['readFileSync', 'existsSync'].includes(fnName as string)) { const filename = args[0]; if (!/test\/fixtures/.test(filename)) { return false; @@ -87,24 +91,41 @@ describe('fs instrumentation', () => { context.disable(); }); - const syncTest: TestCreator = ( + const syncTest: TestCreator = ( name: FMember, args, { error, result, resultAsError = null }, spans ) => { - const syncName: FMember = `${name}Sync` as FMember; + const [functionNamePart1, functionNamePart2] = + splitTwoLevels(name); + const syncName = `${functionNamePart1}Sync${ + functionNamePart2 ? `.${functionNamePart2}` : '' + }` as FMember; const rootSpanName = `${syncName} test span`; it(`${syncName} ${error ? 'error' : 'success'}`, () => { + const { objectToPatch, functionNameToPatch } = indexFs(fs, syncName); const rootSpan = tracer.startSpan(rootSpanName); assert.strictEqual(memoryExporter.getFinishedSpans().length, 0); context.with(trace.setSpan(context.active(), rootSpan), () => { if (error) { - assert.throws(() => Reflect.apply(fs[syncName], fs, args), error); + assert.throws( + () => + Reflect.apply( + objectToPatch[functionNameToPatch], + objectToPatch, + args + ), + error + ); } else { assert.deepEqual( - Reflect.apply(fs[syncName], fs, args), + Reflect.apply( + objectToPatch[functionNameToPatch], + objectToPatch, + args + ), result ?? resultAsError ); } @@ -129,20 +150,21 @@ describe('fs instrumentation', () => { }); }; - const callbackTest: TestCreator = ( + const callbackTest: TestCreator = ( name: FMember, args, { error, result, resultAsError = null }, spans ) => { - const rootSpanName = `${name} test span`; + const rootSpanName = makeRootSpanName(name); it(`${name} ${error ? 'error' : 'success'}`, done => { + const { objectToPatch, functionNameToPatch } = indexFs(fs, name); const rootSpan = tracer.startSpan(rootSpanName); assert.strictEqual(memoryExporter.getFinishedSpans().length, 0); context.with(trace.setSpan(context.active(), rootSpan), () => { - (fs[name] as Function)( + (objectToPatch[functionNameToPatch] as Function)( ...args, (actualError: any | undefined, actualResult: any) => { assert.strictEqual(trace.getSpan(context.active()), rootSpan); @@ -199,13 +221,14 @@ describe('fs instrumentation', () => { }); }; - const promiseTest: TestCreator = ( + const promiseTest: TestCreator = ( name: FPMember, args, - { error, result, resultAsError = null }, + { error, result, resultAsError = null, hasPromiseVersion = true }, spans ) => { - const rootSpanName = `${name} test span`; + if (!hasPromiseVersion) return; + const rootSpanName = makeRootSpanName(name); it(`promises.${name} ${error ? 'error' : 'success'}`, async () => { const rootSpan = tracer.startSpan(rootSpanName); @@ -260,6 +283,43 @@ describe('fs instrumentation', () => { }); }; + describe('Synchronous API native', () => { + beforeEach(() => { + plugin.enable(); + }); + it('should not remove fs functions', () => { + const isNode14 = process.versions.node.startsWith('14'); + const node14MissingFunctionNames = new Set([ + 'cpSync', + 'cp', + 'promises.cp', + ]); + for (const fname of [...SYNC_FUNCTIONS, ...CALLBACK_FUNCTIONS]) { + // some function were added after node 14 + if (node14MissingFunctionNames.has(fname) && isNode14) continue; + + const { objectToPatch, functionNameToPatch } = indexFs(fs, fname); + assert.strictEqual( + typeof objectToPatch[functionNameToPatch], + 'function', + `fs.${fname} is not a function` + ); + } + for (const fname of PROMISE_FUNCTIONS) { + if (node14MissingFunctionNames.has(fname) && isNode14) continue; + const { objectToPatch, functionNameToPatch } = indexFs( + fs.promises, + fname + ); + assert.strictEqual( + typeof objectToPatch[functionNameToPatch], + 'function', + `fs.promises.${fname} is not a function` + ); + } + }); + }); + describe('Syncronous API', () => { const selection: TestCase[] = tests.filter( ([, , , , options = {}]) => options.sync !== false @@ -351,74 +411,25 @@ describe('fs instrumentation', () => { }); }); - if (supportsPromises) { - describe('Promise API', () => { - const selection: TestCase[] = tests.filter( - ([, , , , options = {}]) => options.promise !== false - ); + describe('Promise API', () => { + const selection: TestCase[] = tests.filter( + ([, , , , options = {}]) => options.promise !== false + ); - describe('Instrumentation enabled', () => { - selection.forEach(([name, args, result, spans]) => { - promiseTest(name as FPMember, args, result, spans); - }); + describe('Instrumentation enabled', () => { + selection.forEach(([name, args, result, spans]) => { + promiseTest(name as FPMember, args, result, spans); }); + }); - describe('Instrumentation disabled', () => { - beforeEach(() => { - plugin.disable(); - }); + describe('Instrumentation disabled', () => { + beforeEach(() => { + plugin.disable(); + }); - selection.forEach(([name, args, result]) => { - promiseTest(name as FPMember, args, result, []); - }); + selection.forEach(([name, args, result]) => { + promiseTest(name as FPMember, args, result, []); }); }); - } -}); - -const assertSpans = (spans: ReadableSpan[], expected: any) => { - assert.strictEqual( - spans.length, - expected.length, - `Expected ${expected.length} spans, got ${spans.length}(${spans - .map((s: any) => `"${s.name}"`) - .join(', ')})` - ); - - spans.forEach((span, i) => { - assertSpan(span, expected[i]); }); -}; - -const assertSpan = (span: ReadableSpan, expected: any) => { - assert(span); - assert.strictEqual(span.name, expected.name); - assert.strictEqual( - span.kind, - SpanKind.INTERNAL, - 'Expected to be of INTERNAL kind' - ); - if (expected.parentSpan) { - assert.strictEqual( - span.parentSpanId, - expected.parentSpan.spanContext().spanId - ); - } - if (expected.attributes) { - assert.deepEqual(span.attributes, expected.attributes); - } - if (expected.error) { - assert( - expected.error.test(span.status.message), - `Expected "${span.status.message}" to match ${expected.error}` - ); - assert.strictEqual(span.status.code, SpanStatusCode.ERROR); - } else { - assert.strictEqual( - span.status.code, - SpanStatusCode.UNSET, - 'Expected status to be unset' - ); - assert.strictEqual(span.status.message, undefined); - } -}; +}); diff --git a/plugins/node/instrumentation-fs/test/hooks.test.ts b/plugins/node/instrumentation-fs/test/fsHooks.test.ts similarity index 84% rename from plugins/node/instrumentation-fs/test/hooks.test.ts rename to plugins/node/instrumentation-fs/test/fsHooks.test.ts index a85c83fcc2..1ae9e5b0eb 100644 --- a/plugins/node/instrumentation-fs/test/hooks.test.ts +++ b/plugins/node/instrumentation-fs/test/fsHooks.test.ts @@ -24,8 +24,6 @@ import * as sinon from 'sinon'; import type * as FSType from 'fs'; import type { FsInstrumentationConfig } from '../src/types'; -const supportsPromises = parseInt(process.versions.node.split('.')[0], 10) > 8; - const createHookError = new Error('createHook failed'); const createHook = sinon.spy((_functionName: string) => { throw createHookError; @@ -107,7 +105,7 @@ describe('fs instrumentation: hooks', () => { it('should not shadow the error from original call when hooks throw', () => { try { fs.accessSync('./test/fixtures/readtest-404', fs.constants.R_OK); - } catch (e) { + } catch (e: any) { assertNotHookError(e); } @@ -142,23 +140,21 @@ describe('fs instrumentation: hooks', () => { }); }); - if (supportsPromises) { - describe('Promise API', () => { - it('should not fail the original successful call when hooks throw', async () => { - // eslint-disable-next-line node/no-unsupported-features/node-builtins - await fs.promises.access('./test/fixtures/readtest', fs.constants.R_OK); + describe('Promise API', () => { + it('should not fail the original successful call when hooks throw', async () => { + // eslint-disable-next-line node/no-unsupported-features/node-builtins + await fs.promises.access('./test/fixtures/readtest', fs.constants.R_OK); - assertSuccessfulCallHooks('access'); - }); + assertSuccessfulCallHooks('access'); + }); - it('should not shadow the error from original call when hooks throw', async () => { - // eslint-disable-next-line node/no-unsupported-features/node-builtins - await fs.promises - .access('./test/fixtures/readtest-404', fs.constants.R_OK) - .catch(assertNotHookError); + it('should not shadow the error from original call when hooks throw', async () => { + // eslint-disable-next-line node/no-unsupported-features/node-builtins + await fs.promises + .access('./test/fixtures/readtest-404', fs.constants.R_OK) + .catch(assertNotHookError); - assertFailingCallHooks('access'); - }); + assertFailingCallHooks('access'); }); - } + }); }); diff --git a/plugins/node/instrumentation-fs/test/fsPromises.test.ts b/plugins/node/instrumentation-fs/test/fsPromises.test.ts new file mode 100644 index 0000000000..9af00a13a5 --- /dev/null +++ b/plugins/node/instrumentation-fs/test/fsPromises.test.ts @@ -0,0 +1,148 @@ +/* + * 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 { context, trace } from '@opentelemetry/api'; +import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks'; +import { + BasicTracerProvider, + InMemorySpanExporter, + SimpleSpanProcessor, +} from '@opentelemetry/sdk-trace-base'; +import * as assert from 'assert'; +import Instrumentation from '../src'; +import * as sinon from 'sinon'; +import type * as FSPromisesType from 'fs/promises'; +import tests, { FsFunction, TestCase, TestCreator } from './definitions'; +import type { FPMember, EndHook } from '../src/types'; +import { assertSpans, makeRootSpanName } from './utils'; + +const TEST_ATTRIBUTE = 'test.attr'; +const TEST_VALUE = 'test.attr.value'; + +const endHook = sinon.spy((fnName, { args, span }) => { + span.setAttribute(TEST_ATTRIBUTE, TEST_VALUE); +}); +const pluginConfig = { + endHook, +}; +const provider = new BasicTracerProvider(); +const tracer = provider.getTracer('default'); +const memoryExporter = new InMemorySpanExporter(); +provider.addSpanProcessor(new SimpleSpanProcessor(memoryExporter)); + +describe('fs/promises instrumentation', () => { + let contextManager: AsyncHooksContextManager; + let fsPromises: typeof FSPromisesType; + let plugin: Instrumentation; + + beforeEach(async () => { + contextManager = new AsyncHooksContextManager(); + context.setGlobalContextManager(contextManager.enable()); + plugin = new Instrumentation(pluginConfig); + plugin.setTracerProvider(provider); + plugin.enable(); + fsPromises = require('fs/promises'); + assert.strictEqual(memoryExporter.getFinishedSpans().length, 0); + }); + + afterEach(() => { + plugin.disable(); + memoryExporter.reset(); + context.disable(); + }); + + const promiseTest: TestCreator = ( + name: FPMember, + args, + { error, result, resultAsError = null, hasPromiseVersion = true }, + spans + ) => { + if (!hasPromiseVersion) return; + const rootSpanName = makeRootSpanName(name); + it(`promises.${name} ${error ? 'error' : 'success'}`, async () => { + const rootSpan = tracer.startSpan(rootSpanName); + + assert.strictEqual(memoryExporter.getFinishedSpans().length, 0); + await context + .with(trace.setSpan(context.active(), rootSpan), () => { + // eslint-disable-next-line node/no-unsupported-features/node-builtins + assert( + typeof fsPromises[name] === 'function', + `Expected fsPromises.${name} to be a function` + ); + return Reflect.apply(fsPromises[name], fsPromises, args); + }) + .then((actualResult: any) => { + if (error) { + assert.fail(`promises.${name} did not reject`); + } else { + assert.deepEqual(actualResult, result ?? resultAsError); + } + }) + .catch((actualError: any) => { + assert( + actualError instanceof Error, + `Expected caugth error to be instance of Error. Got ${actualError}` + ); + if (error) { + assert( + error.test(actualError?.message ?? ''), + `Expected "${actualError?.message}" to match ${error}` + ); + } else { + actualError.message = `Did not expect promises.${name} to reject: ${actualError.message}`; + assert.fail(actualError); + } + }); + rootSpan.end(); + assertSpans(memoryExporter.getFinishedSpans(), [ + ...spans.map((s: any) => { + const spanName = s.name.replace(/%NAME/, name); + const attributes = { + ...(s.attributes ?? {}), + }; + attributes[TEST_ATTRIBUTE] = TEST_VALUE; + return { + ...s, + name: spanName, + attributes, + }; + }), + { name: rootSpanName }, + ]); + }); + }; + + const selection: TestCase[] = tests.filter( + ([name, , , , options = {}]) => + options.promise !== false && name !== ('exists' as FsFunction) + ); + + describe('Instrumentation enabled', () => { + selection.forEach(([name, args, result, spans]) => { + promiseTest(name as FPMember, args, result, spans); + }); + }); + + describe('Instrumentation disabled', () => { + beforeEach(() => { + plugin.disable(); + }); + + selection.forEach(([name, args, result]) => { + promiseTest(name as FPMember, args, result, []); + }); + }); +}); diff --git a/plugins/node/instrumentation-fs/test/fsPromisesHooks.test.ts b/plugins/node/instrumentation-fs/test/fsPromisesHooks.test.ts new file mode 100644 index 0000000000..d69be21ed9 --- /dev/null +++ b/plugins/node/instrumentation-fs/test/fsPromisesHooks.test.ts @@ -0,0 +1,117 @@ +/* + * 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 { + BasicTracerProvider, + InMemorySpanExporter, + SimpleSpanProcessor, +} from '@opentelemetry/sdk-trace-base'; +import * as assert from 'assert'; +import Instrumentation from '../src'; +import * as sinon from 'sinon'; +import type * as FSPromisesType from 'fs/promises'; +import type { FsInstrumentationConfig } from '../src/types'; + +const createHookError = new Error('createHook failed'); +const createHook = sinon.spy((_functionName: string) => { + throw createHookError; +}); +const endHookError = new Error('endHook failed'); +const endHook = sinon.spy((_functionName: string) => { + throw endHookError; +}); +const pluginConfig = { + createHook, + endHook, +}; + +const provider = new BasicTracerProvider(); +const memoryExporter = new InMemorySpanExporter(); +provider.addSpanProcessor(new SimpleSpanProcessor(memoryExporter)); + +const assertNotHookError = (err?: Error | null) => { + assert.ok( + err && + err.message !== createHookError.message && + err.message !== endHookError.message, + 'Hook error shadowed the error from the original call' + ); +}; + +const assertSuccessfulCallHooks = (expectedFunctionName: string) => { + const createHookCall = createHook.withArgs(expectedFunctionName); + sinon.assert.called(createHookCall); + sinon.assert.threw(createHookCall, createHookError); + + const endHookCall = endHook.withArgs(expectedFunctionName); + sinon.assert.called(endHookCall); + sinon.assert.threw(endHookCall, endHookError); + assert( + !(endHookCall.getCall(0).args as any)[1].error, + 'Did not expect an error' + ); +}; + +const assertFailingCallHooks = (expectedFunctionName: string) => { + const createHookCall = createHook.withArgs(expectedFunctionName); + sinon.assert.called(createHookCall); + sinon.assert.threw(createHookCall, createHookError); + + const endHookCall = endHook.withArgs(expectedFunctionName); + sinon.assert.called(endHookCall); + sinon.assert.threw(endHookCall, endHookError); + assert((endHookCall.getCall(0).args as any)[1].error, 'Expected an error'); +}; + +// This should equal `fs.constants.R_OK`. +// We are hard-coding this because Node 14 and below does not include `constants` in `fsPromises`. +const fsConstantsR_OK = 4; + +describe('fs/promises instrumentation: hooks', () => { + let plugin: Instrumentation; + let fsPromises: typeof FSPromisesType; + + beforeEach(async () => { + plugin = new Instrumentation(pluginConfig); + plugin.setTracerProvider(provider); + plugin.setConfig(pluginConfig as FsInstrumentationConfig); + plugin.enable(); + fsPromises = require('fs/promises'); + createHook.resetHistory(); + endHook.resetHistory(); + assert.strictEqual(memoryExporter.getFinishedSpans().length, 0); + }); + + afterEach(() => { + plugin.disable(); + memoryExporter.reset(); + }); + + it('should not fail the original successful call when hooks throw', async () => { + // eslint-disable-next-line node/no-unsupported-features/node-builtins + await fsPromises.access('./test/fixtures/readtest', fsConstantsR_OK); + + assertSuccessfulCallHooks('access'); + }); + + it('should not shadow the error from original call when hooks throw', async () => { + // eslint-disable-next-line node/no-unsupported-features/node-builtins + await fsPromises + .access('./test/fixtures/readtest-404', fsConstantsR_OK) + .catch(assertNotHookError); + + assertFailingCallHooks('access'); + }); +}); diff --git a/plugins/node/instrumentation-fs/test/parent.test.ts b/plugins/node/instrumentation-fs/test/parent.test.ts new file mode 100644 index 0000000000..9ca6d90059 --- /dev/null +++ b/plugins/node/instrumentation-fs/test/parent.test.ts @@ -0,0 +1,165 @@ +/* + * 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 { + BasicTracerProvider, + InMemorySpanExporter, + SimpleSpanProcessor, +} from '@opentelemetry/sdk-trace-base'; +import Instrumentation from '../src'; +import * as assert from 'assert'; +import type * as FSType from 'fs'; +import type { FsInstrumentationConfig } from '../src/types'; +import * as api from '@opentelemetry/api'; +import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks'; + +const provider = new BasicTracerProvider(); +const memoryExporter = new InMemorySpanExporter(); +provider.addSpanProcessor(new SimpleSpanProcessor(memoryExporter)); + +const tracer = provider.getTracer('default'); + +describe('fs instrumentation: requireParentSpan', () => { + let plugin: Instrumentation; + let fs: typeof FSType; + let ambientContext: api.Context; + let endRootSpan: () => void; + let expectedAmbientSpanCount: number; + + const initializePlugin = (pluginConfig: FsInstrumentationConfig) => { + plugin = new Instrumentation(); + plugin.setTracerProvider(provider); + plugin.setConfig(pluginConfig); + plugin.enable(); + fs = require('fs'); + assert.strictEqual(memoryExporter.getFinishedSpans().length, 0); + }; + + beforeEach(() => { + const contextManager = new AsyncHooksContextManager(); + api.context.setGlobalContextManager(contextManager.enable()); + }); + + afterEach(() => { + plugin.disable(); + memoryExporter.reset(); + }); + + const generateTestsForVariants = ({ + expectFSSpan, + }: { + expectFSSpan: boolean; + }) => { + const prefix = expectFSSpan ? 'creates' : 'does not create'; + const expectedSpanCount = () => + (expectFSSpan ? 1 : 0) + expectedAmbientSpanCount; + + it(`${prefix} a span with the callback API`, async () => { + await new Promise(resolve => { + api.context.with(ambientContext, () => { + fs.access('./test/fixtures/readtest', fs.constants.R_OK, () => + resolve() + ); + }); + }).then(() => endRootSpan()); + + assert.deepEqual( + memoryExporter.getFinishedSpans().length, + expectedSpanCount() + ); + }); + + it(`${prefix} a span with the synchronous API`, () => { + api.context.with(ambientContext, () => { + fs.accessSync('./test/fixtures/readtest', fs.constants.R_OK); + endRootSpan(); + }); + + assert.deepEqual( + memoryExporter.getFinishedSpans().length, + expectedSpanCount() + ); + }); + + it(`${prefix} a span with the promises API`, async () => { + await new Promise(resolve => { + api.context.with(ambientContext, () => { + fs.promises + .access('./test/fixtures/readtest', fs.constants.R_OK) + .finally(() => resolve(endRootSpan())); + }); + }); + + assert.deepEqual( + memoryExporter.getFinishedSpans().length, + expectedSpanCount() + ); + }); + }; + + const withRootSpan = (fn: () => void) => { + describe('with a root span', () => { + beforeEach(() => { + const rootSpan = tracer.startSpan('root span'); + + ambientContext = api.trace.setSpan(api.context.active(), rootSpan); + endRootSpan = () => rootSpan.end(); + expectedAmbientSpanCount = 1; + }); + + fn(); + }); + }; + + const withoutRootSpan = (fn: () => void) => { + describe('without a root span', () => { + beforeEach(() => { + ambientContext = api.context.active(); + endRootSpan = () => {}; + expectedAmbientSpanCount = 0; + }); + + fn(); + }); + }; + + describe('requireParentSpan enabled', () => { + beforeEach(() => { + initializePlugin({ requireParentSpan: true }); + }); + + withRootSpan(() => { + generateTestsForVariants({ expectFSSpan: true }); + }); + + withoutRootSpan(() => { + generateTestsForVariants({ expectFSSpan: false }); + }); + }); + + describe('requireParentSpan disabled', () => { + beforeEach(() => { + initializePlugin({ requireParentSpan: false }); + }); + + withRootSpan(() => { + generateTestsForVariants({ expectFSSpan: true }); + }); + + withoutRootSpan(() => { + generateTestsForVariants({ expectFSSpan: true }); + }); + }); +}); diff --git a/plugins/node/instrumentation-fs/test/utils.ts b/plugins/node/instrumentation-fs/test/utils.ts new file mode 100644 index 0000000000..a3f2cd33f7 --- /dev/null +++ b/plugins/node/instrumentation-fs/test/utils.ts @@ -0,0 +1,77 @@ +/* + * 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 { ReadableSpan } from '@opentelemetry/sdk-trace-base'; +import * as assert from 'assert'; +import { SpanKind, SpanStatusCode } from '@opentelemetry/api'; +import type { FMember } from '../src/types'; + +export const assertSpans = (spans: ReadableSpan[], expected: any) => { + assert.strictEqual( + spans.length, + expected.length, + `Expected ${expected.length} spans, got ${spans.length}(${spans + .map((s: any) => `"${s.name}"`) + .join(', ')})` + ); + + spans.forEach((span, i) => { + assertSpan(span, expected[i]); + }); +}; + +const assertSpan = (span: ReadableSpan, expected: any) => { + assert(span); + assert.strictEqual(span.name, expected.name); + assert.strictEqual( + span.kind, + SpanKind.INTERNAL, + 'Expected to be of INTERNAL kind' + ); + if (expected.parentSpan) { + assert.strictEqual( + span.parentSpanId, + expected.parentSpan.spanContext().spanId + ); + } + if (expected.attributes) { + assert.deepEqual(span.attributes, expected.attributes); + } + if (expected.error) { + assert( + expected.error.test(span.status.message), + `Expected "${span.status.message}" to match ${expected.error}` + ); + assert.strictEqual(span.status.code, SpanStatusCode.ERROR); + } else { + assert.strictEqual( + span.status.code, + SpanStatusCode.UNSET, + 'Expected status to be unset' + ); + assert.strictEqual(span.status.message, undefined); + } +}; + +export const makeRootSpanName = (name: FMember): string => { + let rsn: string; + if (Array.isArray(name)) { + rsn = `${name[0]}.${name[1]}`; + } else { + rsn = `${name}`; + } + rsn = `${rsn} test span`; + return rsn; +}; diff --git a/plugins/node/instrumentation-lru-memoizer/CHANGELOG.md b/plugins/node/instrumentation-lru-memoizer/CHANGELOG.md index 3cde6a4bfa..c8ef8b6d13 100644 --- a/plugins/node/instrumentation-lru-memoizer/CHANGELOG.md +++ b/plugins/node/instrumentation-lru-memoizer/CHANGELOG.md @@ -1,5 +1,47 @@ # Changelog +## [0.32.2](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-lru-memoizer-v0.32.1...instrumentation-lru-memoizer-v0.32.2) (2023-04-25) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.38.0 ([#1468](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1468)) ([565a2b2](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/565a2b2c6fde88af3f5401ef6a5a9643d0d66349)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.1 to ^0.33.2 + +## [0.32.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-lru-memoizer-v0.32.0...instrumentation-lru-memoizer-v0.32.1) (2023-02-07) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.35.1 ([#1358](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1358)) ([ff109b7](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/ff109b77928cc9a139a21c63d6b54399bb017fa4)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.0 to ^0.33.1 + +## [0.32.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-lru-memoizer-v0.31.0...instrumentation-lru-memoizer-v0.32.0) (2022-11-16) + + +### Features + +* update experimental deps to `^0.34.0`, core deps to `^1.8.0`, api to `^1.3.0` ([#1278](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1278)) ([e9fe8e1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/e9fe8e13e34f54e96c50525cadeb74ac048c5624)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.32.0 to ^0.33.0 + ## [0.31.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-lru-memoizer-v0.30.0...instrumentation-lru-memoizer-v0.31.0) (2022-09-02) diff --git a/plugins/node/instrumentation-lru-memoizer/package.json b/plugins/node/instrumentation-lru-memoizer/package.json index 4264d5a57a..ff2a39aef4 100644 --- a/plugins/node/instrumentation-lru-memoizer/package.json +++ b/plugins/node/instrumentation-lru-memoizer/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/instrumentation-lru-memoizer", - "version": "0.31.0", + "version": "0.32.2", "description": "OpenTelemetry automatic instrumentation package for lru-memoizer", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -39,26 +39,25 @@ "access": "public" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@opentelemetry/api": "^1.3.0" }, "devDependencies": { - "@opentelemetry/api": "^1.0.0", - "@opentelemetry/contrib-test-utils": "^0.32.0", + "@opentelemetry/api": "^1.3.0", + "@opentelemetry/contrib-test-utils": "^0.33.2", "@types/lru-cache": "7.10.9", "@types/mocha": "8.2.3", "@types/node": "18.11.7", - "expect": "25.5.0", - "gts": "3.1.0", + "expect": "29.2.0", "lru-memoizer": "2.1.4", "mocha": "7.2.0", "nyc": "15.1.0", - "rimraf": "3.0.2", + "rimraf": "4.2.0", "test-all-versions": "5.0.1", "ts-mocha": "10.0.0", - "typescript": "4.3.5" + "typescript": "4.4.4" }, "dependencies": { - "@opentelemetry/instrumentation": "^0.32.0" + "@opentelemetry/instrumentation": "^0.38.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/instrumentation-lru-memoizer#readme" } diff --git a/plugins/node/instrumentation-lru-memoizer/test/index.test.ts b/plugins/node/instrumentation-lru-memoizer/test/index.test.ts index 95969e8be8..bb80c9994d 100644 --- a/plugins/node/instrumentation-lru-memoizer/test/index.test.ts +++ b/plugins/node/instrumentation-lru-memoizer/test/index.test.ts @@ -15,7 +15,7 @@ */ import LruMemoizerInstrumentation from '../src'; import { trace, context } from '@opentelemetry/api'; -import * as expect from 'expect'; +import { expect } from 'expect'; import { registerInstrumentationTesting } from '@opentelemetry/contrib-test-utils'; diff --git a/plugins/node/instrumentation-mongoose/CHANGELOG.md b/plugins/node/instrumentation-mongoose/CHANGELOG.md index 5250d17b4f..205fe474f1 100644 --- a/plugins/node/instrumentation-mongoose/CHANGELOG.md +++ b/plugins/node/instrumentation-mongoose/CHANGELOG.md @@ -1,5 +1,47 @@ # Changelog +## [0.32.2](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-mongoose-v0.32.1...instrumentation-mongoose-v0.32.2) (2023-04-25) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.38.0 ([#1468](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1468)) ([565a2b2](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/565a2b2c6fde88af3f5401ef6a5a9643d0d66349)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.1 to ^0.33.2 + +## [0.32.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-mongoose-v0.32.0...instrumentation-mongoose-v0.32.1) (2023-02-07) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.35.1 ([#1358](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1358)) ([ff109b7](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/ff109b77928cc9a139a21c63d6b54399bb017fa4)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.0 to ^0.33.1 + +## [0.32.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-mongoose-v0.31.1...instrumentation-mongoose-v0.32.0) (2022-11-16) + + +### Features + +* update experimental deps to `^0.34.0`, core deps to `^1.8.0`, api to `^1.3.0` ([#1278](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1278)) ([e9fe8e1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/e9fe8e13e34f54e96c50525cadeb74ac048c5624)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.32.0 to ^0.33.0 + ## [0.31.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-mongoose-v0.31.0...instrumentation-mongoose-v0.31.1) (2022-11-02) diff --git a/plugins/node/instrumentation-mongoose/package.json b/plugins/node/instrumentation-mongoose/package.json index 0279cd947f..33358620a3 100644 --- a/plugins/node/instrumentation-mongoose/package.json +++ b/plugins/node/instrumentation-mongoose/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/instrumentation-mongoose", - "version": "0.31.1", + "version": "0.32.2", "description": "OpenTelemetry automatic instrumentation package for mongoose", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -42,27 +42,26 @@ "access": "public" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@opentelemetry/api": "^1.3.0" }, "devDependencies": { - "@opentelemetry/api": "^1.0.0", - "@opentelemetry/contrib-test-utils": "^0.32.0", - "@opentelemetry/sdk-trace-base": "^1.3.1", + "@opentelemetry/api": "^1.3.0", + "@opentelemetry/contrib-test-utils": "^0.33.2", + "@opentelemetry/sdk-trace-base": "^1.8.0", "@types/mocha": "8.2.3", "@types/node": "18.11.7", - "expect": "27.4.2", - "gts": "3.1.0", + "expect": "29.2.0", "mocha": "7.2.0", "mongoose": "6.5.2", "nyc": "15.1.0", - "rimraf": "3.0.2", + "rimraf": "4.2.0", "test-all-versions": "5.0.1", "ts-mocha": "10.0.0", - "typescript": "4.3.5" + "typescript": "4.4.4" }, "dependencies": { - "@opentelemetry/core": "^1.0.0", - "@opentelemetry/instrumentation": "^0.32.0", + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.38.0", "@opentelemetry/semantic-conventions": "^1.0.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/instrumentation-mongoose#readme" diff --git a/plugins/node/instrumentation-mongoose/test/asserts.ts b/plugins/node/instrumentation-mongoose/test/asserts.ts index f6c7e15ec3..ad21f9a716 100644 --- a/plugins/node/instrumentation-mongoose/test/asserts.ts +++ b/plugins/node/instrumentation-mongoose/test/asserts.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import * as expect from 'expect'; +import { expect } from 'expect'; import { ReadableSpan } from '@opentelemetry/sdk-trace-base'; import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; import { SpanStatusCode } from '@opentelemetry/api'; diff --git a/plugins/node/instrumentation-mongoose/test/mongoose.test.ts b/plugins/node/instrumentation-mongoose/test/mongoose.test.ts index 6ba0297bd5..37ce6c70ec 100644 --- a/plugins/node/instrumentation-mongoose/test/mongoose.test.ts +++ b/plugins/node/instrumentation-mongoose/test/mongoose.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import 'mocha'; -import * as expect from 'expect'; +import { expect } from 'expect'; import { context, ROOT_CONTEXT } from '@opentelemetry/api'; import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; import { MongooseInstrumentation } from '../src'; @@ -44,7 +44,7 @@ describe('mongoose instrumentation', () => { useCreateIndex: true, dbName: DB_NAME, } as any); // TODO: amir - document older mongoose support - } catch (err) { + } catch (err: any) { // connect signature changed from mongo v5 to v6. // the following check tries both signatures, so test-all-versions // can run against both versions. diff --git a/plugins/node/instrumentation-socket.io/.eslintignore b/plugins/node/instrumentation-socket.io/.eslintignore new file mode 100644 index 0000000000..378eac25d3 --- /dev/null +++ b/plugins/node/instrumentation-socket.io/.eslintignore @@ -0,0 +1 @@ +build diff --git a/plugins/node/instrumentation-socket.io/.eslintrc.js b/plugins/node/instrumentation-socket.io/.eslintrc.js new file mode 100644 index 0000000000..f756f4488b --- /dev/null +++ b/plugins/node/instrumentation-socket.io/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + "env": { + "mocha": true, + "node": true + }, + ...require('../../../eslint.config.js') +} diff --git a/plugins/node/instrumentation-socket.io/.npmignore b/plugins/node/instrumentation-socket.io/.npmignore new file mode 100644 index 0000000000..9505ba9450 --- /dev/null +++ b/plugins/node/instrumentation-socket.io/.npmignore @@ -0,0 +1,4 @@ +/bin +/coverage +/doc +/test diff --git a/plugins/node/instrumentation-socket.io/.tav.yml b/plugins/node/instrumentation-socket.io/.tav.yml new file mode 100644 index 0000000000..2c704e4634 --- /dev/null +++ b/plugins/node/instrumentation-socket.io/.tav.yml @@ -0,0 +1,15 @@ +'socket.io': + - versions: "2.1.1 || 2.2.0 || 2.3.0 || 2.4.0 || ^2.5.0" + peerDependencies: socket.io-client@^2 + commands: + - npm run test + + - versions: "^3.1.3" + peerDependencies: socket.io-client@^3 + commands: + - npm run test + + - versions: "4.4.1 || 4.5.1 || 4.5.2 || ^4.5.3" + peerDependencies: socket.io-client@^4 + commands: + - npm run test diff --git a/plugins/node/instrumentation-socket.io/CHANGELOG.md b/plugins/node/instrumentation-socket.io/CHANGELOG.md new file mode 100644 index 0000000000..77ef5af556 --- /dev/null +++ b/plugins/node/instrumentation-socket.io/CHANGELOG.md @@ -0,0 +1,37 @@ +# Changelog + +## [0.33.2](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-socket.io-v0.33.1...instrumentation-socket.io-v0.33.2) (2023-04-25) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.38.0 ([#1468](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1468)) ([565a2b2](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/565a2b2c6fde88af3f5401ef6a5a9643d0d66349)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.1 to ^0.33.2 + +## [0.33.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-socket.io-v0.33.0...instrumentation-socket.io-v0.33.1) (2023-02-07) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.35.1 ([#1358](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1358)) ([ff109b7](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/ff109b77928cc9a139a21c63d6b54399bb017fa4)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.0 to ^0.33.1 + +## [0.33.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-socket.io-v0.32.0...instrumentation-socket.io-v0.33.0) (2022-12-20) + + +### Features + +* add socket.io instrumentation ([#1284](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1284)) ([f865143](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/f865143d9042c41ebed6adbe906097ad7622f2c7)) +* upstream mocha instrumentation testing plugin from ext-js [#621](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/621) ([#669](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/669)) ([a5170c4](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/a5170c494706a2bec3ba51e59966d0ca8a41d00e)) diff --git a/plugins/node/instrumentation-socket.io/LICENSE b/plugins/node/instrumentation-socket.io/LICENSE new file mode 100644 index 0000000000..261eeb9e9f --- /dev/null +++ b/plugins/node/instrumentation-socket.io/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/plugins/node/instrumentation-socket.io/README.md b/plugins/node/instrumentation-socket.io/README.md new file mode 100644 index 0000000000..ca242046f9 --- /dev/null +++ b/plugins/node/instrumentation-socket.io/README.md @@ -0,0 +1,76 @@ +# OpenTelemetry socket.io Instrumentation for Node.js + +[![NPM Published Version][npm-img]][npm-url] +[![Apache License][license-image]][license-image] + +This module provides automatic instrumentation for the [`socket.io`](https://github.com/socketio/socket.io) module, which may be loaded using the [`@opentelemetry/sdk-trace-node`](https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-sdk-trace-node) package and is included in the [`@opentelemetry/auto-instrumentations-node`](https://www.npmjs.com/package/@opentelemetry/auto-instrumentations-node) bundle. + +If total installation size is not constrained, it is recommended to use the [`@opentelemetry/auto-instrumentations-node`](https://www.npmjs.com/package/@opentelemetry/auto-instrumentations-node) bundle with [@opentelemetry/sdk-node](`https://www.npmjs.com/package/@opentelemetry/sdk-node`) for the most seamless instrumentation experience. + +Compatible with OpenTelemetry JS API and SDK `1.0+`. + +## Installation + +```bash +npm install --save @opentelemetry/instrumentation-socket.io +``` + +## Supported Versions + +- `>=2 <5` + +## Usage + +To load a specific plugin, specify it in the registerInstrumentations's configuration: + +```js +const { NodeTracerProvider } = require("@opentelemetry/sdk-trace-node"); +const { + SocketIoInstrumentation, +} = require("@opentelemetry/instrumentation-socket.io"); +const { registerInstrumentations } = require("@opentelemetry/instrumentation"); + +const provider = new NodeTracerProvider(); +provider.register(); + +registerInstrumentations({ + instrumentations: [new SocketIoInstrumentation()], +}); +``` + +## Optional Parameters + +| Option | Type | Default | Description | +| ------ | ---- | ------- | ----------- | +| `emitHook` | `SocketIoHookFunction` | `undefined` | hook for adding custom attributes before socket.io emits the event | +| `emitIgnoreEventList` | `string[]` | `[]` | names of emitted events to ignore tracing for | +| `onHook` | `SocketIoHookFunction` | `undefined` | hook for adding custom attributes before the event listener (callback) is invoked | +| `onIgnoreEventList` | `string[]` | `[]` | names of listened events to ignore tracing for | +| `traceReserved` | `boolean` | `false` | set to true if you want to trace socket.io reserved events (see [docs](https://socket.io/docs/v4/emit-cheatsheet/#Reserved-events)) | + +## Migration From opentelemetry-instrumentation-socket.io + +This instrumentation was originally published and maintained under the name `"opentelemetry-instrumentation-socket.io"` in [this repo](https://github.com/aspecto-io/opentelemetry-ext-js). + +Few breaking changes were made during porting to the contrib repo: + +### filterHttpTransport + +The instrumentation's config `filterHttpTransport` option was removed to decouple this instrumentation from the http instrumentation. +if you do not want to trace the socket.io http requests, add the default socket.io route (`/socket.io/`) to the `HttpInstrumentationConfig.ignoreIncomingPaths` array + +## Useful links + +- For more information on OpenTelemetry, visit: +- For more about OpenTelemetry JavaScript: +- For help or feedback on this project, join us in [GitHub Discussions][discussions-url] + +## License + +Apache 2.0 - See [LICENSE][license-url] for more information. + +[discussions-url]: https://github.com/open-telemetry/opentelemetry-js/discussions +[license-url]: https://github.com/open-telemetry/opentelemetry-js-contrib/blob/main/LICENSE +[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat +[npm-url]: https://www.npmjs.com/package/@opentelemetry/instrumentation-socket.io +[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Finstrumentation-socket.io.svg diff --git a/plugins/node/instrumentation-socket.io/package.json b/plugins/node/instrumentation-socket.io/package.json new file mode 100644 index 0000000000..513504f4a5 --- /dev/null +++ b/plugins/node/instrumentation-socket.io/package.json @@ -0,0 +1,65 @@ +{ + "name": "@opentelemetry/instrumentation-socket.io", + "version": "0.33.2", + "description": "OpenTelemetry automatic instrumentation package for socket.io", + "main": "build/src/index.js", + "types": "build/src/index.d.ts", + "repository": "open-telemetry/opentelemetry-js-contrib", + "scripts": { + "test": "ts-mocha -p tsconfig.json --require '@opentelemetry/contrib-test-utils' 'test/**/*.test.ts'", + "test-all-versions": "tav", + "tdd": "npm run test -- --watch-extensions ts --watch", + "clean": "rimraf build/*", + "lint": "eslint . --ext .ts", + "lint:fix": "eslint . --ext .ts --fix", + "precompile": "tsc --version && lerna run version --scope @opentelemetry/instrumentation-socket.io --include-dependencies", + "prewatch": "npm run precompile", + "prepare": "npm run compile", + "version:update": "node ../../../scripts/version-update.js", + "compile": "npm run version:update && tsc -p ." + }, + "keywords": [ + "socket.io", + "instrumentation", + "nodejs", + "opentelemetry", + "tracing" + ], + "author": "OpenTelemetry Authors", + "license": "Apache-2.0", + "engines": { + "node": ">=14.0" + }, + "files": [ + "build/src/**/*.js", + "build/src/**/*.js.map", + "build/src/**/*.d.ts" + ], + "publishConfig": { + "access": "public" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + }, + "devDependencies": { + "@opentelemetry/api": "^1.3.0", + "@opentelemetry/contrib-test-utils": "^0.33.2", + "@opentelemetry/sdk-trace-base": "^1.8.0", + "@types/mocha": "8.2.3", + "@types/node": "18.11.7", + "expect": "27.4.2", + "mocha": "7.2.0", + "nyc": "15.1.0", + "rimraf": "4.2.0", + "socket.io": "^4.1.3", + "socket.io-client": "^4.1.3", + "test-all-versions": "5.0.1", + "ts-mocha": "10.0.0", + "typescript": "4.4.4" + }, + "dependencies": { + "@opentelemetry/instrumentation": "^0.38.0", + "@opentelemetry/semantic-conventions": "^1.0.0" + }, + "homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/instrumentation-socket.io#readme" +} diff --git a/plugins/node/instrumentation-socket.io/src/AttributeNames.ts b/plugins/node/instrumentation-socket.io/src/AttributeNames.ts new file mode 100644 index 0000000000..ce46246b25 --- /dev/null +++ b/plugins/node/instrumentation-socket.io/src/AttributeNames.ts @@ -0,0 +1,20 @@ +/* + * 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. + */ +export const SocketIoInstrumentationAttributes = { + SOCKET_IO_ROOMS: 'messaging.socket.io.rooms', + SOCKET_IO_NAMESPACE: 'messaging.socket.io.namespace', + SOCKET_IO_EVENT_NAME: 'messaging.socket.io.event_name', +}; diff --git a/plugins/node/instrumentation-socket.io/src/index.ts b/plugins/node/instrumentation-socket.io/src/index.ts new file mode 100644 index 0000000000..c32b37405f --- /dev/null +++ b/plugins/node/instrumentation-socket.io/src/index.ts @@ -0,0 +1,18 @@ +/* + * 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. + */ +export * from './socket.io'; +export * from './types'; +export * from './AttributeNames'; diff --git a/plugins/node/instrumentation-socket.io/src/socket.io.ts b/plugins/node/instrumentation-socket.io/src/socket.io.ts new file mode 100644 index 0000000000..db37e5c375 --- /dev/null +++ b/plugins/node/instrumentation-socket.io/src/socket.io.ts @@ -0,0 +1,450 @@ +/* + * 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 { + context, + trace, + Span, + SpanKind, + SpanStatusCode, +} from '@opentelemetry/api'; +import { + InstrumentationBase, + InstrumentationNodeModuleFile, + InstrumentationNodeModuleDefinition, + isWrapped, + safeExecuteInTheMiddle, +} from '@opentelemetry/instrumentation'; +import { + SemanticAttributes, + MessagingOperationValues, + MessagingDestinationKindValues, +} from '@opentelemetry/semantic-conventions'; +import { SocketIoInstrumentationConfig } from './types'; +import { SocketIoInstrumentationAttributes } from './AttributeNames'; +import { VERSION } from './version'; +import { + extractRoomsAttributeValue, + isPromise, + normalizeConfig, +} from './utils'; + +const reservedEvents = [ + 'connect', + 'connect_error', + 'disconnect', + 'disconnecting', + 'newListener', + 'removeListener', +]; + +export class SocketIoInstrumentation extends InstrumentationBase { + protected override _config!: SocketIoInstrumentationConfig; + + constructor(config: SocketIoInstrumentationConfig = {}) { + super( + '@opentelemetry/instrumentation-socket.io', + VERSION, + normalizeConfig(config) + ); + } + + protected init() { + const socketInstrumentation = new InstrumentationNodeModuleFile( + 'socket.io/dist/socket.js', + ['>=3 <5'], + (moduleExports, moduleVersion) => { + if (moduleExports === undefined || moduleExports === null) { + return moduleExports; + } + if (moduleVersion === undefined) { + return moduleExports; + } + this._diag.debug(`applying patch to socket.io@${moduleVersion} Socket`); + if (isWrapped(moduleExports?.Socket?.prototype?.on)) { + this._unwrap(moduleExports.Socket.prototype, 'on'); + } + this._wrap( + moduleExports.Socket.prototype, + 'on', + this._patchOn(moduleVersion) + ); + if (isWrapped(moduleExports?.Socket?.prototype?.emit)) { + this._unwrap(moduleExports.Socket.prototype, 'emit'); + } + this._wrap( + moduleExports.Socket.prototype, + 'emit', + this._patchEmit(moduleVersion) + ); + return moduleExports; + }, + moduleExports => { + if (isWrapped(moduleExports?.Socket?.prototype?.on)) { + this._unwrap(moduleExports.Socket.prototype, 'on'); + } + if (isWrapped(moduleExports?.Socket?.prototype?.emit)) { + this._unwrap(moduleExports.Socket.prototype, 'emit'); + } + return moduleExports; + } + ); + + const broadcastOperatorInstrumentation = + new InstrumentationNodeModuleFile( + 'socket.io/dist/broadcast-operator.js', + ['>=4 <5'], + (moduleExports, moduleVersion) => { + if (moduleExports === undefined || moduleExports === null) { + return moduleExports; + } + if (moduleVersion === undefined) { + return moduleExports; + } + this._diag.debug( + `applying patch to socket.io@${moduleVersion} StrictEventEmitter` + ); + if (isWrapped(moduleExports?.BroadcastOperator?.prototype?.emit)) { + this._unwrap(moduleExports.BroadcastOperator.prototype, 'emit'); + } + this._wrap( + moduleExports.BroadcastOperator.prototype, + 'emit', + this._patchEmit(moduleVersion) + ); + return moduleExports; + }, + moduleExports => { + if (isWrapped(moduleExports?.BroadcastOperator?.prototype?.emit)) { + this._unwrap(moduleExports.BroadcastOperator.prototype, 'emit'); + } + return moduleExports; + } + ); + const namespaceInstrumentation = new InstrumentationNodeModuleFile( + 'socket.io/dist/namespace.js', + ['<4'], + (moduleExports, moduleVersion) => { + if (moduleExports === undefined || moduleExports === null) { + return moduleExports; + } + if (moduleVersion === undefined) { + return moduleExports; + } + this._diag.debug( + `applying patch to socket.io@${moduleVersion} Namespace` + ); + if (isWrapped(moduleExports?.Namespace?.prototype?.emit)) { + this._unwrap(moduleExports.Namespace.prototype, 'emit'); + } + this._wrap( + moduleExports.Namespace.prototype, + 'emit', + this._patchEmit(moduleVersion) + ); + return moduleExports; + }, + moduleExports => { + if (isWrapped(moduleExports?.Namespace?.prototype?.emit)) { + this._unwrap(moduleExports.Namespace.prototype, 'emit'); + } + } + ); + const socketInstrumentationLegacy = new InstrumentationNodeModuleFile( + 'socket.io/lib/socket.js', + ['2'], + (moduleExports, moduleVersion) => { + if (moduleExports === undefined || moduleExports === null) { + return moduleExports; + } + if (moduleVersion === undefined) { + return moduleExports; + } + this._diag.debug(`applying patch to socket.io@${moduleVersion} Socket`); + if (isWrapped(moduleExports.prototype?.on)) { + this._unwrap(moduleExports.prototype, 'on'); + } + this._wrap(moduleExports.prototype, 'on', this._patchOn(moduleVersion)); + if (isWrapped(moduleExports.prototype?.emit)) { + this._unwrap(moduleExports.prototype, 'emit'); + } + this._wrap( + moduleExports.prototype, + 'emit', + this._patchEmit(moduleVersion) + ); + return moduleExports; + }, + moduleExports => { + if (isWrapped(moduleExports.prototype?.on)) { + this._unwrap(moduleExports.prototype, 'on'); + } + if (isWrapped(moduleExports.prototype?.emit)) { + this._unwrap(moduleExports.prototype, 'emit'); + } + return moduleExports; + } + ); + const namespaceInstrumentationLegacy = + new InstrumentationNodeModuleFile( + 'socket.io/lib/namespace.js', + ['2'], + (moduleExports, moduleVersion) => { + if (moduleExports === undefined || moduleExports === null) { + return moduleExports; + } + if (moduleVersion === undefined) { + return moduleExports; + } + this._diag.debug( + `applying patch to socket.io@${moduleVersion} Namespace` + ); + if (isWrapped(moduleExports?.prototype?.emit)) { + this._unwrap(moduleExports.prototype, 'emit'); + } + this._wrap( + moduleExports.prototype, + 'emit', + this._patchEmit(moduleVersion) + ); + return moduleExports; + }, + moduleExports => { + if (isWrapped(moduleExports?.prototype?.emit)) { + this._unwrap(moduleExports.prototype, 'emit'); + } + } + ); + + return [ + new InstrumentationNodeModuleDefinition( + 'socket.io', + ['>=3 <5'], + (moduleExports, moduleVersion) => { + if (moduleExports === undefined || moduleExports === null) { + return moduleExports; + } + if (moduleVersion === undefined) { + return moduleExports; + } + this._diag.debug( + `applying patch to socket.io@${moduleVersion} Server` + ); + if (isWrapped(moduleExports?.Server?.prototype?.on)) { + this._unwrap(moduleExports.Server.prototype, 'on'); + } + this._wrap( + moduleExports.Server.prototype, + 'on', + this._patchOn(moduleVersion) + ); + return moduleExports; + }, + (moduleExports, moduleVersion) => { + if (isWrapped(moduleExports?.Server?.prototype?.on)) { + this._unwrap(moduleExports.Server.prototype, 'on'); + } + return moduleExports; + }, + [ + broadcastOperatorInstrumentation, + namespaceInstrumentation, + socketInstrumentation, + ] + ), + new InstrumentationNodeModuleDefinition( + 'socket.io', + ['2'], + (moduleExports, moduleVersion) => { + if (moduleExports === undefined || moduleExports === null) { + return moduleExports; + } + if (moduleVersion === undefined) { + return moduleExports; + } + this._diag.debug( + `applying patch to socket.io@${moduleVersion} Server` + ); + if (isWrapped(moduleExports?.prototype?.on)) { + this._unwrap(moduleExports.prototype, 'on'); + } + this._wrap( + moduleExports.prototype, + 'on', + this._patchOn(moduleVersion) + ); + return moduleExports; + }, + (moduleExports, moduleVersion) => { + if (isWrapped(moduleExports?.prototype?.on)) { + this._unwrap(moduleExports.prototype, 'on'); + } + return moduleExports; + }, + [namespaceInstrumentationLegacy, socketInstrumentationLegacy] + ), + ]; + } + + override setConfig(config: SocketIoInstrumentationConfig = {}) { + return super.setConfig(normalizeConfig(config)); + } + + private _patchOn(moduleVersion: string) { + const self = this; + return (original: Function) => { + return function (this: any, ev: any, originalListener: Function) { + if (!self._config.traceReserved && reservedEvents.includes(ev)) { + return original.apply(this, arguments); + } + if (self._config.onIgnoreEventList?.includes(ev)) { + return original.apply(this, arguments); + } + const wrappedListener = function (this: any, ...args: any[]) { + const eventName = ev; + const defaultNamespace = '/'; + const namespace = this.name || this.adapter?.nsp?.name; + const destination = + namespace === defaultNamespace + ? eventName + : `${namespace} ${eventName}`; + const span: Span = self.tracer.startSpan( + `${destination} ${MessagingOperationValues.RECEIVE}`, + { + kind: SpanKind.CONSUMER, + attributes: { + [SemanticAttributes.MESSAGING_SYSTEM]: 'socket.io', + [SemanticAttributes.MESSAGING_DESTINATION]: namespace, + [SemanticAttributes.MESSAGING_OPERATION]: + MessagingOperationValues.RECEIVE, + [SocketIoInstrumentationAttributes.SOCKET_IO_EVENT_NAME]: + eventName, + }, + } + ); + + if (self._config.onHook) { + safeExecuteInTheMiddle( + () => + self._config?.onHook?.(span, { moduleVersion, payload: args }), + e => { + if (e) self._diag.error('onHook error', e); + }, + true + ); + } + return context.with(trace.setSpan(context.active(), span), () => + self.endSpan(() => originalListener.apply(this, arguments), span) + ); + }; + return original.apply(this, [ev, wrappedListener]); + }; + }; + } + + private endSpan(traced: () => any | Promise, span: Span) { + try { + const result = traced(); + if (isPromise(result)) { + return result.then( + value => { + span.end(); + return value; + }, + err => { + span.recordException(err); + span.setStatus({ + code: SpanStatusCode.ERROR, + message: err?.message, + }); + span.end(); + throw err; + } + ); + } else { + span.end(); + return result; + } + } catch (error: any) { + span.recordException(error); + span.setStatus({ code: SpanStatusCode.ERROR, message: error?.message }); + span.end(); + throw error; + } + } + + private _patchEmit(moduleVersion: string) { + const self = this; + return (original: Function) => { + return function (this: any, ev: any, ...args: any[]) { + if (!self._config.traceReserved && reservedEvents.includes(ev)) { + return original.apply(this, arguments); + } + if (self._config?.emitIgnoreEventList?.includes(ev)) { + return original.apply(this, arguments); + } + const messagingSystem = 'socket.io'; + const eventName = ev; + const attributes: any = { + [SemanticAttributes.MESSAGING_SYSTEM]: messagingSystem, + [SemanticAttributes.MESSAGING_DESTINATION_KIND]: + MessagingDestinationKindValues.TOPIC, + [SocketIoInstrumentationAttributes.SOCKET_IO_EVENT_NAME]: eventName, + }; + + const rooms = extractRoomsAttributeValue(this); + if (rooms.length) { + attributes[SocketIoInstrumentationAttributes.SOCKET_IO_ROOMS] = rooms; + } + const namespace = + this.name || this.adapter?.nsp?.name || this.sockets?.name; + if (namespace) { + attributes[SocketIoInstrumentationAttributes.SOCKET_IO_NAMESPACE] = + namespace; + attributes[SemanticAttributes.MESSAGING_DESTINATION] = namespace; + } + const spanRooms = rooms.length ? `[${rooms.join()}]` : ''; + const span = self.tracer.startSpan(`${namespace}${spanRooms} send`, { + kind: SpanKind.PRODUCER, + attributes, + }); + + if (self._config.emitHook) { + safeExecuteInTheMiddle( + () => + self._config.emitHook?.(span, { moduleVersion, payload: args }), + e => { + if (e) self._diag.error('emitHook error', e); + }, + true + ); + } + try { + return context.with(trace.setSpan(context.active(), span), () => + original.apply(this, arguments) + ); + } catch (error: any) { + span.setStatus({ + code: SpanStatusCode.ERROR, + message: error.message, + }); + throw error; + } finally { + span.end(); + } + }; + }; + } +} diff --git a/plugins/node/instrumentation-socket.io/src/types.ts b/plugins/node/instrumentation-socket.io/src/types.ts new file mode 100644 index 0000000000..ec432e0566 --- /dev/null +++ b/plugins/node/instrumentation-socket.io/src/types.ts @@ -0,0 +1,40 @@ +/* + * 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 { Span } from '@opentelemetry/api'; +import { InstrumentationConfig } from '@opentelemetry/instrumentation'; + +export const defaultSocketIoPath = '/socket.io/'; + +export interface SocketIoHookInfo { + moduleVersion?: string; + payload: any[]; +} +export interface SocketIoHookFunction { + (span: Span, hookInfo: SocketIoHookInfo): void; +} + +export interface SocketIoInstrumentationConfig extends InstrumentationConfig { + /** Hook for adding custom attributes before socket.io emits the event */ + emitHook?: SocketIoHookFunction; + /** list of events to ignore tracing on for socket.io emits */ + emitIgnoreEventList?: string[]; + /** Hook for adding custom attributes before the event listener (callback) is invoked */ + onHook?: SocketIoHookFunction; + /** list of events to ignore tracing on for socket.io listeners */ + onIgnoreEventList?: string[]; + /** Set to `true` if you want to trace socket.io reserved events (see https://socket.io/docs/v4/emit-cheatsheet/#Reserved-events) */ + traceReserved?: boolean; +} diff --git a/plugins/node/instrumentation-socket.io/src/utils.ts b/plugins/node/instrumentation-socket.io/src/utils.ts new file mode 100644 index 0000000000..a4ace3a485 --- /dev/null +++ b/plugins/node/instrumentation-socket.io/src/utils.ts @@ -0,0 +1,49 @@ +/* + * 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 { SocketIoInstrumentationConfig } from './types'; + +export const isPromise = (value: any): value is Promise => { + return typeof value?.then === 'function'; +}; + +export const normalizeConfig = (config?: SocketIoInstrumentationConfig) => { + config = Object.assign({}, config); + if (!Array.isArray(config.emitIgnoreEventList)) { + config.emitIgnoreEventList = []; + } + if (!Array.isArray(config.onIgnoreEventList)) { + config.onIgnoreEventList = []; + } + return config; +}; + +export const extractRoomsAttributeValue = (self: any): any[] => { + let rooms = + self.rooms || + self._rooms || + self.sockets?._rooms || + self.sockets?.rooms || + []; + // Some of the attributes above are of Set type. Convert it. + if (!Array.isArray(rooms)) { + rooms = Array.from(rooms); + } + // only for v2: this.id is only set for v2. That's to mimic later versions which have this.id in the rooms Set. + if (rooms.length === 0 && self.id) { + rooms.push(self.id); + } + return rooms; +}; diff --git a/plugins/node/instrumentation-socket.io/test/config.test.ts b/plugins/node/instrumentation-socket.io/test/config.test.ts new file mode 100644 index 0000000000..de1b89c7ac --- /dev/null +++ b/plugins/node/instrumentation-socket.io/test/config.test.ts @@ -0,0 +1,32 @@ +/* + * 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 { SocketIoInstrumentation, SocketIoInstrumentationConfig } from '../src'; +import * as expect from 'expect'; + +describe('SocketIoInstrumentationConfig', () => { + it('forces *IgnoreEventList to be an Array', () => { + const socketIoInstrumentation = new SocketIoInstrumentation({ + onIgnoreEventList: {} as any, + emitIgnoreEventList: 1 as any, + }); + + const { onIgnoreEventList, emitIgnoreEventList } = + socketIoInstrumentation.getConfig() as SocketIoInstrumentationConfig; + + expect(Array.isArray(onIgnoreEventList)).toEqual(true); + expect(Array.isArray(emitIgnoreEventList)).toEqual(true); + }); +}); diff --git a/plugins/node/instrumentation-socket.io/test/socket.io.test.ts b/plugins/node/instrumentation-socket.io/test/socket.io.test.ts new file mode 100644 index 0000000000..1b47fd5d73 --- /dev/null +++ b/plugins/node/instrumentation-socket.io/test/socket.io.test.ts @@ -0,0 +1,449 @@ +/* + * 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 { + MessagingDestinationKindValues, + SemanticAttributes, +} from '@opentelemetry/semantic-conventions'; +import { + SocketIoInstrumentation, + SocketIoInstrumentationAttributes, + SocketIoInstrumentationConfig, +} from '../src'; +import { SpanKind, SpanStatusCode } from '@opentelemetry/api'; +import * as expect from 'expect'; +import 'mocha'; +import { registerInstrumentationTesting } from '@opentelemetry/contrib-test-utils'; + +const instrumentation = registerInstrumentationTesting( + new SocketIoInstrumentation() +); +import { Socket } from 'socket.io'; +import { + createServer, + createServerInstance, + io, + getSocketIoSpans, + expectSpan, + isV2, +} from './utils'; + +describe('SocketIoInstrumentation', () => { + beforeEach(() => { + instrumentation.enable(); + instrumentation.setConfig({}); + }); + + afterEach(() => { + instrumentation.disable(); + }); + + describe('Server', () => { + it('emit is instrumented', () => { + const io = createServerInstance(); + io.emit('test'); + expectSpan('/ send', span => { + expect(span.kind).toEqual(SpanKind.PRODUCER); + expect(span.attributes[SemanticAttributes.MESSAGING_SYSTEM]).toEqual( + 'socket.io' + ); + expect( + span.attributes[SemanticAttributes.MESSAGING_DESTINATION_KIND] + ).toEqual(MessagingDestinationKindValues.TOPIC); + }); + }); + + it('emitIgnoreEventList events are ignored', () => { + const io = createServerInstance(); + const config: SocketIoInstrumentationConfig = { + emitIgnoreEventList: ['ignored'], + }; + instrumentation.setConfig(config); + io.emit('test'); + io.emit('ignored'); + expect(getSocketIoSpans().length).toEqual(1); + }); + + it('emit reserved events error is instrumented', () => { + const config: SocketIoInstrumentationConfig = { + traceReserved: true, + }; + instrumentation.setConfig(config); + const io = createServerInstance(); + try { + io.emit('connect'); + } catch (error) {} + if (isV2) { + // only for v2: connect do not throw, but are just ignored + return expectSpan('/ send', span => { + expect(span.kind).toEqual(SpanKind.PRODUCER); + expect(span.attributes[SemanticAttributes.MESSAGING_SYSTEM]).toEqual( + 'socket.io' + ); + }); + } + expectSpan('/ send', span => { + expect(span.status.code).toEqual(SpanStatusCode.ERROR); + expect(span.status.message).toEqual( + '"connect" is a reserved event name' + ); + }); + }); + + it('send is instrumented', () => { + const io = createServerInstance(); + io.send('test'); + expectSpan('/ send', span => { + expect(span.kind).toEqual(SpanKind.PRODUCER); + expect(span.attributes[SemanticAttributes.MESSAGING_SYSTEM]).toEqual( + 'socket.io' + ); + expect( + span.attributes[SemanticAttributes.MESSAGING_DESTINATION_KIND] + ).toEqual(MessagingDestinationKindValues.TOPIC); + }); + }); + + it('emitHook is called', () => { + const config: SocketIoInstrumentationConfig = { + traceReserved: true, + emitHook: (span, hookInfo) => { + span.setAttribute('payload', JSON.stringify(hookInfo.payload)); + }, + }; + instrumentation.setConfig(config); + + const io = createServerInstance(); + io.emit('test', 1234); + expectSpan('/ send', span => { + expect(span.attributes['payload']).toEqual(JSON.stringify([1234])); + }); + }); + + it('emitHook error does not effect trace', () => { + const config: SocketIoInstrumentationConfig = { + emitHook: () => { + throw new Error('Throwing'); + }, + }; + instrumentation.setConfig(config); + const io = createServerInstance(); + io.emit('test'); + const spans = getSocketIoSpans(); + expect(spans.length).toBe(1); + }); + + it('onHook is called', done => { + const config: SocketIoInstrumentationConfig = { + onHook: (span, hookInfo) => { + span.setAttribute('payload', JSON.stringify(hookInfo.payload)); + }, + // only for v2: v2 emits connection on the client side, newer versions do not + emitIgnoreEventList: ['connection'], + }; + instrumentation.setConfig(config); + const data = { + name: 'bob', + age: 28, + }; + createServer((sio, port) => { + const client = io(`http://localhost:${port}`); + client.on('test', () => client.emit('test_reply', data)); + sio.on('connection', (socket: Socket) => { + socket.emit('test'); + socket.on('test_reply', data => { + client.close(); + sio.close(); + //trace is created after the listener method is completed + setTimeout(() => { + expectSpan( + 'test_reply receive', + span => { + try { + expect(span.kind).toEqual(SpanKind.CONSUMER); + expect( + span.attributes[SemanticAttributes.MESSAGING_SYSTEM] + ).toEqual('socket.io'); + expect(span.attributes['payload']).toEqual( + JSON.stringify([data]) + ); + done(); + } catch (e) { + done(e); + } + }, + 3 + ); + }); + }); + }); + }); + }); + + it('traceReserved:true on is instrumented', done => { + const config: SocketIoInstrumentationConfig = { + traceReserved: true, + // only for v2: v2 emits [dis]connect[ing] events which later versions do not + emitIgnoreEventList: [ + 'disconnect', + 'disconnecting', + 'connection', + 'connect', + ], + }; + instrumentation.setConfig(config); + createServer((sio, port) => { + const client = io(`http://localhost:${port}`); + sio.on('connection', () => { + client.close(); + sio.close(); + //trace is created after the listener method is completed + setTimeout(() => { + expectSpan('connection receive', span => { + expect(span.kind).toEqual(SpanKind.CONSUMER); + expect( + span.attributes[SemanticAttributes.MESSAGING_SYSTEM] + ).toEqual('socket.io'); + done(); + }); + }); + }); + }); + }); + + it('on is instrumented', done => { + const config: SocketIoInstrumentationConfig = { + // only for v2: v2 emits connection events which later versions do not + emitIgnoreEventList: ['connection'], + }; + instrumentation.setConfig(config); + createServer((sio, port) => { + const client = io(`http://localhost:${port}`); + client.on('test', () => client.emit('test_reply')); + sio.on('connection', (socket: Socket) => { + socket.emit('test'); + socket.on('test_reply', () => { + client.close(); + sio.close(); + //trace is created after the listener method is completed + setTimeout(() => { + expectSpan( + 'test_reply receive', + span => { + try { + expect(span.kind).toEqual(SpanKind.CONSUMER); + expect( + span.attributes[SemanticAttributes.MESSAGING_SYSTEM] + ).toEqual('socket.io'); + done(); + } catch (e) { + done(e); + } + }, + 3 + ); + }); + }); + }); + }); + }); + + it('onIgnoreEventList events are ignored', done => { + const config: SocketIoInstrumentationConfig = { + onIgnoreEventList: ['test_reply'], + // only for v2: v2 emits connection events which later versions do not + emitIgnoreEventList: ['connection'], + }; + instrumentation.setConfig(config); + createServer((sio, port) => { + const client = io(`http://localhost:${port}`); + client.on('test', () => client.emit('test_reply')); + sio.on('connection', (socket: Socket) => { + socket.emit('test'); + socket.on('test_reply', () => { + client.close(); + sio.close(); + //trace is created after the listener method is completed + setTimeout(() => { + try { + expect(getSocketIoSpans().length).toEqual(2); + done(); + } catch (e) { + done(e); + } + }); + }); + }); + }); + }); + + it('broadcast is instrumented', () => { + const roomName = 'room'; + const sio = createServerInstance(); + sio.to(roomName).emit('broadcast', '1234'); + expectSpan('/[room] send', span => { + expect( + span.attributes[SemanticAttributes.MESSAGING_DESTINATION] + ).toEqual('/'); + expect( + span.attributes[SocketIoInstrumentationAttributes.SOCKET_IO_ROOMS] + ).toEqual([roomName]); + }); + }); + + it('broadcast to multiple rooms', () => { + const sio = createServerInstance(); + sio.to('room1').to('room2').emit('broadcast', '1234'); + expectSpan('/[room1,room2] send', span => { + expect( + span.attributes[SemanticAttributes.MESSAGING_DESTINATION] + ).toEqual('/'); + expect( + span.attributes[SocketIoInstrumentationAttributes.SOCKET_IO_ROOMS] + ).toEqual(['room1', 'room2']); + }); + }); + }); + + describe('Namespace', () => { + it('emit is instrumented', () => { + const io = createServerInstance(); + const namespace = io.of('/testing'); + namespace.emit('namespace'); + expectSpan('/testing send', span => { + expect( + span.attributes[SemanticAttributes.MESSAGING_DESTINATION] + ).toEqual('/testing'); + expect( + span.attributes[SocketIoInstrumentationAttributes.SOCKET_IO_NAMESPACE] + ).toEqual('/testing'); + }); + }); + + it('broadcast is instrumented', () => { + const roomName = 'room'; + const io = createServerInstance(); + const namespace = io.of('/testing'); + namespace.to(roomName).emit('broadcast', '1234'); + expectSpan('/testing[room] send', span => { + expect( + span.attributes[SemanticAttributes.MESSAGING_DESTINATION] + ).toEqual('/testing'); + expect( + span.attributes[SocketIoInstrumentationAttributes.SOCKET_IO_ROOMS] + ).toEqual([roomName]); + expect( + span.attributes[SocketIoInstrumentationAttributes.SOCKET_IO_NAMESPACE] + ).toEqual('/testing'); + }); + }); + + it('broadcast to multiple rooms', () => { + const io = createServerInstance(); + const namespace = io.of('/testing'); + namespace.to('room1').to('room2').emit('broadcast', '1234'); + expectSpan('/testing[room1,room2] send', span => { + expect( + span.attributes[SemanticAttributes.MESSAGING_DESTINATION] + ).toEqual('/testing'); + expect( + span.attributes[SocketIoInstrumentationAttributes.SOCKET_IO_NAMESPACE] + ).toEqual('/testing'); + expect( + span.attributes[SocketIoInstrumentationAttributes.SOCKET_IO_ROOMS] + ).toEqual(['room1', 'room2']); + }); + }); + + it('on is instrumented', done => { + const config: SocketIoInstrumentationConfig = { + // only for v2: v2 emits connection events which later versions do not + emitIgnoreEventList: ['connection'], + }; + instrumentation.setConfig(config); + createServer((sio, port) => { + const namespace = sio.of('/testing'); + const client = io(`http://localhost:${port}/testing`); + client.on('test', () => client.emit('test_reply')); + namespace.on('connection', (socket: Socket) => { + socket.emit('test'); + socket.on('test_reply', () => { + client.close(); + sio.close(); + //trace is created after the listener method is completed + setTimeout(() => { + expectSpan( + '/testing test_reply receive', + span => { + try { + expect(span.kind).toEqual(SpanKind.CONSUMER); + expect( + span.attributes[SemanticAttributes.MESSAGING_SYSTEM] + ).toEqual('socket.io'); + expect( + span.attributes[SemanticAttributes.MESSAGING_DESTINATION] + ).toEqual('/testing'); + done(); + } catch (e) { + done(e); + } + }, + 2 + ); + }); + }); + }); + }); + }); + }); + + describe('Socket', () => { + it('emit is instrumented', done => { + const config: SocketIoInstrumentationConfig = { + // only for v2: v2 emits connection events which later versions do not + emitIgnoreEventList: ['connection'], + }; + instrumentation.setConfig(config); + createServer((sio, port) => { + const client = io(`http://localhost:${port}`, { + // websockets transport disconnects without the delay of the polling interval + transports: ['websocket'], + }); + sio.on('connection', (socket: Socket) => { + socket.emit('test'); + client.close(); + sio.close(); + setTimeout(() => { + expectSpan( + `/[${socket.id}] send`, + span => { + try { + expect(span.kind).toEqual(SpanKind.PRODUCER); + expect( + span.attributes[SemanticAttributes.MESSAGING_SYSTEM] + ).toEqual('socket.io'); + done(); + } catch (e) { + done(e); + } + }, + 2 + ); + }); + }); + }); + }); + }); +}); diff --git a/plugins/node/instrumentation-socket.io/test/utils.ts b/plugins/node/instrumentation-socket.io/test/utils.ts new file mode 100644 index 0000000000..86144d5f4d --- /dev/null +++ b/plugins/node/instrumentation-socket.io/test/utils.ts @@ -0,0 +1,75 @@ +/* + * 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 { strict as assert } from 'assert'; +import * as http from 'http'; +import { AddressInfo } from 'net'; + +import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; +import { ReadableSpan } from '@opentelemetry/sdk-trace-base'; +import { getTestSpans } from '@opentelemetry/contrib-test-utils'; + +import * as expect from 'expect'; +import { Server } from 'socket.io'; +import * as socketIo from 'socket.io'; +import * as ioClient from 'socket.io-client'; +import * as path from 'path'; + +export const io = ioClient.io || ioClient; + +const packageJsonPath = (packageName: string) => + path.join(path.dirname(require.resolve(packageName)), '..', 'package.json'); +const version = require(packageJsonPath('socket.io')).version; + +assert.equal(typeof version, 'string'); + +export const isV2 = version && /^2\./.test(version); + +export const createServer = ( + callback: (server: Server, port: number) => void +) => { + const server = http.createServer(); + const sio = createServerInstance(server); + server.listen(0, () => { + const port = (server.address() as AddressInfo).port; + callback(sio, port); + }); +}; + +export const createServerInstance = (server?: http.Server) => { + if (isV2) { + return (socketIo as any)(server, { serveClient: false }); + } + return new Server(server); +}; + +export const getSocketIoSpans = (): ReadableSpan[] => + getTestSpans().filter( + s => s.attributes[SemanticAttributes.MESSAGING_SYSTEM] === 'socket.io' + ) as ReadableSpan[]; + +export const expectSpan = ( + spanName: string, + callback?: (span: ReadableSpan) => void, + spanCount?: number +) => { + const spans = getSocketIoSpans(); + expect(spans.length).toEqual(spanCount || 1); + const span = spans.find(s => s.name === spanName); + expect(span).toBeDefined(); + if (span && callback) { + callback(span); + } +}; diff --git a/plugins/node/instrumentation-socket.io/tsconfig.json b/plugins/node/instrumentation-socket.io/tsconfig.json new file mode 100644 index 0000000000..3feff66260 --- /dev/null +++ b/plugins/node/instrumentation-socket.io/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../../tsconfig.base", + "compilerOptions": { + "rootDir": ".", + "outDir": "build", + }, + "include": [ + "src/**/*.ts", + "test/**/*.ts" + ] +} diff --git a/plugins/node/instrumentation-tedious/CHANGELOG.md b/plugins/node/instrumentation-tedious/CHANGELOG.md index 6cee1df00f..239ea8f525 100644 --- a/plugins/node/instrumentation-tedious/CHANGELOG.md +++ b/plugins/node/instrumentation-tedious/CHANGELOG.md @@ -1,5 +1,47 @@ # Changelog +## [0.5.2](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-tedious-v0.5.1...instrumentation-tedious-v0.5.2) (2023-04-25) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.38.0 ([#1468](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1468)) ([565a2b2](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/565a2b2c6fde88af3f5401ef6a5a9643d0d66349)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.1 to ^0.33.2 + +## [0.5.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-tedious-v0.5.0...instrumentation-tedious-v0.5.1) (2023-02-07) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.35.1 ([#1358](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1358)) ([ff109b7](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/ff109b77928cc9a139a21c63d6b54399bb017fa4)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.0 to ^0.33.1 + +## [0.5.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-tedious-v0.4.1...instrumentation-tedious-v0.5.0) (2022-11-16) + + +### Features + +* update experimental deps to `^0.34.0`, core deps to `^1.8.0`, api to `^1.3.0` ([#1278](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1278)) ([e9fe8e1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/e9fe8e13e34f54e96c50525cadeb74ac048c5624)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.32.0 to ^0.33.0 + ## [0.4.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-tedious-v0.4.0...instrumentation-tedious-v0.4.1) (2022-11-02) diff --git a/plugins/node/instrumentation-tedious/package.json b/plugins/node/instrumentation-tedious/package.json index d263bcad61..5468815ee7 100644 --- a/plugins/node/instrumentation-tedious/package.json +++ b/plugins/node/instrumentation-tedious/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/instrumentation-tedious", - "version": "0.4.1", + "version": "0.5.2", "description": "OpenTelemetry instrumentation for `tedious`", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -44,26 +44,25 @@ "access": "public" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@opentelemetry/api": "^1.3.0" }, "devDependencies": { - "@opentelemetry/api": "^1.0.0", - "@opentelemetry/context-async-hooks": "^1.3.1", - "@opentelemetry/contrib-test-utils": "^0.32.0", - "@opentelemetry/sdk-trace-base": "^1.3.1", + "@opentelemetry/api": "^1.3.0", + "@opentelemetry/context-async-hooks": "^1.8.0", + "@opentelemetry/contrib-test-utils": "^0.33.2", + "@opentelemetry/sdk-trace-base": "^1.8.0", "@types/mocha": "7.0.2", "@types/node": "18.11.7", - "gts": "3.1.0", "mocha": "7.2.0", "nyc": "15.1.0", - "rimraf": "3.0.2", + "rimraf": "4.2.0", "tedious": "14.1.0", "test-all-versions": "5.0.1", "ts-mocha": "10.0.0", - "typescript": "4.3.5" + "typescript": "4.4.4" }, "dependencies": { - "@opentelemetry/instrumentation": "^0.32.0", + "@opentelemetry/instrumentation": "^0.38.0", "@opentelemetry/semantic-conventions": "^1.0.0", "@types/tedious": "^4.0.6" }, diff --git a/plugins/node/opentelemetry-instrumentation-aws-lambda/CHANGELOG.md b/plugins/node/opentelemetry-instrumentation-aws-lambda/CHANGELOG.md index f0661aaa96..360a1d4fac 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-lambda/CHANGELOG.md +++ b/plugins/node/opentelemetry-instrumentation-aws-lambda/CHANGELOG.md @@ -1,5 +1,45 @@ # Changelog +## [0.35.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-aws-lambda-v0.35.0...instrumentation-aws-lambda-v0.35.1) (2023-04-25) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.38.0 ([#1468](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1468)) ([565a2b2](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/565a2b2c6fde88af3f5401ef6a5a9643d0d66349)) + +## [0.35.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-aws-lambda-v0.34.1...instrumentation-aws-lambda-v0.35.0) (2023-02-08) + + +### Features + +* **instrumentation-lambda:** Flush MeterProvider at end of handler ([#1370](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1370)) ([096129c](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/096129c9c1b68c7f6cccbfab42f8d2167bc40927)) + + +### Bug Fixes + +* **instrumentation/aws-lambda:** Ensure callback is only called once ([#1384](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1384)) ([d822f75](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/d822f75e10d6d0421fe8fbd4b1dca261de736e69)) + +## [0.34.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-aws-lambda-v0.34.0...instrumentation-aws-lambda-v0.34.1) (2023-02-07) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.35.1 ([#1358](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1358)) ([ff109b7](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/ff109b77928cc9a139a21c63d6b54399bb017fa4)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @opentelemetry/propagator-aws-xray bumped from ^1.1.1 to ^1.2.0 + +## [0.34.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-aws-lambda-v0.33.1...instrumentation-aws-lambda-v0.34.0) (2022-11-16) + + +### Features + +* update experimental deps to `^0.34.0`, core deps to `^1.8.0`, api to `^1.3.0` ([#1278](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1278)) ([e9fe8e1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/e9fe8e13e34f54e96c50525cadeb74ac048c5624)) + ## [0.33.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-aws-lambda-v0.33.0...instrumentation-aws-lambda-v0.33.1) (2022-11-02) diff --git a/plugins/node/opentelemetry-instrumentation-aws-lambda/README.md b/plugins/node/opentelemetry-instrumentation-aws-lambda/README.md index 98cf98025e..22a6095920 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-lambda/README.md +++ b/plugins/node/opentelemetry-instrumentation-aws-lambda/README.md @@ -3,7 +3,7 @@ [![NPM Published Version][npm-img]][npm-url] [![Apache License][license-image]][license-image] -[component owners](https://github.com/open-telemetry/opentelemetry-js-contrib/blob/main/.github/component_owners.yml): @willarmiros +[component owners](https://github.com/open-telemetry/opentelemetry-js-contrib/blob/main/.github/component_owners.yml): @carolabadeer This module provides automatic instrumentation for the [`AWS Lambda`](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-handler.html) module, which may be loaded using the [`@opentelemetry/sdk-trace-node`](https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-sdk-trace-node) package and is included in the [`@opentelemetry/auto-instrumentations-node`](https://www.npmjs.com/package/@opentelemetry/auto-instrumentations-node) bundle. @@ -60,11 +60,11 @@ const { AwsLambdaInstrumentation } = require('@opentelemetry/instrumentation-aws new AwsLambdaInstrumentation({ requestHook: (span, { event, context }) => { - span.setAttributes('faas.name', context.functionName); + span.setAttribute('faas.name', context.functionName); }, responseHook: (span, { err, res }) => { - if (err instanceof Error) span.setAttributes('faas.error', err.message); - if (res) span.setAttributes('faas.res', res); + if (err instanceof Error) span.setAttribute('faas.error', err.message); + if (res) span.setAttribute('faas.res', res); } }) ``` diff --git a/plugins/node/opentelemetry-instrumentation-aws-lambda/package.json b/plugins/node/opentelemetry-instrumentation-aws-lambda/package.json index 322b7da82b..d1959d99ac 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-lambda/package.json +++ b/plugins/node/opentelemetry-instrumentation-aws-lambda/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/instrumentation-aws-lambda", - "version": "0.33.1", + "version": "0.35.1", "description": "OpenTelemetry AWS Lambda automatic instrumentation package.", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -42,26 +42,26 @@ "access": "public" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@opentelemetry/api": "^1.3.0" }, "devDependencies": { - "@opentelemetry/api": "^1.0.0", - "@opentelemetry/core": "^1.3.1", - "@opentelemetry/sdk-trace-base": "^1.3.1", - "@opentelemetry/sdk-trace-node": "^1.3.1", + "@opentelemetry/api": "^1.3.0", + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/sdk-trace-base": "^1.8.0", + "@opentelemetry/sdk-trace-node": "^1.8.0", + "@opentelemetry/sdk-metrics": "^1.8.0", "@types/mocha": "7.0.2", "@types/node": "18.11.7", - "gts": "3.1.0", "mocha": "7.2.0", "nyc": "15.1.0", - "rimraf": "3.0.2", + "rimraf": "4.2.0", "ts-mocha": "10.0.0", - "typescript": "4.3.5" + "typescript": "4.4.4" }, "dependencies": { - "@opentelemetry/instrumentation": "^0.32.0", - "@opentelemetry/propagator-aws-xray": "^1.1.1", - "@opentelemetry/resources": "^1.0.0", + "@opentelemetry/instrumentation": "^0.38.0", + "@opentelemetry/propagator-aws-xray": "^1.2.0", + "@opentelemetry/resources": "^1.8.0", "@opentelemetry/semantic-conventions": "^1.0.0", "@types/aws-lambda": "8.10.81" }, diff --git a/plugins/node/opentelemetry-instrumentation-aws-lambda/src/instrumentation.ts b/plugins/node/opentelemetry-instrumentation-aws-lambda/src/instrumentation.ts index 76d4410240..0110293ef7 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-lambda/src/instrumentation.ts +++ b/plugins/node/opentelemetry-instrumentation-aws-lambda/src/instrumentation.ts @@ -15,6 +15,7 @@ */ import * as path from 'path'; +import * as fs from 'fs'; import { InstrumentationBase, @@ -29,6 +30,7 @@ import { diag, trace, propagation, + MeterProvider, Span, SpanKind, SpanStatusCode, @@ -70,7 +72,8 @@ const headerGetter: TextMapGetter = { export const traceContextEnvironmentKey = '_X_AMZN_TRACE_ID'; export class AwsLambdaInstrumentation extends InstrumentationBase { - private _forceFlush?: () => Promise; + private _traceForceFlusher?: () => Promise; + private _metricForceFlusher?: () => Promise; constructor(protected override _config: AwsLambdaInstrumentationConfig = {}) { super('@opentelemetry/instrumentation-aws-lambda', VERSION, _config); @@ -97,8 +100,15 @@ export class AwsLambdaInstrumentation extends InstrumentationBase { // Lambda loads user function using an absolute path. let filename = path.resolve(taskRoot, moduleRoot, module); if (!filename.endsWith('.js')) { - // Patching infrastructure currently requires a filename when requiring with an absolute path. - filename += '.js'; + // its impossible to know in advance if the user has a cjs or js file. + // check that the .js file exists otherwise fallback to next known possibility + try { + fs.statSync(`${filename}.js`); + filename += '.js'; + } catch (e) { + // fallback to .cjs + filename += '.cjs'; + } } return [ @@ -226,10 +236,10 @@ export class AwsLambdaInstrumentation extends InstrumentationBase { override setTracerProvider(tracerProvider: TracerProvider) { super.setTracerProvider(tracerProvider); - this._forceFlush = this._getForceFlush(tracerProvider); + this._traceForceFlusher = this._traceForceFlush(tracerProvider); } - private _getForceFlush(tracerProvider: TracerProvider) { + private _traceForceFlush(tracerProvider: TracerProvider) { if (!tracerProvider) return undefined; // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -246,6 +256,24 @@ export class AwsLambdaInstrumentation extends InstrumentationBase { return undefined; } + override setMeterProvider(meterProvider: MeterProvider) { + super.setMeterProvider(meterProvider); + this._metricForceFlusher = this._metricForceFlush(meterProvider); + } + + private _metricForceFlush(meterProvider: MeterProvider) { + if (!meterProvider) return undefined; + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const currentProvider: any = meterProvider; + + if (typeof currentProvider.forceFlush === 'function') { + return currentProvider.forceFlush.bind(currentProvider); + } + + return undefined; + } + private _wrapCallback(original: Callback, span: Span): Callback { const plugin = this; return function wrappedCallback(this: never, err, res) { @@ -283,17 +311,23 @@ export class AwsLambdaInstrumentation extends InstrumentationBase { span.end(); - if (this._forceFlush) { - this._forceFlush().then( - () => callback(), - () => callback() - ); + const flushers = []; + if (this._traceForceFlusher) { + flushers.push(this._traceForceFlusher()); } else { diag.error( 'Spans may not be exported for the lambda function because we are not force flushing before callback.' ); - callback(); } + if (this._metricForceFlusher) { + flushers.push(this._metricForceFlusher()); + } else { + diag.error( + 'Metrics may not be exported for the lambda function because we are not force flushing before callback.' + ); + } + + Promise.all(flushers).then(callback, callback); } private _applyResponseHook( diff --git a/plugins/node/opentelemetry-instrumentation-aws-lambda/test/integrations/lambda-handler.force-flush.test.ts b/plugins/node/opentelemetry-instrumentation-aws-lambda/test/integrations/lambda-handler.force-flush.test.ts index e57e43f2f0..0a067dc758 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-lambda/test/integrations/lambda-handler.force-flush.test.ts +++ b/plugins/node/opentelemetry-instrumentation-aws-lambda/test/integrations/lambda-handler.force-flush.test.ts @@ -28,8 +28,17 @@ import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node'; import { Context } from 'aws-lambda'; import * as assert from 'assert'; import { ProxyTracerProvider, TracerProvider } from '@opentelemetry/api'; +import { + AggregationTemporality, + InMemoryMetricExporter, + MeterProvider, + PeriodicExportingMetricReader, +} from '@opentelemetry/sdk-metrics'; -const memoryExporter = new InMemorySpanExporter(); +const traceMemoryExporter = new InMemorySpanExporter(); +const metricMemoryExporter = new InMemoryMetricExporter( + AggregationTemporality.CUMULATIVE +); describe('force flush', () => { let instrumentation: AwsLambdaInstrumentation; @@ -42,13 +51,26 @@ describe('force flush', () => { awsRequestId: 'aws_request_id', } as Context; - const initializeHandler = (handler: string, provider: TracerProvider) => { + const initializeHandlerTracing = ( + handler: string, + provider: TracerProvider + ) => { process.env._HANDLER = handler; instrumentation = new AwsLambdaInstrumentation(); instrumentation.setTracerProvider(provider); }; + const initializeHandlerMetrics = ( + handler: string, + provider: MeterProvider + ) => { + process.env._HANDLER = handler; + + instrumentation = new AwsLambdaInstrumentation(); + instrumentation.setMeterProvider(provider); + }; + const lambdaRequire = (module: string) => require(path.resolve(__dirname, '..', module)); @@ -61,12 +83,13 @@ describe('force flush', () => { process.env = oldEnv; instrumentation.disable(); - memoryExporter.reset(); + traceMemoryExporter.reset(); + metricMemoryExporter.reset(); }); it('should force flush NodeTracerProvider', async () => { const provider = new NodeTracerProvider(); - provider.addSpanProcessor(new BatchSpanProcessor(memoryExporter)); + provider.addSpanProcessor(new BatchSpanProcessor(traceMemoryExporter)); provider.register(); let forceFlushed = false; const forceFlush = () => @@ -75,7 +98,7 @@ describe('force flush', () => { resolve(); }); provider.forceFlush = forceFlush; - initializeHandler('lambda-test/sync.handler', provider); + initializeHandlerTracing('lambda-test/sync.handler', provider); await new Promise((resolve, reject) => { lambdaRequire('lambda-test/sync').handler( @@ -96,7 +119,9 @@ describe('force flush', () => { it('should force flush ProxyTracerProvider with NodeTracerProvider', async () => { const nodeTracerProvider = new NodeTracerProvider(); - nodeTracerProvider.addSpanProcessor(new BatchSpanProcessor(memoryExporter)); + nodeTracerProvider.addSpanProcessor( + new BatchSpanProcessor(traceMemoryExporter) + ); nodeTracerProvider.register(); const provider = new ProxyTracerProvider(); provider.setDelegate(nodeTracerProvider); @@ -107,7 +132,7 @@ describe('force flush', () => { resolve(); }); nodeTracerProvider.forceFlush = forceFlush; - initializeHandler('lambda-test/sync.handler', provider); + initializeHandlerTracing('lambda-test/sync.handler', provider); await new Promise((resolve, reject) => { lambdaRequire('lambda-test/sync').handler( @@ -125,4 +150,90 @@ describe('force flush', () => { assert.strictEqual(forceFlushed, true); }); + + it('should force flush MeterProvider', async () => { + const provider = new MeterProvider(); + provider.addMetricReader( + new PeriodicExportingMetricReader({ exporter: metricMemoryExporter }) + ); + let forceFlushed = false; + const forceFlush = () => + new Promise(resolve => { + forceFlushed = true; + resolve(); + }); + provider.forceFlush = forceFlush; + initializeHandlerMetrics('lambda-test/sync.handler', provider); + + await new Promise((resolve, reject) => { + lambdaRequire('lambda-test/sync').handler( + 'arg', + ctx, + (err: Error, res: any) => { + if (err) { + reject(err); + } else { + resolve(res); + } + } + ); + }); + + assert.strictEqual(forceFlushed, true); + }); + + it('should callback once after force flush providers', async () => { + const nodeTracerProvider = new NodeTracerProvider(); + nodeTracerProvider.addSpanProcessor( + new BatchSpanProcessor(traceMemoryExporter) + ); + nodeTracerProvider.register(); + const tracerProvider = new ProxyTracerProvider(); + tracerProvider.setDelegate(nodeTracerProvider); + let tracerForceFlushed = false; + const tracerForceFlush = () => + new Promise(resolve => { + tracerForceFlushed = true; + resolve(); + }); + nodeTracerProvider.forceFlush = tracerForceFlush; + + const meterProvider = new MeterProvider(); + meterProvider.addMetricReader( + new PeriodicExportingMetricReader({ exporter: metricMemoryExporter }) + ); + let meterForceFlushed = false; + const meterForceFlush = () => + new Promise(resolve => { + meterForceFlushed = true; + resolve(); + }); + meterProvider.forceFlush = meterForceFlush; + + process.env._HANDLER = 'lambda-test/sync.handler'; + + instrumentation = new AwsLambdaInstrumentation(); + instrumentation.setTracerProvider(tracerProvider); + instrumentation.setMeterProvider(meterProvider); + + let callbackCount = 0; + await new Promise((resolve, reject) => { + lambdaRequire('lambda-test/sync').handler( + 'arg', + ctx, + (err: Error, res: any) => { + callbackCount++; + if (err) { + reject(err); + } else { + resolve(res); + } + } + ); + }); + + assert.strictEqual(tracerForceFlushed, true); + assert.strictEqual(meterForceFlushed, true); + assert.strictEqual(callbackCount, 1); + }); }); diff --git a/plugins/node/opentelemetry-instrumentation-aws-lambda/test/integrations/lambda-handler.test.ts b/plugins/node/opentelemetry-instrumentation-aws-lambda/test/integrations/lambda-handler.test.ts index cabb6d0f37..681922fbee 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-lambda/test/integrations/lambda-handler.test.ts +++ b/plugins/node/opentelemetry-instrumentation-aws-lambda/test/integrations/lambda-handler.test.ts @@ -51,9 +51,6 @@ import { AWSXRayPropagator } from '@opentelemetry/propagator-aws-xray'; import { W3CTraceContextPropagator } from '@opentelemetry/core'; const memoryExporter = new InMemorySpanExporter(); -const provider = new NodeTracerProvider(); -provider.addSpanProcessor(new BatchSpanProcessor(memoryExporter)); -provider.register(); const assertSpanSuccess = (span: ReadableSpan) => { assert.strictEqual(span.kind, SpanKind.SERVER); @@ -118,8 +115,14 @@ describe('lambda handler', () => { ) => { process.env._HANDLER = handler; + const provider = new NodeTracerProvider(); + provider.addSpanProcessor(new BatchSpanProcessor(memoryExporter)); + provider.register(); + instrumentation = new AwsLambdaInstrumentation(config); instrumentation.setTracerProvider(provider); + + return provider; }; const lambdaRequire = (module: string) => @@ -214,7 +217,7 @@ describe('lambda handler', () => { let err: Error; try { await lambdaRequire('lambda-test/async').error('arg', ctx); - } catch (e) { + } catch (e: any) { err = e; } assert.strictEqual(err!.message, 'handler error'); @@ -231,7 +234,7 @@ describe('lambda handler', () => { let err: string; try { await lambdaRequire('lambda-test/async').stringerror('arg', ctx); - } catch (e) { + } catch (e: any) { err = e; } assert.strictEqual(err!, 'handler error'); @@ -301,7 +304,7 @@ describe('lambda handler', () => { ctx, (err: Error, res: any) => {} ); - } catch (e) { + } catch (e: any) { err = e; } assert.strictEqual(err!.message, 'handler error'); @@ -330,7 +333,7 @@ describe('lambda handler', () => { } ); }); - } catch (e) { + } catch (e: any) { err = e; } assert.strictEqual(err!.message, 'handler error'); @@ -351,7 +354,7 @@ describe('lambda handler', () => { ctx, (err: Error, res: any) => {} ); - } catch (e) { + } catch (e: any) { err = e; } assert.strictEqual(err!, 'handler error'); @@ -423,7 +426,7 @@ describe('lambda handler', () => { } ); }); - } catch (e) { + } catch (e: any) { err = e; } assert.strictEqual(err!, 'handler error'); @@ -667,7 +670,7 @@ describe('lambda handler', () => { return propagation.extract(context.active(), event.contextCarrier); }; - initializeHandler('lambda-test/async.handler', { + const provider = initializeHandler('lambda-test/async.handler', { disableAwsContextPropagation: true, eventContextExtractor: customExtractor, }); @@ -806,7 +809,7 @@ describe('lambda handler', () => { let err: Error; try { await lambdaRequire('lambda-test/async').error('arg', ctx); - } catch (e) { + } catch (e: any) { err = e; } const [span] = memoryExporter.getFinishedSpans(); @@ -833,7 +836,7 @@ describe('lambda handler', () => { let err: Error; try { lambdaRequire('lambda-test/sync').error('arg', ctx, () => {}); - } catch (e) { + } catch (e: any) { err = e; } const [span] = memoryExporter.getFinishedSpans(); @@ -858,5 +861,21 @@ describe('lambda handler', () => { assert.strictEqual(span.attributes[ERR_ATTR], error!.message); }); }); + + describe('.cjs lambda bundle', () => { + it('should export a valid span', async () => { + initializeHandler('lambda-test/commonjs.handler'); + const result = await lambdaRequire('lambda-test/commonjs.cjs').handler( + 'arg', + ctx + ); + assert.strictEqual(result, 'ok'); + const spans = memoryExporter.getFinishedSpans(); + const [span] = spans; + assert.strictEqual(spans.length, 1); + assertSpanSuccess(span); + assert.strictEqual(span.parentSpanId, undefined); + }); + }); }); }); diff --git a/plugins/node/opentelemetry-instrumentation-aws-lambda/test/lambda-test/commonjs.cjs b/plugins/node/opentelemetry-instrumentation-aws-lambda/test/lambda-test/commonjs.cjs new file mode 100644 index 0000000000..3fc61adccf --- /dev/null +++ b/plugins/node/opentelemetry-instrumentation-aws-lambda/test/lambda-test/commonjs.cjs @@ -0,0 +1,3 @@ +exports.handler = async function (event, context) { + return "ok"; +}; \ No newline at end of file diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/.tav.yml b/plugins/node/opentelemetry-instrumentation-aws-sdk/.tav.yml index 4e23df61dc..d905375e40 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-sdk/.tav.yml +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/.tav.yml @@ -1,21 +1,21 @@ "aws-sdk": # there are so many version to test, it can take forever. # we will just sample few of them - versions: ">=2.1230.0 || 2.1219.0 || 2.1152.0 || 2.1048.0 || 2.1012.0 || 2.647.0 || 2.308.0" + versions: ">=2.1266.0 || 2.1262.0 || 2.1219.0 || 2.1048.0 || 2.1012.0 || 2.647.0 || 2.308.0" commands: - npm run test # Fix missing `contrib-test-utils` package pretest: npm run --prefix ../../../ lerna:link "@aws-sdk/client-s3": - versions: ">=3.188.0 || 3.154.0 || 3.107.0 || 3.54.0 || 3.6.1" + versions: ">=3.223.0 || 3.218.0 || 3.216.0 || 3.154.0 || 3.107.0 || 3.54.0 || 3.6.1" commands: - npm run test # Fix missing `contrib-test-utils` package pretest: npm run --prefix ../../../ lerna:link "@aws-sdk/client-sqs": - versions: ">=3.188.0 || 3.171.0 || 3.107.0 || 3.58.0 || 3.54.0 || 3.43.0 || 3.24.0" + versions: ">=3.216.0 || 3.171.0 || 3.58.0 || 3.54.0 || 3.43.0 || 3.24.0" commands: - npm run test # Fix missing `contrib-test-utils` package diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/CHANGELOG.md b/plugins/node/opentelemetry-instrumentation-aws-sdk/CHANGELOG.md index dd9c135621..0705b1ece4 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-sdk/CHANGELOG.md +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/CHANGELOG.md @@ -1,5 +1,82 @@ # Changelog +## [0.34.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-aws-sdk-v0.34.0...instrumentation-aws-sdk-v0.34.1) (2023-04-25) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.38.0 ([#1468](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1468)) ([565a2b2](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/565a2b2c6fde88af3f5401ef6a5a9643d0d66349)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @opentelemetry/propagation-utils bumped from ^0.29.2 to ^0.29.3 + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.1 to ^0.33.2 + +## [0.34.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-aws-sdk-v0.33.0...instrumentation-aws-sdk-v0.34.0) (2023-02-07) + + +### Features + +* add supported node versions for all packages ([#973](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/973)) ([baaacbd](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/baaacbdd35ca4baab0afae64647aa8c0380ee4b7)) +* AWS-SDK SNS Context propagation ([#728](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/728)) ([78cd4e1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/78cd4e118e5a41107d84dfd1ae8c4c28e885b27e)) +* **aws-sdk:** add http status code attribute to aws sdk span ([#844](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/844)) ([09b8555](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/09b8555007c3c05ad046dd67925f3640a7b35fbe)) +* **aws-sdk:** lambda client instrumentation ([#916](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/916)) ([dc6c2b5](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/dc6c2b5121977814f854b674ec3e519f689637c9)) +* config option to extract sqs context from message payload ([#737](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/737)) ([28e2113](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/28e2113ec1091e73a1d1b62b48fee8c01c72afee)) +* **instrumentation-aws-sdk:** upstream aws-sdk instrumentation from ext-js ([#678](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/678)) ([f5851e7](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/f5851e72512117dbce571a42930a90c560dbf63d)) +* update core dependencies stable ^1.3.1 experimental ^0.29.2 ([141b155](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/141b155e344980b51264e26b26c117b2113bcef6)) +* update experimental deps to `^0.34.0`, core deps to `^1.8.0`, api to `^1.3.0` ([#1278](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1278)) ([e9fe8e1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/e9fe8e13e34f54e96c50525cadeb74ac048c5624)) +* update experimental Otel deps to ^0.31.0 ([#1096](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1096)) ([4c8843b](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/4c8843be14896d1159a622c07eb3a049401ccba1)) +* update experimental Otel deps to ^0.32.0 ([#1143](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1143)) ([6fb1911](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/6fb191139aed2ca763300dcf9adb51121a88f97e)) +* upstream mocha instrumentation testing plugin from ext-js [#621](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/621) ([#669](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/669)) ([a5170c4](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/a5170c494706a2bec3ba51e59966d0ca8a41d00e)) +* use latest instrumentation base ([#769](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/769)) ([7aff23e](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/7aff23ebebbe209fa3b78c2e7f513c9cd2231be4)) +* use Otel SDK 1.2/0.28 ([#984](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/984)) ([098c2ed](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/098c2ed6f9c5ab7bd865685018c0777245aab3b7)) + + +### Bug Fixes + +* avoid type imports of the aws-sdk package in the built assets ([#1066](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1066)) ([457be50](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/457be5035b9ba87211fe3553c901b7408dd2d593)) +* **aws-sdk:** avoid repeating MessageAttributeNames in sqs receiveMessage ([#1044](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1044)) ([4b4ded6](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/4b4ded6e5b781b9a9cb2c55102ec0949da062511)) +* **aws-sdk:** bump aws-sdk instrumentation version to align with previous release ([#1247](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1247)) ([fd2480a](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/fd2480a4ea7b4093da523ecbc30743a55f38ab6c)) +* **aws-sdk:** calc propagation fields count before context inject ([#738](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/738)) ([033cc1f](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/033cc1f7ed09c33e401b9514ed30d1160cf58899)) +* **aws-sdk:** set spanKind to CLIENT by default in v3 ([#1177](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1177)) ([d463695](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/d463695f5258875f1da0c7b17c20f7df93494d4e)) +* **aws-sdk:** sns span name should be with low cardinality ([#841](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/841)) ([7032a33](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/7032a33b6eef331ab327ab57b9bd3a1aed361fb2)) +* **aws-sdk:** sns-sqs extract the correct context key from message payload ([#761](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/761)) ([e5cae76](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/e5cae76d90b5e6d2eb9c6cd5da984a07cdd5048c)) +* **deps:** update otel core experimental to ^0.35.1 ([#1358](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1358)) ([ff109b7](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/ff109b77928cc9a139a21c63d6b54399bb017fa4)) +* **instrumentation-aws-sdk:** sqs message id missing on send command ([#968](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/968)) ([8b36fe1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/8b36fe16abca0a6326d48e5a22fd9302f2936609)) +* **opentelemetry-instrumentation-aws-sdk:** error when ReturnConsumedCapacity is set to None ([#899](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/899)) ([e7ab4d0](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/e7ab4d056b6663f593b47af7c3e8014a72a963fe)) +* rename lerna's --include-filtered-dependencies option ([#817](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/817)) ([cf268e7](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/cf268e7a92b7800ad6dbec9ca77466f9ee03ee1a)) +* **sns-publish-test-v3:** add test for sns.publish for aws sdk v3 ([#1015](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1015)) ([0293d89](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/0293d897f789bdeb7b843f673be2c2dc62e16010)) +* use localhost for services in CI ([#816](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/816)) ([f497313](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/f4973133e86549bbca301983085cc67788a10acd)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @opentelemetry/propagation-utils bumped from ^0.29.1 to ^0.29.2 + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.0 to ^0.33.1 + +## [0.10.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-aws-sdk-v0.9.3...instrumentation-aws-sdk-v0.10.0) (2022-11-16) + + +### Features + +* update experimental deps to `^0.34.0`, core deps to `^1.8.0`, api to `^1.3.0` ([#1278](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1278)) ([e9fe8e1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/e9fe8e13e34f54e96c50525cadeb74ac048c5624)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @opentelemetry/propagation-utils bumped from ^0.29.0 to ^0.29.1 + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.32.0 to ^0.33.0 + ## [0.9.3](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-aws-sdk-v0.9.2...instrumentation-aws-sdk-v0.9.3) (2022-11-02) diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/README.md b/plugins/node/opentelemetry-instrumentation-aws-sdk/README.md index 6c6a49c893..63c7a4cd38 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-sdk/README.md +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/README.md @@ -3,7 +3,7 @@ [![NPM Published Version][npm-img]][npm-url] [![Apache License][license-image]][license-image] -[component owners](https://github.com/open-telemetry/opentelemetry-js-contrib/blob/main/.github/component_owners.yml): @willarmiros @blumamir +[component owners](https://github.com/open-telemetry/opentelemetry-js-contrib/blob/main/.github/component_owners.yml): @carolabadeer @blumamir This module provides automatic instrumentation for the [`aws-sdk` v2](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/) and [`@aws-sdk` v3](https://github.com/aws/aws-sdk-js-v3) modules, which may be loaded using the [`@opentelemetry/sdk-trace-node`](https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-sdk-trace-node) package and is included in the [`@opentelemetry/auto-instrumentations-node`](https://www.npmjs.com/package/@opentelemetry/auto-instrumentations-node) bundle. diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/package.json b/plugins/node/opentelemetry-instrumentation-aws-sdk/package.json index 88d956b078..d1714eebfe 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-sdk/package.json +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/instrumentation-aws-sdk", - "version": "0.9.3", + "version": "0.34.1", "description": "OpenTelemetry automatic instrumentation for the `aws-sdk` package", "keywords": [ "aws", @@ -43,13 +43,13 @@ "watch": "tsc -w" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@opentelemetry/api": "^1.3.0" }, "dependencies": { - "@opentelemetry/core": "^1.0.0", - "@opentelemetry/instrumentation": "^0.32.0", + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.38.0", "@opentelemetry/semantic-conventions": "^1.0.0", - "@opentelemetry/propagation-utils": "^0.29.0" + "@opentelemetry/propagation-utils": "^0.29.3" }, "devDependencies": { "@aws-sdk/client-dynamodb": "3.85.0", @@ -58,21 +58,20 @@ "@aws-sdk/client-sqs": "3.85.0", "@aws-sdk/client-sns": "3.85.0", "@aws-sdk/types": "3.78.0", - "@opentelemetry/api": "^1.0.0", - "@opentelemetry/contrib-test-utils": "^0.32.0", - "@opentelemetry/sdk-trace-base": "^1.3.1", + "@opentelemetry/api": "^1.3.0", + "@opentelemetry/contrib-test-utils": "^0.33.2", + "@opentelemetry/sdk-trace-base": "^1.8.0", "@types/mocha": "8.2.3", "@types/node": "18.11.7", "@types/sinon": "10.0.6", "aws-sdk": "2.1008.0", "eslint": "8.7.0", - "expect": "27.4.2", - "gts": "3.1.0", + "expect": "29.2.0", "mocha": "7.2.0", "nock": "13.2.1", "nyc": "15.1.0", - "rimraf": "3.0.2", - "sinon": "14.0.0", + "rimraf": "4.2.0", + "sinon": "15.0.1", "test-all-versions": "5.0.1", "ts-mocha": "10.0.0", "typescript": "4.3.4" diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/MessageAttributes.test.ts b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/MessageAttributes.test.ts index 77717b53c5..51d63442f0 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/MessageAttributes.test.ts +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/MessageAttributes.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import * as expect from 'expect'; +import { expect } from 'expect'; import { MAX_MESSAGE_ATTRIBUTES, contextSetter, diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/aws-sdk-v2.test.ts b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/aws-sdk-v2.test.ts index f40f80903b..0d7d8a8aea 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/aws-sdk-v2.test.ts +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/aws-sdk-v2.test.ts @@ -31,7 +31,7 @@ import { ReadableSpan } from '@opentelemetry/sdk-trace-base'; import { SpanStatusCode, Span, SpanKind } from '@opentelemetry/api'; import { AttributeNames } from '../src/enums'; import { mockV2AwsSend } from './testing-utils'; -import * as expect from 'expect'; +import { expect } from 'expect'; import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; describe('instrumentation-aws-sdk-v2', () => { diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/aws-sdk-v3.test.ts b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/aws-sdk-v3.test.ts index 8623b6e873..0fb17f7ffd 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/aws-sdk-v3.test.ts +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/aws-sdk-v3.test.ts @@ -47,7 +47,7 @@ import { SemanticAttributes, } from '@opentelemetry/semantic-conventions'; import { AttributeNames } from '../src/enums'; -import * as expect from 'expect'; +import { expect } from 'expect'; import * as fs from 'fs'; import * as nock from 'nock'; diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/dynamodb.test.ts b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/dynamodb.test.ts index 41b715770a..5ff0c2b0ab 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/dynamodb.test.ts +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/dynamodb.test.ts @@ -27,7 +27,7 @@ import { DbSystemValues, SemanticAttributes, } from '@opentelemetry/semantic-conventions'; -import * as expect from 'expect'; +import { expect } from 'expect'; import type { ConsumedCapacity as ConsumedCapacityV2 } from 'aws-sdk/clients/dynamodb'; import type { ConsumedCapacity as ConsumedCapacityV3 } from '@aws-sdk/client-dynamodb'; diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/lambda.test.ts b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/lambda.test.ts index 372ebc4e67..be3965a872 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/lambda.test.ts +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/lambda.test.ts @@ -27,7 +27,7 @@ import { SpanKind } from '@opentelemetry/api'; import { Lambda, InvocationType } from '@aws-sdk/client-lambda'; import { ClientRequest } from 'http'; import * as nock from 'nock'; -import * as expect from 'expect'; +import { expect } from 'expect'; process.env.AWS_ACCESS_KEY_ID = 'testing'; process.env.AWS_SECRET_ACCESS_KEY = 'testing'; diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/sns.test.ts b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/sns.test.ts index a930dba4a1..ce6ce9c885 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/sns.test.ts +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/sns.test.ts @@ -27,7 +27,7 @@ import * as fs from 'fs'; import * as nock from 'nock'; import { mockV2AwsSend } from './testing-utils'; -import * as expect from 'expect'; +import { expect } from 'expect'; import { ReadableSpan } from '@opentelemetry/sdk-trace-base'; import * as sinon from 'sinon'; import { diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/sqs.test.ts b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/sqs.test.ts index 901b4fca1d..e162fa57e8 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/sqs.test.ts +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/sqs.test.ts @@ -39,7 +39,7 @@ import { import { ReadableSpan } from '@opentelemetry/sdk-trace-base'; import { mockV2AwsSend } from './testing-utils'; import { Message } from 'aws-sdk/clients/sqs'; -import * as expect from 'expect'; +import { expect } from 'expect'; import * as sinon from 'sinon'; import * as messageAttributes from '../src/services/MessageAttributes'; import { AttributeNames } from '../src/enums'; diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/testing-utils.ts b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/testing-utils.ts index a08f3e1237..7ce6d373cc 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/testing-utils.ts +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/testing-utils.ts @@ -16,7 +16,7 @@ import { context } from '@opentelemetry/api'; import { isTracingSuppressed } from '@opentelemetry/core'; import { getInstrumentation } from '@opentelemetry/contrib-test-utils'; -import * as expect from 'expect'; +import { expect } from 'expect'; import * as AWS from 'aws-sdk'; // we want to mock the request object and trigger events on it's events emitter. diff --git a/plugins/node/opentelemetry-instrumentation-bunyan/CHANGELOG.md b/plugins/node/opentelemetry-instrumentation-bunyan/CHANGELOG.md index a73061831e..284b791f9d 100644 --- a/plugins/node/opentelemetry-instrumentation-bunyan/CHANGELOG.md +++ b/plugins/node/opentelemetry-instrumentation-bunyan/CHANGELOG.md @@ -1,5 +1,26 @@ # Changelog +## [0.31.2](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-bunyan-v0.31.1...instrumentation-bunyan-v0.31.2) (2023-04-25) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.38.0 ([#1468](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1468)) ([565a2b2](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/565a2b2c6fde88af3f5401ef6a5a9643d0d66349)) + +## [0.31.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-bunyan-v0.31.0...instrumentation-bunyan-v0.31.1) (2023-02-07) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.35.1 ([#1358](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1358)) ([ff109b7](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/ff109b77928cc9a139a21c63d6b54399bb017fa4)) + +## [0.31.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-bunyan-v0.30.1...instrumentation-bunyan-v0.31.0) (2022-11-16) + + +### Features + +* update experimental deps to `^0.34.0`, core deps to `^1.8.0`, api to `^1.3.0` ([#1278](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1278)) ([e9fe8e1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/e9fe8e13e34f54e96c50525cadeb74ac048c5624)) + ## [0.30.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-bunyan-v0.30.0...instrumentation-bunyan-v0.30.1) (2022-11-02) diff --git a/plugins/node/opentelemetry-instrumentation-bunyan/package.json b/plugins/node/opentelemetry-instrumentation-bunyan/package.json index 2bcb3981bc..6c3c66c7f1 100644 --- a/plugins/node/opentelemetry-instrumentation-bunyan/package.json +++ b/plugins/node/opentelemetry-instrumentation-bunyan/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/instrumentation-bunyan", - "version": "0.30.1", + "version": "0.31.2", "description": "OpenTelemetry instrumentation for bunyan", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -44,28 +44,27 @@ "access": "public" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@opentelemetry/api": "^1.3.0" }, "devDependencies": { - "@opentelemetry/api": "^1.0.0", - "@opentelemetry/context-async-hooks": "^1.3.1", - "@opentelemetry/sdk-trace-base": "^1.3.1", - "@opentelemetry/sdk-trace-node": "^1.3.1", + "@opentelemetry/api": "^1.3.0", + "@opentelemetry/context-async-hooks": "^1.8.0", + "@opentelemetry/sdk-trace-base": "^1.8.0", + "@opentelemetry/sdk-trace-node": "^1.8.0", "@types/mocha": "7.0.2", "@types/node": "18.11.7", "@types/sinon": "10.0.2", "bunyan": "1.8.15", - "gts": "3.1.0", "mocha": "7.2.0", "nyc": "15.1.0", - "rimraf": "3.0.2", - "sinon": "14.0.0", + "rimraf": "4.2.0", + "sinon": "15.0.1", "test-all-versions": "5.0.1", "ts-mocha": "10.0.0", - "typescript": "4.3.5" + "typescript": "4.4.4" }, "dependencies": { - "@opentelemetry/instrumentation": "^0.32.0", + "@opentelemetry/instrumentation": "^0.38.0", "@types/bunyan": "1.8.7" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-bunyan#readme" diff --git a/plugins/node/opentelemetry-instrumentation-cassandra/CHANGELOG.md b/plugins/node/opentelemetry-instrumentation-cassandra/CHANGELOG.md index a9f73fee48..ace63fe55e 100644 --- a/plugins/node/opentelemetry-instrumentation-cassandra/CHANGELOG.md +++ b/plugins/node/opentelemetry-instrumentation-cassandra/CHANGELOG.md @@ -1,5 +1,47 @@ # Changelog +## [0.32.2](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-cassandra-driver-v0.32.1...instrumentation-cassandra-driver-v0.32.2) (2023-04-25) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.38.0 ([#1468](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1468)) ([565a2b2](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/565a2b2c6fde88af3f5401ef6a5a9643d0d66349)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.1 to ^0.33.2 + +## [0.32.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-cassandra-driver-v0.32.0...instrumentation-cassandra-driver-v0.32.1) (2023-02-07) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.35.1 ([#1358](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1358)) ([ff109b7](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/ff109b77928cc9a139a21c63d6b54399bb017fa4)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.0 to ^0.33.1 + +## [0.32.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-cassandra-driver-v0.31.0...instrumentation-cassandra-driver-v0.32.0) (2022-11-16) + + +### Features + +* update experimental deps to `^0.34.0`, core deps to `^1.8.0`, api to `^1.3.0` ([#1278](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1278)) ([e9fe8e1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/e9fe8e13e34f54e96c50525cadeb74ac048c5624)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.32.0 to ^0.33.0 + ## [0.31.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-cassandra-driver-v0.30.0...instrumentation-cassandra-driver-v0.31.0) (2022-11-02) diff --git a/plugins/node/opentelemetry-instrumentation-cassandra/package.json b/plugins/node/opentelemetry-instrumentation-cassandra/package.json index c3173cadfb..20eedc419a 100644 --- a/plugins/node/opentelemetry-instrumentation-cassandra/package.json +++ b/plugins/node/opentelemetry-instrumentation-cassandra/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/instrumentation-cassandra-driver", - "version": "0.31.0", + "version": "0.32.2", "description": "OpenTelemetry instrumentation for cassandra-driver", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -43,29 +43,28 @@ "access": "public" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@opentelemetry/api": "^1.3.0" }, "devDependencies": { - "@opentelemetry/api": "^1.0.0", - "@opentelemetry/context-async-hooks": "^1.3.1", - "@opentelemetry/contrib-test-utils": "^0.32.0", - "@opentelemetry/sdk-trace-base": "^1.3.1", - "@opentelemetry/sdk-trace-node": "^1.3.1", + "@opentelemetry/api": "^1.3.0", + "@opentelemetry/context-async-hooks": "^1.8.0", + "@opentelemetry/contrib-test-utils": "^0.33.2", + "@opentelemetry/sdk-trace-base": "^1.8.0", + "@opentelemetry/sdk-trace-node": "^1.8.0", "@types/mocha": "7.0.2", "@types/node": "18.11.7", "@types/semver": "7.3.8", "@types/sinon": "10.0.2", "cassandra-driver": "4.6.3", - "gts": "3.1.0", "mocha": "7.2.0", "nyc": "15.1.0", - "rimraf": "3.0.2", - "sinon": "14.0.0", + "rimraf": "4.2.0", + "sinon": "15.0.1", "ts-mocha": "10.0.0", - "typescript": "4.3.5" + "typescript": "4.4.4" }, "dependencies": { - "@opentelemetry/instrumentation": "^0.32.0", + "@opentelemetry/instrumentation": "^0.38.0", "@opentelemetry/semantic-conventions": "^1.0.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-cassandra#readme" diff --git a/plugins/node/opentelemetry-instrumentation-cassandra/test/cassandra-driver.test.ts b/plugins/node/opentelemetry-instrumentation-cassandra/test/cassandra-driver.test.ts index bd696df85f..5be436877a 100644 --- a/plugins/node/opentelemetry-instrumentation-cassandra/test/cassandra-driver.test.ts +++ b/plugins/node/opentelemetry-instrumentation-cassandra/test/cassandra-driver.test.ts @@ -109,6 +109,7 @@ function assertErrorSpan( const events = [ { name: 'exception', + droppedAttributesCount: 0, attributes: { [SemanticAttributes.EXCEPTION_STACKTRACE]: error.stack, [SemanticAttributes.EXCEPTION_MESSAGE]: error.message, @@ -204,7 +205,7 @@ describe('CassandraDriverInstrumentation', () => { it('creates an error span', async () => { try { await client.execute('selec * from'); - } catch (e) { + } catch (e: any) { assertErrorSpan('cassandra-driver.execute', e); return; } @@ -322,7 +323,7 @@ describe('CassandraDriverInstrumentation', () => { const query = 'insert into foobar'; try { await client.batch([query]); - } catch (e) { + } catch (e: any) { assertErrorSpan('cassandra-driver.batch', e); return; } diff --git a/plugins/node/opentelemetry-instrumentation-connect/CHANGELOG.md b/plugins/node/opentelemetry-instrumentation-connect/CHANGELOG.md index 8551fe1108..7bb82f0c85 100644 --- a/plugins/node/opentelemetry-instrumentation-connect/CHANGELOG.md +++ b/plugins/node/opentelemetry-instrumentation-connect/CHANGELOG.md @@ -1,5 +1,26 @@ # Changelog +## [0.31.2](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-connect-v0.31.1...instrumentation-connect-v0.31.2) (2023-04-25) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.38.0 ([#1468](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1468)) ([565a2b2](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/565a2b2c6fde88af3f5401ef6a5a9643d0d66349)) + +## [0.31.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-connect-v0.31.0...instrumentation-connect-v0.31.1) (2023-02-07) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.35.1 ([#1358](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1358)) ([ff109b7](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/ff109b77928cc9a139a21c63d6b54399bb017fa4)) + +## [0.31.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-connect-v0.30.1...instrumentation-connect-v0.31.0) (2022-11-16) + + +### Features + +* update experimental deps to `^0.34.0`, core deps to `^1.8.0`, api to `^1.3.0` ([#1278](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1278)) ([e9fe8e1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/e9fe8e13e34f54e96c50525cadeb74ac048c5624)) + ## [0.30.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-connect-v0.30.0...instrumentation-connect-v0.30.1) (2022-11-02) diff --git a/plugins/node/opentelemetry-instrumentation-connect/package.json b/plugins/node/opentelemetry-instrumentation-connect/package.json index 90b059495b..ebd9f11bcb 100644 --- a/plugins/node/opentelemetry-instrumentation-connect/package.json +++ b/plugins/node/opentelemetry-instrumentation-connect/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/instrumentation-connect", - "version": "0.30.1", + "version": "0.31.2", "description": "OpenTelemetry connect automatic instrumentation package.", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -41,26 +41,25 @@ "access": "public" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@opentelemetry/api": "^1.3.0" }, "devDependencies": { - "@opentelemetry/api": "^1.0.0", - "@opentelemetry/context-async-hooks": "^1.3.1", - "@opentelemetry/sdk-trace-base": "^1.3.1", - "@opentelemetry/sdk-trace-node": "^1.3.1", + "@opentelemetry/api": "^1.3.0", + "@opentelemetry/context-async-hooks": "^1.8.0", + "@opentelemetry/sdk-trace-base": "^1.8.0", + "@opentelemetry/sdk-trace-node": "^1.8.0", "@types/mocha": "7.0.2", "@types/node": "18.11.7", "connect": "3.7.0", - "gts": "3.1.0", "mocha": "7.2.0", "nyc": "15.1.0", - "rimraf": "3.0.2", + "rimraf": "4.2.0", "ts-mocha": "10.0.0", - "typescript": "4.3.5" + "typescript": "4.4.4" }, "dependencies": { - "@opentelemetry/core": "^1.0.0", - "@opentelemetry/instrumentation": "^0.32.0", + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.38.0", "@opentelemetry/semantic-conventions": "^1.0.0", "@types/connect": "3.4.35" }, diff --git a/plugins/node/opentelemetry-instrumentation-dns/CHANGELOG.md b/plugins/node/opentelemetry-instrumentation-dns/CHANGELOG.md index b278c4b9ca..2bb4d8a55f 100644 --- a/plugins/node/opentelemetry-instrumentation-dns/CHANGELOG.md +++ b/plugins/node/opentelemetry-instrumentation-dns/CHANGELOG.md @@ -1,5 +1,33 @@ # Changelog +## [0.31.3](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-dns-v0.31.2...instrumentation-dns-v0.31.3) (2023-04-25) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.38.0 ([#1468](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1468)) ([565a2b2](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/565a2b2c6fde88af3f5401ef6a5a9643d0d66349)) + +## [0.31.2](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-dns-v0.31.1...instrumentation-dns-v0.31.2) (2023-02-14) + + +### Bug Fixes + +* **instrumentation-dns:** fix instrumentation of `dns/promises` ([#1377](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1377)) ([6d08157](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/6d08157300faf418e886315384e6b705a0e13683)) + +## [0.31.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-dns-v0.31.0...instrumentation-dns-v0.31.1) (2023-02-07) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.35.1 ([#1358](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1358)) ([ff109b7](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/ff109b77928cc9a139a21c63d6b54399bb017fa4)) + +## [0.31.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-dns-v0.30.1...instrumentation-dns-v0.31.0) (2022-11-16) + + +### Features + +* update experimental deps to `^0.34.0`, core deps to `^1.8.0`, api to `^1.3.0` ([#1278](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1278)) ([e9fe8e1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/e9fe8e13e34f54e96c50525cadeb74ac048c5624)) + ## [0.30.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-dns-v0.30.0...instrumentation-dns-v0.30.1) (2022-11-02) diff --git a/plugins/node/opentelemetry-instrumentation-dns/package.json b/plugins/node/opentelemetry-instrumentation-dns/package.json index 915a17c704..7b5f5d7ff7 100644 --- a/plugins/node/opentelemetry-instrumentation-dns/package.json +++ b/plugins/node/opentelemetry-instrumentation-dns/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/instrumentation-dns", - "version": "0.30.1", + "version": "0.31.3", "description": "OpenTelemetry dns automatic instrumentation package.", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -42,28 +42,27 @@ "access": "public" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@opentelemetry/api": "^1.3.0" }, "devDependencies": { - "@opentelemetry/api": "^1.0.0", - "@opentelemetry/core": "^1.3.1", - "@opentelemetry/sdk-trace-base": "^1.3.1", - "@opentelemetry/sdk-trace-node": "^1.3.1", + "@opentelemetry/api": "^1.3.0", + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/sdk-trace-base": "^1.8.0", + "@opentelemetry/sdk-trace-node": "^1.8.0", "@types/mocha": "7.0.2", "@types/node": "18.11.7", "@types/semver": "7.3.8", "@types/shimmer": "1.0.2", "@types/sinon": "10.0.2", - "gts": "3.1.0", "mocha": "7.2.0", "nyc": "15.1.0", - "rimraf": "3.0.2", - "sinon": "14.0.0", + "rimraf": "4.2.0", + "sinon": "15.0.1", "ts-mocha": "10.0.0", - "typescript": "4.3.5" + "typescript": "4.4.4" }, "dependencies": { - "@opentelemetry/instrumentation": "^0.32.0", + "@opentelemetry/instrumentation": "^0.38.0", "@opentelemetry/semantic-conventions": "^1.0.0", "semver": "^7.3.2" }, diff --git a/plugins/node/opentelemetry-instrumentation-dns/src/enums/AttributeNames.ts b/plugins/node/opentelemetry-instrumentation-dns/src/enums/AttributeNames.ts index 2364b3769c..81bf053fad 100644 --- a/plugins/node/opentelemetry-instrumentation-dns/src/enums/AttributeNames.ts +++ b/plugins/node/opentelemetry-instrumentation-dns/src/enums/AttributeNames.ts @@ -15,7 +15,6 @@ */ export enum AttributeNames { // NOT ON OFFICIAL SPEC - DNS_ERROR_CODE = 'dns.error_code', DNS_ERROR_NAME = 'dns.error_name', DNS_ERROR_MESSAGE = 'dns.error_message', } diff --git a/plugins/node/opentelemetry-instrumentation-dns/src/instrumentation.ts b/plugins/node/opentelemetry-instrumentation-dns/src/instrumentation.ts index 9a057ca0bd..319a27e1c1 100644 --- a/plugins/node/opentelemetry-instrumentation-dns/src/instrumentation.ts +++ b/plugins/node/opentelemetry-instrumentation-dns/src/instrumentation.ts @@ -22,13 +22,13 @@ import { isWrapped, safeExecuteInTheMiddle, } from '@opentelemetry/instrumentation'; -import * as semver from 'semver'; import { AddressFamily } from './enums/AddressFamily'; import { DnsInstrumentationConfig } from './types'; import * as utils from './utils'; import { VERSION } from './version'; import { Dns, + DnsPromises, LookupCallbackSignature, LookupPromiseSignature, } from './internal-types'; @@ -41,7 +41,10 @@ export class DnsInstrumentation extends InstrumentationBase { super('@opentelemetry/instrumentation-dns', VERSION, _config); } - init(): InstrumentationNodeModuleDefinition[] { + init(): ( + | InstrumentationNodeModuleDefinition + | InstrumentationNodeModuleDefinition + )[] { return [ new InstrumentationNodeModuleDefinition( 'dns', @@ -53,25 +56,37 @@ export class DnsInstrumentation extends InstrumentationBase { } // eslint-disable-next-line @typescript-eslint/no-explicit-any this._wrap(moduleExports, 'lookup', this._getLookup() as any); - // new promise methods in node >= 10.6.0 - // https://nodejs.org/docs/latest/api/dns.html#dns_dnspromises_lookup_hostname_options - if (semver.gte(process.version, '10.6.0')) { - this._wrap( - moduleExports.promises, - 'lookup', - // eslint-disable-next-line @typescript-eslint/no-explicit-any - this._getLookup() as any - ); - } + this._wrap( + moduleExports.promises, + 'lookup', + // eslint-disable-next-line @typescript-eslint/no-explicit-any + this._getLookup() as any + ); return moduleExports; }, moduleExports => { if (moduleExports === undefined) return; diag.debug('Removing patch for dns'); this._unwrap(moduleExports, 'lookup'); - if (semver.gte(process.version, '10.6.0')) { - this._unwrap(moduleExports.promises, 'lookup'); + this._unwrap(moduleExports.promises, 'lookup'); + } + ), + new InstrumentationNodeModuleDefinition( + 'dns/promises', + ['*'], + moduleExports => { + diag.debug('Applying patch for dns/promises'); + if (isWrapped(moduleExports.lookup)) { + this._unwrap(moduleExports, 'lookup'); } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + this._wrap(moduleExports, 'lookup', this._getLookup() as any); + return moduleExports; + }, + moduleExports => { + if (moduleExports === undefined) return; + diag.debug('Removing patch for dns/promises'); + this._unwrap(moduleExports, 'lookup'); } ), ]; @@ -124,7 +139,7 @@ export class DnsInstrumentation extends InstrumentationBase { () => original.apply(this, [hostname, ...args]), error => { if (error != null) { - utils.setError(error, span, process.version); + utils.setError(error, span); span.end(); } } @@ -138,7 +153,7 @@ export class DnsInstrumentation extends InstrumentationBase { ]), error => { if (error != null) { - utils.setError(error, span, process.version); + utils.setError(error, span); span.end(); } } @@ -149,7 +164,7 @@ export class DnsInstrumentation extends InstrumentationBase { span.end(); }, (e: NodeJS.ErrnoException) => { - utils.setError(e, span, process.version); + utils.setError(e, span); span.end(); } ); @@ -175,7 +190,7 @@ export class DnsInstrumentation extends InstrumentationBase { diag.debug('executing wrapped lookup callback function'); if (err !== null) { - utils.setError(err, span, process.version); + utils.setError(err, span); } else { utils.setLookupAttributes(span, address, family); } diff --git a/plugins/node/opentelemetry-instrumentation-dns/src/internal-types.ts b/plugins/node/opentelemetry-instrumentation-dns/src/internal-types.ts index e3ae4e0f55..26638ba1a7 100644 --- a/plugins/node/opentelemetry-instrumentation-dns/src/internal-types.ts +++ b/plugins/node/opentelemetry-instrumentation-dns/src/internal-types.ts @@ -15,8 +15,10 @@ */ import type * as dns from 'dns'; +import type * as dnsPromises from 'dns/promises'; export type Dns = typeof dns; +export type DnsPromises = typeof dnsPromises; export type LookupFunction = (( hostname: string, diff --git a/plugins/node/opentelemetry-instrumentation-dns/src/utils.ts b/plugins/node/opentelemetry-instrumentation-dns/src/utils.ts index 3d620d65ef..9fae671bca 100644 --- a/plugins/node/opentelemetry-instrumentation-dns/src/utils.ts +++ b/plugins/node/opentelemetry-instrumentation-dns/src/utils.ts @@ -26,21 +26,13 @@ import { IgnoreMatcher } from './types'; * @param span the span to be set * @param nodeVersion the node version */ -export const setError = ( - err: NodeJS.ErrnoException, - span: Span, - nodeVersion: string -) => { - const { code, message, name } = err; +export const setError = (err: NodeJS.ErrnoException, span: Span) => { + const { message, name } = err; const attributes = { [AttributeNames.DNS_ERROR_MESSAGE]: message, [AttributeNames.DNS_ERROR_NAME]: name, } as SpanAttributes; - if (nodeVersion.startsWith('v12')) { - attributes[AttributeNames.DNS_ERROR_CODE] = code!; - } - span.setAttributes(attributes); span.setStatus({ @@ -146,7 +138,7 @@ export const isIgnored = ( return true; } } - } catch (e) { + } catch (e: any) { if (onException) { onException(e); } diff --git a/plugins/node/opentelemetry-instrumentation-dns/test/functionals/utils.test.ts b/plugins/node/opentelemetry-instrumentation-dns/test/functionals/utils.test.ts index 51d92e8b96..c995ca0261 100644 --- a/plugins/node/opentelemetry-instrumentation-dns/test/functionals/utils.test.ts +++ b/plugins/node/opentelemetry-instrumentation-dns/test/functionals/utils.test.ts @@ -154,7 +154,7 @@ describe('Utility', () => { { spanId: '', traceId: '', traceFlags: TraceFlags.NONE }, SpanKind.INTERNAL ); - utils.setError(new Error(errorMessage), span, process.versions.node); + utils.setError(new Error(errorMessage), span); const attributes = span.attributes; assert.strictEqual( attributes[AttributeNames.DNS_ERROR_MESSAGE], diff --git a/plugins/node/opentelemetry-instrumentation-dns/test/integrations/dns-lookup.test.ts b/plugins/node/opentelemetry-instrumentation-dns/test/integrations/dns-lookup.test.ts index 8bd5ad698a..2aa4c20985 100644 --- a/plugins/node/opentelemetry-instrumentation-dns/test/integrations/dns-lookup.test.ts +++ b/plugins/node/opentelemetry-instrumentation-dns/test/integrations/dns-lookup.test.ts @@ -130,7 +130,7 @@ describe('dns.lookup()', () => { try { dns.lookup(hostname, -1, () => {}); assert.fail(); - } catch (error) { + } catch (error: any) { const spans = memoryExporter.getFinishedSpans(); const [span] = spans; assert.strictEqual(spans.length, 1); @@ -151,7 +151,7 @@ describe('dns.lookup()', () => { // tslint:disable-next-line:no-any dns.lookup(hostname as any, 4, () => {}); assert.fail(); - } catch (error) { + } catch (error: any) { const spans = memoryExporter.getFinishedSpans(); const [span] = spans; assert.strictEqual(spans.length, 1); diff --git a/plugins/node/opentelemetry-instrumentation-dns/test/integrations/dns-slash-promises-lookup.test.ts b/plugins/node/opentelemetry-instrumentation-dns/test/integrations/dns-slash-promises-lookup.test.ts new file mode 100644 index 0000000000..7489e25153 --- /dev/null +++ b/plugins/node/opentelemetry-instrumentation-dns/test/integrations/dns-slash-promises-lookup.test.ts @@ -0,0 +1,223 @@ +/* + * 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 { + InMemorySpanExporter, + SimpleSpanProcessor, +} from '@opentelemetry/sdk-trace-base'; +import * as assert from 'assert'; +import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node'; +import { DnsInstrumentation } from '../../src'; +import type * as DnsPromisesType from 'dns/promises'; +import * as utils from '../utils/utils'; +import { assertSpan } from '../utils/assertSpan'; +import { SpanStatusCode } from '@opentelemetry/api'; + +const memoryExporter = new InMemorySpanExporter(); +const provider = new NodeTracerProvider(); +provider.addSpanProcessor(new SimpleSpanProcessor(memoryExporter)); + +const supportsPromises = + parseInt(process.versions.node.split('.')[0], 10) >= 15; + +if (supportsPromises) { + describe('dns/promises.lookup()', () => { + let instrumentation: DnsInstrumentation; + let dnsPromises: typeof DnsPromisesType; + + before(function (done) { + // if node version is supported, it's mandatory for CI + if (process.env.CI) { + instrumentation = new DnsInstrumentation(); + instrumentation.setTracerProvider(provider); + dnsPromises = require('dns/promises'); + done(); + return; + } + + utils.checkInternet(isConnected => { + if (!isConnected) { + this.skip(); + // don't disturb people + } + done(); + }); + instrumentation = new DnsInstrumentation(); + instrumentation.setTracerProvider(provider); + dnsPromises = require('dns/promises'); + }); + + afterEach(() => { + memoryExporter.reset(); + }); + + after(() => { + instrumentation.disable(); + }); + + describe('with family param', () => { + [4, 6].forEach(ipversion => { + it(`should export a valid span with "family" arg to ${ipversion}`, async () => { + const hostname = 'google.com'; + const { address, family } = await dnsPromises.lookup(hostname, { + family: ipversion, + }); + assert.ok(address); + assert.ok(family); + + const spans = memoryExporter.getFinishedSpans(); + const [span] = spans; + assert.strictEqual(spans.length, 1); + assertSpan(span, { addresses: [{ address, family }], hostname }); + }); + }); + }); + + describe('with no options param', () => { + it('should export a valid span', async () => { + const hostname = 'google.com'; + const { address, family } = await dnsPromises.lookup(hostname); + + assert.ok(address); + assert.ok(family); + + const spans = memoryExporter.getFinishedSpans(); + const [span] = spans; + assert.strictEqual(spans.length, 1); + assertSpan(span, { addresses: [{ address, family }], hostname }); + }); + + describe('extended timeout', function () { + // Extending the default timeout as some environments are taking longer than 2 seconds to fail + // So rather than fail the test -- just take a little longer + this.timeout(10000); + + it('should export a valid span with error NOT_FOUND', async () => { + const hostname = 'áš•'; + try { + await dnsPromises.lookup(hostname); + assert.fail(); + } catch (error: any) { + const spans = memoryExporter.getFinishedSpans(); + const [span] = spans; + + assert.strictEqual(spans.length, 1); + assertSpan(span, { + addresses: [], + hostname, + forceStatus: { + code: SpanStatusCode.ERROR, + message: error!.message, + }, + }); + } + }); + }); + + it('should export a valid span with error INVALID_ARGUMENT when "family" param is equal to -1', async () => { + const hostname = 'google.com'; + try { + await dnsPromises.lookup(hostname, { family: -1 }); + assert.fail(); + } catch (error: any) { + const spans = memoryExporter.getFinishedSpans(); + const [span] = spans; + + assert.strictEqual(spans.length, 1); + assertSpan(span, { + addresses: [], + // tslint:disable-next-line:no-any + hostname: hostname as any, + forceStatus: { + code: SpanStatusCode.ERROR, + message: error!.message, + }, + }); + } + }); + + it('should export a valid span with error INVALID_ARGUMENT when "hostname" param is a number', async () => { + const hostname = 1234; + try { + await dnsPromises.lookup(hostname as any, { family: 4 }); + assert.fail(); + } catch (error: any) { + const spans = memoryExporter.getFinishedSpans(); + const [span] = spans; + + assert.strictEqual(spans.length, 1); + assertSpan(span, { + addresses: [], + // tslint:disable-next-line:no-any + hostname: hostname as any, + forceStatus: { + code: SpanStatusCode.ERROR, + message: error!.message, + }, + }); + } + }); + }); + describe('with options param', () => { + [4, 6].forEach(ipversion => { + it(`should export a valid span with "family" to ${ipversion}`, async () => { + const hostname = 'google.com'; + const { address, family } = await dnsPromises.lookup(hostname, { + family: ipversion, + }); + + assert.ok(address); + assert.ok(family); + + const spans = memoryExporter.getFinishedSpans(); + const [span] = spans; + assert.strictEqual(spans.length, 1); + + assertSpan(span, { addresses: [{ address, family }], hostname }); + }); + + it(`should export a valid span when setting "verbatim" property to true and "family" to ${ipversion}`, async () => { + const hostname = 'google.com'; + const { address, family } = await dnsPromises.lookup(hostname, { + family: ipversion, + verbatim: true, + }); + + assert.ok(address); + assert.ok(family); + + const spans = memoryExporter.getFinishedSpans(); + const [span] = spans; + assert.strictEqual(spans.length, 1); + + assertSpan(span, { addresses: [{ address, family }], hostname }); + }); + }); + + it('should export a valid span when setting "all" property to true', async () => { + const hostname = 'montreal.ca'; + const addresses = await dnsPromises.lookup(hostname, { all: true }); + + assert.ok(addresses instanceof Array); + + const spans = memoryExporter.getFinishedSpans(); + const [span] = spans; + assert.strictEqual(spans.length, 1); + assertSpan(span, { addresses, hostname }); + }); + }); + }); +} diff --git a/plugins/node/opentelemetry-instrumentation-dns/test/integrations/dnspromise-lookup.test.ts b/plugins/node/opentelemetry-instrumentation-dns/test/integrations/dnspromise-lookup.test.ts index 73e19f40e1..1338f43bac 100644 --- a/plugins/node/opentelemetry-instrumentation-dns/test/integrations/dnspromise-lookup.test.ts +++ b/plugins/node/opentelemetry-instrumentation-dns/test/integrations/dnspromise-lookup.test.ts @@ -105,7 +105,7 @@ describe('dns.promises.lookup()', () => { try { await dns.promises.lookup(hostname); assert.fail(); - } catch (error) { + } catch (error: any) { const spans = memoryExporter.getFinishedSpans(); const [span] = spans; @@ -127,7 +127,7 @@ describe('dns.promises.lookup()', () => { try { await dns.promises.lookup(hostname, { family: -1 }); assert.fail(); - } catch (error) { + } catch (error: any) { const spans = memoryExporter.getFinishedSpans(); const [span] = spans; @@ -149,7 +149,7 @@ describe('dns.promises.lookup()', () => { try { await dns.promises.lookup(hostname as any, { family: 4 }); assert.fail(); - } catch (error) { + } catch (error: any) { const spans = memoryExporter.getFinishedSpans(); const [span] = spans; diff --git a/plugins/node/opentelemetry-instrumentation-express/CHANGELOG.md b/plugins/node/opentelemetry-instrumentation-express/CHANGELOG.md index 1b3a87942b..fc1e4ef374 100644 --- a/plugins/node/opentelemetry-instrumentation-express/CHANGELOG.md +++ b/plugins/node/opentelemetry-instrumentation-express/CHANGELOG.md @@ -1,5 +1,26 @@ # Changelog +## [0.32.2](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-express-v0.32.1...instrumentation-express-v0.32.2) (2023-04-25) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.38.0 ([#1468](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1468)) ([565a2b2](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/565a2b2c6fde88af3f5401ef6a5a9643d0d66349)) + +## [0.32.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-express-v0.32.0...instrumentation-express-v0.32.1) (2023-02-07) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.35.1 ([#1358](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1358)) ([ff109b7](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/ff109b77928cc9a139a21c63d6b54399bb017fa4)) + +## [0.32.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-express-v0.31.3...instrumentation-express-v0.32.0) (2022-11-16) + + +### Features + +* update experimental deps to `^0.34.0`, core deps to `^1.8.0`, api to `^1.3.0` ([#1278](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1278)) ([e9fe8e1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/e9fe8e13e34f54e96c50525cadeb74ac048c5624)) + ## [0.31.3](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-express-v0.31.2...instrumentation-express-v0.31.3) (2022-11-02) diff --git a/plugins/node/opentelemetry-instrumentation-express/examples/package.json b/plugins/node/opentelemetry-instrumentation-express/examples/package.json index d9881839a1..e2d5cc1eaf 100644 --- a/plugins/node/opentelemetry-instrumentation-express/examples/package.json +++ b/plugins/node/opentelemetry-instrumentation-express/examples/package.json @@ -32,9 +32,9 @@ "@opentelemetry/api": "^1.0.0", "@opentelemetry/exporter-jaeger": "^1.0.0", "@opentelemetry/exporter-zipkin": "^1.0.0", - "@opentelemetry/instrumentation": "^0.32.0", + "@opentelemetry/instrumentation": "^0.38.0", "@opentelemetry/instrumentation-express": "0.28.0", - "@opentelemetry/instrumentation-http": "^0.32.0", + "@opentelemetry/instrumentation-http": "^0.38.0", "@opentelemetry/resources": "^1.0.0", "@opentelemetry/sdk-trace-base": "^1.0.0", "@opentelemetry/sdk-trace-node": "^1.0.0", @@ -47,6 +47,6 @@ "devDependencies": { "@types/express": "^4.17.13", "ts-node": "^10.6.0", - "typescript": "4.3.5" + "typescript": "4.4.4" } } diff --git a/plugins/node/opentelemetry-instrumentation-express/package.json b/plugins/node/opentelemetry-instrumentation-express/package.json index 9e9ec55e6e..1db32213b7 100644 --- a/plugins/node/opentelemetry-instrumentation-express/package.json +++ b/plugins/node/opentelemetry-instrumentation-express/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/instrumentation-express", - "version": "0.31.3", + "version": "0.32.2", "description": "OpenTelemetry express automatic instrumentation package.", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -45,29 +45,28 @@ "access": "public" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@opentelemetry/api": "^1.3.0" }, "devDependencies": { - "@opentelemetry/api": "^1.0.0", - "@opentelemetry/context-async-hooks": "^1.3.1", - "@opentelemetry/sdk-trace-base": "^1.3.1", - "@opentelemetry/sdk-trace-node": "^1.3.1", + "@opentelemetry/api": "^1.3.0", + "@opentelemetry/context-async-hooks": "^1.8.0", + "@opentelemetry/sdk-trace-base": "^1.8.0", + "@opentelemetry/sdk-trace-node": "^1.8.0", "@types/mocha": "7.0.2", "@types/node": "18.11.7", "@types/sinon": "10.0.9", - "express": "4.17.1", - "gts": "3.1.0", + "express": "4.17.3", "mocha": "7.2.0", "nyc": "15.1.0", - "rimraf": "3.0.2", - "sinon": "14.0.0", + "rimraf": "4.2.0", + "sinon": "15.0.1", "test-all-versions": "5.0.1", "ts-mocha": "10.0.0", - "typescript": "4.3.5" + "typescript": "4.4.4" }, "dependencies": { - "@opentelemetry/core": "^1.0.0", - "@opentelemetry/instrumentation": "^0.32.0", + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.38.0", "@opentelemetry/semantic-conventions": "^1.0.0", "@types/express": "4.17.13" }, diff --git a/plugins/node/opentelemetry-instrumentation-fastify/CHANGELOG.md b/plugins/node/opentelemetry-instrumentation-fastify/CHANGELOG.md index e3e13b0fe2..a4fef65d38 100644 --- a/plugins/node/opentelemetry-instrumentation-fastify/CHANGELOG.md +++ b/plugins/node/opentelemetry-instrumentation-fastify/CHANGELOG.md @@ -1,5 +1,32 @@ # Changelog +## [0.31.2](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-fastify-v0.31.1...instrumentation-fastify-v0.31.2) (2023-04-25) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.38.0 ([#1468](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1468)) ([565a2b2](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/565a2b2c6fde88af3f5401ef6a5a9643d0d66349)) + +## [0.31.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-fastify-v0.31.0...instrumentation-fastify-v0.31.1) (2023-02-07) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.35.1 ([#1358](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1358)) ([ff109b7](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/ff109b77928cc9a139a21c63d6b54399bb017fa4)) + +## [0.31.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-fastify-v0.30.1...instrumentation-fastify-v0.31.0) (2022-11-16) + + +### Features + +* **fastify:** add requestHook support ([#1255](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1255)) ([c9923e3](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/c9923e3636649c67e5122531f164909b48dbb58d)) +* update experimental deps to `^0.34.0`, core deps to `^1.8.0`, api to `^1.3.0` ([#1278](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1278)) ([e9fe8e1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/e9fe8e13e34f54e96c50525cadeb74ac048c5624)) + + +### Bug Fixes + +* **instrumentation-fastify:** stop using fastify types in public api ([#1267](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1267)) ([40515c3](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/40515c3dca81d1c177d71af2663fce3b8813bbf2)) + ## [0.30.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-fastify-v0.30.0...instrumentation-fastify-v0.30.1) (2022-11-02) diff --git a/plugins/node/opentelemetry-instrumentation-fastify/package.json b/plugins/node/opentelemetry-instrumentation-fastify/package.json index 71b0a1b843..cfde7f78e6 100644 --- a/plugins/node/opentelemetry-instrumentation-fastify/package.json +++ b/plugins/node/opentelemetry-instrumentation-fastify/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/instrumentation-fastify", - "version": "0.30.1", + "version": "0.31.2", "description": "OpenTelemetry fastify automatic instrumentation package.", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -42,29 +42,28 @@ "access": "public" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@opentelemetry/api": "^1.3.0" }, "devDependencies": { "@fastify/express": "^2.0.2", - "@opentelemetry/api": "^1.0.0", - "@opentelemetry/context-async-hooks": "^1.3.1", - "@opentelemetry/instrumentation-http": "0.30.0", - "@opentelemetry/sdk-trace-base": "^1.3.1", - "@opentelemetry/sdk-trace-node": "^1.3.1", + "@opentelemetry/api": "^1.3.0", + "@opentelemetry/context-async-hooks": "^1.8.0", + "@opentelemetry/instrumentation-http": "0.38.0", + "@opentelemetry/sdk-trace-base": "^1.8.0", + "@opentelemetry/sdk-trace-node": "^1.8.0", "@types/express": "4.17.13", "@types/mocha": "7.0.2", "@types/node": "18.11.7", "fastify": "^4.5.3", - "gts": "3.1.0", "mocha": "7.2.0", "nyc": "15.1.0", - "rimraf": "3.0.2", + "rimraf": "4.2.0", "ts-mocha": "10.0.0", - "typescript": "4.3.5" + "typescript": "4.4.4" }, "dependencies": { - "@opentelemetry/core": "^1.0.0", - "@opentelemetry/instrumentation": "^0.32.0", + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.38.0", "@opentelemetry/semantic-conventions": "^1.0.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-fastify#readme" diff --git a/plugins/node/opentelemetry-instrumentation-fastify/src/instrumentation.ts b/plugins/node/opentelemetry-instrumentation-fastify/src/instrumentation.ts index 94b4feb035..d3ac0a74a7 100644 --- a/plugins/node/opentelemetry-instrumentation-fastify/src/instrumentation.ts +++ b/plugins/node/opentelemetry-instrumentation-fastify/src/instrumentation.ts @@ -27,10 +27,12 @@ import { safeExecuteInTheMiddle, } from '@opentelemetry/instrumentation'; import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; -import type { HookHandlerDoneFunction } from 'fastify/types/hooks'; -import type { FastifyInstance } from 'fastify/types/instance'; -import type { FastifyReply } from 'fastify/types/reply'; -import type { FastifyRequest } from 'fastify/types/request'; +import type { + HookHandlerDoneFunction, + FastifyInstance, + FastifyRequest, + FastifyReply, +} from 'fastify'; import { applicationHookNames } from './constants'; import { AttributeNames, diff --git a/plugins/node/opentelemetry-instrumentation-fastify/test/instrumentation.test.ts b/plugins/node/opentelemetry-instrumentation-fastify/test/instrumentation.test.ts index d80595728a..8180eeb047 100644 --- a/plugins/node/opentelemetry-instrumentation-fastify/test/instrumentation.test.ts +++ b/plugins/node/opentelemetry-instrumentation-fastify/test/instrumentation.test.ts @@ -25,9 +25,6 @@ import { SimpleSpanProcessor, } from '@opentelemetry/sdk-trace-base'; import { Span } from '@opentelemetry/api'; -import { HookHandlerDoneFunction } from 'fastify/types/hooks'; -import { FastifyReply } from 'fastify/types/reply'; -import { FastifyRequest } from 'fastify/types/request'; import * as http from 'http'; import { HttpInstrumentation } from '@opentelemetry/instrumentation-http'; import { ANONYMOUS_NAME } from '../src/instrumentation'; @@ -70,7 +67,12 @@ instrumentation.enable(); httpInstrumentation.enable(); import '@fastify/express'; -import { FastifyInstance } from 'fastify/types/instance'; +import { + FastifyInstance, + HookHandlerDoneFunction, + FastifyReply, + FastifyRequest, +} from 'fastify'; const Fastify = require('fastify'); @@ -144,7 +146,7 @@ describe('fastify', () => { const spans = memoryExporter.getFinishedSpans(); assert.strictEqual(spans.length, 5); - const span = spans[3]; + const span = spans[2]; assert.deepStrictEqual(span.attributes, { 'fastify.type': 'request_handler', 'plugin.name': 'fastify -> @fastify/express', @@ -166,7 +168,7 @@ describe('fastify', () => { const spans = memoryExporter.getFinishedSpans(); assert.strictEqual(spans.length, 5); - const span = spans[3]; + const span = spans[2]; assert.deepStrictEqual(span.attributes, { 'fastify.type': 'request_handler', 'fastify.name': 'namedHandler', @@ -218,11 +220,11 @@ describe('fastify', () => { const spans = memoryExporter.getFinishedSpans(); assert.strictEqual(spans.length, 6); - const changedRootSpan = spans[2]; - const span = spans[4]; + const changedRootSpan = spans[4]; + const span = spans[3]; assert.strictEqual(changedRootSpan.name, 'GET /test/:id'); assert.strictEqual(span.name, 'request handler - foo'); - assert.strictEqual(span.parentSpanId, spans[3].spanContext().spanId); + assert.strictEqual(span.parentSpanId, spans[2].spanContext().spanId); }); it('should create span for fastify express runConnect', async () => { @@ -245,7 +247,7 @@ describe('fastify', () => { const spans = memoryExporter.getFinishedSpans(); assert.strictEqual(spans.length, 6); - const baseSpan = spans[2]; + const baseSpan = spans[4]; const span = spans[0]; assert.strictEqual(span.name, 'middleware - enhanceRequest'); assert.deepStrictEqual(span.attributes, { @@ -261,8 +263,8 @@ describe('fastify', () => { const spans = memoryExporter.getFinishedSpans(); assert.strictEqual(spans.length, 6); - const baseSpan = spans[3]; - const span = spans[4]; + const baseSpan = spans[2]; + const span = spans[3]; assert.strictEqual(span.name, 'request handler - foo'); assert.deepStrictEqual(span.attributes, { 'plugin.name': 'subsystem', @@ -278,7 +280,7 @@ describe('fastify', () => { const spans = memoryExporter.getFinishedSpans(); assert.strictEqual(spans.length, 6); - const span = spans[2]; + const span = spans[4]; assert.strictEqual(span.attributes['http.route'], '/test/:id'); }); @@ -287,7 +289,7 @@ describe('fastify', () => { assert.strictEqual(spans.length, 6); const baseSpan = spans[1]; - const span = spans[3]; + const span = spans[2]; assert.strictEqual(span.name, `middleware - ${ANONYMOUS_NAME}`); assert.deepStrictEqual(span.attributes, { 'fastify.type': 'middleware', @@ -304,7 +306,7 @@ describe('fastify', () => { const spans = memoryExporter.getFinishedSpans(); assert.strictEqual(spans.length, 6); - const span = spans[4]; + const span = spans[3]; assert.strictEqual(span.name, 'request handler - anonymous'); assert.deepStrictEqual(span.status, { code: SpanStatusCode.ERROR, @@ -452,7 +454,7 @@ describe('fastify', () => { const spans = memoryExporter.getFinishedSpans(); assert.strictEqual(spans.length, 5); - const span = spans[3]; + const span = spans[2]; assert.deepStrictEqual(span.attributes, { 'fastify.type': 'request_handler', 'plugin.name': 'fastify -> @fastify/express', @@ -485,7 +487,7 @@ describe('fastify', () => { const spans = memoryExporter.getFinishedSpans(); assert.strictEqual(spans.length, 5); - const span = spans[3]; + const span = spans[2]; assert.deepStrictEqual(span.attributes, { 'fastify.type': 'request_handler', 'plugin.name': 'fastify -> @fastify/express', diff --git a/plugins/node/opentelemetry-instrumentation-generic-pool/CHANGELOG.md b/plugins/node/opentelemetry-instrumentation-generic-pool/CHANGELOG.md index 6af49a5b54..5dc40f5877 100644 --- a/plugins/node/opentelemetry-instrumentation-generic-pool/CHANGELOG.md +++ b/plugins/node/opentelemetry-instrumentation-generic-pool/CHANGELOG.md @@ -1,5 +1,26 @@ # Changelog +## [0.31.2](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-generic-pool-v0.31.1...instrumentation-generic-pool-v0.31.2) (2023-04-25) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.38.0 ([#1468](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1468)) ([565a2b2](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/565a2b2c6fde88af3f5401ef6a5a9643d0d66349)) + +## [0.31.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-generic-pool-v0.31.0...instrumentation-generic-pool-v0.31.1) (2023-02-07) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.35.1 ([#1358](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1358)) ([ff109b7](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/ff109b77928cc9a139a21c63d6b54399bb017fa4)) + +## [0.31.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-generic-pool-v0.30.0...instrumentation-generic-pool-v0.31.0) (2022-11-16) + + +### Features + +* update experimental deps to `^0.34.0`, core deps to `^1.8.0`, api to `^1.3.0` ([#1278](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1278)) ([e9fe8e1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/e9fe8e13e34f54e96c50525cadeb74ac048c5624)) + ## [0.30.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-generic-pool-v0.29.0...instrumentation-generic-pool-v0.30.0) (2022-09-02) diff --git a/plugins/node/opentelemetry-instrumentation-generic-pool/package.json b/plugins/node/opentelemetry-instrumentation-generic-pool/package.json index 20c5add2c7..33eef11c7b 100644 --- a/plugins/node/opentelemetry-instrumentation-generic-pool/package.json +++ b/plugins/node/opentelemetry-instrumentation-generic-pool/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/instrumentation-generic-pool", - "version": "0.30.0", + "version": "0.31.2", "description": "OpenTelemetry Generic Pool automatic instrumentation package", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -42,27 +42,26 @@ "access": "public" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@opentelemetry/api": "^1.3.0" }, "devDependencies": { - "@opentelemetry/api": "^1.0.0", - "@opentelemetry/context-async-hooks": "^1.3.1", - "@opentelemetry/sdk-trace-base": "^1.3.1", - "@opentelemetry/sdk-trace-node": "^1.3.1", + "@opentelemetry/api": "^1.3.0", + "@opentelemetry/context-async-hooks": "^1.8.0", + "@opentelemetry/sdk-trace-base": "^1.8.0", + "@opentelemetry/sdk-trace-node": "^1.8.0", "@types/mocha": "7.0.2", "@types/node": "18.11.7", "@types/semver": "7.3.8", "generic-pool": "3.8.2", - "gts": "3.1.0", "mocha": "7.2.0", "nyc": "15.1.0", - "rimraf": "3.0.2", + "rimraf": "4.2.0", "semver": "7.3.5", "ts-mocha": "10.0.0", - "typescript": "4.3.5" + "typescript": "4.4.4" }, "dependencies": { - "@opentelemetry/instrumentation": "^0.32.0", + "@opentelemetry/instrumentation": "^0.38.0", "@opentelemetry/semantic-conventions": "^1.0.0", "@types/generic-pool": "^3.1.9" }, diff --git a/plugins/node/opentelemetry-instrumentation-graphql/CHANGELOG.md b/plugins/node/opentelemetry-instrumentation-graphql/CHANGELOG.md index c7c7b9bd79..ad90b3f5f8 100644 --- a/plugins/node/opentelemetry-instrumentation-graphql/CHANGELOG.md +++ b/plugins/node/opentelemetry-instrumentation-graphql/CHANGELOG.md @@ -1,5 +1,50 @@ # Changelog +## [0.34.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-graphql-v0.34.0...instrumentation-graphql-v0.34.1) (2023-04-25) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.38.0 ([#1468](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1468)) ([565a2b2](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/565a2b2c6fde88af3f5401ef6a5a9643d0d66349)) + +## [0.34.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-graphql-v0.33.2...instrumentation-graphql-v0.34.0) (2023-04-06) + + +### âš  BREAKING CHANGES + +* **gql:** conform GraphQL span name to spec ([#1444](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1444)) + +### Bug Fixes + +* **gql:** conform GraphQL span name to spec ([#1444](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1444)) ([7d070db](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/7d070db276dffd82faa906e8e4a8ed8dcb790c6d)) + +## [0.33.2](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-graphql-v0.33.1...instrumentation-graphql-v0.33.2) (2023-03-03) + + +### Bug Fixes + +* remove component attribute from instrumentations ([#1399](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1399)) ([e93a192](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/e93a192b672c8db361bac83ad60294ca49b95361)) + +## [0.33.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-graphql-v0.33.0...instrumentation-graphql-v0.33.1) (2023-02-07) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.35.1 ([#1358](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1358)) ([ff109b7](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/ff109b77928cc9a139a21c63d6b54399bb017fa4)) + +## [0.33.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-graphql-v0.32.0...instrumentation-graphql-v0.33.0) (2022-11-16) + + +### Features + +* **graphql:** add ignoreTrivialResolveSpans config option ([#1256](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1256)) ([aff84bb](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/aff84bba1d391ec2061b8d0121ac8dd36fc1980c)) +* update experimental deps to `^0.34.0`, core deps to `^1.8.0`, api to `^1.3.0` ([#1278](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1278)) ([e9fe8e1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/e9fe8e13e34f54e96c50525cadeb74ac048c5624)) + + +### Bug Fixes + +* **instrumentation-graphql:** stop using types from `graphql` library in public api ([#1268](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1268)) ([f8cabf3](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/f8cabf306faa3e3eb4b9ce38ccdde842abdb2b82)) + ## [0.32.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-graphql-v0.31.0...instrumentation-graphql-v0.32.0) (2022-11-02) diff --git a/plugins/node/opentelemetry-instrumentation-graphql/package.json b/plugins/node/opentelemetry-instrumentation-graphql/package.json index 8eb844c1f2..0d3619a1ac 100644 --- a/plugins/node/opentelemetry-instrumentation-graphql/package.json +++ b/plugins/node/opentelemetry-instrumentation-graphql/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/instrumentation-graphql", - "version": "0.32.0", + "version": "0.34.1", "description": "OpenTelemetry @opentelemetry/instrumentation-graphql automatic instrumentation package.", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -44,25 +44,24 @@ "access": "public" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@opentelemetry/api": "^1.3.0" }, "devDependencies": { - "@opentelemetry/api": "^1.0.0", - "@opentelemetry/sdk-trace-base": "^1.3.1", + "@opentelemetry/api": "^1.3.0", + "@opentelemetry/sdk-trace-base": "^1.8.0", "@opentelemetry/semantic-conventions": "^1.3.1", "@types/mocha": "8.2.3", "@types/node": "18.11.7", "graphql": "^16.5.0", - "gts": "3.1.0", "mocha": "7.2.0", "nyc": "15.1.0", - "rimraf": "3.0.2", + "rimraf": "4.2.0", "test-all-versions": "5.0.1", "ts-mocha": "10.0.0", - "typescript": "4.3.5" + "typescript": "4.4.4" }, "dependencies": { - "@opentelemetry/instrumentation": "^0.32.0" + "@opentelemetry/instrumentation": "^0.38.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/enums/AttributeNames.ts b/plugins/node/opentelemetry-instrumentation-graphql/src/enums/AttributeNames.ts index d264930721..79032ab55d 100644 --- a/plugins/node/opentelemetry-instrumentation-graphql/src/enums/AttributeNames.ts +++ b/plugins/node/opentelemetry-instrumentation-graphql/src/enums/AttributeNames.ts @@ -14,7 +14,6 @@ * limitations under the License. */ export enum AttributeNames { - COMPONENT = 'graphql', SOURCE = 'graphql.source', FIELD_NAME = 'graphql.field.name', FIELD_PATH = 'graphql.field.path', diff --git a/plugins/node/opentelemetry-instrumentation-graphql/src/instrumentation.ts b/plugins/node/opentelemetry-instrumentation-graphql/src/instrumentation.ts index 3803ef5880..438121605d 100644 --- a/plugins/node/opentelemetry-instrumentation-graphql/src/instrumentation.ts +++ b/plugins/node/opentelemetry-instrumentation-graphql/src/instrumentation.ts @@ -404,18 +404,21 @@ export class GraphQLInstrumentation extends InstrumentationBase { const span = this.tracer.startSpan(SpanNames.EXECUTE, {}); if (operation) { - const operationDefinition = + const { operation: operationType, name: nameNode } = operation as graphqlTypes.OperationDefinitionNode; - span.setAttribute( - AttributeNames.OPERATION_TYPE, - operationDefinition.operation - ); - if (operationDefinition.name) { - span.setAttribute( - AttributeNames.OPERATION_NAME, - operationDefinition.name.value - ); + span.setAttribute(AttributeNames.OPERATION_TYPE, operationType); + + const operationName = nameNode?.value; + + // https://opentelemetry.io/docs/reference/specification/trace/semantic_conventions/instrumentation/graphql/ + // > The span name MUST be of the format provided that graphql.operation.type and graphql.operation.name are available. + // > If graphql.operation.name is not available, the span SHOULD be named . + if (operationName) { + span.setAttribute(AttributeNames.OPERATION_NAME, operationName); + span.updateName(`${operationType} ${operationName}`); + } else { + span.updateName(operationType); } } else { let operationName = ' '; diff --git a/plugins/node/opentelemetry-instrumentation-graphql/src/internal-types.ts b/plugins/node/opentelemetry-instrumentation-graphql/src/internal-types.ts index 4fb6b5858d..3242ea94e4 100644 --- a/plugins/node/opentelemetry-instrumentation-graphql/src/internal-types.ts +++ b/plugins/node/opentelemetry-instrumentation-graphql/src/internal-types.ts @@ -18,8 +18,8 @@ import { InstrumentationConfig } from '@opentelemetry/instrumentation'; import type * as graphqlTypes from 'graphql'; import type * as api from '@opentelemetry/api'; import type { PromiseOrValue } from 'graphql/jsutils/PromiseOrValue'; -import { DocumentNode } from 'graphql/language/ast'; -import { +import type { DocumentNode } from 'graphql/language/ast'; +import type { GraphQLFieldResolver, GraphQLTypeResolver, } from 'graphql/type/definition'; diff --git a/plugins/node/opentelemetry-instrumentation-graphql/test/graphql.test.ts b/plugins/node/opentelemetry-instrumentation-graphql/test/graphql.test.ts index f5c908c3ea..e694fa8f49 100644 --- a/plugins/node/opentelemetry-instrumentation-graphql/test/graphql.test.ts +++ b/plugins/node/opentelemetry-instrumentation-graphql/test/graphql.test.ts @@ -169,7 +169,7 @@ describe('graphql', () => { executeSpan.attributes[AttributeNames.OPERATION_NAME], undefined ); - assert.deepStrictEqual(executeSpan.name, SpanNames.EXECUTE); + assert.deepStrictEqual(executeSpan.name, 'query'); assert.deepStrictEqual(executeSpan.parentSpanId, undefined); }); @@ -297,7 +297,7 @@ describe('graphql', () => { executeSpan.attributes[AttributeNames.OPERATION_NAME], undefined ); - assert.deepStrictEqual(executeSpan.name, SpanNames.EXECUTE); + assert.deepStrictEqual(executeSpan.name, 'query'); assert.deepStrictEqual(executeSpan.parentSpanId, undefined); }); @@ -395,7 +395,7 @@ describe('graphql', () => { executeSpan.attributes[`${AttributeNames.VARIABLES}id`], undefined ); - assert.deepStrictEqual(executeSpan.name, SpanNames.EXECUTE); + assert.deepStrictEqual(executeSpan.name, 'query Query1'); assert.deepStrictEqual(executeSpan.parentSpanId, undefined); }); @@ -487,7 +487,7 @@ describe('graphql', () => { executeSpan.attributes[AttributeNames.OPERATION_NAME], undefined ); - assert.deepStrictEqual(executeSpan.name, SpanNames.EXECUTE); + assert.deepStrictEqual(executeSpan.name, 'query'); assert.deepStrictEqual(executeSpan.parentSpanId, undefined); }); }); @@ -555,7 +555,7 @@ describe('graphql', () => { executeSpan.attributes[AttributeNames.OPERATION_NAME], undefined ); - assert.deepStrictEqual(executeSpan.name, SpanNames.EXECUTE); + assert.deepStrictEqual(executeSpan.name, 'query'); assert.deepStrictEqual(executeSpan.parentSpanId, undefined); }); }); @@ -752,7 +752,7 @@ describe('graphql', () => { executeSpan.attributes[AttributeNames.OPERATION_NAME], undefined ); - assert.deepStrictEqual(executeSpan.name, SpanNames.EXECUTE); + assert.deepStrictEqual(executeSpan.name, 'query'); assert.deepStrictEqual(executeSpan.parentSpanId, undefined); }); @@ -848,7 +848,7 @@ describe('graphql', () => { executeSpan.attributes[AttributeNames.OPERATION_NAME], 'AddBook' ); - assert.deepStrictEqual(executeSpan.name, SpanNames.EXECUTE); + assert.deepStrictEqual(executeSpan.name, 'mutation AddBook'); assert.deepStrictEqual(executeSpan.parentSpanId, undefined); }); @@ -946,7 +946,7 @@ describe('graphql', () => { executeSpan.attributes[`${AttributeNames.VARIABLES}id`], 2 ); - assert.deepStrictEqual(executeSpan.name, SpanNames.EXECUTE); + assert.deepStrictEqual(executeSpan.name, 'query Query1'); assert.deepStrictEqual(executeSpan.parentSpanId, undefined); }); @@ -1044,7 +1044,7 @@ describe('graphql', () => { executeSpan.attributes[AttributeNames.OPERATION_NAME], 'AddBook' ); - assert.deepStrictEqual(executeSpan.name, SpanNames.EXECUTE); + assert.deepStrictEqual(executeSpan.name, 'mutation AddBook'); assert.deepStrictEqual(executeSpan.parentSpanId, undefined); }); @@ -1317,7 +1317,7 @@ describe('graphql', () => { // validate execute span is present const spans = exporter.getFinishedSpans(); - const executeSpans = spans.filter(s => s.name === SpanNames.EXECUTE); + const executeSpans = spans.filter(s => s.name === 'query'); assert.deepStrictEqual(executeSpans.length, 1); const [executeSpan] = executeSpans; assert.deepStrictEqual( @@ -1371,7 +1371,7 @@ describe('graphql', () => { ); // single execute span - const executeSpans = spans.filter(s => s.name === SpanNames.EXECUTE); + const executeSpans = spans.filter(s => s.name === 'query'); assert.deepStrictEqual(executeSpans.length, 1); }); }); diff --git a/plugins/node/opentelemetry-instrumentation-hapi/CHANGELOG.md b/plugins/node/opentelemetry-instrumentation-hapi/CHANGELOG.md index 1fa8c69f40..1ffe858da4 100644 --- a/plugins/node/opentelemetry-instrumentation-hapi/CHANGELOG.md +++ b/plugins/node/opentelemetry-instrumentation-hapi/CHANGELOG.md @@ -1,5 +1,26 @@ # Changelog +## [0.31.2](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-hapi-v0.31.1...instrumentation-hapi-v0.31.2) (2023-04-25) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.38.0 ([#1468](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1468)) ([565a2b2](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/565a2b2c6fde88af3f5401ef6a5a9643d0d66349)) + +## [0.31.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-hapi-v0.31.0...instrumentation-hapi-v0.31.1) (2023-02-07) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.35.1 ([#1358](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1358)) ([ff109b7](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/ff109b77928cc9a139a21c63d6b54399bb017fa4)) + +## [0.31.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-hapi-v0.30.1...instrumentation-hapi-v0.31.0) (2022-11-16) + + +### Features + +* update experimental deps to `^0.34.0`, core deps to `^1.8.0`, api to `^1.3.0` ([#1278](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1278)) ([e9fe8e1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/e9fe8e13e34f54e96c50525cadeb74ac048c5624)) + ## [0.30.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-hapi-v0.30.0...instrumentation-hapi-v0.30.1) (2022-11-02) diff --git a/plugins/node/opentelemetry-instrumentation-hapi/package.json b/plugins/node/opentelemetry-instrumentation-hapi/package.json index 33b622d037..532833bfdf 100644 --- a/plugins/node/opentelemetry-instrumentation-hapi/package.json +++ b/plugins/node/opentelemetry-instrumentation-hapi/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/instrumentation-hapi", - "version": "0.30.1", + "version": "0.31.2", "description": "OpenTelemetry Hapi automatic instrumentation package.", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -42,26 +42,25 @@ "access": "public" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@opentelemetry/api": "^1.3.0" }, "devDependencies": { "@hapi/hapi": "20.1.5", - "@opentelemetry/api": "^1.0.0", - "@opentelemetry/context-async-hooks": "^1.3.1", - "@opentelemetry/sdk-trace-base": "^1.3.1", - "@opentelemetry/sdk-trace-node": "^1.3.1", + "@opentelemetry/api": "^1.3.0", + "@opentelemetry/context-async-hooks": "^1.8.0", + "@opentelemetry/sdk-trace-base": "^1.8.0", + "@opentelemetry/sdk-trace-node": "^1.8.0", "@types/mocha": "7.0.2", "@types/node": "18.11.7", - "gts": "3.1.0", "mocha": "7.2.0", "nyc": "15.1.0", - "rimraf": "3.0.2", + "rimraf": "4.2.0", "ts-mocha": "10.0.0", - "typescript": "4.3.5" + "typescript": "4.4.4" }, "dependencies": { - "@opentelemetry/core": "^1.0.0", - "@opentelemetry/instrumentation": "^0.32.0", + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.38.0", "@opentelemetry/semantic-conventions": "^1.0.0", "@types/hapi__hapi": "20.0.9" }, diff --git a/plugins/node/opentelemetry-instrumentation-hapi/src/instrumentation.ts b/plugins/node/opentelemetry-instrumentation-hapi/src/instrumentation.ts index 1e15b28276..e671041b54 100644 --- a/plugins/node/opentelemetry-instrumentation-hapi/src/instrumentation.ts +++ b/plugins/node/opentelemetry-instrumentation-hapi/src/instrumentation.ts @@ -57,7 +57,7 @@ export class HapiInstrumentation extends InstrumentationBase { protected init() { return new InstrumentationNodeModuleDefinition( HapiComponentName, - ['>=17.0.0'], + ['>=17 <21'], moduleExports => { if (!isWrapped(moduleExports.server)) { api.diag.debug('Patching Hapi.server'); @@ -348,7 +348,7 @@ export class HapiInstrumentation extends InstrumentationBase { undefined, ...params ); - } catch (err) { + } catch (err: any) { span.recordException(err); span.setStatus({ code: api.SpanStatusCode.ERROR, @@ -401,7 +401,7 @@ export class HapiInstrumentation extends InstrumentationBase { api.trace.setSpan(api.context.active(), span), () => oldHandler(...params) ); - } catch (err) { + } catch (err: any) { span.recordException(err); span.setStatus({ code: api.SpanStatusCode.ERROR, diff --git a/plugins/node/opentelemetry-instrumentation-ioredis/.tav.yml b/plugins/node/opentelemetry-instrumentation-ioredis/.tav.yml index 5b1b56c88c..29bd4413db 100644 --- a/plugins/node/opentelemetry-instrumentation-ioredis/.tav.yml +++ b/plugins/node/opentelemetry-instrumentation-ioredis/.tav.yml @@ -1,6 +1,6 @@ ioredis: # Ignoring v4.19.0. Tests never ends. Caused by https://github.com/luin/ioredis/pull/1219 - versions: "^2.5.0 || ^3.2.2 || 4.14.1 || 4.16.3 || 4.17.3 || 4.18.0 || 4.19.2 || 4.19.4 || 4.22.0 || 4.24.5 || 4.26.0 || 4.27.2 || ^4.27.6" + versions: "^2.5.0 || ^3.2.2 || 4.14.1 || 4.16.3 || 4.17.3 || 4.18.0 || 4.19.2 || 4.19.4 || 4.22.0 || 4.24.5 || 4.26.0 || 4.27.2 || ^4.27.6 || 5.0.4 || ^5.2.4" commands: npm run test # Fix missing `contrib-test-utils` package diff --git a/plugins/node/opentelemetry-instrumentation-ioredis/CHANGELOG.md b/plugins/node/opentelemetry-instrumentation-ioredis/CHANGELOG.md index aa5869ee41..2cd7b7f802 100644 --- a/plugins/node/opentelemetry-instrumentation-ioredis/CHANGELOG.md +++ b/plugins/node/opentelemetry-instrumentation-ioredis/CHANGELOG.md @@ -1,5 +1,75 @@ # Changelog +## [0.34.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-ioredis-v0.34.0...instrumentation-ioredis-v0.34.1) (2023-04-25) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.38.0 ([#1468](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1468)) ([565a2b2](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/565a2b2c6fde88af3f5401ef6a5a9643d0d66349)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.1 to ^0.33.2 + +## [0.34.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-ioredis-v0.33.2...instrumentation-ioredis-v0.34.0) (2023-03-03) + + +### Features + +* **ioredis:** Update instrumentation-ioredis to version 5.x.x ([#1121](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1121)) ([f5f7ac6](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/f5f7ac6196b5422e030a6913c491117a6a3a0690)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @opentelemetry/redis-common bumped from ^0.34.0 to ^0.35.0 + +## [0.33.2](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-ioredis-v0.33.1...instrumentation-ioredis-v0.33.2) (2023-02-07) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.35.1 ([#1358](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1358)) ([ff109b7](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/ff109b77928cc9a139a21c63d6b54399bb017fa4)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.0 to ^0.33.1 + +## [0.33.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-ioredis-v0.33.0...instrumentation-ioredis-v0.33.1) (2022-12-20) + + +### Bug Fixes + +* **redis:** serialize non sensitive arguments into db.statement attribute ([#1299](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1299)) ([092a250](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/092a2509bcf884e1b997e0eaec3a6ca02cfd2058)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @opentelemetry/redis-common bumped from ^0.33.0 to ^0.34.0 + +## [0.33.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-ioredis-v0.32.2...instrumentation-ioredis-v0.33.0) (2022-11-16) + + +### Features + +* update experimental deps to `^0.34.0`, core deps to `^1.8.0`, api to `^1.3.0` ([#1278](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1278)) ([e9fe8e1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/e9fe8e13e34f54e96c50525cadeb74ac048c5624)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.32.0 to ^0.33.0 + ## [0.32.2](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-ioredis-v0.32.1...instrumentation-ioredis-v0.32.2) (2022-11-02) diff --git a/plugins/node/opentelemetry-instrumentation-ioredis/README.md b/plugins/node/opentelemetry-instrumentation-ioredis/README.md index 79159202f4..61444f28e7 100644 --- a/plugins/node/opentelemetry-instrumentation-ioredis/README.md +++ b/plugins/node/opentelemetry-instrumentation-ioredis/README.md @@ -17,7 +17,7 @@ npm install --save @opentelemetry/instrumentation-ioredis ### Supported Versions -- `>=2.0.0 <5` +- `>=2.0.0 <6` ## Usage @@ -47,7 +47,7 @@ registerInstrumentations({ IORedis instrumentation has few options available to choose from. You can set the following: | Options | Type | Description | -| ----------------------- | ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | +|-------------------------|---------------------------------------------------|-------------------------------------------------------------------------------------------------------------------| | `dbStatementSerializer` | `DbStatementSerializer` | IORedis instrumentation will serialize db.statement using the specified function. | | `requestHook` | `RedisRequestCustomAttributeFunction` (function) | Function for adding custom attributes on db request. Receives params: `span, { moduleVersion, cmdName, cmdArgs }` | | `responseHook` | `RedisResponseCustomAttributeFunction` (function) | Function for adding custom attributes on db response | @@ -57,7 +57,8 @@ IORedis instrumentation has few options available to choose from. You can set th The instrumentation serializes the command into a Span attribute called `db.statement`. The standard serialization format attempts to be as informative as possible while avoiding the export of potentially sensitive data. The number of serialized arguments depends on the specific command, see the configuration -list in `src/utils.ts`. +list in `@opentelemetry/redis-common`. + It is also possible to define a custom serialization function. The function will receive the command name and arguments and must return a string. Here is a simple example to serialize the command name skipping arguments: diff --git a/plugins/node/opentelemetry-instrumentation-ioredis/package.json b/plugins/node/opentelemetry-instrumentation-ioredis/package.json index 9ac5cbc7f8..70eb4acfb3 100644 --- a/plugins/node/opentelemetry-instrumentation-ioredis/package.json +++ b/plugins/node/opentelemetry-instrumentation-ioredis/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/instrumentation-ioredis", - "version": "0.32.2", + "version": "0.34.1", "description": "OpenTelemetry ioredis automatic instrumentation package.", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -47,32 +47,32 @@ "access": "public" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@opentelemetry/api": "^1.3.0" }, "devDependencies": { - "@opentelemetry/api": "^1.0.0", - "@opentelemetry/context-async-hooks": "^1.3.1", - "@opentelemetry/contrib-test-utils": "^0.32.0", - "@opentelemetry/sdk-trace-base": "^1.3.1", - "@opentelemetry/sdk-trace-node": "^1.3.1", + "@opentelemetry/api": "^1.3.0", + "@opentelemetry/context-async-hooks": "^1.8.0", + "@opentelemetry/contrib-test-utils": "^0.33.2", + "@opentelemetry/sdk-trace-base": "^1.8.0", + "@opentelemetry/sdk-trace-node": "^1.8.0", "@types/mocha": "7.0.2", "@types/sinon": "10.0.9", "@types/node": "18.11.7", "cross-env": "7.0.3", - "gts": "3.1.0", - "ioredis": "4.27.7", + "ioredis": "5.2.2", "mocha": "7.2.0", "nyc": "15.1.0", - "rimraf": "3.0.2", - "sinon": "14.0.0", + "rimraf": "4.2.0", + "sinon": "15.0.1", "test-all-versions": "5.0.1", "ts-mocha": "10.0.0", - "typescript": "4.3.5" + "typescript": "4.4.4" }, "dependencies": { - "@opentelemetry/instrumentation": "^0.32.0", + "@opentelemetry/instrumentation": "^0.38.0", + "@opentelemetry/redis-common": "^0.35.0", "@opentelemetry/semantic-conventions": "^1.0.0", - "@types/ioredis": "4.26.6" + "@types/ioredis4": "npm:@types/ioredis@^4.28.10" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-ioredis#readme" } diff --git a/plugins/node/opentelemetry-instrumentation-ioredis/src/instrumentation.ts b/plugins/node/opentelemetry-instrumentation-ioredis/src/instrumentation.ts index ce5b9d10a8..94f8b850ed 100644 --- a/plugins/node/opentelemetry-instrumentation-ioredis/src/instrumentation.ts +++ b/plugins/node/opentelemetry-instrumentation-ioredis/src/instrumentation.ts @@ -15,28 +15,27 @@ */ import { diag, trace, context, SpanKind } from '@opentelemetry/api'; -import type * as ioredisTypes from 'ioredis'; import { InstrumentationBase, InstrumentationNodeModuleDefinition, isWrapped, } from '@opentelemetry/instrumentation'; -import { IORedisInstrumentationConfig, IORedisCommand } from './types'; +import { IORedisInstrumentationConfig } from './types'; +import { IORedisCommand, RedisInterface } from './internal-types'; import { DbSystemValues, SemanticAttributes, } from '@opentelemetry/semantic-conventions'; import { safeExecuteInTheMiddle } from '@opentelemetry/instrumentation'; -import { endSpan, defaultDbStatementSerializer } from './utils'; +import { endSpan } from './utils'; +import { defaultDbStatementSerializer } from '@opentelemetry/redis-common'; import { VERSION } from './version'; const DEFAULT_CONFIG: IORedisInstrumentationConfig = { requireParentSpan: true, }; -export class IORedisInstrumentation extends InstrumentationBase< - typeof ioredisTypes -> { +export class IORedisInstrumentation extends InstrumentationBase { constructor(_config: IORedisInstrumentationConfig = {}) { super( '@opentelemetry/instrumentation-ioredis', @@ -45,11 +44,11 @@ export class IORedisInstrumentation extends InstrumentationBase< ); } - init(): InstrumentationNodeModuleDefinition[] { + init(): InstrumentationNodeModuleDefinition[] { return [ - new InstrumentationNodeModuleDefinition( + new InstrumentationNodeModuleDefinition( 'ioredis', - ['>1 <5'], + ['>1', '<6'], (moduleExports, moduleVersion?: string) => { diag.debug('Applying patch for ioredis'); if (isWrapped(moduleExports.prototype.sendCommand)) { @@ -97,7 +96,7 @@ export class IORedisInstrumentation extends InstrumentationBase< private traceSendCommand = (original: Function, moduleVersion?: string) => { const instrumentation = this; - return function (this: ioredisTypes.Redis, cmd?: IORedisCommand) { + return function (this: RedisInterface, cmd?: IORedisCommand) { if (arguments.length < 1 || typeof cmd !== 'object') { return original.apply(this, arguments); } @@ -174,7 +173,7 @@ export class IORedisInstrumentation extends InstrumentationBase< }; return result; - } catch (error) { + } catch (error: any) { endSpan(span, error); throw error; } @@ -183,7 +182,7 @@ export class IORedisInstrumentation extends InstrumentationBase< private traceConnection = (original: Function) => { const instrumentation = this; - return function (this: ioredisTypes.Redis) { + return function (this: RedisInterface) { const config = instrumentation.getConfig() as IORedisInstrumentationConfig; const hasNoParentSpan = trace.getSpan(context.active()) === undefined; @@ -209,7 +208,7 @@ export class IORedisInstrumentation extends InstrumentationBase< const client = original.apply(this, arguments); endSpan(span, null); return client; - } catch (error) { + } catch (error: any) { endSpan(span, error); throw error; } diff --git a/plugins/node/opentelemetry-instrumentation-ioredis/src/internal-types.ts b/plugins/node/opentelemetry-instrumentation-ioredis/src/internal-types.ts new file mode 100644 index 0000000000..b399a1eb79 --- /dev/null +++ b/plugins/node/opentelemetry-instrumentation-ioredis/src/internal-types.ts @@ -0,0 +1,29 @@ +/* + * 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 { Command, Redis } from 'ioredis'; +import type * as LegacyIORedis from 'ioredis4'; + +interface LegacyIORedisCommand { + reject: (err: Error) => void; + resolve: (result: {}) => void; + promise: Promise<{}>; + args: Array; + callback: LegacyIORedis.CallbackFunction; + name: string; +} + +export type IORedisCommand = Command | LegacyIORedisCommand; +export type RedisInterface = Redis | LegacyIORedis.Redis; diff --git a/plugins/node/opentelemetry-instrumentation-ioredis/src/types.ts b/plugins/node/opentelemetry-instrumentation-ioredis/src/types.ts index 66f3137484..5d32116a67 100644 --- a/plugins/node/opentelemetry-instrumentation-ioredis/src/types.ts +++ b/plugins/node/opentelemetry-instrumentation-ioredis/src/types.ts @@ -14,18 +14,10 @@ * limitations under the License. */ -import type * as ioredisTypes from 'ioredis'; import { InstrumentationConfig } from '@opentelemetry/instrumentation'; import { Span } from '@opentelemetry/api'; -export interface IORedisCommand { - reject: (err: Error) => void; - resolve: (result: {}) => void; - promise: Promise<{}>; - args: Array; - callback: ioredisTypes.CallbackFunction; - name: string; -} +export type CommandArgs = Array; /** * Function that can be used to serialize db.statement tag @@ -35,14 +27,14 @@ export interface IORedisCommand { * @returns serialized string that will be used as the db.statement attribute. */ export type DbStatementSerializer = ( - cmdName: IORedisCommand['name'], - cmdArgs: IORedisCommand['args'] + cmdName: string, + cmdArgs: CommandArgs ) => string; export interface IORedisRequestHookInformation { moduleVersion?: string; - cmdName: IORedisCommand['name']; - cmdArgs: IORedisCommand['args']; + cmdName: string; + cmdArgs: CommandArgs; } export interface RedisRequestCustomAttributeFunction { @@ -59,12 +51,7 @@ export interface RedisRequestCustomAttributeFunction { * The type of the response varies depending on the specific command. */ export interface RedisResponseCustomAttributeFunction { - ( - span: Span, - cmdName: IORedisCommand['name'], - cmdArgs: IORedisCommand['args'], - response: unknown - ): void; + (span: Span, cmdName: string, cmdArgs: CommandArgs, response: unknown): void; } /** diff --git a/plugins/node/opentelemetry-instrumentation-ioredis/src/utils.ts b/plugins/node/opentelemetry-instrumentation-ioredis/src/utils.ts index 55c93fee0f..6250284342 100644 --- a/plugins/node/opentelemetry-instrumentation-ioredis/src/utils.ts +++ b/plugins/node/opentelemetry-instrumentation-ioredis/src/utils.ts @@ -15,35 +15,6 @@ */ import { Span, SpanStatusCode } from '@opentelemetry/api'; -import { DbStatementSerializer } from './types'; - -/** - * List of regexes and the number of arguments that should be serialized for matching commands. - * For example, HSET should serialize which key and field it's operating on, but not its value. - * Setting the subset to -1 will serialize all arguments. - * Commands without a match will have their first argument serialized. - * - * Refer to https://redis.io/commands/ for the full list. - */ -const serializationSubsets = [ - { - regex: /^ECHO/i, - args: 0, - }, - { - regex: /^(LPUSH|MSET|PFA|PUBLISH|RPUSH|SADD|SET|SPUBLISH|XADD|ZADD)/i, - args: 1, - }, - { - regex: /^(HSET|HMSET|LSET|LINSERT)/i, - args: 2, - }, - { - regex: - /^(ACL|BIT|B[LRZ]|CLIENT|CLUSTER|CONFIG|COMMAND|DECR|DEL|EVAL|EX|FUNCTION|GEO|GET|HINCR|HMGET|HSCAN|INCR|L[TRLM]|MEMORY|P[EFISTU]|RPOP|S[CDIMORSU]|XACK|X[CDGILPRT]|Z[CDILMPRS])/i, - args: -1, - }, -]; export const endSpan = ( span: Span, @@ -58,24 +29,3 @@ export const endSpan = ( } span.end(); }; - -export const defaultDbStatementSerializer: DbStatementSerializer = ( - cmdName, - cmdArgs -) => { - if (Array.isArray(cmdArgs) && cmdArgs.length) { - const nArgsToSerialize = - serializationSubsets.find(({ regex }) => { - return regex.test(cmdName); - })?.args ?? 0; - const argsToSerialize = - nArgsToSerialize >= 0 ? cmdArgs.slice(0, nArgsToSerialize) : cmdArgs; - if (cmdArgs.length > argsToSerialize.length) { - argsToSerialize.push( - `[${cmdArgs.length - nArgsToSerialize} other arguments]` - ); - } - return `${cmdName} ${argsToSerialize.join(' ')}`; - } - return cmdName; -}; diff --git a/plugins/node/opentelemetry-instrumentation-ioredis/test/ioredis.test.ts b/plugins/node/opentelemetry-instrumentation-ioredis/test/ioredis.test.ts index dae05f48ba..5df678ea4d 100644 --- a/plugins/node/opentelemetry-instrumentation-ioredis/test/ioredis.test.ts +++ b/plugins/node/opentelemetry-instrumentation-ioredis/test/ioredis.test.ts @@ -43,7 +43,6 @@ import { DbSystemValues, SemanticAttributes, } from '@opentelemetry/semantic-conventions'; -import { defaultDbStatementSerializer } from '../src/utils'; const memoryExporter = new InMemorySpanExporter(); @@ -82,7 +81,7 @@ const sanitizeEventForAssertion = (span: ReadableSpan) => { describe('ioredis', () => { const provider = new NodeTracerProvider(); - let ioredis: typeof ioredisTypes; + let ioredis: typeof ioredisTypes.default; let instrumentation: IORedisInstrumentation; const shouldTestLocal = process.env.RUN_REDIS_TESTS_LOCAL; const shouldTest = process.env.RUN_REDIS_TESTS || shouldTestLocal; @@ -188,23 +187,23 @@ describe('ioredis', () => { description: string; name: string; args: Array; - serializedArgs: Array; - method: (cb: ioredisTypes.CallbackFunction) => unknown; + expectedDbStatement: string; + method: (cb: ioredisTypes.Callback) => unknown; }> = [ { description: 'insert', name: 'hset', args: [hashKeyName, 'testField', 'testValue'], - serializedArgs: [hashKeyName, 'testField', '[1 other arguments]'], - method: (cb: ioredisTypes.CallbackFunction) => + expectedDbStatement: `${hashKeyName} testField [1 other arguments]`, + method: (cb: ioredisTypes.Callback) => client.hset(hashKeyName, 'testField', 'testValue', cb), }, { description: 'get', name: 'get', args: [testKeyName], - serializedArgs: [testKeyName], - method: (cb: ioredisTypes.CallbackFunction) => + expectedDbStatement: `${testKeyName}`, + method: (cb: ioredisTypes.Callback) => client.get(testKeyName, cb), }, ]; @@ -245,9 +244,7 @@ describe('ioredis', () => { it(`should create a child span for cb style ${command.description}`, done => { const attributes = { ...DEFAULT_ATTRIBUTES, - [SemanticAttributes.DB_STATEMENT]: `${ - command.name - } ${command.serializedArgs.join(' ')}`, + [SemanticAttributes.DB_STATEMENT]: `${command.name} ${command.expectedDbStatement}`, }; const span = provider .getTracer('ioredis-test') @@ -310,7 +307,7 @@ describe('ioredis', () => { // should throw 'ReplyError: ERR value is not an integer or out of range' // because the value im the key is not numeric and we try to increment it await client.incr('non-int-key'); - } catch (ex) { + } catch (ex: any) { const endedSpans = memoryExporter.getFinishedSpans(); assert.strictEqual(endedSpans.length, 2); const ioredisSpan = endedSpans[1]; @@ -963,7 +960,7 @@ describe('ioredis', () => { describe('setConfig - custom dbStatementSerializer config', () => { const dbStatementSerializer = ( cmdName: string, - cmdArgs: Array + cmdArgs: Array ) => { return Array.isArray(cmdArgs) && cmdArgs.length ? `FooBar_${cmdName} ${cmdArgs.join(',')}` @@ -1002,41 +999,4 @@ describe('ioredis', () => { }); }); }); - - describe('#defaultDbStatementSerializer()', () => { - [ - { - cmdName: 'UNKNOWN', - cmdArgs: ['something'], - expected: 'UNKNOWN [1 other arguments]', - }, - { - cmdName: 'ECHO', - cmdArgs: ['echo'], - expected: 'ECHO [1 other arguments]', - }, - { - cmdName: 'LPUSH', - cmdArgs: ['list', 'value'], - expected: 'LPUSH list [1 other arguments]', - }, - { - cmdName: 'HSET', - cmdArgs: ['hash', 'field', 'value'], - expected: 'HSET hash field [1 other arguments]', - }, - { - cmdName: 'INCRBY', - cmdArgs: ['key', 5], - expected: 'INCRBY key 5', - }, - ].forEach(({ cmdName, cmdArgs, expected }) => { - it(`should serialize the correct number of arguments for ${cmdName}`, () => { - assert.strictEqual( - defaultDbStatementSerializer(cmdName, cmdArgs), - expected - ); - }); - }); - }); }); diff --git a/plugins/node/opentelemetry-instrumentation-knex/CHANGELOG.md b/plugins/node/opentelemetry-instrumentation-knex/CHANGELOG.md index de3dff2f22..c4d63514bb 100644 --- a/plugins/node/opentelemetry-instrumentation-knex/CHANGELOG.md +++ b/plugins/node/opentelemetry-instrumentation-knex/CHANGELOG.md @@ -1,5 +1,26 @@ # Changelog +## [0.31.2](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-knex-v0.31.1...instrumentation-knex-v0.31.2) (2023-04-25) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.38.0 ([#1468](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1468)) ([565a2b2](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/565a2b2c6fde88af3f5401ef6a5a9643d0d66349)) + +## [0.31.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-knex-v0.31.0...instrumentation-knex-v0.31.1) (2023-02-07) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.35.1 ([#1358](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1358)) ([ff109b7](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/ff109b77928cc9a139a21c63d6b54399bb017fa4)) + +## [0.31.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-knex-v0.30.1...instrumentation-knex-v0.31.0) (2022-11-16) + + +### Features + +* update experimental deps to `^0.34.0`, core deps to `^1.8.0`, api to `^1.3.0` ([#1278](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1278)) ([e9fe8e1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/e9fe8e13e34f54e96c50525cadeb74ac048c5624)) + ## [0.30.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-knex-v0.30.0...instrumentation-knex-v0.30.1) (2022-11-02) diff --git a/plugins/node/opentelemetry-instrumentation-knex/package.json b/plugins/node/opentelemetry-instrumentation-knex/package.json index 68b687e507..911ea3c18f 100644 --- a/plugins/node/opentelemetry-instrumentation-knex/package.json +++ b/plugins/node/opentelemetry-instrumentation-knex/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/instrumentation-knex", - "version": "0.30.1", + "version": "0.31.2", "description": "OpenTelemetry Knex automatic instrumentation package", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -42,26 +42,25 @@ "access": "public" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@opentelemetry/api": "^1.3.0" }, "devDependencies": { - "@opentelemetry/api": "^1.0.0", - "@opentelemetry/context-async-hooks": "^1.3.1", - "@opentelemetry/sdk-trace-base": "^1.3.1", - "@opentelemetry/sdk-trace-node": "^1.3.1", + "@opentelemetry/api": "^1.3.0", + "@opentelemetry/context-async-hooks": "^1.8.0", + "@opentelemetry/sdk-trace-base": "^1.8.0", + "@opentelemetry/sdk-trace-node": "^1.8.0", "@types/mocha": "7.0.2", "@types/node": "18.11.7", - "gts": "3.1.0", "knex": "0.95.9", "mocha": "7.2.0", "nyc": "15.1.0", - "rimraf": "3.0.2", - "sqlite3": "5.0.3", + "rimraf": "4.2.0", + "sqlite3": "5.1.5", "ts-mocha": "10.0.0", - "typescript": "4.3.5" + "typescript": "4.4.4" }, "dependencies": { - "@opentelemetry/instrumentation": "^0.32.0", + "@opentelemetry/instrumentation": "^0.38.0", "@opentelemetry/semantic-conventions": "^1.0.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-knex#readme" diff --git a/plugins/node/opentelemetry-instrumentation-knex/test/index.test.ts b/plugins/node/opentelemetry-instrumentation-knex/test/index.test.ts index 8e90950660..f939160b0f 100644 --- a/plugins/node/opentelemetry-instrumentation-knex/test/index.test.ts +++ b/plugins/node/opentelemetry-instrumentation-knex/test/index.test.ts @@ -246,7 +246,7 @@ const assertSpans = (actualSpans: any[], expectedSpans: any[]) => { span.parentSpanId, expected.parentSpan?.spanContext().spanId ); - } catch (e) { + } catch (e: any) { e.message = `At span[${idx}]: ${e.message}`; throw e; } diff --git a/plugins/node/opentelemetry-instrumentation-koa/.tav.yml b/plugins/node/opentelemetry-instrumentation-koa/.tav.yml index 4f6d442e38..2cd22120aa 100644 --- a/plugins/node/opentelemetry-instrumentation-koa/.tav.yml +++ b/plugins/node/opentelemetry-instrumentation-koa/.tav.yml @@ -1,3 +1,7 @@ +"@koa/router": + versions: "8.0.8 || 9.4.0 || 10.0.0 || 10.1.1 || 11.0.1 || >=12.0.0" + commands: npm run test + koa: # Testing ^2.7.0 covers at least 97% of the downloaded koa versions versions: "^2.7.0" diff --git a/plugins/node/opentelemetry-instrumentation-koa/CHANGELOG.md b/plugins/node/opentelemetry-instrumentation-koa/CHANGELOG.md index 256429128b..25bbc422c4 100644 --- a/plugins/node/opentelemetry-instrumentation-koa/CHANGELOG.md +++ b/plugins/node/opentelemetry-instrumentation-koa/CHANGELOG.md @@ -1,5 +1,40 @@ # Changelog +## [0.34.4](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-koa-v0.34.3...instrumentation-koa-v0.34.4) (2023-04-25) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.38.0 ([#1468](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1468)) ([565a2b2](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/565a2b2c6fde88af3f5401ef6a5a9643d0d66349)) + +## [0.34.3](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-koa-v0.34.2...instrumentation-koa-v0.34.3) (2023-04-06) + + +### Bug Fixes + +* **@types/koa:** update @types/koa version to latest ([#1447](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1447)) ([5f180aa](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/5f180aa05d3140010642287de933c708e915b619)) + +## [0.34.2](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-koa-v0.34.1...instrumentation-koa-v0.34.2) (2023-03-03) + + +### Bug Fixes + +* remove component attribute from instrumentations ([#1399](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1399)) ([e93a192](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/e93a192b672c8db361bac83ad60294ca49b95361)) + +## [0.34.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-koa-v0.34.0...instrumentation-koa-v0.34.1) (2023-02-07) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.35.1 ([#1358](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1358)) ([ff109b7](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/ff109b77928cc9a139a21c63d6b54399bb017fa4)) + +## [0.34.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-koa-v0.33.0...instrumentation-koa-v0.34.0) (2022-11-16) + + +### Features + +* update experimental deps to `^0.34.0`, core deps to `^1.8.0`, api to `^1.3.0` ([#1278](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1278)) ([e9fe8e1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/e9fe8e13e34f54e96c50525cadeb74ac048c5624)) + ## [0.33.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-koa-v0.32.0...instrumentation-koa-v0.33.0) (2022-11-02) diff --git a/plugins/node/opentelemetry-instrumentation-koa/README.md b/plugins/node/opentelemetry-instrumentation-koa/README.md index 26f1d1a289..d964ca8c78 100644 --- a/plugins/node/opentelemetry-instrumentation-koa/README.md +++ b/plugins/node/opentelemetry-instrumentation-koa/README.md @@ -17,7 +17,8 @@ npm install --save @opentelemetry/instrumentation-koa ### Supported Versions -- `^2.0.0` +- `koa`: `^2.0.0` +- `@koa/router`: `>=8` ## Usage diff --git a/plugins/node/opentelemetry-instrumentation-koa/examples/package.json b/plugins/node/opentelemetry-instrumentation-koa/examples/package.json index 71733c6b81..09fa88ab1e 100644 --- a/plugins/node/opentelemetry-instrumentation-koa/examples/package.json +++ b/plugins/node/opentelemetry-instrumentation-koa/examples/package.json @@ -30,12 +30,12 @@ "url": "https://github.com/open-telemetry/opentelemetry-js-contrib/issues" }, "dependencies": { - "@koa/router": "^9.3.1", + "@koa/router": "^12.0.0", "@opentelemetry/api": "^1.0.0", "@opentelemetry/exporter-jaeger": "^1.0.0", "@opentelemetry/exporter-zipkin": "^1.0.0", - "@opentelemetry/instrumentation": "^0.32.0", - "@opentelemetry/instrumentation-http": "^0.32.0", + "@opentelemetry/instrumentation": "^0.38.0", + "@opentelemetry/instrumentation-http": "^0.38.0", "@opentelemetry/instrumentation-koa": "^0.31.0", "@opentelemetry/sdk-trace-node": "^1.0.0", "@opentelemetry/sdk-trace-base": "^1.0.0", @@ -46,7 +46,7 @@ "devDependencies": { "cross-env": "^6.0.0", "ts-node": "^10.6.0", - "typescript": "4.3.5", + "typescript": "4.4.4", "@types/koa": "^2.13.5" } } diff --git a/plugins/node/opentelemetry-instrumentation-koa/package.json b/plugins/node/opentelemetry-instrumentation-koa/package.json index 292f455199..504b0781af 100644 --- a/plugins/node/opentelemetry-instrumentation-koa/package.json +++ b/plugins/node/opentelemetry-instrumentation-koa/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/instrumentation-koa", - "version": "0.33.0", + "version": "0.34.4", "description": "OpenTelemetry Koa automatic instrumentation package.", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -46,32 +46,31 @@ "access": "public" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@opentelemetry/api": "^1.3.0" }, "devDependencies": { - "@koa/router": "9.4.0", - "@opentelemetry/api": "^1.0.0", - "@opentelemetry/context-async-hooks": "^1.3.1", - "@opentelemetry/sdk-trace-base": "^1.3.1", - "@opentelemetry/sdk-trace-node": "^1.3.1", + "@koa/router": "12.0.0", + "@opentelemetry/api": "^1.3.0", + "@opentelemetry/context-async-hooks": "^1.8.0", + "@opentelemetry/sdk-trace-base": "^1.8.0", + "@opentelemetry/sdk-trace-node": "^1.8.0", "@types/mocha": "7.0.2", "@types/node": "18.11.7", "@types/sinon": "10.0.9", - "gts": "3.1.0", "koa": "2.13.1", "mocha": "7.2.0", "nyc": "15.1.0", - "rimraf": "3.0.2", - "sinon": "14.0.0", + "rimraf": "4.2.0", + "sinon": "15.0.1", "test-all-versions": "5.0.1", "ts-mocha": "10.0.0", - "typescript": "4.3.5" + "typescript": "4.4.4" }, "dependencies": { - "@opentelemetry/core": "^1.0.0", - "@opentelemetry/instrumentation": "^0.32.0", + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.38.0", "@opentelemetry/semantic-conventions": "^1.0.0", - "@types/koa": "2.13.4", + "@types/koa": "2.13.6", "@types/koa__router": "8.0.7" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-koa#readme" diff --git a/plugins/node/opentelemetry-instrumentation-koa/src/instrumentation.ts b/plugins/node/opentelemetry-instrumentation-koa/src/instrumentation.ts index 2a454e0ef8..f270875efa 100644 --- a/plugins/node/opentelemetry-instrumentation-koa/src/instrumentation.ts +++ b/plugins/node/opentelemetry-instrumentation-koa/src/instrumentation.ts @@ -33,15 +33,10 @@ import { AttributeNames } from './enums/AttributeNames'; import { VERSION } from './version'; import { getMiddlewareMetadata, isLayerIgnored } from './utils'; import { getRPCMetadata, RPCType, setRPCMetadata } from '@opentelemetry/core'; -import { - kLayerPatched, - KoaComponentName, - KoaPatchedMiddleware, -} from './internal-types'; +import { kLayerPatched, KoaPatchedMiddleware } from './internal-types'; /** Koa instrumentation for OpenTelemetry */ export class KoaInstrumentation extends InstrumentationBase { - static readonly component = KoaComponentName; constructor(config: KoaInstrumentationConfig = {}) { super( '@opentelemetry/instrumentation-koa', @@ -216,7 +211,7 @@ export class KoaInstrumentation extends InstrumentationBase { return api.context.with(newContext, async () => { try { return await middlewareLayer(context, next); - } catch (err) { + } catch (err: any) { span.recordException(err); throw err; } finally { diff --git a/plugins/node/opentelemetry-instrumentation-koa/src/internal-types.ts b/plugins/node/opentelemetry-instrumentation-koa/src/internal-types.ts index d228b0f4fc..05557e938a 100644 --- a/plugins/node/opentelemetry-instrumentation-koa/src/internal-types.ts +++ b/plugins/node/opentelemetry-instrumentation-koa/src/internal-types.ts @@ -24,5 +24,3 @@ export const kLayerPatched: unique symbol = Symbol('koa-layer-patched'); export type KoaPatchedMiddleware = KoaMiddleware & { [kLayerPatched]?: boolean; }; - -export const KoaComponentName = 'koa'; diff --git a/plugins/node/opentelemetry-instrumentation-memcached/CHANGELOG.md b/plugins/node/opentelemetry-instrumentation-memcached/CHANGELOG.md index ce4ae15f4a..7d7f658cdf 100644 --- a/plugins/node/opentelemetry-instrumentation-memcached/CHANGELOG.md +++ b/plugins/node/opentelemetry-instrumentation-memcached/CHANGELOG.md @@ -1,5 +1,47 @@ # Changelog +## [0.31.2](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-memcached-v0.31.1...instrumentation-memcached-v0.31.2) (2023-04-25) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.38.0 ([#1468](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1468)) ([565a2b2](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/565a2b2c6fde88af3f5401ef6a5a9643d0d66349)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.1 to ^0.33.2 + +## [0.31.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-memcached-v0.31.0...instrumentation-memcached-v0.31.1) (2023-02-07) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.35.1 ([#1358](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1358)) ([ff109b7](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/ff109b77928cc9a139a21c63d6b54399bb017fa4)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.0 to ^0.33.1 + +## [0.31.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-memcached-v0.30.1...instrumentation-memcached-v0.31.0) (2022-11-16) + + +### Features + +* update experimental deps to `^0.34.0`, core deps to `^1.8.0`, api to `^1.3.0` ([#1278](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1278)) ([e9fe8e1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/e9fe8e13e34f54e96c50525cadeb74ac048c5624)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.32.0 to ^0.33.0 + ## [0.30.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-memcached-v0.30.0...instrumentation-memcached-v0.30.1) (2022-11-02) diff --git a/plugins/node/opentelemetry-instrumentation-memcached/package.json b/plugins/node/opentelemetry-instrumentation-memcached/package.json index 2b8a05cc60..5ed4ce9f71 100644 --- a/plugins/node/opentelemetry-instrumentation-memcached/package.json +++ b/plugins/node/opentelemetry-instrumentation-memcached/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/instrumentation-memcached", - "version": "0.30.1", + "version": "0.31.2", "description": "OpenTelemetry memcached automatic instrumentation package.", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -44,27 +44,26 @@ "access": "public" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@opentelemetry/api": "^1.3.0" }, "devDependencies": { - "@opentelemetry/api": "^1.0.0", - "@opentelemetry/context-async-hooks": "^1.3.1", - "@opentelemetry/contrib-test-utils": "^0.32.0", - "@opentelemetry/sdk-trace-base": "^1.3.1", - "@opentelemetry/sdk-trace-node": "^1.3.1", + "@opentelemetry/api": "^1.3.0", + "@opentelemetry/context-async-hooks": "^1.8.0", + "@opentelemetry/contrib-test-utils": "^0.33.2", + "@opentelemetry/sdk-trace-base": "^1.8.0", + "@opentelemetry/sdk-trace-node": "^1.8.0", "@types/mocha": "7.0.2", "@types/node": "18.11.7", "cross-env": "7.0.3", - "gts": "3.1.0", "memcached": "2.2.2", "mocha": "7.2.0", "nyc": "15.1.0", - "rimraf": "3.0.2", + "rimraf": "4.2.0", "ts-mocha": "10.0.0", - "typescript": "4.3.5" + "typescript": "4.4.4" }, "dependencies": { - "@opentelemetry/instrumentation": "^0.32.0", + "@opentelemetry/instrumentation": "^0.38.0", "@opentelemetry/semantic-conventions": "^1.0.0", "@types/memcached": "^2.2.6" }, diff --git a/plugins/node/opentelemetry-instrumentation-memcached/test/index.test.ts b/plugins/node/opentelemetry-instrumentation-memcached/test/index.test.ts index 4639035b6a..01f116d0fc 100644 --- a/plugins/node/opentelemetry-instrumentation-memcached/test/index.test.ts +++ b/plugins/node/opentelemetry-instrumentation-memcached/test/index.test.ts @@ -301,7 +301,7 @@ const assertSpans = (actualSpans: any[], expectedSpans: any[]) => { span.parentSpanId, expected.parentSpan?.spanContext().spanId ); - } catch (e) { + } catch (e: any) { e.message = `At span[${idx}]: ${e.message}`; throw e; } diff --git a/plugins/node/opentelemetry-instrumentation-mongodb/.tav.yml b/plugins/node/opentelemetry-instrumentation-mongodb/.tav.yml index 00de6af24f..c369d133f6 100644 --- a/plugins/node/opentelemetry-instrumentation-mongodb/.tav.yml +++ b/plugins/node/opentelemetry-instrumentation-mongodb/.tav.yml @@ -2,7 +2,7 @@ mongodb: jobs: - versions: ">=3.3 <4" commands: npm run test - - versions: ">=4" + - versions: ">=4 <5" commands: npm run test-new-versions # Fix missing `contrib-test-utils` package diff --git a/plugins/node/opentelemetry-instrumentation-mongodb/CHANGELOG.md b/plugins/node/opentelemetry-instrumentation-mongodb/CHANGELOG.md index c302a9912c..caef8b4082 100644 --- a/plugins/node/opentelemetry-instrumentation-mongodb/CHANGELOG.md +++ b/plugins/node/opentelemetry-instrumentation-mongodb/CHANGELOG.md @@ -1,5 +1,54 @@ # Changelog +## [0.34.2](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-mongodb-v0.34.1...instrumentation-mongodb-v0.34.2) (2023-04-25) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.38.0 ([#1468](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1468)) ([565a2b2](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/565a2b2c6fde88af3f5401ef6a5a9643d0d66349)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.1 to ^0.33.2 + +## [0.34.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-mongodb-v0.34.0...instrumentation-mongodb-v0.34.1) (2023-02-07) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.35.1 ([#1358](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1358)) ([ff109b7](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/ff109b77928cc9a139a21c63d6b54399bb017fa4)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.0 to ^0.33.1 + +## [0.34.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-mongodb-v0.33.0...instrumentation-mongodb-v0.34.0) (2022-12-20) + + +### Features + +* **mongodb:** add db.operation span attribute ([#1321](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1321)) ([97305e1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/97305e1880ecbfb3b87d6c38f0c6521570583510)) + +## [0.33.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-mongodb-v0.32.2...instrumentation-mongodb-v0.33.0) (2022-11-16) + + +### Features + +* update experimental deps to `^0.34.0`, core deps to `^1.8.0`, api to `^1.3.0` ([#1278](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1278)) ([e9fe8e1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/e9fe8e13e34f54e96c50525cadeb74ac048c5624)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.32.0 to ^0.33.0 + ## [0.32.2](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-mongodb-v0.32.1...instrumentation-mongodb-v0.32.2) (2022-11-02) diff --git a/plugins/node/opentelemetry-instrumentation-mongodb/examples/README.md b/plugins/node/opentelemetry-instrumentation-mongodb/examples/README.md index d30fb9ed20..120f97fc84 100644 --- a/plugins/node/opentelemetry-instrumentation-mongodb/examples/README.md +++ b/plugins/node/opentelemetry-instrumentation-mongodb/examples/README.md @@ -37,11 +37,11 @@ Setup [Jaeger Tracing](https://www.jaegertracing.io/docs/latest/getting-started/ npm run zipkin:server ``` -- Run the zipkin:client +- Run the client ```sh # from this directory - npm run client + npm run zipkin:client ``` #### Zipkin UI diff --git a/plugins/node/opentelemetry-instrumentation-mongodb/examples/package.json b/plugins/node/opentelemetry-instrumentation-mongodb/examples/package.json index f25bbe36ab..4f74cc9ff5 100644 --- a/plugins/node/opentelemetry-instrumentation-mongodb/examples/package.json +++ b/plugins/node/opentelemetry-instrumentation-mongodb/examples/package.json @@ -33,8 +33,8 @@ "@opentelemetry/api": "^1.0.0", "@opentelemetry/exporter-jaeger": "^1.0.0", "@opentelemetry/exporter-zipkin": "^1.0.0", - "@opentelemetry/instrumentation": "^0.32.0", - "@opentelemetry/instrumentation-http": "^0.32.0", + "@opentelemetry/instrumentation": "^0.38.0", + "@opentelemetry/instrumentation-http": "^0.38.0", "@opentelemetry/instrumentation-mongodb": "^0.32.0", "@opentelemetry/sdk-trace-node": "^1.0.0", "@opentelemetry/sdk-trace-base": "^1.0.0", @@ -44,6 +44,6 @@ "devDependencies": { "cross-env": "^7.0.3", "ts-node": "^10.6.0", - "typescript": "4.3.5" + "typescript": "4.4.4" } } diff --git a/plugins/node/opentelemetry-instrumentation-mongodb/package.json b/plugins/node/opentelemetry-instrumentation-mongodb/package.json index 6cd13f4079..fc1526c84c 100644 --- a/plugins/node/opentelemetry-instrumentation-mongodb/package.json +++ b/plugins/node/opentelemetry-instrumentation-mongodb/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/instrumentation-mongodb", - "version": "0.32.2", + "version": "0.34.2", "description": "OpenTelemetry mongodb automatic instrumentation package.", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -47,28 +47,28 @@ "access": "public" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@opentelemetry/api": "^1.3.0" }, "devDependencies": { - "@opentelemetry/api": "^1.0.0", - "@opentelemetry/contrib-test-utils": "^0.32.0", - "@opentelemetry/context-async-hooks": "^1.3.1", - "@opentelemetry/sdk-trace-base": "^1.3.1", - "@opentelemetry/sdk-trace-node": "^1.3.1", + "@opentelemetry/api": "^1.3.0", + "@opentelemetry/contrib-test-utils": "^0.33.2", + "@opentelemetry/context-async-hooks": "^1.8.0", + "@opentelemetry/sdk-trace-base": "^1.8.0", + "@opentelemetry/sdk-trace-node": "^1.8.0", "@types/mocha": "7.0.2", "@types/node": "18.11.7", - "gts": "3.1.0", "mocha": "7.2.0", "mongodb": "3.6.11", "@types/mongodb": "3.6.20", + "@types/bson": "4.0.5", "nyc": "15.1.0", - "rimraf": "3.0.2", + "rimraf": "4.2.0", "test-all-versions": "5.0.1", "ts-mocha": "10.0.0", - "typescript": "4.3.5" + "typescript": "4.4.4" }, "dependencies": { - "@opentelemetry/instrumentation": "^0.32.0", + "@opentelemetry/instrumentation": "^0.38.0", "@opentelemetry/semantic-conventions": "^1.0.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-mongodb#readme" diff --git a/plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts b/plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts index f950dd49a8..8361de772c 100644 --- a/plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts +++ b/plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts @@ -210,7 +210,8 @@ export class MongoDBInstrumentation extends InstrumentationBase { ns, server, // eslint-disable-next-line @typescript-eslint/no-explicit-any - ops[0] as any + ops[0] as any, + operationName ); const patchedCallback = instrumentation._patchEnd(span, resultHandler); // handle when options is the callback to send the correct number of args @@ -255,7 +256,9 @@ export class MongoDBInstrumentation extends InstrumentationBase { const span = instrumentation.tracer.startSpan(`mongodb.${type}`, { kind: SpanKind.CLIENT, }); - instrumentation._populateV3Attributes(span, ns, server, cmd); + const operation = + commandType === MongodbCommandType.UNKNOWN ? undefined : commandType; + instrumentation._populateV3Attributes(span, ns, server, cmd, operation); const patchedCallback = instrumentation._patchEnd(span, resultHandler); // handle when options is the callback to send the correct number of args if (typeof options === 'function') { @@ -296,7 +299,7 @@ export class MongoDBInstrumentation extends InstrumentationBase { kind: SpanKind.CLIENT, } ); - instrumentation._populateV4Attributes(span, this, ns, cmd); + instrumentation._populateV4Attributes(span, this, ns, cmd, commandType); const patchedCallback = instrumentation._patchEnd(span, resultHandler); return original.call(this, ns, cmd, options, patchedCallback); }; @@ -341,7 +344,7 @@ export class MongoDBInstrumentation extends InstrumentationBase { const span = instrumentation.tracer.startSpan('mongodb.find', { kind: SpanKind.CLIENT, }); - instrumentation._populateV3Attributes(span, ns, server, cmd); + instrumentation._populateV3Attributes(span, ns, server, cmd, 'find'); const patchedCallback = instrumentation._patchEnd(span, resultHandler); // handle when options is the callback to send the correct number of args if (typeof options === 'function') { @@ -413,7 +416,8 @@ export class MongoDBInstrumentation extends InstrumentationBase { span, ns, server, - cursorState.cmd + cursorState.cmd, + 'getMore' ); const patchedCallback = instrumentation._patchEnd(span, resultHandler); // handle when options is the callback to send the correct number of args @@ -472,7 +476,8 @@ export class MongoDBInstrumentation extends InstrumentationBase { span: Span, connectionCtx: any, ns: any, - command?: any + command?: any, + operation?: string ) { let host, port: undefined | string; if (connectionCtx) { @@ -501,7 +506,8 @@ export class MongoDBInstrumentation extends InstrumentationBase { ns.collection, host, port, - commandObj + commandObj, + operation ); } @@ -516,7 +522,8 @@ export class MongoDBInstrumentation extends InstrumentationBase { span: Span, ns: string, topology: MongoInternalTopology, - command?: MongoInternalCommand + command?: MongoInternalCommand, + operation?: string | undefined ) { // add network attributes to determine the remote server let host: undefined | string; @@ -548,7 +555,8 @@ export class MongoDBInstrumentation extends InstrumentationBase { dbCollection, host, port, - commandObj + commandObj, + operation ); } @@ -558,13 +566,15 @@ export class MongoDBInstrumentation extends InstrumentationBase { dbCollection?: string, host?: undefined | string, port?: undefined | string, - commandObj?: any + commandObj?: any, + operation?: string | undefined ) { // add database related attributes span.setAttributes({ [SemanticAttributes.DB_SYSTEM]: DbSystemValues.MONGODB, [SemanticAttributes.DB_NAME]: dbName, [SemanticAttributes.DB_MONGODB_COLLECTION]: dbCollection, + [SemanticAttributes.DB_OPERATION]: operation, }); if (host && port) { diff --git a/plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v3.test.ts b/plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v3.test.ts index 3a663957f6..5a0b39e773 100644 --- a/plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v3.test.ts +++ b/plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v3.test.ts @@ -112,7 +112,12 @@ describe('MongoDBInstrumentation', () => { .insertMany(insertData) .then(() => { span.end(); - assertSpans(getTestSpans(), 'mongodb.insert', SpanKind.CLIENT); + assertSpans( + getTestSpans(), + 'mongodb.insert', + SpanKind.CLIENT, + 'insert' + ); done(); }) .catch(err => { @@ -128,7 +133,12 @@ describe('MongoDBInstrumentation', () => { .updateOne({ a: 2 }, { $set: { b: 1 } }) .then(() => { span.end(); - assertSpans(getTestSpans(), 'mongodb.update', SpanKind.CLIENT); + assertSpans( + getTestSpans(), + 'mongodb.update', + SpanKind.CLIENT, + 'update' + ); done(); }) .catch(err => { @@ -144,7 +154,12 @@ describe('MongoDBInstrumentation', () => { .deleteOne({ a: 3 }) .then(() => { span.end(); - assertSpans(getTestSpans(), 'mongodb.remove', SpanKind.CLIENT); + assertSpans( + getTestSpans(), + 'mongodb.remove', + SpanKind.CLIENT, + 'remove' + ); done(); }) .catch(err => { @@ -164,7 +179,12 @@ describe('MongoDBInstrumentation', () => { .toArray() .then(() => { span.end(); - assertSpans(getTestSpans(), 'mongodb.find', SpanKind.CLIENT); + assertSpans( + getTestSpans(), + 'mongodb.find', + SpanKind.CLIENT, + 'find' + ); done(); }) .catch(err => { @@ -190,7 +210,8 @@ describe('MongoDBInstrumentation', () => { span => !span.name.includes('mongodb.getMore') ), 'mongodb.find', - SpanKind.CLIENT + SpanKind.CLIENT, + 'find' ); // assert that we correctly got the first as a find assertSpans( @@ -198,7 +219,8 @@ describe('MongoDBInstrumentation', () => { span => !span.name.includes('mongodb.find') ), 'mongodb.getMore', - SpanKind.CLIENT + SpanKind.CLIENT, + 'getMore' ); done(); }) @@ -222,7 +244,8 @@ describe('MongoDBInstrumentation', () => { assertSpans( getTestSpans(), 'mongodb.createIndexes', - SpanKind.CLIENT + SpanKind.CLIENT, + 'createIndexes' ); done(); }) @@ -253,7 +276,14 @@ describe('MongoDBInstrumentation', () => { span.end(); const spans = getTestSpans(); const operationName = 'mongodb.insert'; - assertSpans(spans, operationName, SpanKind.CLIENT, false, false); + assertSpans( + spans, + operationName, + SpanKind.CLIENT, + 'insert', + false, + false + ); const mongoSpan = spans.find(s => s.name === operationName); const dbStatement = JSON.parse( mongoSpan!.attributes[SemanticAttributes.DB_STATEMENT] as string @@ -291,7 +321,14 @@ describe('MongoDBInstrumentation', () => { span.end(); const spans = getTestSpans(); const operationName = 'mongodb.insert'; - assertSpans(spans, operationName, SpanKind.CLIENT, false, true); + assertSpans( + spans, + operationName, + SpanKind.CLIENT, + 'insert', + false, + true + ); const mongoSpan = spans.find(s => s.name === operationName); const dbStatement = JSON.parse( mongoSpan!.attributes[SemanticAttributes.DB_STATEMENT] as string @@ -324,7 +361,7 @@ describe('MongoDBInstrumentation', () => { .then(() => { span.end(); const spans = getTestSpans(); - assertSpans(spans, 'mongodb.insert', SpanKind.CLIENT); + assertSpans(spans, 'mongodb.insert', SpanKind.CLIENT, 'insert'); done(); }) .catch(err => { @@ -421,7 +458,7 @@ describe('MongoDBInstrumentation', () => { .then(() => { span.end(); const spans = getTestSpans(); - assertSpans(spans, 'mongodb.find', SpanKind.CLIENT); + assertSpans(spans, 'mongodb.find', SpanKind.CLIENT, 'find'); done(); }) .catch(err => { @@ -443,7 +480,7 @@ describe('MongoDBInstrumentation', () => { span.end(); const spans = getTestSpans(); const mainSpan = spans[spans.length - 1]; - assertSpans(spans, 'mongodb.insert', SpanKind.CLIENT); + assertSpans(spans, 'mongodb.insert', SpanKind.CLIENT, 'insert'); resetMemoryExporter(); collection @@ -453,7 +490,7 @@ describe('MongoDBInstrumentation', () => { const spans2 = getTestSpans(); spans2.push(mainSpan); - assertSpans(spans2, 'mongodb.find', SpanKind.CLIENT); + assertSpans(spans2, 'mongodb.find', SpanKind.CLIENT, 'find'); assert.strictEqual( mainSpan.spanContext().spanId, spans2[0].parentSpanId diff --git a/plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v4.test.ts b/plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v4.test.ts index f42be4b03b..3101a947d2 100644 --- a/plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v4.test.ts +++ b/plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v4.test.ts @@ -111,7 +111,12 @@ describe('MongoDBInstrumentation', () => { .insertMany(insertData) .then(() => { span.end(); - assertSpans(getTestSpans(), 'mongodb.insert', SpanKind.CLIENT); + assertSpans( + getTestSpans(), + 'mongodb.insert', + SpanKind.CLIENT, + 'insert' + ); done(); }) .catch(err => { @@ -127,7 +132,12 @@ describe('MongoDBInstrumentation', () => { .updateOne({ a: 2 }, { $set: { b: 1 } }) .then(() => { span.end(); - assertSpans(getTestSpans(), 'mongodb.update', SpanKind.CLIENT); + assertSpans( + getTestSpans(), + 'mongodb.update', + SpanKind.CLIENT, + 'update' + ); done(); }) .catch(err => { @@ -143,7 +153,12 @@ describe('MongoDBInstrumentation', () => { .deleteOne({ a: 3 }) .then(() => { span.end(); - assertSpans(getTestSpans(), 'mongodb.delete', SpanKind.CLIENT); + assertSpans( + getTestSpans(), + 'mongodb.delete', + SpanKind.CLIENT, + 'delete' + ); done(); }) .catch(err => { @@ -163,7 +178,12 @@ describe('MongoDBInstrumentation', () => { .toArray() .then(() => { span.end(); - assertSpans(getTestSpans(), 'mongodb.find', SpanKind.CLIENT); + assertSpans( + getTestSpans(), + 'mongodb.find', + SpanKind.CLIENT, + 'find' + ); done(); }) .catch(err => { @@ -189,7 +209,8 @@ describe('MongoDBInstrumentation', () => { span => !span.name.includes('mongodb.getMore') ), 'mongodb.find', - SpanKind.CLIENT + SpanKind.CLIENT, + 'find' ); // assert that we correctly got the first as a find assertSpans( @@ -197,7 +218,8 @@ describe('MongoDBInstrumentation', () => { span => !span.name.includes('mongodb.find') ), 'mongodb.getMore', - SpanKind.CLIENT + SpanKind.CLIENT, + 'getMore' ); done(); }) @@ -221,7 +243,8 @@ describe('MongoDBInstrumentation', () => { assertSpans( getTestSpans(), 'mongodb.createIndexes', - SpanKind.CLIENT + SpanKind.CLIENT, + 'createIndexes' ); done(); }) @@ -252,7 +275,14 @@ describe('MongoDBInstrumentation', () => { span.end(); const spans = getTestSpans(); const operationName = 'mongodb.insert'; - assertSpans(spans, operationName, SpanKind.CLIENT, false, false); + assertSpans( + spans, + operationName, + SpanKind.CLIENT, + 'insert', + false, + false + ); const mongoSpan = spans.find(s => s.name === operationName); const dbStatement = JSON.parse( mongoSpan!.attributes[SemanticAttributes.DB_STATEMENT] as string @@ -290,7 +320,14 @@ describe('MongoDBInstrumentation', () => { span.end(); const spans = getTestSpans(); const operationName = 'mongodb.insert'; - assertSpans(spans, operationName, SpanKind.CLIENT, false, true); + assertSpans( + spans, + operationName, + SpanKind.CLIENT, + 'insert', + false, + true + ); const mongoSpan = spans.find(s => s.name === operationName); const dbStatement = JSON.parse( mongoSpan!.attributes[SemanticAttributes.DB_STATEMENT] as string @@ -323,7 +360,7 @@ describe('MongoDBInstrumentation', () => { .then(() => { span.end(); const spans = getTestSpans(); - assertSpans(spans, 'mongodb.insert', SpanKind.CLIENT); + assertSpans(spans, 'mongodb.insert', SpanKind.CLIENT, 'insert'); done(); }) .catch(err => { @@ -417,7 +454,7 @@ describe('MongoDBInstrumentation', () => { .then(() => { span.end(); const spans = getTestSpans(); - assertSpans(spans, 'mongodb.find', SpanKind.CLIENT); + assertSpans(spans, 'mongodb.find', SpanKind.CLIENT, 'find'); done(); }) .catch(err => { @@ -439,7 +476,7 @@ describe('MongoDBInstrumentation', () => { span.end(); const spans = getTestSpans(); const mainSpan = spans[spans.length - 1]; - assertSpans(spans, 'mongodb.insert', SpanKind.CLIENT); + assertSpans(spans, 'mongodb.insert', SpanKind.CLIENT, 'insert'); resetMemoryExporter(); collection @@ -448,7 +485,7 @@ describe('MongoDBInstrumentation', () => { .then(() => { const spans2 = getTestSpans(); spans2.push(mainSpan); - assertSpans(spans2, 'mongodb.find', SpanKind.CLIENT); + assertSpans(spans2, 'mongodb.find', SpanKind.CLIENT, 'find'); assert.strictEqual( mainSpan.spanContext().spanId, spans2[0].parentSpanId diff --git a/plugins/node/opentelemetry-instrumentation-mongodb/test/utils.ts b/plugins/node/opentelemetry-instrumentation-mongodb/test/utils.ts index fde0af56d8..3da0a1833c 100644 --- a/plugins/node/opentelemetry-instrumentation-mongodb/test/utils.ts +++ b/plugins/node/opentelemetry-instrumentation-mongodb/test/utils.ts @@ -65,6 +65,7 @@ export function assertSpans( spans: ReadableSpan[], expectedName: string, expectedKind: SpanKind, + expectedOperation: string, log = false, isEnhancedDatabaseReportingEnabled = false ) { @@ -79,6 +80,10 @@ export function assertSpans( const [mongoSpan] = spans; assert.strictEqual(mongoSpan.name, expectedName); assert.strictEqual(mongoSpan.kind, expectedKind); + assert.strictEqual( + mongoSpan.attributes[SemanticAttributes.DB_OPERATION], + expectedOperation + ); assert.strictEqual( mongoSpan.attributes[SemanticAttributes.DB_SYSTEM], 'mongodb' diff --git a/plugins/node/opentelemetry-instrumentation-mongodb/tsconfig.json b/plugins/node/opentelemetry-instrumentation-mongodb/tsconfig.json index 28be80d266..5c3680dd33 100644 --- a/plugins/node/opentelemetry-instrumentation-mongodb/tsconfig.json +++ b/plugins/node/opentelemetry-instrumentation-mongodb/tsconfig.json @@ -2,7 +2,8 @@ "extends": "../../../tsconfig.base", "compilerOptions": { "rootDir": ".", - "outDir": "build" + "outDir": "build", + "skipLibCheck": true }, "include": [ "src/**/*.ts", diff --git a/plugins/node/opentelemetry-instrumentation-mysql/CHANGELOG.md b/plugins/node/opentelemetry-instrumentation-mysql/CHANGELOG.md index 3c268dc429..f5b1a6a6c1 100644 --- a/plugins/node/opentelemetry-instrumentation-mysql/CHANGELOG.md +++ b/plugins/node/opentelemetry-instrumentation-mysql/CHANGELOG.md @@ -1,5 +1,53 @@ # Changelog +## [0.33.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-mysql-v0.33.0...instrumentation-mysql-v0.33.1) (2023-04-25) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.38.0 ([#1468](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1468)) ([565a2b2](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/565a2b2c6fde88af3f5401ef6a5a9643d0d66349)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.1 to ^0.33.2 + +## [0.33.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-mysql-v0.32.0...instrumentation-mysql-v0.33.0) (2023-02-07) + + +### Features + +* **mysql:** Metrics for mysql ([#1220](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1220)) ([8b8bfeb](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/8b8bfebdd6b4f43a8df540979874a6c01c999957)) + + +### Bug Fixes + +* **deps:** update otel core experimental to ^0.35.1 ([#1358](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1358)) ([ff109b7](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/ff109b77928cc9a139a21c63d6b54399bb017fa4)) +* **mysql:** add enhancedDatabaseReporting to mysql ([#1337](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1337)) ([04d583b](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/04d583bc879c275d521ed5cbee84a3b79e1292eb)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.33.0 to ^0.33.1 + +## [0.32.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-mysql-v0.31.2...instrumentation-mysql-v0.32.0) (2022-11-16) + + +### Features + +* update experimental deps to `^0.34.0`, core deps to `^1.8.0`, api to `^1.3.0` ([#1278](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1278)) ([e9fe8e1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/e9fe8e13e34f54e96c50525cadeb74ac048c5624)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @opentelemetry/contrib-test-utils bumped from ^0.32.0 to ^0.33.0 + ## [0.31.2](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-mysql-v0.31.1...instrumentation-mysql-v0.31.2) (2022-11-02) diff --git a/plugins/node/opentelemetry-instrumentation-mysql/README.md b/plugins/node/opentelemetry-instrumentation-mysql/README.md index 94074d0448..72b95ab438 100644 --- a/plugins/node/opentelemetry-instrumentation-mysql/README.md +++ b/plugins/node/opentelemetry-instrumentation-mysql/README.md @@ -42,6 +42,13 @@ registerInstrumentations({ See [examples](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-mysql/examples) for a short example. +### MySQL instrumentation Options + +| Options | Type | Default | Description | +| ------- | ---- | --------| ----------- | +| [`enhancedDatabaseReporting`](./src/types.ts#L24) | `boolean` | `false` | If true, an attribute containing the query's parameters will be attached the spans generated to represent the query | +| + ## Useful links - For more information on OpenTelemetry, visit: diff --git a/plugins/node/opentelemetry-instrumentation-mysql/examples/README.md b/plugins/node/opentelemetry-instrumentation-mysql/examples/README.md index 7b3180e372..f9bad1d088 100644 --- a/plugins/node/opentelemetry-instrumentation-mysql/examples/README.md +++ b/plugins/node/opentelemetry-instrumentation-mysql/examples/README.md @@ -1,6 +1,6 @@ # Overview -OpenTelemetry MySQL Instrumentation allows the user to automatically collect trace data and export them to the backend of choice (we can use Zipkin or Jaeger for this example), to give observability to distributed systems. +OpenTelemetry MySQL Instrumentation allows the user to automatically collect trace data and metrics and export them to the backend of choice (we can use Zipkin, Jaeger or Grafana for this example), to give observability to distributed systems. This is a modification of the HTTP example that executes multiple parallel requests that interact with a MySQL server backend using the `mysql` npm module. The example displays traces using multiple connection methods. @@ -8,6 +8,10 @@ This is a modification of the HTTP example that executes multiple parallel reque - Pool Connection Query - Cluster Pool Connection Query +## supported metrics + +- Currently only `db.client.connections.usage` is supported, which denoted the number of idle/used connections. + ## Installation ```sh @@ -19,6 +23,12 @@ Setup [Zipkin Tracing](https://zipkin.io/pages/quickstart.html) or Setup [Jaeger Tracing](https://www.jaegertracing.io/docs/latest/getting-started/#all-in-one) +In case you want to see also metrics: + +1. Go to `docker` folder +2. Run `docker compose up`. This will set up Zipkin, Jaeger, otel collector, Prometheus and Grafana. +3. To see your metrics, go to `http://localhost:3000/`. + ## Run the Application ### Zipkin diff --git a/plugins/node/opentelemetry-instrumentation-mysql/examples/docker/collector/otel-collector-config.yaml b/plugins/node/opentelemetry-instrumentation-mysql/examples/docker/collector/otel-collector-config.yaml new file mode 100644 index 0000000000..bf4e67b135 --- /dev/null +++ b/plugins/node/opentelemetry-instrumentation-mysql/examples/docker/collector/otel-collector-config.yaml @@ -0,0 +1,44 @@ +receivers: + otlp: + protocols: + grpc: + +exporters: + prometheus: + endpoint: "0.0.0.0:8889" + const_labels: + label1: value1 + + logging: + loglevel: debug + + zipkin: + endpoint: "http://zipkin-all-in-one:9411/api/v2/spans" + format: proto + + jaeger: + endpoint: jaeger-all-in-one:14250 + tls: + insecure: true + +processors: + batch: + +extensions: + health_check: + pprof: + endpoint: :1888 + zpages: + endpoint: :55679 + +service: + extensions: [pprof, zpages, health_check] + pipelines: + traces: + receivers: [otlp] + processors: [batch] + exporters: [logging] + metrics: + receivers: [otlp] + processors: [batch] + exporters: [logging, prometheus] diff --git a/plugins/node/opentelemetry-instrumentation-mysql/examples/docker/docker-compose.yaml b/plugins/node/opentelemetry-instrumentation-mysql/examples/docker/docker-compose.yaml new file mode 100644 index 0000000000..88cc5e4c0e --- /dev/null +++ b/plugins/node/opentelemetry-instrumentation-mysql/examples/docker/docker-compose.yaml @@ -0,0 +1,68 @@ +version: "2" +services: + +# mysql + mysql: + image: mysql:5.7 + command: --init-file /etc/mysql/init.sql + volumes: + - ./mysql/init.sql:/etc/mysql/init.sql + environment: + - MYSQL_ROOT_PASSWORD=secret + ports: + - "3306:3306" + +# Jaeger + + jaeger-all-in-one: + image: jaegertracing/all-in-one:latest + ports: + - "16686:16686" + - "14268" + - "14250" + +# Zipkin + + zipkin-all-in-one: + image: openzipkin/zipkin:latest + ports: + - "9411:9411" + +# Collector + + otel-collector: + image: otel/opentelemetry-collector-contrib:0.61.0 + command: ["--config=/etc/otel-collector-config.yaml", ""] + volumes: + - ./collector/otel-collector-config.yaml:/etc/otel-collector-config.yaml + ports: + - "1888:1888" # pprof extension + - "8888:8888" # Prometheus metrics exposed by the collector + - "8889:8889" # Prometheus exporter metrics + - "13133:13133" # health_check extension + - "4317:4317" # OTLP gRPC receiver + - "55679:55679" # zpages extension + depends_on: + - jaeger-all-in-one + - zipkin-all-in-one + +# Prometheus + + prometheus: + image: quay.io/prometheus/prometheus:v2.34.0 + command: --config.file=/etc/prometheus/prometheus.yml --no-scrape.adjust-timestamps + volumes: + - ./prometheus/prometheus.yaml:/etc/prometheus/prometheus.yml + ports: + - "9090:9090" + +# Grafana + + grafana: + image: grafana/grafana:9.0.1 + container_name: grafana + volumes: + - ./grafana/grafana.ini:/etc/grafana/grafana.ini + - ./grafana/provisioning/:/etc/grafana/provisioning/ + ports: + - "3000:3000" diff --git a/plugins/node/opentelemetry-instrumentation-mysql/examples/docker/grafana/grafana.ini b/plugins/node/opentelemetry-instrumentation-mysql/examples/docker/grafana/grafana.ini new file mode 100644 index 0000000000..519810a52b --- /dev/null +++ b/plugins/node/opentelemetry-instrumentation-mysql/examples/docker/grafana/grafana.ini @@ -0,0 +1,1170 @@ +##################### Grafana Configuration Example ##################### +# +# Everything has defaults so you only need to uncomment things you want to +# change + +# possible values : production, development +;app_mode = production + +# instance name, defaults to HOSTNAME environment variable value or hostname if HOSTNAME var is empty +;instance_name = ${HOSTNAME} + +# force migration will run migrations that might cause dataloss +;force_migration = false + +#################################### Paths #################################### +[paths] +# Path to where grafana can store temp files, sessions, and the sqlite3 db (if that is used) +;data = /var/lib/grafana + +# Temporary files in `data` directory older than given duration will be removed +;temp_data_lifetime = 24h + +# Directory where grafana can store logs +;logs = /var/log/grafana + +# Directory where grafana will automatically scan and look for plugins +;plugins = /var/lib/grafana/plugins + +# folder that contains provisioning config files that grafana will apply on startup and while running. +provisioning = /etc/grafana/provisioning + +#################################### Server #################################### +[server] +# Protocol (http, https, h2, socket) +;protocol = http + +# The ip address to bind to, empty will bind to all interfaces +;http_addr = + +# The http port to use +;http_port = 3000 + +# The public facing domain name used to access grafana from a browser +;domain = localhost + +# Redirect to correct domain if host header does not match domain +# Prevents DNS rebinding attacks +;enforce_domain = false + +# The full public facing url you use in browser, used for redirects and emails +# If you use reverse proxy and sub path specify full url (with sub path) +;root_url = %(protocol)s://%(domain)s:%(http_port)s/ + +# Serve Grafana from subpath specified in `root_url` setting. By default it is set to `false` for compatibility reasons. +;serve_from_sub_path = false + +# Log web requests +;router_logging = false + +# the path relative working path +;static_root_path = public + +# enable gzip +;enable_gzip = false + +# https certs & key file +;cert_file = +;cert_key = + +# Unix socket path +;socket = + +# CDN Url +;cdn_url = + +# Sets the maximum time using a duration format (5s/5m/5ms) before timing out read of an incoming request and closing idle connections. +# `0` means there is no timeout for reading the request. +;read_timeout = 0 + +#################################### Database #################################### +[database] +# You can configure the database connection by specifying type, host, name, user and password +# as separate properties or as on string using the url properties. + +# Either "mysql", "postgres" or "sqlite3", it's your choice +;type = sqlite3 +;host = 127.0.0.1:3306 +;name = grafana +;user = root +# If the password contains # or ; you have to wrap it with triple quotes. Ex """#password;""" +;password = + +# Use either URL or the previous fields to configure the database +# Example: mysql://user:secret@host:port/database +;url = + +# For "postgres" only, either "disable", "require" or "verify-full" +;ssl_mode = disable + +# Database drivers may support different transaction isolation levels. +# Currently, only "mysql" driver supports isolation levels. +# If the value is empty - driver's default isolation level is applied. +# For "mysql" use "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ" or "SERIALIZABLE". +;isolation_level = + +;ca_cert_path = +;client_key_path = +;client_cert_path = +;server_cert_name = + +# For "sqlite3" only, path relative to data_path setting +;path = grafana.db + +# Max idle conn setting default is 2 +;max_idle_conn = 2 + +# Max conn setting default is 0 (mean not set) +;max_open_conn = + +# Connection Max Lifetime default is 14400 (means 14400 seconds or 4 hours) +;conn_max_lifetime = 14400 + +# Set to true to log the sql calls and execution times. +;log_queries = + +# For "sqlite3" only. cache mode setting used for connecting to the database. (private, shared) +;cache_mode = private + +# For "mysql" only if lockingMigration feature toggle is set. How many seconds to wait before failing to lock the database for the migrations, default is 0. +;locking_attempt_timeout_sec = 0 + +################################### Data sources ######################### +[datasources] +# Upper limit of data sources that Grafana will return. This limit is a temporary configuration and it will be deprecated when pagination will be introduced on the list data sources API. +;datasource_limit = 5000 + +#################################### Cache server ############################# +[remote_cache] +# Either "redis", "memcached" or "database" default is "database" +;type = database + +# cache connectionstring options +# database: will use Grafana primary database. +# redis: config like redis server e.g. `addr=127.0.0.1:6379,pool_size=100,db=0,ssl=false`. Only addr is required. ssl may be 'true', 'false', or 'insecure'. +# memcache: 127.0.0.1:11211 +;connstr = + +#################################### Data proxy ########################### +[dataproxy] + +# This enables data proxy logging, default is false +;logging = false + +# How long the data proxy waits to read the headers of the response before timing out, default is 30 seconds. +# This setting also applies to core backend HTTP data sources where query requests use an HTTP client with timeout set. +;timeout = 30 + +# How long the data proxy waits to establish a TCP connection before timing out, default is 10 seconds. +;dialTimeout = 10 + +# How many seconds the data proxy waits before sending a keepalive probe request. +;keep_alive_seconds = 30 + +# How many seconds the data proxy waits for a successful TLS Handshake before timing out. +;tls_handshake_timeout_seconds = 10 + +# How many seconds the data proxy will wait for a server's first response headers after +# fully writing the request headers if the request has an "Expect: 100-continue" +# header. A value of 0 will result in the body being sent immediately, without +# waiting for the server to approve. +;expect_continue_timeout_seconds = 1 + +# Optionally limits the total number of connections per host, including connections in the dialing, +# active, and idle states. On limit violation, dials will block. +# A value of zero (0) means no limit. +;max_conns_per_host = 0 + +# The maximum number of idle connections that Grafana will keep alive. +;max_idle_connections = 100 + +# How many seconds the data proxy keeps an idle connection open before timing out. +;idle_conn_timeout_seconds = 90 + +# If enabled and user is not anonymous, data proxy will add X-Grafana-User header with username into the request, default is false. +;send_user_header = false + +# Limit the amount of bytes that will be read/accepted from responses of outgoing HTTP requests. +;response_limit = 0 + +# Limits the number of rows that Grafana will process from SQL data sources. +;row_limit = 1000000 + +#################################### Analytics #################################### +[analytics] +# Server reporting, sends usage counters to stats.grafana.org every 24 hours. +# No ip addresses are being tracked, only simple counters to track +# running instances, dashboard and error counts. It is very helpful to us. +# Change this option to false to disable reporting. +;reporting_enabled = true + +# The name of the distributor of the Grafana instance. Ex hosted-grafana, grafana-labs +;reporting_distributor = grafana-labs + +# Set to false to disable all checks to https://grafana.com +# for new versions of grafana. The check is used +# in some UI views to notify that a grafana update exists. +# This option does not cause any auto updates, nor send any information +# only a GET request to https://raw.githubusercontent.com/grafana/grafana/main/latest.json to get the latest version. +;check_for_updates = true + +# Set to false to disable all checks to https://grafana.com +# for new versions of plugins. The check is used +# in some UI views to notify that a plugin update exists. +# This option does not cause any auto updates, nor send any information +# only a GET request to https://grafana.com to get the latest versions. +;check_for_plugin_updates = true + +# Google Analytics universal tracking code, only enabled if you specify an id here +;google_analytics_ua_id = + +# Google Tag Manager ID, only enabled if you specify an id here +;google_tag_manager_id = + +# Rudderstack write key, enabled only if rudderstack_data_plane_url is also set +;rudderstack_write_key = + +# Rudderstack data plane url, enabled only if rudderstack_write_key is also set +;rudderstack_data_plane_url = + +# Rudderstack SDK url, optional, only valid if rudderstack_write_key and rudderstack_data_plane_url is also set +;rudderstack_sdk_url = + +# Rudderstack Config url, optional, used by Rudderstack SDK to fetch source config +;rudderstack_config_url = + +# Controls if the UI contains any links to user feedback forms +;feedback_links_enabled = true + +#################################### Security #################################### +[security] +# disable creation of admin user on first start of grafana +;disable_initial_admin_creation = false + +# default admin user, created on startup +;admin_user = admin + +# default admin password, can be changed before first start of grafana, or in profile settings +;admin_password = admin + +# used for signing +;secret_key = SW2YcwTIb9zpOOhoPsMm + +# current key provider used for envelope encryption, default to static value specified by secret_key +;encryption_provider = secretKey.v1 + +# list of configured key providers, space separated (Enterprise only): e.g., awskms.v1 azurekv.v1 +;available_encryption_providers = + +# disable gravatar profile images +;disable_gravatar = false + +# data source proxy whitelist (ip_or_domain:port separated by spaces) +;data_source_proxy_whitelist = + +# disable protection against brute force login attempts +;disable_brute_force_login_protection = false + +# set to true if you host Grafana behind HTTPS. default is false. +;cookie_secure = false + +# set cookie SameSite attribute. defaults to `lax`. can be set to "lax", "strict", "none" and "disabled" +;cookie_samesite = lax + +# set to true if you want to allow browsers to render Grafana in a ,