diff --git a/.commitlintrc.yml b/.commitlintrc.yml deleted file mode 100644 index 1a5e5ac793..0000000000 --- a/.commitlintrc.yml +++ /dev/null @@ -1,29 +0,0 @@ -extends: - - '@commitlint/config-conventional' -rules: - header-max-length: [1, 'always', 72] - type-enum: - - 2 - - always - - - ci - - feat - - fix - - docs - - style - - refactor - - perf - - test - - revert - - chore -help: | - **Possible types**: - `ci`: Changes to our CI configuration files and scripts (example scopes: Travis, Circle CI, BrowserStack, SauceLabs) - `feat`: Adds a new feature. - `fix`: Solves a bug. - `docs`: Adds or alters documentation. (example scopes: readme, worker, code_of_conduct, contributors) - `style`: Improves formatting, white-space. - `refactor`: Rewrites code without feature, performance or bug changes. - `perf`: Improves performance. - `test`: Adds or modifies tests. (example scopes: functionals, unit-tests) - `revert`: Changes that reverting other changes - `chore`: No production code change. Updating grunt tasks etc; diff --git a/CHANGELOG.md b/CHANGELOG.md index a3c28f68e5..f288a54e4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # CHANGELOG -All notable changes to this project will be documented in this file. Do not remove the "Unreleased" header; it is used in the automated release workflow. +As of v0.25.1 (2022-01-24) changelog content has moved to separate CHANGELOG.md files for each package. Use [this search for a list of all CHANGELOG.md files in this repo](https://github.com/search?q=repo%3Aopen-telemetry%2Fopentelemetry-js-contrib+path%3A**%2FCHANGELOG.md&type=code). ## Unreleased diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5b4271439f..8f673ece5d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -42,16 +42,9 @@ for general practices for OpenTelemetry project. #### Conventional commit -The Conventional Commits specification is a lightweight convention on top of commit messages. It provides an easy set of rules for creating an explicit commit history; which makes it easier to write automated tools on top of. This convention dovetails with SemVer, by describing the features, fixes, and breaking changes made in commit messages. You can see examples [here](https://www.conventionalcommits.org/en/v1.0.0-beta.4/#examples). -We use [commitlint](https://github.com/conventional-changelog/commitlint) and [husky](https://github.com/typicode/husky) to prevent bad commit message. -For example, you want to submit the following commit message `git commit -s -am "my bad commit"`. -You will receive the following error : +The Conventional Commits specification is a lightweight convention on top of commit messages. It provides an easy set of rules for creating an explicit commit history; which makes it easier to write automated tools on top of. This convention dovetails with SemVer, by describing the features, fixes, and breaking changes made in commit messages. You can see examples [here](https://www.conventionalcommits.org/en/v1.0.0/#examples). -```text -✖ type must be one of [ci, feat, fix, docs, style, refactor, perf, test, revert, chore] [type-enum] -``` - -Here an example that will pass the verification: `git commit -s -am "chore(opentelemetry-core): update deps"` +We use [the "pr-title" CI workflow](./.github/workflows/pr-title.yml) to ensure PR titles, and hence the commit message from those PRs, follow the Conventional Commits spec. ### Fork diff --git a/package-lock.json b/package-lock.json index 3722ec4183..d5be22d9a8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,8 +19,6 @@ "metapackages/*" ], "devDependencies": { - "@commitlint/cli": "18.4.1", - "@commitlint/config-conventional": "18.4.0", "@typescript-eslint/eslint-plugin": "5.8.1", "@typescript-eslint/parser": "5.8.1", "eslint": "8.7.0", @@ -30,7 +28,6 @@ "eslint-plugin-import": "2.27.5", "eslint-plugin-node": "11.1.0", "eslint-plugin-prettier": "4.2.1", - "husky": "7.0.4", "lerna": "6.6.2", "lerna-changelog": "2.2.0", "prettier": "2.8.8", @@ -2524,584 +2521,6 @@ "node": ">=0.1.90" } }, - "node_modules/@commitlint/cli": { - "version": "18.4.1", - "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-18.4.1.tgz", - "integrity": "sha512-4+jljfd29Udw9RDDyigavLO9LvdbmB8O9xjDzVZ0R3lJuG7nCeyHgnKWIVpFaN590isZMV/cMeQK0gH7hRF40A==", - "dev": true, - "dependencies": { - "@commitlint/format": "^18.4.0", - "@commitlint/lint": "^18.4.0", - "@commitlint/load": "^18.4.1", - "@commitlint/read": "^18.4.0", - "@commitlint/types": "^18.4.0", - "execa": "^5.0.0", - "lodash.isfunction": "^3.0.9", - "resolve-from": "5.0.0", - "resolve-global": "1.0.0", - "yargs": "^17.0.0" - }, - "bin": { - "commitlint": "cli.js" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/config-conventional": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-18.4.0.tgz", - "integrity": "sha512-vArwCZopsZs0FnGsh9AR7uUTPZ5oVGk8+qnEZWq2KTsMjrE0k80b+oZ32GSQmXQT2iMKVrDC8pKX5uKNkCe9Sw==", - "dev": true, - "dependencies": { - "conventional-changelog-conventionalcommits": "^7.0.2" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/config-validator": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-18.4.0.tgz", - "integrity": "sha512-1y6qHMU3o4cYQSK+Y9EnmH6H1GRiwQGjnLIUOIKlekrmfc8MrMk1ByNmb8od4vK3qHJAaL/77/5n+1uyyIF5dA==", - "dev": true, - "dependencies": { - "@commitlint/types": "^18.4.0", - "ajv": "^8.11.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/config-validator/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@commitlint/config-validator/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/@commitlint/ensure": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-18.4.0.tgz", - "integrity": "sha512-N5cJo/n61ULSwz3W5Iz/IZJ0I9H/PaHc+OMcF2XcRVbLa6B3YwzEW66XGCRKVULlsBNSrIH6tk5un9ayXAXIdw==", - "dev": true, - "dependencies": { - "@commitlint/types": "^18.4.0", - "lodash.camelcase": "^4.3.0", - "lodash.kebabcase": "^4.1.1", - "lodash.snakecase": "^4.1.1", - "lodash.startcase": "^4.4.0", - "lodash.upperfirst": "^4.3.1" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/execute-rule": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-18.4.0.tgz", - "integrity": "sha512-g013SWki6ZWhURBLOSXTaVQGWHdA0QlPJGiW4a+YpThezmJOemvc4LiKVpn13AjSKQ40QnmBqpBrxujOaSo+3A==", - "dev": true, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/format": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-18.4.0.tgz", - "integrity": "sha512-MiAe4D5/ahty38CzULdQbpRa3ReKZtx0kyigOWcntq+N5uqez+Ac4/MO7H+3j1kC4G7nfJVfBu6TqcXeyNvhCQ==", - "dev": true, - "dependencies": { - "@commitlint/types": "^18.4.0", - "chalk": "^4.1.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/format/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@commitlint/format/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@commitlint/format/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@commitlint/format/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@commitlint/format/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@commitlint/is-ignored": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-18.4.0.tgz", - "integrity": "sha512-vyBKBj3Q4N3Xe4ZQcJXW9ef6gVrDL9Fl2HXnnC3F0Qt/F6E4runhJkEuUh5DB3WCXTJUHIJkByKPqrnz4RNrZw==", - "dev": true, - "dependencies": { - "@commitlint/types": "^18.4.0", - "semver": "7.5.4" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/lint": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-18.4.0.tgz", - "integrity": "sha512-Wkkf1DPVeLdHYGqtzMBfWoMbUtCojvlzDR89OKVic1rid41iZbb0FzTcwgMYs/1TNWNxoIq9PVVwY7ovLX1aJQ==", - "dev": true, - "dependencies": { - "@commitlint/is-ignored": "^18.4.0", - "@commitlint/parse": "^18.4.0", - "@commitlint/rules": "^18.4.0", - "@commitlint/types": "^18.4.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/load": { - "version": "18.4.1", - "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-18.4.1.tgz", - "integrity": "sha512-o/plBiPJQgbSq/4ipDpsq4HCmURjBAEjr1EO/p2falr3VhwV0WGXTvb8NlihgI8xtSyO6lHvtycrE535GMLQbA==", - "dev": true, - "dependencies": { - "@commitlint/config-validator": "^18.4.0", - "@commitlint/execute-rule": "^18.4.0", - "@commitlint/resolve-extends": "^18.4.0", - "@commitlint/types": "^18.4.0", - "@types/node": "^18.11.9", - "chalk": "^4.1.0", - "cosmiconfig": "^8.3.6", - "cosmiconfig-typescript-loader": "^5.0.0", - "lodash.isplainobject": "^4.0.6", - "lodash.merge": "^4.6.2", - "lodash.uniq": "^4.5.0", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/load/node_modules/@types/node": { - "version": "18.18.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.9.tgz", - "integrity": "sha512-0f5klcuImLnG4Qreu9hPj/rEfFq6YRc5n2mAjSsH+ec/mJL+3voBH0+8T7o8RpFjH7ovc+TRsL/c7OYIQsPTfQ==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@commitlint/load/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@commitlint/load/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@commitlint/load/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@commitlint/load/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@commitlint/load/node_modules/cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dev": true, - "dependencies": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@commitlint/load/node_modules/cosmiconfig-typescript-loader": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-5.0.0.tgz", - "integrity": "sha512-+8cK7jRAReYkMwMiG+bxhcNKiHJDM6bR9FD/nGBXOWdMLuYawjF5cGrtLilJ+LGd3ZjCXnJjR5DkfWPoIVlqJA==", - "dev": true, - "dependencies": { - "jiti": "^1.19.1" - }, - "engines": { - "node": ">=v16" - }, - "peerDependencies": { - "@types/node": "*", - "cosmiconfig": ">=8.2", - "typescript": ">=4" - } - }, - "node_modules/@commitlint/load/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@commitlint/load/node_modules/typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", - "dev": true, - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/@commitlint/message": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-18.4.0.tgz", - "integrity": "sha512-3kg6NQO6pJ+VdBTWi51KInT8ngkxPJaW+iI7URtUALjKcO9K4XY3gf80ZPmS1hDessrjb7qCr1lau8eWMINAQw==", - "dev": true, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/parse": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-18.4.0.tgz", - "integrity": "sha512-SxTCSUZH8CJNYWOlFg18YUQ2RLz8ubXKbpHUIiSNwCbiQx7UDCydp1JnhoB4sOYOxgV8d3nuDwYluRU5KnEY4A==", - "dev": true, - "dependencies": { - "@commitlint/types": "^18.4.0", - "conventional-changelog-angular": "^6.0.0", - "conventional-commits-parser": "^5.0.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/parse/node_modules/conventional-commits-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", - "integrity": "sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==", - "dev": true, - "dependencies": { - "is-text-path": "^2.0.0", - "JSONStream": "^1.3.5", - "meow": "^12.0.1", - "split2": "^4.0.0" - }, - "bin": { - "conventional-commits-parser": "cli.mjs" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@commitlint/parse/node_modules/is-text-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-2.0.0.tgz", - "integrity": "sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==", - "dev": true, - "dependencies": { - "text-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@commitlint/parse/node_modules/meow": { - "version": "12.1.1", - "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", - "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", - "dev": true, - "engines": { - "node": ">=16.10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@commitlint/parse/node_modules/split2": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", - "dev": true, - "engines": { - "node": ">= 10.x" - } - }, - "node_modules/@commitlint/parse/node_modules/text-extensions": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz", - "integrity": "sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@commitlint/read": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-18.4.0.tgz", - "integrity": "sha512-IpnABCbDeOw5npZ09SZZGLfd3T7cFtsxUYm6wT3aGmIB2fXKE3fMeuj3jxXjMibiGIyA3Z5voCMuOcKWpkNySA==", - "dev": true, - "dependencies": { - "@commitlint/top-level": "^18.4.0", - "@commitlint/types": "^18.4.0", - "fs-extra": "^11.0.0", - "git-raw-commits": "^2.0.11", - "minimist": "^1.2.6" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/resolve-extends": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-18.4.0.tgz", - "integrity": "sha512-qhgU6ach+S6sJMD9NjCYiEycOObGhxzWQLQzqlScJCv9zkPs15Bg0ffLXTQ3z7ipXv46XEKYMnSJzjLRw2Tlkg==", - "dev": true, - "dependencies": { - "@commitlint/config-validator": "^18.4.0", - "@commitlint/types": "^18.4.0", - "import-fresh": "^3.0.0", - "lodash.mergewith": "^4.6.2", - "resolve-from": "^5.0.0", - "resolve-global": "^1.0.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/rules": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-18.4.0.tgz", - "integrity": "sha512-T3ChRxQZ6g0iNCpVLc6KeQId0/86TnyQA8PFkng+dWElO2DAA5km/yirgKZV1Xlc+gF7Rf6d+a0ottxdKpOY+w==", - "dev": true, - "dependencies": { - "@commitlint/ensure": "^18.4.0", - "@commitlint/message": "^18.4.0", - "@commitlint/to-lines": "^18.4.0", - "@commitlint/types": "^18.4.0", - "execa": "^5.0.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/to-lines": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-18.4.0.tgz", - "integrity": "sha512-bZXuCtfBPjNgtEnG3gwJrveIgfKK2UdhIhFvKpMTrQl/gAwoto/3mzmE7qGAHwmuP4eZ2U8X7iwMnqIlWmv2Tw==", - "dev": true, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/top-level": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-18.4.0.tgz", - "integrity": "sha512-TfulcA8UHF7MZ6tm4Ci3aqZgMBZa1OoCg4prccWHvwG/hsHujZ7+0FKbeKqDbcSli/YWm4NJwEjl4uh5itIJeA==", - "dev": true, - "dependencies": { - "find-up": "^5.0.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/types": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-18.4.0.tgz", - "integrity": "sha512-MKeaFxt0I9fhqUb2E+YIzX/gZtmkuodJET/XKiZIMvXUff8Ee4Ih86eLg+yAm2jf1pwGBmU02uNOp0y094w2Uw==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/types/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@commitlint/types/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@commitlint/types/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@commitlint/types/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@commitlint/types/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", @@ -9983,7 +9402,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "devOptional": true }, "node_modules/base": { "version": "0.11.2", @@ -10303,7 +9722,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, + "devOptional": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -10532,7 +9951,6 @@ "version": "1.8.15", "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.15.tgz", "integrity": "sha512-0tECWShh6wUysgucJcBAoYegf3JJoZWibxdqhTm7OHPeT42qdjkZ29QCMcKwbgU1kiH+auSIasNRXMLWXafXig==", - "dev": true, "engines": [ "node >=0.10.0" ], @@ -10546,6 +9964,10 @@ "safe-json-stringify": "~1" } }, + "node_modules/bunyan-example": { + "resolved": "plugins/node/opentelemetry-instrumentation-bunyan/examples", + "link": true + }, "node_modules/busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -11461,7 +10883,7 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "devOptional": true }, "node_modules/concat-stream": { "version": "2.0.0", @@ -11579,30 +11001,6 @@ "node": ">= 0.6" } }, - "node_modules/conventional-changelog-angular": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-6.0.0.tgz", - "integrity": "sha512-6qLgrBF4gueoC7AFVHu51nHL9pF9FRjXrH+ceVf7WmAfH3gs+gEYOkvxhjMPjZu57I4AGUGoNTY8V7Hrgf1uqg==", - "dev": true, - "dependencies": { - "compare-func": "^2.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/conventional-changelog-conventionalcommits": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-7.0.2.tgz", - "integrity": "sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==", - "dev": true, - "dependencies": { - "compare-func": "^2.0.0" - }, - "engines": { - "node": ">=16" - } - }, "node_modules/conventional-changelog-core": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.2.4.tgz", @@ -12489,7 +11887,6 @@ "version": "0.8.8", "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.8.tgz", "integrity": "sha512-b7Z7cNtHPhH9EJhNNbbeqTcXB8LGFFZhq1PGgEvpeHlzd36bhbdTWoE/Ba/YguqpBSlAPKnARWhVlhunCMwfxg==", - "dev": true, "hasInstallScript": true, "optional": true, "dependencies": { @@ -16045,21 +15442,6 @@ "ms": "^2.0.0" } }, - "node_modules/husky": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.4.tgz", - "integrity": "sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ==", - "dev": true, - "bin": { - "husky": "lib/bin.js" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/typicode" - } - }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -16222,7 +15604,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, + "devOptional": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -17731,15 +17113,6 @@ "node": ">=8" } }, - "node_modules/jiti": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", - "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", - "dev": true, - "bin": { - "jiti": "bin/jiti.js" - } - }, "node_modules/jmespath": { "version": "0.15.0", "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", @@ -19744,12 +19117,6 @@ "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", "dev": true }, - "node_modules/lodash.isfunction": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", - "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==", - "dev": true - }, "node_modules/lodash.isinteger": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", @@ -19780,12 +19147,6 @@ "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", "dev": true }, - "node_modules/lodash.kebabcase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", - "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==", - "dev": true - }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -19803,30 +19164,6 @@ "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", "dev": true }, - "node_modules/lodash.snakecase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", - "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", - "dev": true - }, - "node_modules/lodash.startcase": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", - "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", - "dev": true - }, - "node_modules/lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", - "dev": true - }, - "node_modules/lodash.upperfirst": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz", - "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==", - "dev": true - }, "node_modules/log-symbols": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", @@ -20622,7 +19959,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, + "devOptional": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -21465,7 +20802,6 @@ "version": "2.29.4", "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", - "dev": true, "optional": true, "engines": { "node": "*" @@ -21832,7 +21168,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", "integrity": "sha512-at/ZndSy3xEGJ8i0ygALh8ru9qy7gWW1cmkaqBN29JmMlIvM//MEO9y1sk/avxuwnPcfhkejkLsuPxH81BrkSg==", - "dev": true, "optional": true, "dependencies": { "mkdirp": "~0.5.1", @@ -21847,7 +21182,6 @@ "version": "6.0.4", "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", "integrity": "sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A==", - "dev": true, "optional": true, "dependencies": { "inflight": "^1.0.4", @@ -21864,7 +21198,6 @@ "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, "optional": true, "dependencies": { "minimist": "^1.2.6" @@ -21877,7 +21210,6 @@ "version": "2.4.5", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", "integrity": "sha512-J5xnxTyqaiw06JjMftq7L9ouA448dw/E7dKghkP9WpKNuwmARNNg+Gk8/u5ryb9N/Yo2+z3MCwuqFK/+qPOPfQ==", - "dev": true, "optional": true, "dependencies": { "glob": "^6.0.1" @@ -22036,7 +21368,7 @@ "version": "2.18.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==", - "dev": true + "devOptional": true }, "node_modules/nanomatch": { "version": "1.2.13", @@ -22127,7 +21459,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", "integrity": "sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA==", - "dev": true, "optional": true, "bin": { "ncp": "bin/ncp" @@ -23835,7 +23166,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, + "devOptional": true, "dependencies": { "wrappy": "1" } @@ -24714,7 +24045,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -26243,36 +25574,6 @@ "node": ">=8" } }, - "node_modules/resolve-global": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-global/-/resolve-global-1.0.0.tgz", - "integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==", - "dev": true, - "dependencies": { - "global-dirs": "^0.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-global/node_modules/global-dirs": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", - "integrity": "sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==", - "dev": true, - "dependencies": { - "ini": "^1.3.4" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/resolve-global/node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, "node_modules/resolve-pkg": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/resolve-pkg/-/resolve-pkg-2.0.0.tgz", @@ -26815,7 +26116,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz", "integrity": "sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg==", - "dev": true, "optional": true }, "node_modules/safe-regex": { @@ -30152,12 +29452,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true - }, "node_modules/union-value": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", @@ -31747,7 +31041,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "devOptional": true }, "node_modules/write-file-atomic": { "version": "4.0.1", @@ -33127,14 +32421,17 @@ "version": "0.33.0", "license": "Apache-2.0", "dependencies": { + "@opentelemetry/api-logs": "^0.45.1", "@opentelemetry/instrumentation": "^0.45.1", "@types/bunyan": "1.8.9" }, "devDependencies": { "@opentelemetry/api": "^1.3.0", - "@opentelemetry/context-async-hooks": "^1.8.0", + "@opentelemetry/resources": "^1.8.0", + "@opentelemetry/sdk-logs": "^0.45.1", "@opentelemetry/sdk-trace-base": "^1.8.0", "@opentelemetry/sdk-trace-node": "^1.8.0", + "@opentelemetry/semantic-conventions": "^1.0.0", "@types/mocha": "7.0.2", "@types/node": "18.6.5", "@types/sinon": "10.0.18", @@ -33154,6 +32451,20 @@ "@opentelemetry/api": "^1.3.0" } }, + "plugins/node/opentelemetry-instrumentation-bunyan/examples": { + "version": "0.45.1", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.3.0", + "@opentelemetry/instrumentation-bunyan": "../", + "@opentelemetry/resources": "^1.8.0", + "@opentelemetry/sdk-node": "^0.45.1", + "bunyan": "^1.8.15" + }, + "engines": { + "node": ">=14" + } + }, "plugins/node/opentelemetry-instrumentation-bunyan/node_modules/@types/mocha": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz", @@ -33626,16 +32937,19 @@ "@fastify/express": "^2.0.2", "@opentelemetry/api": "^1.3.0", "@opentelemetry/context-async-hooks": "^1.8.0", + "@opentelemetry/contrib-test-utils": "^0.35.0", "@opentelemetry/instrumentation-http": "^0.45.1", "@opentelemetry/sdk-trace-base": "^1.8.0", "@opentelemetry/sdk-trace-node": "^1.8.0", "@types/express": "4.17.18", "@types/mocha": "7.0.2", "@types/node": "18.15.3", + "@types/semver": "7.5.5", "fastify": "4.18.0", "mocha": "7.2.0", "nyc": "15.1.0", "rimraf": "5.0.5", + "semver": "^7.5.4", "test-all-versions": "5.0.1", "ts-mocha": "10.0.0", "typescript": "4.4.4" @@ -33659,6 +32973,12 @@ "integrity": "sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw==", "dev": true }, + "plugins/node/opentelemetry-instrumentation-fastify/node_modules/@types/semver": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.5.tgz", + "integrity": "sha512-+d+WYC1BxJ6yVOgUgzK8gWvp5qF8ssV5r4nsDcZWKRWcDQLQ619tvWAxJQYGgBrO1MnLJC7a5GtiYsAoQ47dJg==", + "dev": true + }, "plugins/node/opentelemetry-instrumentation-generic-pool": { "name": "@opentelemetry/instrumentation-generic-pool", "version": "0.32.4", @@ -37157,429 +36477,6 @@ "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", "dev": true }, - "@commitlint/cli": { - "version": "18.4.1", - "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-18.4.1.tgz", - "integrity": "sha512-4+jljfd29Udw9RDDyigavLO9LvdbmB8O9xjDzVZ0R3lJuG7nCeyHgnKWIVpFaN590isZMV/cMeQK0gH7hRF40A==", - "dev": true, - "requires": { - "@commitlint/format": "^18.4.0", - "@commitlint/lint": "^18.4.0", - "@commitlint/load": "^18.4.1", - "@commitlint/read": "^18.4.0", - "@commitlint/types": "^18.4.0", - "execa": "^5.0.0", - "lodash.isfunction": "^3.0.9", - "resolve-from": "5.0.0", - "resolve-global": "1.0.0", - "yargs": "^17.0.0" - } - }, - "@commitlint/config-conventional": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-18.4.0.tgz", - "integrity": "sha512-vArwCZopsZs0FnGsh9AR7uUTPZ5oVGk8+qnEZWq2KTsMjrE0k80b+oZ32GSQmXQT2iMKVrDC8pKX5uKNkCe9Sw==", - "dev": true, - "requires": { - "conventional-changelog-conventionalcommits": "^7.0.2" - } - }, - "@commitlint/config-validator": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-18.4.0.tgz", - "integrity": "sha512-1y6qHMU3o4cYQSK+Y9EnmH6H1GRiwQGjnLIUOIKlekrmfc8MrMk1ByNmb8od4vK3qHJAaL/77/5n+1uyyIF5dA==", - "dev": true, - "requires": { - "@commitlint/types": "^18.4.0", - "ajv": "^8.11.0" - }, - "dependencies": { - "ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - } - } - }, - "@commitlint/ensure": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-18.4.0.tgz", - "integrity": "sha512-N5cJo/n61ULSwz3W5Iz/IZJ0I9H/PaHc+OMcF2XcRVbLa6B3YwzEW66XGCRKVULlsBNSrIH6tk5un9ayXAXIdw==", - "dev": true, - "requires": { - "@commitlint/types": "^18.4.0", - "lodash.camelcase": "^4.3.0", - "lodash.kebabcase": "^4.1.1", - "lodash.snakecase": "^4.1.1", - "lodash.startcase": "^4.4.0", - "lodash.upperfirst": "^4.3.1" - } - }, - "@commitlint/execute-rule": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-18.4.0.tgz", - "integrity": "sha512-g013SWki6ZWhURBLOSXTaVQGWHdA0QlPJGiW4a+YpThezmJOemvc4LiKVpn13AjSKQ40QnmBqpBrxujOaSo+3A==", - "dev": true - }, - "@commitlint/format": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-18.4.0.tgz", - "integrity": "sha512-MiAe4D5/ahty38CzULdQbpRa3ReKZtx0kyigOWcntq+N5uqez+Ac4/MO7H+3j1kC4G7nfJVfBu6TqcXeyNvhCQ==", - "dev": true, - "requires": { - "@commitlint/types": "^18.4.0", - "chalk": "^4.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@commitlint/is-ignored": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-18.4.0.tgz", - "integrity": "sha512-vyBKBj3Q4N3Xe4ZQcJXW9ef6gVrDL9Fl2HXnnC3F0Qt/F6E4runhJkEuUh5DB3WCXTJUHIJkByKPqrnz4RNrZw==", - "dev": true, - "requires": { - "@commitlint/types": "^18.4.0", - "semver": "7.5.4" - } - }, - "@commitlint/lint": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-18.4.0.tgz", - "integrity": "sha512-Wkkf1DPVeLdHYGqtzMBfWoMbUtCojvlzDR89OKVic1rid41iZbb0FzTcwgMYs/1TNWNxoIq9PVVwY7ovLX1aJQ==", - "dev": true, - "requires": { - "@commitlint/is-ignored": "^18.4.0", - "@commitlint/parse": "^18.4.0", - "@commitlint/rules": "^18.4.0", - "@commitlint/types": "^18.4.0" - } - }, - "@commitlint/load": { - "version": "18.4.1", - "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-18.4.1.tgz", - "integrity": "sha512-o/plBiPJQgbSq/4ipDpsq4HCmURjBAEjr1EO/p2falr3VhwV0WGXTvb8NlihgI8xtSyO6lHvtycrE535GMLQbA==", - "dev": true, - "requires": { - "@commitlint/config-validator": "^18.4.0", - "@commitlint/execute-rule": "^18.4.0", - "@commitlint/resolve-extends": "^18.4.0", - "@commitlint/types": "^18.4.0", - "@types/node": "^18.11.9", - "chalk": "^4.1.0", - "cosmiconfig": "^8.3.6", - "cosmiconfig-typescript-loader": "^5.0.0", - "lodash.isplainobject": "^4.0.6", - "lodash.merge": "^4.6.2", - "lodash.uniq": "^4.5.0", - "resolve-from": "^5.0.0" - }, - "dependencies": { - "@types/node": { - "version": "18.18.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.9.tgz", - "integrity": "sha512-0f5klcuImLnG4Qreu9hPj/rEfFq6YRc5n2mAjSsH+ec/mJL+3voBH0+8T7o8RpFjH7ovc+TRsL/c7OYIQsPTfQ==", - "dev": true, - "requires": { - "undici-types": "~5.26.4" - } - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dev": true, - "requires": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" - } - }, - "cosmiconfig-typescript-loader": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-5.0.0.tgz", - "integrity": "sha512-+8cK7jRAReYkMwMiG+bxhcNKiHJDM6bR9FD/nGBXOWdMLuYawjF5cGrtLilJ+LGd3ZjCXnJjR5DkfWPoIVlqJA==", - "dev": true, - "requires": { - "jiti": "^1.19.1" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", - "dev": true, - "peer": true - } - } - }, - "@commitlint/message": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-18.4.0.tgz", - "integrity": "sha512-3kg6NQO6pJ+VdBTWi51KInT8ngkxPJaW+iI7URtUALjKcO9K4XY3gf80ZPmS1hDessrjb7qCr1lau8eWMINAQw==", - "dev": true - }, - "@commitlint/parse": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-18.4.0.tgz", - "integrity": "sha512-SxTCSUZH8CJNYWOlFg18YUQ2RLz8ubXKbpHUIiSNwCbiQx7UDCydp1JnhoB4sOYOxgV8d3nuDwYluRU5KnEY4A==", - "dev": true, - "requires": { - "@commitlint/types": "^18.4.0", - "conventional-changelog-angular": "^6.0.0", - "conventional-commits-parser": "^5.0.0" - }, - "dependencies": { - "conventional-commits-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", - "integrity": "sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==", - "dev": true, - "requires": { - "is-text-path": "^2.0.0", - "JSONStream": "^1.3.5", - "meow": "^12.0.1", - "split2": "^4.0.0" - } - }, - "is-text-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-2.0.0.tgz", - "integrity": "sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==", - "dev": true, - "requires": { - "text-extensions": "^2.0.0" - } - }, - "meow": { - "version": "12.1.1", - "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", - "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", - "dev": true - }, - "split2": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", - "dev": true - }, - "text-extensions": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz", - "integrity": "sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==", - "dev": true - } - } - }, - "@commitlint/read": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-18.4.0.tgz", - "integrity": "sha512-IpnABCbDeOw5npZ09SZZGLfd3T7cFtsxUYm6wT3aGmIB2fXKE3fMeuj3jxXjMibiGIyA3Z5voCMuOcKWpkNySA==", - "dev": true, - "requires": { - "@commitlint/top-level": "^18.4.0", - "@commitlint/types": "^18.4.0", - "fs-extra": "^11.0.0", - "git-raw-commits": "^2.0.11", - "minimist": "^1.2.6" - } - }, - "@commitlint/resolve-extends": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-18.4.0.tgz", - "integrity": "sha512-qhgU6ach+S6sJMD9NjCYiEycOObGhxzWQLQzqlScJCv9zkPs15Bg0ffLXTQ3z7ipXv46XEKYMnSJzjLRw2Tlkg==", - "dev": true, - "requires": { - "@commitlint/config-validator": "^18.4.0", - "@commitlint/types": "^18.4.0", - "import-fresh": "^3.0.0", - "lodash.mergewith": "^4.6.2", - "resolve-from": "^5.0.0", - "resolve-global": "^1.0.0" - } - }, - "@commitlint/rules": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-18.4.0.tgz", - "integrity": "sha512-T3ChRxQZ6g0iNCpVLc6KeQId0/86TnyQA8PFkng+dWElO2DAA5km/yirgKZV1Xlc+gF7Rf6d+a0ottxdKpOY+w==", - "dev": true, - "requires": { - "@commitlint/ensure": "^18.4.0", - "@commitlint/message": "^18.4.0", - "@commitlint/to-lines": "^18.4.0", - "@commitlint/types": "^18.4.0", - "execa": "^5.0.0" - } - }, - "@commitlint/to-lines": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-18.4.0.tgz", - "integrity": "sha512-bZXuCtfBPjNgtEnG3gwJrveIgfKK2UdhIhFvKpMTrQl/gAwoto/3mzmE7qGAHwmuP4eZ2U8X7iwMnqIlWmv2Tw==", - "dev": true - }, - "@commitlint/top-level": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-18.4.0.tgz", - "integrity": "sha512-TfulcA8UHF7MZ6tm4Ci3aqZgMBZa1OoCg4prccWHvwG/hsHujZ7+0FKbeKqDbcSli/YWm4NJwEjl4uh5itIJeA==", - "dev": true, - "requires": { - "find-up": "^5.0.0" - } - }, - "@commitlint/types": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-18.4.0.tgz", - "integrity": "sha512-MKeaFxt0I9fhqUb2E+YIzX/gZtmkuodJET/XKiZIMvXUff8Ee4Ih86eLg+yAm2jf1pwGBmU02uNOp0y094w2Uw==", - "dev": true, - "requires": { - "chalk": "^4.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, "@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", @@ -40838,10 +39735,13 @@ "version": "file:plugins/node/opentelemetry-instrumentation-bunyan", "requires": { "@opentelemetry/api": "^1.3.0", - "@opentelemetry/context-async-hooks": "^1.8.0", + "@opentelemetry/api-logs": "^0.45.1", "@opentelemetry/instrumentation": "^0.45.1", + "@opentelemetry/resources": "^1.8.0", + "@opentelemetry/sdk-logs": "^0.45.1", "@opentelemetry/sdk-trace-base": "^1.8.0", "@opentelemetry/sdk-trace-node": "^1.8.0", + "@opentelemetry/semantic-conventions": "^1.0.0", "@types/bunyan": "1.8.9", "@types/mocha": "7.0.2", "@types/node": "18.6.5", @@ -41261,6 +40161,7 @@ "@fastify/express": "^2.0.2", "@opentelemetry/api": "^1.3.0", "@opentelemetry/context-async-hooks": "^1.8.0", + "@opentelemetry/contrib-test-utils": "^0.35.0", "@opentelemetry/core": "^1.8.0", "@opentelemetry/instrumentation": "^0.45.1", "@opentelemetry/instrumentation-http": "^0.45.1", @@ -41270,10 +40171,12 @@ "@types/express": "4.17.18", "@types/mocha": "7.0.2", "@types/node": "18.15.3", + "@types/semver": "7.5.5", "fastify": "4.18.0", "mocha": "7.2.0", "nyc": "15.1.0", "rimraf": "5.0.5", + "semver": "^7.5.4", "test-all-versions": "5.0.1", "ts-mocha": "10.0.0", "typescript": "4.4.4" @@ -41290,6 +40193,12 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.3.tgz", "integrity": "sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw==", "dev": true + }, + "@types/semver": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.5.tgz", + "integrity": "sha512-+d+WYC1BxJ6yVOgUgzK8gWvp5qF8ssV5r4nsDcZWKRWcDQLQ619tvWAxJQYGgBrO1MnLJC7a5GtiYsAoQ47dJg==", + "dev": true } } }, @@ -45252,7 +44161,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "devOptional": true }, "base": { "version": "0.11.2", @@ -45522,7 +44431,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, + "devOptional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -45718,7 +44627,6 @@ "version": "1.8.15", "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.15.tgz", "integrity": "sha512-0tECWShh6wUysgucJcBAoYegf3JJoZWibxdqhTm7OHPeT42qdjkZ29QCMcKwbgU1kiH+auSIasNRXMLWXafXig==", - "dev": true, "requires": { "dtrace-provider": "~0.8", "moment": "^2.19.3", @@ -45726,6 +44634,16 @@ "safe-json-stringify": "~1" } }, + "bunyan-example": { + "version": "file:plugins/node/opentelemetry-instrumentation-bunyan/examples", + "requires": { + "@opentelemetry/api": "^1.3.0", + "@opentelemetry/instrumentation-bunyan": "../", + "@opentelemetry/resources": "^1.8.0", + "@opentelemetry/sdk-node": "^0.45.1", + "bunyan": "^1.8.15" + } + }, "busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -46418,7 +45336,7 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "devOptional": true }, "concat-stream": { "version": "2.0.0", @@ -46528,24 +45446,6 @@ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" }, - "conventional-changelog-angular": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-6.0.0.tgz", - "integrity": "sha512-6qLgrBF4gueoC7AFVHu51nHL9pF9FRjXrH+ceVf7WmAfH3gs+gEYOkvxhjMPjZu57I4AGUGoNTY8V7Hrgf1uqg==", - "dev": true, - "requires": { - "compare-func": "^2.0.0" - } - }, - "conventional-changelog-conventionalcommits": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-7.0.2.tgz", - "integrity": "sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==", - "dev": true, - "requires": { - "compare-func": "^2.0.0" - } - }, "conventional-changelog-core": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.2.4.tgz", @@ -47244,7 +46144,6 @@ "version": "0.8.8", "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.8.tgz", "integrity": "sha512-b7Z7cNtHPhH9EJhNNbbeqTcXB8LGFFZhq1PGgEvpeHlzd36bhbdTWoE/Ba/YguqpBSlAPKnARWhVlhunCMwfxg==", - "dev": true, "optional": true, "requires": { "nan": "^2.14.0" @@ -50160,12 +49059,6 @@ "ms": "^2.0.0" } }, - "husky": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.4.tgz", - "integrity": "sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ==", - "dev": true - }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -50282,7 +49175,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, + "devOptional": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -51388,12 +50281,6 @@ } } }, - "jiti": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", - "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", - "dev": true - }, "jmespath": { "version": "0.15.0", "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", @@ -53046,12 +51933,6 @@ "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", "dev": true }, - "lodash.isfunction": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", - "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==", - "dev": true - }, "lodash.isinteger": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", @@ -53082,12 +51963,6 @@ "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", "dev": true }, - "lodash.kebabcase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", - "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==", - "dev": true - }, "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -53105,30 +51980,6 @@ "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", "dev": true }, - "lodash.snakecase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", - "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", - "dev": true - }, - "lodash.startcase": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", - "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", - "dev": true - }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", - "dev": true - }, - "lodash.upperfirst": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz", - "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==", - "dev": true - }, "log-symbols": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", @@ -53779,7 +52630,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, + "devOptional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -54467,7 +53318,6 @@ "version": "2.29.4", "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", - "dev": true, "optional": true }, "mongodb": { @@ -54750,7 +53600,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", "integrity": "sha512-at/ZndSy3xEGJ8i0ygALh8ru9qy7gWW1cmkaqBN29JmMlIvM//MEO9y1sk/avxuwnPcfhkejkLsuPxH81BrkSg==", - "dev": true, "optional": true, "requires": { "mkdirp": "~0.5.1", @@ -54762,7 +53611,6 @@ "version": "6.0.4", "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", "integrity": "sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A==", - "dev": true, "optional": true, "requires": { "inflight": "^1.0.4", @@ -54776,7 +53624,6 @@ "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, "optional": true, "requires": { "minimist": "^1.2.6" @@ -54786,7 +53633,6 @@ "version": "2.4.5", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", "integrity": "sha512-J5xnxTyqaiw06JjMftq7L9ouA448dw/E7dKghkP9WpKNuwmARNNg+Gk8/u5ryb9N/Yo2+z3MCwuqFK/+qPOPfQ==", - "dev": true, "optional": true, "requires": { "glob": "^6.0.1" @@ -54955,7 +53801,7 @@ "version": "2.18.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==", - "dev": true + "devOptional": true }, "nanomatch": { "version": "1.2.13", @@ -55033,7 +53879,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", "integrity": "sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA==", - "dev": true, "optional": true }, "negotiator": { @@ -56406,7 +55251,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, + "devOptional": true, "requires": { "wrappy": "1" } @@ -57078,7 +55923,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true + "devOptional": true }, "path-key": { "version": "3.1.1", @@ -58262,32 +57107,6 @@ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true }, - "resolve-global": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-global/-/resolve-global-1.0.0.tgz", - "integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==", - "dev": true, - "requires": { - "global-dirs": "^0.1.1" - }, - "dependencies": { - "global-dirs": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", - "integrity": "sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==", - "dev": true, - "requires": { - "ini": "^1.3.4" - } - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - } - } - }, "resolve-pkg": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/resolve-pkg/-/resolve-pkg-2.0.0.tgz", @@ -58697,7 +57516,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz", "integrity": "sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg==", - "dev": true, "optional": true }, "safe-regex": { @@ -61328,12 +60146,6 @@ "which-boxed-primitive": "^1.0.2" } }, - "undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true - }, "union-value": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", @@ -62623,7 +61435,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "devOptional": true }, "write-file-atomic": { "version": "4.0.1", diff --git a/package.json b/package.json index 5a989b1a92..f543cb72a0 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,6 @@ "types": "build/src/index.d.ts", "scripts": { "clean": "lerna run clean", - "prepare": "husky install", "precompile": "tsc --version && npm run version:update", "version:update": "lerna run version:update", "compile": "lerna run compile", @@ -40,8 +39,6 @@ "author": "OpenTelemetry Authors", "license": "Apache-2.0", "devDependencies": { - "@commitlint/cli": "18.4.1", - "@commitlint/config-conventional": "18.4.0", "@typescript-eslint/eslint-plugin": "5.8.1", "@typescript-eslint/parser": "5.8.1", "eslint": "8.7.0", @@ -51,7 +48,6 @@ "eslint-plugin-import": "2.27.5", "eslint-plugin-node": "11.1.0", "eslint-plugin-prettier": "4.2.1", - "husky": "7.0.4", "lerna": "6.6.2", "lerna-changelog": "2.2.0", "prettier": "2.8.8", diff --git a/plugins/node/opentelemetry-instrumentation-bunyan/README.md b/plugins/node/opentelemetry-instrumentation-bunyan/README.md index 4feb985aa1..c12b489658 100644 --- a/plugins/node/opentelemetry-instrumentation-bunyan/README.md +++ b/plugins/node/opentelemetry-instrumentation-bunyan/README.md @@ -3,7 +3,7 @@ [![NPM Published Version][npm-img]][npm-url] [![Apache License][license-image]][license-image] -This module provides automatic instrumentation for the injection of trace context to [`bunyan`](https://www.npmjs.com/package/bunyan), 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. +This module provides automatic instrumentation of the [`bunyan`](https://www.npmjs.com/package/bunyan) module to inject trace-context into Bunyan log records (log correlation) and to send Bunyan logging to the OpenTelemetry Logging SDK (log sending). It 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. @@ -15,46 +15,106 @@ Compatible with OpenTelemetry JS API and SDK `1.0+`. npm install --save @opentelemetry/instrumentation-bunyan ``` -### Supported Versions +## Supported Versions -- `^1.0.0` +- `bunyan@^1.0.0` ## Usage ```js -const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node'); +const { NodeSDK, tracing, logs, api } = require('@opentelemetry/sdk-node'); const { BunyanInstrumentation } = require('@opentelemetry/instrumentation-bunyan'); -const { registerInstrumentations } = require('@opentelemetry/instrumentation'); - -const provider = new NodeTracerProvider(); -provider.register(); - -registerInstrumentations({ +const sdk = new NodeSDK({ + spanProcessor: new tracing.SimpleSpanProcessor(new tracing.ConsoleSpanExporter()), + logRecordProcessor: new logs.SimpleLogRecordProcessor(new logs.ConsoleLogRecordExporter()), instrumentations: [ new BunyanInstrumentation({ - // Optional hook to insert additional context to bunyan records. - // Called after trace context is added to the record. - logHook: (span, record) => { - record['resource.service.name'] = provider.resource.attributes['service.name']; - }, + // See below for Bunyan instrumentation options. }), - // other instrumentations - ], -}); - -bunyan.createLogger({ name: 'example' }).info('foo'); -// {"name":"example","msg":"foo","trace_id":"e21c7a95fff34e04f77c7bd518779621","span_id":"b7589a981fde09f4","trace_flags":"01", ...} + ] +}) + +const bunyan = require('bunyan'); +const logger = bunyan.createLogger({name: 'example'}); + +logger.info('hi'); +// 1. Log records will be sent to the SDK-registered log record processor, if any. +// This is called "log sending". + +const tracer = api.trace.getTracer('example'); +tracer.startActiveSpan('manual-span', span => { + logger.info('in a span'); + // 2. Fields identifying the current span will be added to log records: + // {"name":"example",...,"msg":"in a span","trace_id":"d61b4e4af1032e0aae279d12f3ab0159","span_id":"d140da862204f2a2","trace_flags":"01"} + // This is called "log correlation". +}) ``` -### Fields added to bunyan records +### Log sending + +Creation of a Bunyan Logger will automatically add a [Bunyan stream](https://github.com/trentm/node-bunyan#streams) that sends log records to the OpenTelemetry Logs SDK. The OpenTelemetry SDK can be configured to handle those records -- for example, sending them on to an OpenTelemetry collector for log archiving and processing. The example above shows a minimal configuration that emits OpenTelemetry log records to the console for debugging. -For the current active span, the following will be added to the bunyan record: +If the OpenTelemetry SDK is not configured with a Logger provider, then this added stream will be a no-op. + +Log sending can be disabled with the `disableLogSending: true` option. + +### Log correlation + +Bunyan logger calls in the context of a tracing span will have fields +indentifying the span added to the log record. This allows +[correlating](https://opentelemetry.io/docs/specs/otel/logs/#log-correlation) +log records with tracing data. The added fields are +([spec](https://opentelemetry.io/docs/specs/otel/compatibility/logging_trace_context/)): - `trace_id` - `span_id` - `trace_flags` +After adding these fields, the optional `logHook` is called to allow injecting additional fields. For example: + +```js + logHook: (span, record) => { + record['resource.service.name'] = provider.resource.attributes['service.name']; + } +``` + When no span context is active or the span context is invalid, injection is skipped. +Log injection can be disabled with the `disableLogCorrelation: true` option. + +### Bunyan instrumentation options + +| Option | Type | Description | +| ----------------------- | ----------------- | ----------- | +| `disableLogSending` | `boolean` | Whether to disable [log sending](#log-sending). Default `false`. | +| `disableLogCorrelation` | `boolean` | Whether to disable [log correlation](#log-correlation). Default `false`. | +| `logHook` | `LogHookFunction` | An option hook to inject additional context to a log record after trace-context has been added. This requires `disableLogCorrelation` to be false. | + +### Using OpenTelemetryBunyanStream without instrumentation + +This package exports the Bunyan stream class that is used to send records to the +OpenTelemetry Logs SDK. It can be used directly when configuring a Bunyan logger +if one is not using the `BunyanInstrumentation` for whatever reason. For +example: + +```js +const { OpenTelemetryBunyanStream } = require('@opentelemetry/instrumentation-bunyan'); +const bunyan = require('bunyan'); + +// You must register an OpenTelemetry LoggerProvider, otherwise log records will +// be sent to a no-op implementation. "examples/telemetry.js" shows one way +// to configure one. +// ... + +const logger = bunyan.createLogger({ + name: 'my-logger', + streams: [ + { + type: 'raw', + stream: new OpenTelemetryBunyanStream() + } + ], +}); +``` ## Useful links diff --git a/plugins/node/opentelemetry-instrumentation-bunyan/examples/README.md b/plugins/node/opentelemetry-instrumentation-bunyan/examples/README.md new file mode 100644 index 0000000000..89041f4bb1 --- /dev/null +++ b/plugins/node/opentelemetry-instrumentation-bunyan/examples/README.md @@ -0,0 +1,114 @@ +This is a small example app, "app.js", that shows using the +[Bunyan](https://github.com/trentm/node-bunyan) logger with OpenTelemetry. See +[the OpenTelemetry Bunyan instrumentation README](../) for full details. + +# Usage + +```bash +npm install +node -r ./telemetry.js app.js +``` + +# Overview + +"telemetry.js" sets up the OpenTelemetry SDK to write OTel tracing spans and +log records to the *console* for simplicity. In a real setup you would +configure exporters to send to remote observability apps for viewing and +analysis. + +An example run looks like this: + +```bash +$ node -r ./telemetry.js app.js +{"name":"myapp","hostname":"amachine.local","pid":93017,"level":20,"msg":"hi","time":"2023-09-27T23:24:06.074Z","v":0} +{ + timestamp: 1695857046074000, + traceId: undefined, + spanId: undefined, + traceFlags: undefined, + severityText: 'debug', + severityNumber: 5, + body: 'hi', + attributes: { name: 'myapp', foo: 'bar' } +} +{"name":"myapp","hostname":"amachine.local","pid":93017,"level":30,"msg":"this record will have trace_id et al fields for the current span","time":"2023-09-27T23:24:06.079Z","v":0,"trace_id":"af5ce23816c4feabb713ee1dc84ef4d3","span_id":"5f50e181ec7bc621","trace_flags":"01"} +{ + timestamp: 1695857046079000, + traceId: 'af5ce23816c4feabb713ee1dc84ef4d3', + spanId: '5f50e181ec7bc621', + traceFlags: 1, + severityText: 'info', + severityNumber: 9, + body: 'this record will have trace_id et al fields for the current span', + attributes: { + name: 'myapp', + trace_id: 'af5ce23816c4feabb713ee1dc84ef4d3', + span_id: '5f50e181ec7bc621', + trace_flags: '01' + } +} +{ + traceId: 'af5ce23816c4feabb713ee1dc84ef4d3', + parentId: undefined, + traceState: undefined, + name: 'manual-span', + id: '5f50e181ec7bc621', + kind: 0, + timestamp: 1695857046079000, + duration: 1407.196, + attributes: {}, + status: { code: 0 }, + events: [], + links: [] +} +``` + +There are two separate Bunyan instrumentation features. The first, called "log +correlation", is that Bunyan log records emitted in the context of a tracing +span will include `trace_id` and `span_id` fields that can be used for +correlating with collected tracing data. + +The second, called "log sending", is that a [Bunyan +stream](https://github.com/trentm/node-bunyan#streams) is automatically added +to created Loggers that will send every log record to the OpenTelemetry Logs +SDK. This means that if the OpenTelemetry SDK has been configured with a Logger +Provider, it will receive them. (If the OpenTelemetry SDK is not configured for +this, then the added Bunyan stream will be a no-op.) + +# Resource attributes + +One thing the `ConsoleLogRecordExporter` output above does not show is some +additional data that is included in exported log records: resource attributes. + +Every OpenTelemetry LoggerProvider has a "resource". The OpenTelemetry SDK +provides configurable "resource detectors" that collect data that is then +included with log records. This can include "host.name" (provided by the +`HostDetector`) and "process.pid" (provided by the `ProcessDetector`) -- which +is why this instrumentation does **not** include the Bunyan "hostname" and "pid" +fields in the log record attributes. + +When configured with the `HostDetector` and `ProcessDetector` (as shown in +"telemetry.js") the log records above also include resource attributes such +as the following: + +```js +{ + 'process.pid': 93017, + 'process.executable.name': 'node', + 'process.executable.path': '/Users/trentm/.nvm/versions/node/v18.18.2/bin/node', + 'process.command_args': [ + '/Users/trentm/.nvm/versions/node/v18.18.2/bin/node', + '-r', + './telemetry.js', + '/Users/trentm/src/opentelemetry-js-contrib/plugins/node/opentelemetry-instrumentation-bunyan/examples/app.js' + ], + 'process.runtime.version': '18.18.2', + 'process.runtime.name': 'nodejs', + 'process.runtime.description': 'Node.js', + 'process.command': '/Users/trentm/src/opentelemetry-js-contrib/plugins/node/opentelemetry-instrumentation-bunyan/examples/app.js', + 'process.owner': 'trentm' + 'host.name': 'amachine.local', + 'host.arch': 'amd64', + 'host.id': '...' +} +``` diff --git a/plugins/node/opentelemetry-instrumentation-bunyan/examples/app.js b/plugins/node/opentelemetry-instrumentation-bunyan/examples/app.js new file mode 100644 index 0000000000..05214a8073 --- /dev/null +++ b/plugins/node/opentelemetry-instrumentation-bunyan/examples/app.js @@ -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. + */ + +// A small example that shows using OpenTelemetry's instrumentation of +// Bunyan loggers. Usage: +// node --require ./telemetry.js app.js + +const otel = require('@opentelemetry/api'); +const bunyan = require('bunyan'); + +const log = bunyan.createLogger({name: 'myapp', level: 'debug'}); + +log.debug({foo: 'bar'}, 'hi'); + +const tracer = otel.trace.getTracer('example'); +tracer.startActiveSpan('manual-span', span => { + log.info('this record will have trace_id et al fields for the current span'); + span.end(); +}); diff --git a/plugins/node/opentelemetry-instrumentation-bunyan/examples/app.mjs b/plugins/node/opentelemetry-instrumentation-bunyan/examples/app.mjs new file mode 100644 index 0000000000..c20d5ff05b --- /dev/null +++ b/plugins/node/opentelemetry-instrumentation-bunyan/examples/app.mjs @@ -0,0 +1,33 @@ +/* + * 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. + */ + +// The equivalent of "app.js", but showing usage with ESM code. +// Usage: +// node --require ./telemetry.js --experimental-loader ../node_modules/@opentelemetry/instrumentation/hook.mjs app.js + +import { trace } from '@opentelemetry/api'; +import bunyan from 'bunyan'; + +const log = bunyan.createLogger({name: 'myapp', level: 'debug'}); + +log.debug({foo: 'bar'}, 'hi'); + +const tracer = trace.getTracer('example'); +tracer.startActiveSpan('manual-span', span => { + log.info('this record will have trace_id et al fields for the current span'); + span.end(); +}); + diff --git a/plugins/node/opentelemetry-instrumentation-bunyan/examples/package.json b/plugins/node/opentelemetry-instrumentation-bunyan/examples/package.json new file mode 100644 index 0000000000..ccd208cd8c --- /dev/null +++ b/plugins/node/opentelemetry-instrumentation-bunyan/examples/package.json @@ -0,0 +1,26 @@ +{ + "name": "bunyan-example", + "private": true, + "version": "0.45.1", + "description": "Example of Bunyan integration with OpenTelemetry", + "scripts": { + "start": "node -r ./telemetry.js app.js" + }, + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/open-telemetry/opentelemetry-js.git" + }, + "engines": { + "node": ">=14" + }, + "author": "OpenTelemetry Authors", + "license": "Apache-2.0", + "// @opentelemetry/instrumentation-bunyan": "TODO: change to a ver when there is a next release", + "dependencies": { + "@opentelemetry/api": "^1.3.0", + "@opentelemetry/instrumentation-bunyan": "../", + "@opentelemetry/resources": "^1.8.0", + "@opentelemetry/sdk-node": "^0.45.1", + "bunyan": "^1.8.15" + } +} diff --git a/plugins/node/opentelemetry-instrumentation-bunyan/examples/telemetry.js b/plugins/node/opentelemetry-instrumentation-bunyan/examples/telemetry.js new file mode 100644 index 0000000000..20f84ee7d1 --- /dev/null +++ b/plugins/node/opentelemetry-instrumentation-bunyan/examples/telemetry.js @@ -0,0 +1,56 @@ +/* + * 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. + */ + +// Setup telemetry for tracing and Bunyan logging. +// +// This writes OTel spans and log records to the console for simplicity. In a +// real setup you would configure exporters to send to remote observability apps +// for viewing and analysis. + +const { NodeSDK, tracing, logs, api } = require('@opentelemetry/sdk-node'); +const { envDetectorSync, hostDetectorSync, processDetectorSync } = require('@opentelemetry/resources'); +// api.diag.setLogger(new api.DiagConsoleLogger(), api.DiagLogLevel.DEBUG); + +const { BunyanInstrumentation } = require('@opentelemetry/instrumentation-bunyan'); + +const sdk = new NodeSDK({ + serviceName: 'bunyan-example', + resourceDetectors: [ + envDetectorSync, + // ProcessDetector adds `process.pid` (among other resource attributes), + // which replaces the usual Bunyan `pid` field. + processDetectorSync, + // The HostDetector adds `host.name` and `host.arch` fields. `host.name` + // replaces the usual Bunyan `hostname` field. HostDetector is *not* a + // default detector of the `NodeSDK`. + hostDetectorSync + ], + spanProcessor: new tracing.SimpleSpanProcessor(new tracing.ConsoleSpanExporter()), + logRecordProcessor: new logs.SimpleLogRecordProcessor(new logs.ConsoleLogRecordExporter()), + instrumentations: [ + new BunyanInstrumentation(), + ] +}) +process.on("SIGTERM", () => { + sdk + .shutdown() + .then( + () => {}, + (err) => console.log("warning: error shutting down OTel SDK", err) + ) + .finally(() => process.exit(0)); +}); +sdk.start(); diff --git a/plugins/node/opentelemetry-instrumentation-bunyan/package.json b/plugins/node/opentelemetry-instrumentation-bunyan/package.json index b192707782..52a2ed161a 100644 --- a/plugins/node/opentelemetry-instrumentation-bunyan/package.json +++ b/plugins/node/opentelemetry-instrumentation-bunyan/package.json @@ -45,9 +45,11 @@ }, "devDependencies": { "@opentelemetry/api": "^1.3.0", - "@opentelemetry/context-async-hooks": "^1.8.0", + "@opentelemetry/resources": "^1.8.0", + "@opentelemetry/sdk-logs": "^0.45.1", "@opentelemetry/sdk-trace-base": "^1.8.0", "@opentelemetry/sdk-trace-node": "^1.8.0", + "@opentelemetry/semantic-conventions": "^1.0.0", "@types/mocha": "7.0.2", "@types/node": "18.6.5", "@types/sinon": "10.0.18", @@ -61,6 +63,7 @@ "typescript": "4.4.4" }, "dependencies": { + "@opentelemetry/api-logs": "^0.45.1", "@opentelemetry/instrumentation": "^0.45.1", "@types/bunyan": "1.8.9" }, diff --git a/plugins/node/opentelemetry-instrumentation-bunyan/src/OpenTelemetryBunyanStream.ts b/plugins/node/opentelemetry-instrumentation-bunyan/src/OpenTelemetryBunyanStream.ts new file mode 100644 index 0000000000..8b3d1c8977 --- /dev/null +++ b/plugins/node/opentelemetry-instrumentation-bunyan/src/OpenTelemetryBunyanStream.ts @@ -0,0 +1,162 @@ +/* + * 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 { logs, SeverityNumber, Logger } from '@opentelemetry/api-logs'; +import type { LogLevelString } from 'bunyan'; +import { VERSION } from './version'; + +const DEFAULT_INSTRUMENTATION_SCOPE_NAME = + '@opentelemetry/instrumentation-bunyan'; +const DEFAULT_INSTRUMENTATION_SCOPE_VERSION = VERSION; + +// This block is a copy (modulo code style and TypeScript types) of the Bunyan +// code that defines log level value and names. These values won't ever change +// in bunyan@1. This file is part of *instrumenting* Bunyan, so we want to +// avoid a dependency on the library. +const TRACE = 10; +const DEBUG = 20; +const INFO = 30; +const WARN = 40; +const ERROR = 50; +const FATAL = 60; +const levelFromName: Record = { + trace: TRACE, + debug: DEBUG, + info: INFO, + warn: WARN, + error: ERROR, + fatal: FATAL, +}; +const nameFromLevel: { [level: number]: string } = {}; +Object.keys(levelFromName).forEach(function (name) { + nameFromLevel[levelFromName[name as LogLevelString]] = name; +}); + +const OTEL_SEV_NUM_FROM_BUNYAN_LEVEL: { [level: number]: SeverityNumber } = { + [TRACE]: SeverityNumber.TRACE, + [DEBUG]: SeverityNumber.DEBUG, + [INFO]: SeverityNumber.INFO, + [WARN]: SeverityNumber.WARN, + [ERROR]: SeverityNumber.ERROR, + [FATAL]: SeverityNumber.FATAL, +}; + +const EXTRA_SEV_NUMS = [ + SeverityNumber.TRACE2, + SeverityNumber.TRACE3, + SeverityNumber.TRACE4, + SeverityNumber.DEBUG2, + SeverityNumber.DEBUG3, + SeverityNumber.DEBUG4, + SeverityNumber.INFO2, + SeverityNumber.INFO3, + SeverityNumber.INFO4, + SeverityNumber.WARN2, + SeverityNumber.WARN3, + SeverityNumber.WARN4, + SeverityNumber.ERROR2, + SeverityNumber.ERROR3, + SeverityNumber.ERROR4, + SeverityNumber.FATAL2, + SeverityNumber.FATAL3, + SeverityNumber.FATAL4, +]; + +function severityNumberFromBunyanLevel(lvl: number) { + // Fast common case: one of the known levels + const sev = OTEL_SEV_NUM_FROM_BUNYAN_LEVEL[lvl]; + if (sev !== undefined) { + return sev; + } + + // Otherwise, scale the Bunyan level range -- 10 (TRACE) to 70 (FATAL+10) + // -- onto the extra OTel severity numbers (TRACE2, TRACE3, ..., FATAL4). + // Values below bunyan.TRACE map to SeverityNumber.TRACE2, which may be + // considered a bit weird, but it means the unnumbered levels are always + // just for exactly values. + const relativeLevelWeight = (lvl - 10) / (70 - 10); + const otelSevIdx = Math.floor(relativeLevelWeight * EXTRA_SEV_NUMS.length); + const cappedOTelIdx = Math.min( + EXTRA_SEV_NUMS.length - 1, + Math.max(0, otelSevIdx) + ); + const otelSevValue = EXTRA_SEV_NUMS[cappedOTelIdx]; + return otelSevValue; +} + +/** + * A Bunyan stream for sending log records to the OpenTelemetry Logs SDK. + */ +export class OpenTelemetryBunyanStream { + private _otelLogger: Logger; + + constructor() { + this._otelLogger = logs.getLogger( + DEFAULT_INSTRUMENTATION_SCOPE_NAME, + DEFAULT_INSTRUMENTATION_SCOPE_VERSION + ); + } + + /** + * Convert from https://github.com/trentm/node-bunyan#log-record-fields + * to https://opentelemetry.io/docs/specs/otel/logs/data-model/ + * + * Dev Notes: + * - We drop the Bunyan 'v' field. It is meant to indicate the format + * of the Bunyan log record. FWIW, it has always been `0`. + * - The standard Bunyan `hostname` and `pid` fields are removed because they + * are redundant with the OpenTelemetry `host.name` and `process.pid` + * Resource attributes, respectively. This code cannot change the + * LoggerProvider's `resource`, so getting the OpenTelemetry equivalents + * depends on the user using relevant OpenTelemetry resource detectors. + * "examples/telemetry.js" shows using HostDetector and ProcessDetector for + * this. + * - The Bunyan `name` field *could* naturally map to OpenTelemetry's + * `service.name` resource attribute. However, that is debatable, as some + * users might use `name` more like a log4j logger name. + * - Strip the `trace_id` et al fields that may have been added by the + * the _emit wrapper. + */ + write(rec: Record) { + const { + time, + level, + msg, + v, // eslint-disable-line @typescript-eslint/no-unused-vars + hostname, // eslint-disable-line @typescript-eslint/no-unused-vars + pid, // eslint-disable-line @typescript-eslint/no-unused-vars + trace_id, // eslint-disable-line @typescript-eslint/no-unused-vars + span_id, // eslint-disable-line @typescript-eslint/no-unused-vars + trace_flags, // eslint-disable-line @typescript-eslint/no-unused-vars + ...fields + } = rec; + let timestamp = undefined; + if (typeof time.getTime === 'function') { + timestamp = time.getTime(); // ms + } else { + fields.time = time; // Expose non-Date "time" field on attributes. + } + const otelRec = { + timestamp, + observedTimestamp: timestamp, + severityNumber: severityNumberFromBunyanLevel(level), + severityText: nameFromLevel[level], + body: msg, + attributes: fields, + }; + this._otelLogger.emit(otelRec); + } +} diff --git a/plugins/node/opentelemetry-instrumentation-bunyan/src/index.ts b/plugins/node/opentelemetry-instrumentation-bunyan/src/index.ts index c26f998cff..2418a3b930 100644 --- a/plugins/node/opentelemetry-instrumentation-bunyan/src/index.ts +++ b/plugins/node/opentelemetry-instrumentation-bunyan/src/index.ts @@ -16,3 +16,4 @@ export * from './instrumentation'; export * from './types'; +export * from './OpenTelemetryBunyanStream'; diff --git a/plugins/node/opentelemetry-instrumentation-bunyan/src/instrumentation.ts b/plugins/node/opentelemetry-instrumentation-bunyan/src/instrumentation.ts index 0a3a8102a7..c78e27b50b 100644 --- a/plugins/node/opentelemetry-instrumentation-bunyan/src/instrumentation.ts +++ b/plugins/node/opentelemetry-instrumentation-bunyan/src/instrumentation.ts @@ -14,22 +14,32 @@ * limitations under the License. */ +import { inherits } from 'util'; import { context, trace, isSpanContextValid, Span } from '@opentelemetry/api'; import { InstrumentationBase, InstrumentationNodeModuleDefinition, - isWrapped, safeExecuteInTheMiddle, } from '@opentelemetry/instrumentation'; import { BunyanInstrumentationConfig } from './types'; import { VERSION } from './version'; +import { OpenTelemetryBunyanStream } from './OpenTelemetryBunyanStream'; import type * as BunyanLogger from 'bunyan'; +const DEFAULT_CONFIG: BunyanInstrumentationConfig = { + disableLogSending: false, + disableLogCorrelation: false, +}; + export class BunyanInstrumentation extends InstrumentationBase< typeof BunyanLogger > { constructor(config: BunyanInstrumentationConfig = {}) { - super('@opentelemetry/instrumentation-bunyan', VERSION, config); + super( + '@opentelemetry/instrumentation-bunyan', + VERSION, + Object.assign({}, DEFAULT_CONFIG, config) + ); } protected init() { @@ -37,27 +47,55 @@ export class BunyanInstrumentation extends InstrumentationBase< new InstrumentationNodeModuleDefinition( 'bunyan', ['<2.0'], - (logger, moduleVersion) => { + (module: any, moduleVersion) => { this._diag.debug(`Applying patch for bunyan@${moduleVersion}`); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const proto = logger.prototype as any; - if (isWrapped(proto['_emit'])) { - this._unwrap(proto, '_emit'); - } + const instrumentation = this; + const Logger = + module[Symbol.toStringTag] === 'Module' + ? module.default // ESM + : module; // CommonJS this._wrap( - proto, + Logger.prototype, '_emit', // eslint-disable-next-line @typescript-eslint/no-explicit-any this._getPatchedEmit() as any ); - return logger; - }, - (logger, moduleVersion) => { - if (logger === undefined) return; - this._diag.debug(`Removing patch for bunyan@${moduleVersion}`); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - this._unwrap(logger.prototype as any, '_emit'); + + function LoggerTraced(this: any, ...args: unknown[]) { + let inst; + let retval = undefined; + if (this instanceof LoggerTraced) { + // called with `new Logger()` + inst = this; + Logger.apply(this, args); + } else { + // called without `new` + inst = Logger(...args); + retval = inst; + } + // If `_childOptions` is defined, this is a `Logger#child(...)` + // call. We must not add an OTel stream again. + if (args[1] /* _childOptions */ === undefined) { + instrumentation._addStream(inst); + } + return retval; + } + // Must use the deprecated `inherits` to support this style: + // const log = require('bunyan')({name: 'foo'}); + // i.e. calling the constructor function without `new`. + inherits(LoggerTraced, Logger); + + const patchedExports = Object.assign(LoggerTraced, Logger); + + this._wrap( + patchedExports, + 'createLogger', + // eslint-disable-next-line @typescript-eslint/no-explicit-any + this._getPatchedCreateLogger() as any + ); + + return patchedExports; } ), ]; @@ -68,21 +106,24 @@ export class BunyanInstrumentation extends InstrumentationBase< } override setConfig(config: BunyanInstrumentationConfig) { - this._config = config; + this._config = Object.assign({}, DEFAULT_CONFIG, config); } private _getPatchedEmit() { return (original: (...args: unknown[]) => void) => { const instrumentation = this; return function patchedEmit(this: BunyanLogger, ...args: unknown[]) { - const span = trace.getSpan(context.active()); + const config = instrumentation.getConfig(); + if (!instrumentation.isEnabled() || config.disableLogCorrelation) { + return original.apply(this, args); + } + const span = trace.getSpan(context.active()); if (!span) { return original.apply(this, args); } const spanContext = span.spanContext(); - if (!isSpanContextValid(spanContext)) { return original.apply(this, args); } @@ -99,6 +140,30 @@ export class BunyanInstrumentation extends InstrumentationBase< }; } + private _getPatchedCreateLogger() { + return (original: (...args: unknown[]) => void) => { + const instrumentation = this; + return function patchedCreateLogger(...args: unknown[]) { + const logger = original(...args); + instrumentation._addStream(logger); + return logger; + }; + }; + } + + private _addStream(logger: any) { + const config: BunyanInstrumentationConfig = this.getConfig(); + if (!this.isEnabled() || config.disableLogSending) { + return; + } + this._diag.debug('Adding OpenTelemetryBunyanStream to logger'); + logger.addStream({ + type: 'raw', + stream: new OpenTelemetryBunyanStream(), + level: logger.level(), + }); + } + private _callHook(span: Span, record: Record) { const hook = this.getConfig().logHook; diff --git a/plugins/node/opentelemetry-instrumentation-bunyan/src/types.ts b/plugins/node/opentelemetry-instrumentation-bunyan/src/types.ts index 1e1559b463..7a2f5f686b 100644 --- a/plugins/node/opentelemetry-instrumentation-bunyan/src/types.ts +++ b/plugins/node/opentelemetry-instrumentation-bunyan/src/types.ts @@ -21,5 +21,24 @@ import { InstrumentationConfig } from '@opentelemetry/instrumentation'; export type LogHookFunction = (span: Span, record: Record) => void; export interface BunyanInstrumentationConfig extends InstrumentationConfig { + /** + * Whether to disable the automatic sending of log records to the + * OpenTelemetry Logs SDK. + * @default false + */ + disableLogSending?: boolean; + + /** + * Whether to disable the injection trace-context fields, and possibly other + * fields from `logHook()`, into log records for log correlation. + * @default false + */ + disableLogCorrelation?: boolean; + + /** + * A function that allows injecting additional fields in log records. It is + * called, as `logHook(span, record)`, for each log record emitted in a valid + * span context. It requires `disableLogCorrelation` to be false. + */ logHook?: LogHookFunction; } diff --git a/plugins/node/opentelemetry-instrumentation-bunyan/test/bunyan.test.ts b/plugins/node/opentelemetry-instrumentation-bunyan/test/bunyan.test.ts index e82b912638..5ca3744d3d 100644 --- a/plugins/node/opentelemetry-instrumentation-bunyan/test/bunyan.test.ts +++ b/plugins/node/opentelemetry-instrumentation-bunyan/test/bunyan.test.ts @@ -19,47 +19,73 @@ import { SimpleSpanProcessor, } from '@opentelemetry/sdk-trace-base'; import { context, INVALID_SPAN_CONTEXT, trace } from '@opentelemetry/api'; +import { logs, SeverityNumber } from '@opentelemetry/api-logs'; +import { + LoggerProvider, + SimpleLogRecordProcessor, + InMemoryLogRecordExporter, +} from '@opentelemetry/sdk-logs'; import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node'; import { isWrapped } from '@opentelemetry/instrumentation'; -import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks'; +import { Resource } from '@opentelemetry/resources'; +import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions'; import * as assert from 'assert'; -import * as Logger from 'bunyan'; import * as sinon from 'sinon'; import { Writable } from 'stream'; -import { BunyanInstrumentation } from '../src'; +import { BunyanInstrumentation, OpenTelemetryBunyanStream } from '../src'; +import { VERSION } from '../src/version'; + +import type * as BunyanLogger from 'bunyan'; + +// import { diag, DiagConsoleLogger, DiagLogLevel } from '@opentelemetry/api'; +// diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.DEBUG); + +const tracerProvider = new NodeTracerProvider(); +tracerProvider.register(); +tracerProvider.addSpanProcessor( + new SimpleSpanProcessor(new InMemorySpanExporter()) +); +const tracer = tracerProvider.getTracer('default'); + +const resource = new Resource({ + [SemanticResourceAttributes.SERVICE_NAME]: 'test-instrumentation-bunyan', +}); +const loggerProvider = new LoggerProvider({ resource }); +const memExporter = new InMemoryLogRecordExporter(); +loggerProvider.addLogRecordProcessor(new SimpleLogRecordProcessor(memExporter)); +logs.setGlobalLoggerProvider(loggerProvider); -const memoryExporter = new InMemorySpanExporter(); -const provider = new NodeTracerProvider(); -const tracer = provider.getTracer('default'); -provider.addSpanProcessor(new SimpleSpanProcessor(memoryExporter)); -context.setGlobalContextManager(new AsyncHooksContextManager()); +const instrumentation = new BunyanInstrumentation(); +const Logger = require('bunyan'); describe('BunyanInstrumentation', () => { - let logger: Logger; - let stream; + let log: BunyanLogger; + let stream: Writable; let writeSpy: sinon.SinonSpy; - let instrumentation: BunyanInstrumentation; - before(() => { - instrumentation = new BunyanInstrumentation(); - require('bunyan'); + it('is instrumented', () => { assert.ok(isWrapped((Logger.prototype as any)['_emit'])); }); describe('enabled instrumentation', () => { beforeEach(() => { - instrumentation.setConfig({ enabled: true }); + instrumentation.setConfig({}); // reset to defaults + memExporter.getFinishedLogRecords().length = 0; // clear stream = new Writable(); stream._write = () => {}; writeSpy = sinon.spy(stream, 'write'); - logger = Logger.createLogger({ name: 'test', stream }); + log = Logger.createLogger({ + name: 'test-logger-name', + level: 'debug', + stream, + }); }); it('injects span context to records', () => { const span = tracer.startSpan('abc'); context.with(trace.setSpan(context.active(), span), () => { const { traceId, spanId, traceFlags } = span.spanContext(); - logger.info('foo'); + log.info('foo'); sinon.assert.calledOnce(writeSpy); const record = JSON.parse(writeSpy.firstCall.args[0].toString()); assert.strictEqual(record['trace_id'], traceId); @@ -73,16 +99,15 @@ describe('BunyanInstrumentation', () => { }); }); - it('calls the users log hook', () => { + it('calls the logHook', () => { const span = tracer.startSpan('abc'); instrumentation.setConfig({ - enabled: true, logHook: (_span, record) => { record['resource.service.name'] = 'test-service'; }, }); context.with(trace.setSpan(context.active(), span), () => { - logger.info('foo'); + log.info('foo'); sinon.assert.calledOnce(writeSpy); const record = JSON.parse(writeSpy.firstCall.args[0].toString()); assert.strictEqual(record['resource.service.name'], 'test-service'); @@ -90,7 +115,7 @@ describe('BunyanInstrumentation', () => { }); it('does not inject span context if no span is active', () => { - logger.info('foo'); + log.info('foo'); assert.strictEqual(trace.getSpan(context.active()), undefined); sinon.assert.calledOnce(writeSpy); const record = JSON.parse(writeSpy.firstCall.args[0].toString()); @@ -103,7 +128,7 @@ describe('BunyanInstrumentation', () => { it('does not inject span context if span context is invalid', () => { const span = trace.wrapSpanContext(INVALID_SPAN_CONTEXT); context.with(trace.setSpan(context.active(), span), () => { - logger.info('foo'); + log.info('foo'); sinon.assert.calledOnce(writeSpy); const record = JSON.parse(writeSpy.firstCall.args[0].toString()); assert.strictEqual(record['trace_id'], undefined); @@ -113,17 +138,16 @@ describe('BunyanInstrumentation', () => { }); }); - it('does not propagate exceptions from user hooks', () => { + it('does not propagate exceptions from logHook', () => { const span = tracer.startSpan('abc'); instrumentation.setConfig({ - enabled: true, logHook: () => { throw new Error('Oops'); }, }); context.with(trace.setSpan(context.active(), span), () => { const { traceId, spanId } = span.spanContext(); - logger.info('foo'); + log.info('foo'); sinon.assert.calledOnce(writeSpy); const record = JSON.parse(writeSpy.firstCall.args[0].toString()); assert.strictEqual(record['trace_id'], traceId); @@ -131,6 +155,170 @@ describe('BunyanInstrumentation', () => { assert.strictEqual('foo', record['msg']); }); }); + + it('does not inject or call logHook if disableLogCorrelation=true', () => { + instrumentation.setConfig({ + disableLogCorrelation: true, + logHook: (_span, record) => { + record['resource.service.name'] = 'test-service'; + }, + }); + tracer.startActiveSpan('abc', span => { + log.info('foo'); + sinon.assert.calledOnce(writeSpy); + const record = JSON.parse(writeSpy.firstCall.args[0].toString()); + assert.strictEqual('foo', record['msg']); + assert.strictEqual(record['trace_id'], undefined); + assert.strictEqual(record['span_id'], undefined); + assert.strictEqual(record['trace_flags'], undefined); + assert.strictEqual(record['resource.service.name'], undefined); + assert.strictEqual( + memExporter.getFinishedLogRecords().length, + 1, + 'Log sending still works' + ); + span.end(); + }); + }); + + it('emits log records to Logs SDK', () => { + const logRecords = memExporter.getFinishedLogRecords(); + + // levels + log.trace('at trace level'); + log.debug('at debug level'); + log.info('at info level'); + log.warn('at warn level'); + log.error('at error level'); + log.fatal('at fatal level'); + assert.strictEqual(logRecords.length, 5); + assert.strictEqual(logRecords[0].severityNumber, SeverityNumber.DEBUG); + assert.strictEqual(logRecords[0].severityText, 'debug'); + assert.strictEqual(logRecords[1].severityNumber, SeverityNumber.INFO); + assert.strictEqual(logRecords[1].severityText, 'info'); + assert.strictEqual(logRecords[2].severityNumber, SeverityNumber.WARN); + assert.strictEqual(logRecords[2].severityText, 'warn'); + assert.strictEqual(logRecords[3].severityNumber, SeverityNumber.ERROR); + assert.strictEqual(logRecords[3].severityText, 'error'); + assert.strictEqual(logRecords[4].severityNumber, SeverityNumber.FATAL); + assert.strictEqual(logRecords[4].severityText, 'fatal'); + + // attributes, resource, instrumentationScope, etc. + log.info({ foo: 'bar' }, 'a message'); + const rec = logRecords[logRecords.length - 1]; + assert.strictEqual(rec.body, 'a message'); + assert.deepStrictEqual(rec.attributes, { + name: 'test-logger-name', + foo: 'bar', + }); + assert.strictEqual( + rec.resource.attributes['service.name'], + 'test-instrumentation-bunyan' + ); + assert.strictEqual( + rec.instrumentationScope.name, + '@opentelemetry/instrumentation-bunyan' + ); + assert.strictEqual(rec.instrumentationScope.version, VERSION); + assert.strictEqual(rec.spanContext, undefined); + + // spanContext + tracer.startActiveSpan('abc', span => { + const { traceId, spanId, traceFlags } = span.spanContext(); + log.info('in active span'); + const rec = logRecords[logRecords.length - 1]; + assert.strictEqual(rec.spanContext?.traceId, traceId); + assert.strictEqual(rec.spanContext?.spanId, spanId); + assert.strictEqual(rec.spanContext?.traceFlags, traceFlags); + + // This rec should *NOT* have the `trace_id` et al attributes. + assert.strictEqual(rec.attributes.trace_id, undefined); + assert.strictEqual(rec.attributes.span_id, undefined); + assert.strictEqual(rec.attributes.trace_flags, undefined); + + span.end(); + }); + }); + + it('handles log record edge cases', () => { + let rec; + const logRecords = memExporter.getFinishedLogRecords(); + + // A non-Date "time" Bunyan field. + log.info({ time: 'miller' }, 'hi'); + rec = logRecords[logRecords.length - 1]; + assert.deepEqual( + rec.hrTime.map(n => typeof n), + ['number', 'number'] + ); + assert.strictEqual(rec.attributes.time, 'miller'); + + // An atypical Bunyan level number. + log.info({ level: 42 }, 'just above Bunyan WARN==40'); + rec = logRecords[logRecords.length - 1]; + assert.strictEqual(rec.severityNumber, SeverityNumber.WARN2); + assert.strictEqual(rec.severityText, undefined); + + log.info({ level: 200 }, 'far above Bunyan FATAL==60'); + rec = logRecords[logRecords.length - 1]; + assert.strictEqual(rec.severityNumber, SeverityNumber.FATAL4); + assert.strictEqual(rec.severityText, undefined); + }); + + it('does not emit to the Logs SDK if disableLogSending=true', () => { + instrumentation.setConfig({ disableLogSending: true }); + + // Changing `disableLogSending` only has an impact on Loggers created + // *after* it is set. So we cannot test with the `log` created in + // `beforeEach()` above. + log = Logger.createLogger({ name: 'test-logger-name', stream }); + + tracer.startActiveSpan('abc', span => { + const { traceId, spanId } = span.spanContext(); + log.info('foo'); + assert.strictEqual(memExporter.getFinishedLogRecords().length, 0); + + // Test log correlation still works. + sinon.assert.calledOnce(writeSpy); + const record = JSON.parse(writeSpy.firstCall.args[0].toString()); + assert.strictEqual('foo', record['msg']); + assert.strictEqual(record['trace_id'], traceId); + assert.strictEqual(record['span_id'], spanId); + span.end(); + }); + }); + + it('emits to the Logs SDK with `new Logger(...)`', () => { + log = new Logger({ name: 'test-logger-name', stream }); + log.info('foo'); + + const logRecords = memExporter.getFinishedLogRecords(); + assert.strictEqual(logRecords.length, 1); + let rec = logRecords[logRecords.length - 1]; + assert.strictEqual(rec.body, 'foo'); + + const child = log.child({ aProperty: 'bar' }); + child.info('hi'); + rec = logRecords[logRecords.length - 1]; + assert.strictEqual(rec.body, 'hi'); + assert.strictEqual(rec.attributes.aProperty, 'bar'); + }); + + it('emits to the Logs SDK with `Logger(...)`', () => { + log = Logger({ name: 'test-logger-name', stream }); + log.info('foo'); + + const logRecords = memExporter.getFinishedLogRecords(); + assert.strictEqual(logRecords.length, 1); + let rec = logRecords[logRecords.length - 1]; + assert.strictEqual(rec.body, 'foo'); + + const child = log.child({ aProperty: 'bar' }); + child.info('hi'); + rec = logRecords[logRecords.length - 1]; + assert.strictEqual(rec.body, 'hi'); + assert.strictEqual(rec.attributes.aProperty, 'bar'); + }); }); describe('disabled instrumentation', () => { @@ -146,13 +334,14 @@ describe('BunyanInstrumentation', () => { stream = new Writable(); stream._write = () => {}; writeSpy = sinon.spy(stream, 'write'); - logger = Logger.createLogger({ name: 'test', stream }); + log = Logger.createLogger({ name: 'test', stream }); + memExporter.getFinishedLogRecords().length = 0; // clear }); it('does not inject span context', () => { const span = tracer.startSpan('abc'); context.with(trace.setSpan(context.active(), span), () => { - logger.info('foo'); + log.info('foo'); sinon.assert.calledOnce(writeSpy); const record = JSON.parse(writeSpy.firstCall.args[0].toString()); assert.strictEqual(record['trace_id'], undefined); @@ -166,17 +355,102 @@ describe('BunyanInstrumentation', () => { it('does not call log hook', () => { const span = tracer.startSpan('abc'); instrumentation.setConfig({ - enabled: false, logHook: (_span, record) => { record['resource.service.name'] = 'test-service'; }, }); context.with(trace.setSpan(context.active(), span), () => { - logger.info('foo'); + log.info('foo'); sinon.assert.calledOnce(writeSpy); const record = JSON.parse(writeSpy.firstCall.args[0].toString()); assert.strictEqual(record['resource.service.name'], undefined); }); }); + + it('does not emit to the Logs SDK', () => { + tracer.startActiveSpan('abc', span => { + log.info('foo'); + assert.strictEqual(memExporter.getFinishedLogRecords().length, 0); + }); + }); + }); +}); + +describe('OpenTelemetryBunyanStream', () => { + before(() => { + instrumentation.disable(); + }); + + beforeEach(() => { + memExporter.getFinishedLogRecords().length = 0; // clear + }); + + it('can be used directly with createLogger', () => { + const log = Logger.createLogger({ + name: 'test-logger-name', + streams: [ + { + type: 'raw', + stream: new OpenTelemetryBunyanStream(), + level: 'debug', + }, + ], + }); + + // levels + log.trace('at trace level'); + log.debug('at debug level'); + log.info('at info level'); + log.warn('at warn level'); + log.error('at error level'); + log.fatal('at fatal level'); + const logRecords = memExporter.getFinishedLogRecords(); + assert.strictEqual(logRecords.length, 5); + assert.strictEqual(logRecords[0].severityNumber, SeverityNumber.DEBUG); + assert.strictEqual(logRecords[0].severityText, 'debug'); + assert.strictEqual(logRecords[1].severityNumber, SeverityNumber.INFO); + assert.strictEqual(logRecords[1].severityText, 'info'); + assert.strictEqual(logRecords[2].severityNumber, SeverityNumber.WARN); + assert.strictEqual(logRecords[2].severityText, 'warn'); + assert.strictEqual(logRecords[3].severityNumber, SeverityNumber.ERROR); + assert.strictEqual(logRecords[3].severityText, 'error'); + assert.strictEqual(logRecords[4].severityNumber, SeverityNumber.FATAL); + assert.strictEqual(logRecords[4].severityText, 'fatal'); + + // attributes, resource, instrumentationScope, etc. + log.info({ foo: 'bar' }, 'a message'); + const rec = logRecords[logRecords.length - 1]; + assert.strictEqual(rec.body, 'a message'); + assert.deepStrictEqual(rec.attributes, { + name: 'test-logger-name', + foo: 'bar', + }); + assert.strictEqual( + rec.resource.attributes['service.name'], + 'test-instrumentation-bunyan' + ); + assert.strictEqual( + rec.instrumentationScope.name, + '@opentelemetry/instrumentation-bunyan' + ); + assert.strictEqual(rec.instrumentationScope.version, VERSION); + assert.strictEqual(rec.spanContext, undefined); + + // spanContext + tracer.startActiveSpan('abc', span => { + const { traceId, spanId, traceFlags } = span.spanContext(); + log.info('in active span'); + const rec = logRecords[logRecords.length - 1]; + assert.strictEqual(rec.spanContext?.traceId, traceId); + assert.strictEqual(rec.spanContext?.spanId, spanId); + assert.strictEqual(rec.spanContext?.traceFlags, traceFlags); + + // This rec should *NOT* have the `trace_id` et al attributes. + assert.strictEqual(rec.attributes.trace_id, undefined); + assert.strictEqual(rec.attributes.span_id, undefined); + assert.strictEqual(rec.attributes.trace_flags, undefined); + + span.end(); + }); }); }); diff --git a/plugins/node/opentelemetry-instrumentation-express/src/instrumentation.ts b/plugins/node/opentelemetry-instrumentation-express/src/instrumentation.ts index c476649750..61d91b55e6 100644 --- a/plugins/node/opentelemetry-instrumentation-express/src/instrumentation.ts +++ b/plugins/node/opentelemetry-instrumentation-express/src/instrumentation.ts @@ -15,12 +15,23 @@ */ import { getRPCMetadata, RPCType } from '@opentelemetry/core'; -import { trace, context, diag, SpanAttributes } from '@opentelemetry/api'; +import { + trace, + context, + diag, + SpanAttributes, + SpanStatusCode, +} from '@opentelemetry/api'; import type * as express from 'express'; import { ExpressInstrumentationConfig, ExpressRequestInfo } from './types'; import { ExpressLayerType } from './enums/ExpressLayerType'; import { AttributeNames } from './enums/AttributeNames'; -import { getLayerMetadata, storeLayerPath, isLayerIgnored } from './utils'; +import { + asErrorAndMessage, + getLayerMetadata, + isLayerIgnored, + storeLayerPath, +} from './utils'; import { VERSION } from './version'; import { InstrumentationBase, @@ -176,6 +187,7 @@ export class ExpressInstrumentation extends InstrumentationBase< layer[kLayerPatched] = true; this._wrap(layer, 'handle', (original: Function) => { + // TODO: instrument error handlers if (original.length === 4) return original; return function ( this: ExpressLayer, @@ -262,29 +274,55 @@ export class ExpressInstrumentation extends InstrumentationBase< const callbackIdx = args.findIndex(arg => typeof arg === 'function'); if (callbackIdx >= 0) { arguments[callbackIdx] = function () { + // express considers anything but an empty value, "route" or "router" + // passed to its callback to be an error + const maybeError = arguments[0]; + const isError = ![undefined, null, 'route', 'router'].includes( + maybeError + ); + if (isError) { + const [error, message] = asErrorAndMessage(maybeError); + span.recordException(error); + span.setStatus({ + code: SpanStatusCode.ERROR, + message, + }); + } + if (spanHasEnded === false) { spanHasEnded = true; req.res?.removeListener('finish', onResponseFinish); span.end(); } - if (!(req.route && arguments[0] instanceof Error)) { + if (!(req.route && isError)) { (req[_LAYERS_STORE_PROPERTY] as string[]).pop(); } const callback = args[callbackIdx] as Function; return callback.apply(this, arguments); }; } - const result = original.apply(this, arguments); - /** - * At this point if the callback wasn't called, that means either the - * layer is asynchronous (so it will call the callback later on) or that - * the layer directly end the http response, so we'll hook into the "finish" - * event to handle the later case. - */ - if (!spanHasEnded) { - res.once('finish', onResponseFinish); + + try { + return original.apply(this, arguments); + } catch (anyError) { + const [error, message] = asErrorAndMessage(anyError); + span.recordException(error); + span.setStatus({ + code: SpanStatusCode.ERROR, + message, + }); + throw anyError; + } finally { + /** + * At this point if the callback wasn't called, that means either the + * layer is asynchronous (so it will call the callback later on) or that + * the layer directly end the http response, so we'll hook into the "finish" + * event to handle the later case. + */ + if (!spanHasEnded) { + res.once('finish', onResponseFinish); + } } - return result; }; }); } diff --git a/plugins/node/opentelemetry-instrumentation-express/src/utils.ts b/plugins/node/opentelemetry-instrumentation-express/src/utils.ts index d272434422..f543104e49 100644 --- a/plugins/node/opentelemetry-instrumentation-express/src/utils.ts +++ b/plugins/node/opentelemetry-instrumentation-express/src/utils.ts @@ -132,3 +132,16 @@ export const isLayerIgnored = ( return false; }; + +/** + * Converts a user-provided error value into an error and error message pair + * + * @param error - User-provided error value + * @returns Both an Error or string representation of the value and an error message + */ +export const asErrorAndMessage = ( + error: unknown +): [error: string | Error, message: string] => + error instanceof Error + ? [error, error.message] + : [String(error), String(error)]; diff --git a/plugins/node/opentelemetry-instrumentation-express/test/express.test.ts b/plugins/node/opentelemetry-instrumentation-express/test/express.test.ts index 64d6631409..80c0251815 100644 --- a/plugins/node/opentelemetry-instrumentation-express/test/express.test.ts +++ b/plugins/node/opentelemetry-instrumentation-express/test/express.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { context, trace } from '@opentelemetry/api'; +import { SpanStatusCode, context, trace } from '@opentelemetry/api'; import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node'; import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks'; import { @@ -255,6 +255,94 @@ describe('ExpressInstrumentation', () => { ); }); + it('captures sync middleware errors', async () => { + const rootSpan = tracer.startSpan('rootSpan'); + let finishListenerCount: number | undefined; + const httpServer = await serverWithMiddleware(tracer, rootSpan, app => { + app.use((req, res, next) => { + res.on('finish', () => { + finishListenerCount = res.listenerCount('finish'); + }); + next(); + }); + + const errorMiddleware: express.RequestHandler = (req, res, next) => { + throw new Error('message'); + }; + app.use(errorMiddleware); + }); + server = httpServer.server; + port = httpServer.port; + assert.strictEqual(memoryExporter.getFinishedSpans().length, 0); + + await context.with( + trace.setSpan(context.active(), rootSpan), + async () => { + await httpRequest.get(`http://localhost:${port}/toto/tata`); + rootSpan.end(); + assert.strictEqual(finishListenerCount, 3); + + const errorSpan = memoryExporter + .getFinishedSpans() + .find(span => span.name.includes('errorMiddleware')); + assert.notStrictEqual(errorSpan, undefined); + + assert.deepStrictEqual(errorSpan!.status, { + code: SpanStatusCode.ERROR, + message: 'message', + }); + assert.notStrictEqual( + errorSpan!.events.find(event => event.name === 'exception'), + undefined + ); + } + ); + }); + + it('captures async middleware errors', async () => { + const rootSpan = tracer.startSpan('rootSpan'); + let finishListenerCount: number | undefined; + const httpServer = await serverWithMiddleware(tracer, rootSpan, app => { + app.use((req, res, next) => { + res.on('finish', () => { + finishListenerCount = res.listenerCount('finish'); + }); + next(); + }); + + const errorMiddleware: express.RequestHandler = (req, res, next) => { + setTimeout(() => next(new Error('message')), 10); + }; + app.use(errorMiddleware); + }); + server = httpServer.server; + port = httpServer.port; + assert.strictEqual(memoryExporter.getFinishedSpans().length, 0); + + await context.with( + trace.setSpan(context.active(), rootSpan), + async () => { + await httpRequest.get(`http://localhost:${port}/toto/tata`); + rootSpan.end(); + assert.strictEqual(finishListenerCount, 2); + + const errorSpan = memoryExporter + .getFinishedSpans() + .find(span => span.name.includes('errorMiddleware')); + assert.notStrictEqual(errorSpan, undefined); + + assert.deepStrictEqual(errorSpan!.status, { + code: SpanStatusCode.ERROR, + message: 'message', + }); + assert.notStrictEqual( + errorSpan!.events.find(event => event.name === 'exception'), + undefined + ); + } + ); + }); + it('should not create span because there are no parent', async () => { const app = express(); app.use(express.json()); diff --git a/plugins/node/opentelemetry-instrumentation-express/test/utils.test.ts b/plugins/node/opentelemetry-instrumentation-express/test/utils.test.ts index e85a677af1..fc927a9b7f 100644 --- a/plugins/node/opentelemetry-instrumentation-express/test/utils.test.ts +++ b/plugins/node/opentelemetry-instrumentation-express/test/utils.test.ts @@ -142,4 +142,27 @@ describe('Utils', () => { ); }); }); + + describe('asErrorAndMessage', () => { + it('should special case Error instances', () => { + const input = new Error('message'); + const [error, message] = utils.asErrorAndMessage(input); + assert.strictEqual(error, input); + assert.strictEqual(message, 'message'); + }); + + it('should pass strings as-is', () => { + const input = 'error'; + const [error, message] = utils.asErrorAndMessage(input); + assert.strictEqual(error, input); + assert.strictEqual(message, input); + }); + + it('should stringify other types', () => { + const input = 2; + const [error, message] = utils.asErrorAndMessage(input); + assert.strictEqual(error, '2'); + assert.strictEqual(message, '2'); + }); + }); }); diff --git a/plugins/node/opentelemetry-instrumentation-fastify/.tav.yml b/plugins/node/opentelemetry-instrumentation-fastify/.tav.yml index d20da709a9..48410d0903 100644 --- a/plugins/node/opentelemetry-instrumentation-fastify/.tav.yml +++ b/plugins/node/opentelemetry-instrumentation-fastify/.tav.yml @@ -1,5 +1,9 @@ "fastify": - - versions: "4.23.2" + # Sanity check the first 4.x release, instead of all releases, plus recent + # releases. + - versions: "4.0.0 || >=4.24.3 <5" commands: npm run test + +# Fastify versions after 4.18.0 require a typescript greater than 4.4.4. "typescript": - versions: "4.7.4" diff --git a/plugins/node/opentelemetry-instrumentation-fastify/package.json b/plugins/node/opentelemetry-instrumentation-fastify/package.json index c65828d8bc..a0c12a1418 100644 --- a/plugins/node/opentelemetry-instrumentation-fastify/package.json +++ b/plugins/node/opentelemetry-instrumentation-fastify/package.json @@ -46,16 +46,19 @@ "@fastify/express": "^2.0.2", "@opentelemetry/api": "^1.3.0", "@opentelemetry/context-async-hooks": "^1.8.0", + "@opentelemetry/contrib-test-utils": "^0.35.0", "@opentelemetry/instrumentation-http": "^0.45.1", "@opentelemetry/sdk-trace-base": "^1.8.0", "@opentelemetry/sdk-trace-node": "^1.8.0", "@types/express": "4.17.18", "@types/mocha": "7.0.2", "@types/node": "18.15.3", + "@types/semver": "7.5.5", "fastify": "4.18.0", "mocha": "7.2.0", "nyc": "15.1.0", "rimraf": "5.0.5", + "semver": "^7.5.4", "test-all-versions": "5.0.1", "ts-mocha": "10.0.0", "typescript": "4.4.4" diff --git a/plugins/node/opentelemetry-instrumentation-fastify/src/instrumentation.ts b/plugins/node/opentelemetry-instrumentation-fastify/src/instrumentation.ts index e410b93bad..dacc257e97 100644 --- a/plugins/node/opentelemetry-instrumentation-fastify/src/instrumentation.ts +++ b/plugins/node/opentelemetry-instrumentation-fastify/src/instrumentation.ts @@ -96,8 +96,9 @@ export class FastifyInstrumentation extends InstrumentationBase { const anyRequest = request as any; const rpcMetadata = getRPCMetadata(context.active()); - const routeName = - anyRequest.routeOptions?.config?.url || request.routerPath; + const routeName = anyRequest.routeOptions + ? anyRequest.routeOptions.url // since fastify@4.10.0 + : request.routerPath; if (routeName && rpcMetadata?.type === RPCType.HTTP) { rpcMetadata.route = routeName; } @@ -265,9 +266,11 @@ export class FastifyInstrumentation extends InstrumentationBase { const anyRequest = request as any; const handler = - anyRequest.routeOptions?.handler || anyRequest.context?.handler || {}; + anyRequest.routeOptions?.handler || anyRequest.context?.handler; - const handlerName = handler?.name.substr(6); + const handlerName = handler?.name.startsWith('bound ') + ? handler.name.substr(6) + : handler?.name; const spanName = `${FastifyNames.REQUEST_HANDLER} - ${ handlerName || this.pluginName || ANONYMOUS_NAME }`; @@ -275,8 +278,9 @@ export class FastifyInstrumentation extends InstrumentationBase { const spanAttributes: SpanAttributes = { [AttributeNames.PLUGIN_NAME]: this.pluginName, [AttributeNames.FASTIFY_TYPE]: FastifyTypes.REQUEST_HANDLER, - [SemanticAttributes.HTTP_ROUTE]: - anyRequest.routeOptions?.config?.url || request.routerPath, + [SemanticAttributes.HTTP_ROUTE]: anyRequest.routeOptions + ? anyRequest.routeOptions.url // since fastify@4.10.0 + : request.routerPath, }; if (handlerName) { spanAttributes[AttributeNames.FASTIFY_NAME] = handlerName; diff --git a/plugins/node/opentelemetry-instrumentation-fastify/test/fixtures/use-fastify.mjs b/plugins/node/opentelemetry-instrumentation-fastify/test/fixtures/use-fastify.mjs new file mode 100644 index 0000000000..a0d81bcc38 --- /dev/null +++ b/plugins/node/opentelemetry-instrumentation-fastify/test/fixtures/use-fastify.mjs @@ -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. + */ + +// Use fastify from an ES module: +// node --experimental-loader=@opentelemetry/instrumentation/hook.mjs use-fastify.mjs + +import { trace } from '@opentelemetry/api'; +import { createTestNodeSdk } from '@opentelemetry/contrib-test-utils'; + +import { FastifyInstrumentation } from '../../build/src/index.js'; + +const sdk = createTestNodeSdk({ + serviceName: 'use-fastify', + instrumentations: [ + new FastifyInstrumentation() + ] +}) +sdk.start(); + +import Fastify from 'fastify'; +import http from 'http'; + +// Start a fastify server. +const app = Fastify(); +app.get('/a-route', function aRoute(_request, reply) { + reply.send({ hello: 'world' }); +}) +const addr = await app.listen({ port: 0 }); + +// Make a single request to it. +await new Promise(resolve => { + http.get(addr + '/a-route', (res) => { + res.resume(); + res.on('end', () => { + resolve(); + }); + }) +}) + +await app.close(); +await sdk.shutdown(); diff --git a/plugins/node/opentelemetry-instrumentation-fastify/test/instrumentation.test.ts b/plugins/node/opentelemetry-instrumentation-fastify/test/instrumentation.test.ts index 2efccaf724..3c0f541b06 100644 --- a/plugins/node/opentelemetry-instrumentation-fastify/test/instrumentation.test.ts +++ b/plugins/node/opentelemetry-instrumentation-fastify/test/instrumentation.test.ts @@ -25,6 +25,12 @@ import { SimpleSpanProcessor, } from '@opentelemetry/sdk-trace-base'; import { Span } from '@opentelemetry/api'; +import { + getPackageVersion, + runTestFixture, + TestCollector, +} from '@opentelemetry/contrib-test-utils'; +import * as semver from 'semver'; import * as http from 'http'; import { HttpInstrumentation } from '@opentelemetry/instrumentation-http'; import { AttributeNames, FastifyInstrumentation } from '../src'; @@ -32,6 +38,8 @@ import { FastifyRequestInfo } from '../src/types'; const URL = require('url').URL; +const fastifyVersion = getPackageVersion('fastify'); + const httpRequest = { get: (options: http.ClientRequestArgs | string) => { return new Promise((resolve, reject) => { @@ -183,6 +191,23 @@ describe('fastify', () => { assert.strictEqual(span.parentSpanId, baseSpan.spanContext().spanId); }); + it('should generate span for 404 request', async () => { + await startServer(); + await httpRequest.get(`http://localhost:${PORT}/no-such-route`); + + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 5); + const span = spans[2]; + assert.deepStrictEqual(span.attributes, { + 'fastify.name': 'basic404', + 'fastify.type': 'request_handler', + 'plugin.name': 'fastify -> @fastify/express', + }); + assert.strictEqual(span.name, 'request handler - basic404'); + const baseSpan = spans[1]; + assert.strictEqual(span.parentSpanId, baseSpan.spanContext().spanId); + }); + describe('when subsystem is registered', () => { beforeEach(async () => { httpInstrumentation.enable(); @@ -424,12 +449,17 @@ describe('fastify', () => { await startServer(); }); - it('preClose is not instrumented', async () => { - app.addHook('preClose', () => { - assertRootContextActive(); - }); + it('preClose is not instrumented', async function () { + // 'preClose' was added in fastify@4.16.0. + if (semver.lt(fastifyVersion, '4.16.0')) { + this.skip(); + } else { + app.addHook('preClose', () => { + assertRootContextActive(); + }); - await startServer(); + await startServer(); + } }); it('onClose is not instrumented', async () => { @@ -507,4 +537,30 @@ describe('fastify', () => { }); }); }); + + it('should work with ESM usage', async () => { + await runTestFixture({ + cwd: __dirname, + argv: ['fixtures/use-fastify.mjs'], + env: { + NODE_OPTIONS: + '--experimental-loader=@opentelemetry/instrumentation/hook.mjs', + NODE_NO_WARNINGS: '1', + }, + checkResult: (err, stdout, stderr) => { + assert.ifError(err); + }, + checkCollector: (collector: TestCollector) => { + const spans = collector.sortedSpans; + assert.strictEqual(spans.length, 1); + assert.strictEqual(spans[0].name, 'request handler - aRoute'); + assert.strictEqual( + spans[0].attributes.filter(a => a.key === 'plugin.name')[0]?.value + ?.stringValue, + 'fastify', + 'attribute plugin.name' + ); + }, + }); + }); }); diff --git a/plugins/node/opentelemetry-instrumentation-mongodb/.tav.yml b/plugins/node/opentelemetry-instrumentation-mongodb/.tav.yml index 86a2bf927d..518c012a77 100644 --- a/plugins/node/opentelemetry-instrumentation-mongodb/.tav.yml +++ b/plugins/node/opentelemetry-instrumentation-mongodb/.tav.yml @@ -5,7 +5,10 @@ mongodb: - versions: ">=4 <5" commands: npm run test-v4 - versions: ">=5 <6" - commands: npm run test-v5 + commands: npm run test-v5-v6 + - versions: ">=6 <7" + node: '>=15.0.0' + commands: npm run test-v5-v6 # Fix missing `contrib-test-utils` package - pretest: npm run --prefix ../../../ lerna:link + pretest: npm run --prefix ../../../ lerna:link \ No newline at end of file diff --git a/plugins/node/opentelemetry-instrumentation-mongodb/README.md b/plugins/node/opentelemetry-instrumentation-mongodb/README.md index 3ace4bd595..b6c7c16192 100644 --- a/plugins/node/opentelemetry-instrumentation-mongodb/README.md +++ b/plugins/node/opentelemetry-instrumentation-mongodb/README.md @@ -17,7 +17,7 @@ npm install --save @opentelemetry/instrumentation-mongodb ### Supported Versions -- `>=3.3 <5` +- `>=3.3 <7` ## Usage diff --git a/plugins/node/opentelemetry-instrumentation-mongodb/package.json b/plugins/node/opentelemetry-instrumentation-mongodb/package.json index f5e50569f0..64a3d848d4 100644 --- a/plugins/node/opentelemetry-instrumentation-mongodb/package.json +++ b/plugins/node/opentelemetry-instrumentation-mongodb/package.json @@ -9,8 +9,8 @@ "docker:start": "docker run -e MONGODB_DB=opentelemetry-tests -e MONGODB_PORT=27017 -e MONGODB_HOST=127.0.0.1 -p 27017:27017 --rm mongo", "test": "npm run test-v3", "test-v3": "nyc ts-mocha -p tsconfig.json --require '@opentelemetry/contrib-test-utils' 'test/**/mongodb-v3.test.ts'", - "test-v4": "nyc ts-mocha -p tsconfig.json --require '@opentelemetry/contrib-test-utils' 'test/mongodb-v4-v5.metrics.test.ts' 'test/**/mongodb-v4.test.ts'", - "test-v5": "nyc ts-mocha -p tsconfig.json --require '@opentelemetry/contrib-test-utils' 'test/mongodb-v4-v5.metrics.test.ts' 'test/**/mongodb-v5.test.ts'", + "test-v4": "nyc ts-mocha -p tsconfig.json --require '@opentelemetry/contrib-test-utils' 'test/mongodb-v4-v5-v6.metrics.test.ts' 'test/**/mongodb-v4.test.ts'", + "test-v5-v6": "nyc ts-mocha -p tsconfig.json --require '@opentelemetry/contrib-test-utils' 'test/mongodb-v4-v5-v6.metrics.test.ts' 'test/**/mongodb-v5-v6.test.ts'", "test-all-versions": "tav", "tdd": "npm run test -- --watch-extensions ts --watch", "clean": "rimraf build/*", diff --git a/plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts b/plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts index f44e0df2b2..3be3019848 100644 --- a/plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts +++ b/plugins/node/opentelemetry-instrumentation-mongodb/src/instrumentation.ts @@ -97,31 +97,31 @@ export class MongoDBInstrumentation extends InstrumentationBase { ), new InstrumentationNodeModuleDefinition( 'mongodb', - ['4.*', '5.*'], + ['4.*', '5.*', '6.*'], undefined, undefined, [ new InstrumentationNodeModuleFile( 'mongodb/lib/cmap/connection.js', - ['4.*', '5.*'], + ['4.*', '5.*', '6.*'], v4PatchConnection, v4UnpatchConnection ), new InstrumentationNodeModuleFile( 'mongodb/lib/cmap/connection_pool.js', - ['4.*', '5.*'], + ['4.*', '5.*', '6.*'], v4PatchConnectionPool, v4UnpatchConnectionPool ), new InstrumentationNodeModuleFile( 'mongodb/lib/cmap/connect.js', - ['4.*', '5.*'], + ['4.*', '5.*', '6.*'], v4PatchConnect, v4UnpatchConnect ), new InstrumentationNodeModuleFile( 'mongodb/lib/sessions.js', - ['4.*', '5.*'], + ['4.*', '5.*', '6.*'], v4PatchSessions, v4UnpatchSessions ), diff --git a/plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v4-v5.metrics.test.ts b/plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v4-v5-v6.metrics.test.ts similarity index 100% rename from plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v4-v5.metrics.test.ts rename to plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v4-v5-v6.metrics.test.ts diff --git a/plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v5.test.ts b/plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v5-v6.test.ts similarity index 100% rename from plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v5.test.ts rename to plugins/node/opentelemetry-instrumentation-mongodb/test/mongodb-v5-v6.test.ts diff --git a/plugins/node/opentelemetry-instrumentation-net/src/instrumentation.ts b/plugins/node/opentelemetry-instrumentation-net/src/instrumentation.ts index 848744bf42..e3aa6f1e33 100644 --- a/plugins/node/opentelemetry-instrumentation-net/src/instrumentation.ts +++ b/plugins/node/opentelemetry-instrumentation-net/src/instrumentation.ts @@ -162,7 +162,11 @@ export class NetInstrumentation extends InstrumentationBase { } }; - for (const event of [SocketEvent.CLOSE, SocketEvent.ERROR]) { + for (const event of [ + SocketEvent.CLOSE, + SocketEvent.ERROR, + SocketEvent.SECURE_CONNECT, + ]) { socket.once(event, otelTlsRemoveListeners); }