diff --git a/package-lock.json b/package-lock.json index 9f65d70a..054710cb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -65,6 +65,7 @@ "@opentelemetry/sdk-trace-base": "1.25.1", "@opentelemetry/sdk-trace-node": "1.25.1", "@opentelemetry/semantic-conventions": "1.25.1", + "glob": "^11.0.0", "is-promise": "^4.0.0", "nan": "^2.20.0", "node-gyp-build": "^4.8.1", @@ -1520,6 +1521,102 @@ "deprecated": "Use @eslint/object-schema instead", "dev": true }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -3019,6 +3116,16 @@ "@opentelemetry/api": "^1.1.0" } }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@pkgr/core": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", @@ -3921,8 +4028,7 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/base64-js": { "version": "1.5.1", @@ -4565,7 +4671,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -4771,6 +4876,12 @@ "node": ">=0.10" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" + }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", @@ -5660,20 +5771,23 @@ } }, "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz", + "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^4.0.1", + "minimatch": "^10.0.0", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": "*" + "node": "20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -5691,6 +5805,58 @@ "node": ">=10.13.0" } }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/global-directory": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz", @@ -6466,8 +6632,7 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", @@ -6564,6 +6729,24 @@ "node": ">=8" } }, + "node_modules/jackspeak": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.1.tgz", + "integrity": "sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jiti": { "version": "1.21.6", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", @@ -7049,6 +7232,15 @@ "node": ">= 6" } }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -7544,6 +7736,28 @@ "node": ">=8" } }, + "node_modules/nyc/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/nyc/node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -7799,6 +8013,12 @@ "node": ">=8" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "license": "BlueOak-1.0.0" + }, "node_modules/packet-reader": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", @@ -7878,7 +8098,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -7888,6 +8107,31 @@ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, + "node_modules/path-scurry": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.1.tgz", + "integrity": "sha512-CgeuL5uom6j/ZVrg7G/+1IXqRY8JXX4Hghfy5YE0EhoYQWvndP1kufu58cmZLNIDKnRhZrXfdS9urVWx98AipQ==", + "license": "ISC", + "engines": { + "node": "20 || >=22" + } + }, "node_modules/path-to-regexp": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.2.tgz", @@ -8761,6 +9005,28 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/run-async": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", @@ -8962,7 +9228,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -8974,7 +9239,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -9155,6 +9419,21 @@ "node": ">=8" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -9166,6 +9445,19 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", @@ -9309,6 +9601,28 @@ "node": ">=8" } }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/text-extensions": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz", @@ -9980,7 +10294,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -10092,6 +10405,24 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -11235,6 +11566,64 @@ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "dev": true }, + "@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "requires": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==" + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==" + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + } + } + } + }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -12259,6 +12648,12 @@ "@opentelemetry/core": "^1.1.0" } }, + "@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true + }, "@pkgr/core": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", @@ -13000,8 +13395,7 @@ "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "base64-js": { "version": "1.5.1", @@ -13469,7 +13863,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "requires": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -13612,6 +14005,11 @@ "nan": "^2.14.0" } }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, "ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", @@ -14250,17 +14648,48 @@ } }, "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz", + "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "foreground-child": "^3.1.0", + "jackspeak": "^4.0.1", + "minimatch": "^10.0.0", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + } + }, + "minimatch": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==" + } } }, "glob-parent": { @@ -14790,8 +15219,7 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "istanbul-lib-coverage": { "version": "3.2.0", @@ -14867,6 +15295,15 @@ "istanbul-lib-report": "^3.0.0" } }, + "jackspeak": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.1.tgz", + "integrity": "sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog==", + "requires": { + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" + } + }, "jiti": { "version": "1.21.6", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", @@ -15260,6 +15697,11 @@ "kind-of": "^6.0.3" } }, + "minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==" + }, "mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -15667,6 +16109,20 @@ "path-exists": "^4.0.0" } }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, "locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -15864,6 +16320,11 @@ "release-zalgo": "^1.0.0" } }, + "package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==" + }, "packet-reader": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", @@ -15929,14 +16390,29 @@ "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" }, "path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, + "path-scurry": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "requires": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "dependencies": { + "lru-cache": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.1.tgz", + "integrity": "sha512-CgeuL5uom6j/ZVrg7G/+1IXqRY8JXX4Hghfy5YE0EhoYQWvndP1kufu58cmZLNIDKnRhZrXfdS9urVWx98AipQ==" + } + } + }, "path-to-regexp": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.2.tgz", @@ -16574,6 +17050,22 @@ "dev": true, "requires": { "glob": "^7.1.3" + }, + "dependencies": { + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } } }, "run-async": { @@ -16704,7 +17196,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "requires": { "shebang-regex": "^3.0.0" } @@ -16712,8 +17203,7 @@ "shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" }, "shimmer": { "version": "1.2.1", @@ -16871,6 +17361,16 @@ "strip-ansi": "^6.0.1" } }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -16879,6 +17379,14 @@ "ansi-regex": "^5.0.1" } }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, "strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", @@ -16985,6 +17493,22 @@ "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", "minimatch": "^3.0.4" + }, + "dependencies": { + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } } }, "text-extensions": { @@ -17407,7 +17931,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "requires": { "isexe": "^2.0.0" } @@ -17499,6 +18022,16 @@ "strip-ansi": "^6.0.0" } }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/package.json b/package.json index 2beab010..72bb48ae 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "test": "npm run test:unit && npm run test:debug-metrics && npm run test:instrumentations", "test:unit": "cross-env TEST_ALLOW_DOUBLE_START=y nyc ts-mocha --exclude 'test/instrumentation/external/**/*.test.ts' --exclude 'test/separate_process/*' --timeout 60s --parallel --jobs 8 -p tsconfig.json 'test/**/*.test.ts'", "unittest": "ts-mocha -p tsconfig.json 'test/api.test.ts'", + "test:unit:node": "cross-env TEST_ALLOW_DOUBLE_START=y glob -c \"node --require ts-node/register/transpile-only --test --test-timeout=10000 \" \"./test/**/*.test.ts\"", "test:debug-metrics": "nyc --no-clean ts-mocha --timeout 10000 -p tsconfig.json 'test/separate_process/debug_metrics.test.ts'", "test:instrumentations": "nyc ts-mocha --require test/instrumentation/external/setup.ts --jobs 1 'test/instrumentation/external/**/*.test.ts'", "prebuild:current": "node scripts/prebuild-current.js", @@ -153,6 +154,7 @@ "@opentelemetry/sdk-trace-base": "1.25.1", "@opentelemetry/sdk-trace-node": "1.25.1", "@opentelemetry/semantic-conventions": "1.25.1", + "glob": "^11.0.0", "is-promise": "^4.0.0", "nan": "^2.20.0", "node-gyp-build": "^4.8.1", diff --git a/test/instrument.test.ts b/test/instrument.test.ts index a93e56d9..ab14a513 100644 --- a/test/instrument.test.ts +++ b/test/instrument.test.ts @@ -14,44 +14,38 @@ * limitations under the License. */ +import { strict as assert } from 'assert'; +import { afterEach, beforeEach, describe, it, mock } from 'node:test'; import * as tracing from '../src/tracing'; -import * as metrics from '../src/metrics'; import { cleanEnvironment } from './utils'; -import { strict as assert } from 'assert'; -import { describe, it, beforeEach, afterEach, mock } from 'node:test'; describe('instrumentation', () => { let startTracingMock; - let startMetricsMock; beforeEach(() => { delete require.cache[require.resolve('../src/instrument')]; cleanEnvironment(); - startTracingMock = mock.method(tracing, 'startTracing').mock; - startMetricsMock = mock.method(metrics, 'startMetrics').mock; + startTracingMock = mock.method(tracing, 'startTracing', () => {}); }); afterEach(() => { - startTracingMock.restore(); - startMetricsMock.restore(); + startTracingMock.mock.restore(); }); it('importing auto calls startTracing', () => { require('../src/instrument'); - assert.strictEqual(startTracingMock.callCount(), 1); + assert.strictEqual(startTracingMock.mock.callCount(), 1); }); it('calls startTracing when SPLUNK_AUTOINSTRUMENT_PACKAGE_NAMES contains a matching package name', () => { process.env.SPLUNK_AUTOINSTRUMENT_PACKAGE_NAMES = '@splunk/otel,foo'; require('../src/instrument'); - // sinon.assert.calledOnce(startTracingMock); - assert.equal(startTracingMock.callCount(), 1); + assert.equal(startTracingMock.mock.callCount(), 1); }); it('does not call startTracing when SPLUNK_AUTOINSTRUMENT_PACKAGE_NAMES does not contain a matching package name', () => { process.env.SPLUNK_AUTOINSTRUMENT_PACKAGE_NAMES = 'foo,@splunk/zotel'; require('../src/instrument'); - // sinon.assert.notCalled(startTracingMock); - assert.equal(startTracingMock.callCount(), 0); + assert.equal(startTracingMock.mock.callCount(), 0); }); }); diff --git a/test/instrumentation/external/elasticsearch/elasticsearch.test.ts b/test/instrumentation/external/elasticsearch/elasticsearch.test.ts index 5870abfa..5fcd7296 100644 --- a/test/instrumentation/external/elasticsearch/elasticsearch.test.ts +++ b/test/instrumentation/external/elasticsearch/elasticsearch.test.ts @@ -13,20 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { strict as assert } from 'assert'; import * as nock from 'nock'; -import * as assert from 'assert'; +import { after, before, describe, it } from 'node:test'; import * as os from 'os'; import { ElasticsearchInstrumentation } from '../../../../src/instrumentations/external/elasticsearch'; -import { - NodeTracerProvider, - NodeTracerConfig, -} from '@opentelemetry/sdk-trace-node'; -import { - InMemorySpanExporter, - SimpleSpanProcessor, -} from '@opentelemetry/sdk-trace-base'; -import { setInstrumentation, getTestSpans } from '../setup'; +import { getTestSpans, setInstrumentation } from '../setup'; const instrumentation = new ElasticsearchInstrumentation(); diff --git a/test/instrumentation/external/elasticsearch/utils.test.ts b/test/instrumentation/external/elasticsearch/utils.test.ts index 19612894..36762491 100644 --- a/test/instrumentation/external/elasticsearch/utils.test.ts +++ b/test/instrumentation/external/elasticsearch/utils.test.ts @@ -13,11 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import * as sinon from 'sinon'; -import * as assert from 'assert'; -import * as Utils from '../../../../src/instrumentations/external/elasticsearch/utils'; import { SpanKind, SpanStatusCode } from '@opentelemetry/api'; import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; +import { strict as assert } from 'assert'; +import { describe, it, mock } from 'node:test'; +import * as Utils from '../../../../src/instrumentations/external/elasticsearch/utils'; +import { calledWithExactly } from '../../../utils'; describe('elasticsearch utils', () => { const spanMock = { @@ -27,7 +28,7 @@ describe('elasticsearch utils', () => { setAttributes: (obj) => {}, }; - context('defaultDbStatementSerializer', () => { + describe('defaultDbStatementSerializer', () => { it('should serialize', () => { const result = Utils.defaultDbStatementSerializer( 'operationName', @@ -41,59 +42,59 @@ describe('elasticsearch utils', () => { }); }); - context('onError', () => { + describe('onError', () => { it('should record error', () => { - const recordExceptionStub = sinon.stub(spanMock, 'recordException'); - const setStatusStub = sinon.stub(spanMock, 'setStatus'); - const endStub = sinon.stub(spanMock, 'end'); + const recordExceptionStub = mock.method(spanMock, 'recordException'); + const setStatusStub = mock.method(spanMock, 'setStatus'); + const endStub = mock.method(spanMock, 'end'); const error = new Error('test error'); Utils.onError(spanMock, error); - sinon.assert.calledOnce(recordExceptionStub); - sinon.assert.calledWith(recordExceptionStub, error); + assert(recordExceptionStub.mock.callCount() === 1); + calledWithExactly(recordExceptionStub, error); - sinon.assert.calledOnce(setStatusStub); - sinon.assert.calledWith(setStatusStub, { + assert(setStatusStub.mock.callCount() === 1); + calledWithExactly(setStatusStub, { code: SpanStatusCode.ERROR, message: error.message, }); - sinon.assert.calledOnce(endStub); + assert(endStub.mock.callCount() === 1); - recordExceptionStub.restore(); - setStatusStub.restore(); - endStub.restore(); + recordExceptionStub.mock.resetCalls(); + setStatusStub.mock.resetCalls(); + endStub.mock.resetCalls(); }); }); - context('onResponse', () => { + describe('onResponse', () => { it('should record response without responseHook', () => { - const setAttributesStub = sinon.stub(spanMock, 'setAttributes'); - const setStatusStub = sinon.stub(spanMock, 'setStatus'); - const endStub = sinon.stub(spanMock, 'end'); + const setAttributesStub = mock.method(spanMock, 'setAttributes'); + const setStatusStub = mock.method(spanMock, 'setStatus'); + const endStub = mock.method(spanMock, 'end'); Utils.onResponse(spanMock, { meta: { connection: { url: 'http://localhost' } }, }); - sinon.assert.calledOnce(setAttributesStub); - sinon.assert.calledOnce(setStatusStub); - sinon.assert.calledOnce(endStub); - sinon.assert.calledWith(setStatusStub, { code: SpanStatusCode.OK }); + assert(setAttributesStub.mock.callCount() === 1); + assert(setStatusStub.mock.callCount() === 1); + assert(endStub.mock.callCount() === 1); + calledWithExactly(setStatusStub, { code: SpanStatusCode.OK }); - setAttributesStub.restore(); - setStatusStub.restore(); - endStub.restore(); + setAttributesStub.mock.resetCalls(); + setStatusStub.mock.resetCalls(); + endStub.mock.resetCalls(); }); it('should record response with responseHook', () => { - const setAttributesStub = sinon.stub(spanMock, 'setAttributes'); - const setStatusStub = sinon.stub(spanMock, 'setStatus'); - const endStub = sinon.stub(spanMock, 'end'); + const setAttributesStub = mock.method(spanMock, 'setAttributes'); + const setStatusStub = mock.method(spanMock, 'setStatus'); + const endStub = mock.method(spanMock, 'end'); - const responseHook = sinon.spy(); + const responseHook = mock.fn(); Utils.onResponse( spanMock, @@ -101,20 +102,20 @@ describe('elasticsearch utils', () => { responseHook ); - sinon.assert.calledOnce(setAttributesStub); - sinon.assert.calledOnce(setStatusStub); - sinon.assert.calledOnce(endStub); - sinon.assert.calledWith(setStatusStub, { code: SpanStatusCode.OK }); + assert(setAttributesStub.mock.callCount() === 1); + assert(setStatusStub.mock.callCount() === 1); + assert(endStub.mock.callCount() === 1); + calledWithExactly(setStatusStub, { code: SpanStatusCode.OK }); - assert.strictEqual(responseHook.called, true); + assert(responseHook.mock.callCount() === 1); - setAttributesStub.restore(); - setStatusStub.restore(); - endStub.restore(); + setAttributesStub.mock.resetCalls(); + setStatusStub.mock.resetCalls(); + endStub.mock.resetCalls(); }); }); - context('getNetAttributes', () => { + describe('getNetAttributes', () => { const url = 'http://localhost:9200'; const attributes = Utils.getNetAttributes(url); @@ -137,7 +138,7 @@ describe('elasticsearch utils', () => { }); }); - context('getPort', () => { + describe('getPort', () => { it('should get port', () => { const result = Utils.getPort('3030', 'http:'); assert.strictEqual(result, '3030'); @@ -154,7 +155,7 @@ describe('elasticsearch utils', () => { }); }); - context('normalizeArguments', () => { + describe('normalizeArguments', () => { it('should normalize with callback only', () => { const callbackFunction = () => {}; const [params, options, callback] = @@ -176,7 +177,7 @@ describe('elasticsearch utils', () => { }); }); - context('getIndexName', () => { + describe('getIndexName', () => { it('should accept index string', () => { const index = Utils.getIndexName({ index: 'test' }); assert.strictEqual(index, 'test'); @@ -205,22 +206,25 @@ describe('elasticsearch utils', () => { }); }); - context('startSpan', () => { + describe('startSpan', () => { const tracerMock = { startSpan: (name, options?, context?): any => {}, startActiveSpan: () => {}, }; it('should start span with client kind', () => { - const startSpanStub = sinon.stub(tracerMock, 'startSpan'); + const startSpanStub = mock.method(tracerMock, 'startSpan'); Utils.startSpan({ tracer: tracerMock, attributes: { testAttribute: 'testValue' }, }); - sinon.assert.calledOnce(startSpanStub); + assert(startSpanStub.mock.callCount() === 1); - const [operation, options] = startSpanStub.getCall(0).args; + // const [operation, options] = startSpanStub.getCall(0).args; + console.log('startSpanStub.mock.calls[0].arguments'); + console.log(startSpanStub.mock.calls[0].arguments); + const [operation, options] = startSpanStub.mock.calls[0].arguments; assert.strictEqual(operation, 'elasticsearch.request'); assert.strictEqual(options.kind, SpanKind.CLIENT); diff --git a/test/instrumentation/external/sequelize/sequelize.test.ts b/test/instrumentation/external/sequelize/sequelize.test.ts index adc4b1ae..79e90290 100644 --- a/test/instrumentation/external/sequelize/sequelize.test.ts +++ b/test/instrumentation/external/sequelize/sequelize.test.ts @@ -13,22 +13,29 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import * as assert from 'assert'; -import { SequelizeInstrumentation } from '../../../../src/instrumentations/external/sequelize'; -import { extractTableFromQuery } from '../../../../src/instrumentations/external/sequelize/utils'; -import { ReadableSpan, Span } from '@opentelemetry/sdk-trace-base'; import { - context, - diag, - SpanStatusCode, DiagConsoleLogger, ROOT_CONTEXT, + SpanStatusCode, + context, + diag, } from '@opentelemetry/api'; +import { ReadableSpan, Span } from '@opentelemetry/sdk-trace-base'; import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; -import { getTestSpans, setInstrumentation, sqlite3MockModule } from '../setup'; +import { strict as assert } from 'assert'; +import { afterEach, before, beforeEach, describe, it } from 'node:test'; +import { SequelizeInstrumentation } from '../../../../src/instrumentations/external/sequelize'; +import { extractTableFromQuery } from '../../../../src/instrumentations/external/sequelize/utils'; +import { + getTestSpans, + setInstrumentation, + sqlite3MockModule, + provider, + exporter, +} from '../setup'; const instrumentation = new SequelizeInstrumentation(); - +provider.register(); import * as sequelize from 'sequelize'; describe('instrumentation-sequelize', () => { @@ -43,6 +50,8 @@ describe('instrumentation-sequelize', () => { }); beforeEach(() => { + exporter.reset(); + instrumentation.setConfig({}); instrumentation.enable(); }); diff --git a/test/instrumentation/external/setup.ts b/test/instrumentation/external/setup.ts index b4ff4573..83908e1c 100644 --- a/test/instrumentation/external/setup.ts +++ b/test/instrumentation/external/setup.ts @@ -25,15 +25,14 @@ import { diag, DiagConsoleLogger, DiagLogLevel } from '@opentelemetry/api'; diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.ERROR); -const exporter = new InMemorySpanExporter(); -const provider: NodeTracerProvider = new NodeTracerProvider({ +export const exporter = new InMemorySpanExporter(); +export const provider: NodeTracerProvider = new NodeTracerProvider({ resource: new Resource({ [SemanticResourceAttributes.SERVICE_NAME]: 'instrumentations-test', }), }); provider.addSpanProcessor(new SimpleSpanProcessor(exporter)); - -let instrumentation: Instrumentation | undefined = undefined; +export let instrumentation: Instrumentation | undefined = undefined; export function getTestSpans() { return exporter.getFinishedSpans(); @@ -44,18 +43,6 @@ export function setInstrumentation(instr: Instrumentation) { instrumentation = instr; } -export const mochaHooks = { - beforeAll(done: Function) { - provider.register(); - done(); - }, - beforeEach(done: Function) { - exporter.reset(); - instrumentation?.setConfig({}); - done(); - }, -}; - export class MockSqlite3Db { constructor(_db, a, b) { const callback = typeof b === 'function' ? b : a; diff --git a/test/instrumentation/external/typeorm/Connection.test.ts b/test/instrumentation/external/typeorm/Connection.test.ts index 5ed2c38a..42d283c6 100644 --- a/test/instrumentation/external/typeorm/Connection.test.ts +++ b/test/instrumentation/external/typeorm/Connection.test.ts @@ -13,14 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import * as assert from 'assert'; import { SpanStatusCode } from '@opentelemetry/api'; import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; +import { strict as assert } from 'assert'; +import { after, afterEach, before, beforeEach, describe, it } from 'node:test'; import { TypeormInstrumentation } from '../../../../src/instrumentations/external/typeorm'; -import { setInstrumentation, getTestSpans } from '../setup'; +import { exporter, getTestSpans, provider, setInstrumentation } from '../setup'; const instrumentation = new TypeormInstrumentation(); - +provider.register(); import * as typeorm from 'typeorm'; import { rawQueryOptions } from './utils'; @@ -33,6 +34,7 @@ describe('Connection', () => { instrumentation.enable(); }); beforeEach(() => { + exporter.reset(); instrumentation.enable(); }); afterEach(() => { diff --git a/test/instrumentation/external/typeorm/EntityManager.test.ts b/test/instrumentation/external/typeorm/EntityManager.test.ts index 2acb4643..792b2414 100644 --- a/test/instrumentation/external/typeorm/EntityManager.test.ts +++ b/test/instrumentation/external/typeorm/EntityManager.test.ts @@ -13,13 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import * as assert from 'assert'; +import { strict as assert } from 'assert'; +import { afterEach, before, beforeEach, after, describe, it } from 'node:test'; import { SpanStatusCode } from '@opentelemetry/api'; import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; import { TypeormInstrumentation } from '../../../../src/instrumentations/external/typeorm'; -import { setInstrumentation, getTestSpans } from '../setup'; +import { setInstrumentation, getTestSpans, provider, exporter } from '../setup'; const instrumentation = new TypeormInstrumentation(); +provider.register(); import * as typeorm from 'typeorm'; import { defaultOptions, MockSqliteDriver, User } from './utils'; @@ -31,6 +33,7 @@ describe('EntityManager', () => { instrumentation.enable(); }); beforeEach(() => { + exporter.reset(); instrumentation.enable(); }); afterEach(() => { @@ -72,7 +75,6 @@ describe('EntityManager', () => { const user = new User(1, 'aspecto', 'io'); await manager.save(user); const typeOrmSpans = getTestSpans(); - assert.strictEqual(typeOrmSpans.length, 1); assert.strictEqual(typeOrmSpans[0].status.code, SpanStatusCode.UNSET); const attributes = typeOrmSpans[0].attributes; diff --git a/test/instrumentation/external/typeorm/QueryBuilder.test.ts b/test/instrumentation/external/typeorm/QueryBuilder.test.ts index 4c13323d..284e73d4 100644 --- a/test/instrumentation/external/typeorm/QueryBuilder.test.ts +++ b/test/instrumentation/external/typeorm/QueryBuilder.test.ts @@ -13,15 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import * as assert from 'assert'; import { SpanStatusCode } from '@opentelemetry/api'; import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; +import { strict as assert } from 'assert'; +import { afterEach, before, beforeEach, describe, it } from 'node:test'; +import { exporter, getTestSpans, provider, setInstrumentation } from '../setup'; import { TypeormInstrumentation } from '../../../../src/instrumentations/external/typeorm'; -import { setInstrumentation, getTestSpans } from '../setup'; const instrumentation = new TypeormInstrumentation(); import * as typeorm from 'typeorm'; -import { defaultOptions, User } from './utils'; +import { User, defaultOptions } from './utils'; +provider.register(); describe('QueryBuilder', () => { before(() => { @@ -29,6 +31,7 @@ describe('QueryBuilder', () => { }); beforeEach(() => { + exporter.reset(); instrumentation.enable(); }); @@ -46,6 +49,7 @@ describe('QueryBuilder', () => { .where('user.id = :userId', { userId: '1' }) .getManyAndCount(); assert.strictEqual(users.length, 2); + const typeOrmSpans = getTestSpans(); assert.strictEqual(typeOrmSpans.length, 1); assert.strictEqual(typeOrmSpans[0].status.code, SpanStatusCode.UNSET); diff --git a/test/instrumentation/external/typeorm/Repository.test.ts b/test/instrumentation/external/typeorm/Repository.test.ts index 141fb0bb..49d1b3be 100644 --- a/test/instrumentation/external/typeorm/Repository.test.ts +++ b/test/instrumentation/external/typeorm/Repository.test.ts @@ -13,15 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import * as assert from 'assert'; +import { strict as assert } from 'assert'; +import { afterEach, before, beforeEach, describe, it } from 'node:test'; import { TypeormInstrumentation } from '../../../../src/instrumentations/external/typeorm'; -import { setInstrumentation, getTestSpans } from '../setup'; +import { getTestSpans, setInstrumentation, provider, exporter } from '../setup'; const instrumentation = new TypeormInstrumentation(); - -import { defaultOptions, User } from './utils'; -import * as typeorm from 'typeorm'; +provider.register(); import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; +import * as typeorm from 'typeorm'; +import { defaultOptions, User } from './utils'; describe('Repository', () => { before(() => { @@ -29,6 +30,7 @@ describe('Repository', () => { }); beforeEach(() => { + exporter.reset(); instrumentation.enable(); }); diff --git a/test/instrumentation/external/typeorm/config.test.ts b/test/instrumentation/external/typeorm/config.test.ts index 6e7c76c0..af2c4193 100644 --- a/test/instrumentation/external/typeorm/config.test.ts +++ b/test/instrumentation/external/typeorm/config.test.ts @@ -13,29 +13,35 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import * as assert from 'assert'; import { Span } from '@opentelemetry/sdk-trace-base'; import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; +import { strict as assert } from 'assert'; +import { before, beforeEach, describe, it } from 'node:test'; import { ExtendedDatabaseAttribute, TypeormInstrumentation, TypeormInstrumentationConfig, } from '../../../../src/instrumentations/external/typeorm'; -import { setInstrumentation, getTestSpans } from '../setup'; +import { getTestSpans, setInstrumentation, provider, exporter } from '../setup'; const instrumentation = new TypeormInstrumentation(); - +provider.register(); +import { SpanStatusCode } from '@opentelemetry/api'; import * as typeorm from 'typeorm'; import { defaultOptions, User } from './utils'; -import { SpanStatusCode } from '@opentelemetry/api'; describe('TypeormInstrumentationConfig', () => { before(() => { setInstrumentation(instrumentation); }); - it('responseHook', async function () { - this.timeout(3_000); + beforeEach(() => { + exporter.reset(); + instrumentation.setConfig({}); + }); + + it('responseHook', async () => { + await new Promise((resolve) => setTimeout(resolve, 3_000)); instrumentation.disable(); const config: TypeormInstrumentationConfig = { responseHook: (span: Span, response: any) => { diff --git a/test/instrumentation/redis.test.ts b/test/instrumentation/redis.test.ts index 65175d9e..0d2d71d9 100644 --- a/test/instrumentation/redis.test.ts +++ b/test/instrumentation/redis.test.ts @@ -14,21 +14,22 @@ * limitations under the License. */ -import * as assert from 'assert'; -import { startTracing, stopTracing } from '../../src/tracing'; -import { defaultSpanProcessorFactory } from '../../src/tracing/options'; +import * as utils from '../utils'; +utils.mockMocha(); +import { RedisInstrumentation } from '@opentelemetry/instrumentation-redis'; import { InMemorySpanExporter, SpanProcessor, } from '@opentelemetry/sdk-trace-base'; -import * as utils from '../utils'; +import { strict as assert } from 'assert'; import * as net from 'net'; -import type * as Redis from 'redis'; -import { RedisInstrumentation } from '@opentelemetry/instrumentation-redis'; +import { after, afterEach, before, beforeEach, describe, it } from 'node:test'; import { parseOptionsAndConfigureInstrumentations } from '../../src/instrumentations'; +import { startTracing, stopTracing } from '../../src/tracing'; +import { defaultSpanProcessorFactory } from '../../src/tracing/options'; describe('Redis instrumentation', () => { - let redisServer; + let redisServer: net.Server; let exporter; let spanProcessor: SpanProcessor; @@ -41,6 +42,7 @@ describe('Redis instrumentation', () => { if (data.endsWith('bar\r\n')) { socket.write('$2\r\nok\r\n'); data = ''; + socket.end(); } }); }); @@ -70,7 +72,7 @@ describe('Redis instrumentation', () => { }, }); - it('db statement is not added when SPLUNK_REDIS_INCLUDE_COMMAND_ARGS is false', (done) => { + it('db statement is not added when SPLUNK_REDIS_INCLUDE_COMMAND_ARGS is false', async () => { process.env.SPLUNK_REDIS_INCLUDE_COMMAND_ARGS = 'false'; const { tracingOptions } = parseOptionsAndConfigureInstrumentations({ tracing: testOpts(), @@ -79,19 +81,28 @@ describe('Redis instrumentation', () => { const client = require('redis').createClient({ no_ready_check: true, }); - client.hget('foo', 'bar', async () => { - await spanProcessor.forceFlush(); - const [span] = await exporter.getFinishedSpans(); - client.end(false); - assert.deepStrictEqual( - span.attributes['db.statement'], - 'hget [2 other arguments]' - ); - done(); + + await new Promise((resolve, reject) => { + client.hget('foo', 'bar', async (err, res) => { + if (err) { + return reject(err); + } + + await spanProcessor.forceFlush(); + const [span] = await exporter.getFinishedSpans(); + assert.deepStrictEqual( + span.attributes['db.statement'], + 'hget [2 other arguments]' + ); + + resolve(); + }); }); + + await client.quit(); }); - it('db statement is fully added when setting SPLUNK_REDIS_INCLUDE_COMMAND_ARGS env var', (done) => { + it('db statement is fully added when setting SPLUNK_REDIS_INCLUDE_COMMAND_ARGS env var', async () => { process.env.SPLUNK_REDIS_INCLUDE_COMMAND_ARGS = 'true'; const { tracingOptions } = parseOptionsAndConfigureInstrumentations({ tracing: testOpts(), @@ -100,12 +111,21 @@ describe('Redis instrumentation', () => { const client = require('redis').createClient({ no_ready_check: true, }); - client.hget('foo', 'bar', async () => { - await spanProcessor.forceFlush(); - const [span] = await exporter.getFinishedSpans(); - client.end(false); - assert.deepStrictEqual(span.attributes['db.statement'], 'hget foo bar'); - done(); + + await new Promise((resolve, reject) => { + client.hget('foo', 'bar', async (err, res) => { + if (err) { + return reject(err); + } + + await spanProcessor.forceFlush(); + const [span] = await exporter.getFinishedSpans(); + assert.deepStrictEqual(span.attributes['db.statement'], 'hget foo bar'); + + resolve(); + }); }); + + await client.quit(); }); }); diff --git a/test/loginjection.bunyan.test.ts b/test/loginjection.bunyan.test.ts index e1f26f73..bc4d1073 100644 --- a/test/loginjection.bunyan.test.ts +++ b/test/loginjection.bunyan.test.ts @@ -14,11 +14,11 @@ * limitations under the License. */ -import { TestLogStream, assertInjection } from './utils'; -import { startTracing, stopTracing } from '../src/tracing'; -import { parseOptionsAndConfigureInstrumentations } from '../src/instrumentations'; import type * as bunyan from 'bunyan'; -import { describe, it, beforeEach } from 'node:test'; +import { after, before, beforeEach, describe, it } from 'node:test'; +import { parseOptionsAndConfigureInstrumentations } from '../src/instrumentations'; +import { startTracing, stopTracing } from '../src/tracing'; +import { TestLogStream, assertInjection } from './utils'; describe('log injection', () => { let logStream: TestLogStream; diff --git a/test/loginjection.pino.test.ts b/test/loginjection.pino.test.ts index 8f3454a8..4086ec76 100644 --- a/test/loginjection.pino.test.ts +++ b/test/loginjection.pino.test.ts @@ -14,9 +14,10 @@ * limitations under the License. */ +import { TestLogStream, assertInjection, mockMocha } from './utils'; +mockMocha(); import type * as pino from 'pino'; import { startTracing, stopTracing } from '../src/tracing'; -import { TestLogStream, assertInjection } from './utils'; import { defaultLogHook } from '../src/instrumentations/logging'; import { PinoInstrumentation } from '@opentelemetry/instrumentation-pino'; import { parseOptionsAndConfigureInstrumentations } from '../src/instrumentations'; diff --git a/test/profiling/exporter.test.ts b/test/profiling/exporter.test.ts index e081fe31..ce6b2adf 100644 --- a/test/profiling/exporter.test.ts +++ b/test/profiling/exporter.test.ts @@ -14,13 +14,13 @@ * limitations under the License. */ -import * as assert from 'assert'; -import * as sinon from 'sinon'; -import { OTLPProfilingExporter } from '../../src/profiling/OTLPProfilingExporter'; -import { Resource } from '@opentelemetry/resources'; +import * as grpc from '@grpc/grpc-js'; import { VERSION } from '@opentelemetry/core'; +import { Resource } from '@opentelemetry/resources'; +import { strict as assert } from 'assert'; +import { beforeEach, describe, it, mock } from 'node:test'; +import { OTLPProfilingExporter } from '../../src/profiling/OTLPProfilingExporter'; import * as utils from '../utils'; -import * as grpc from '@grpc/grpc-js'; import { cpuProfile, heapProfile } from './profiles'; describe('profiling OTLP exporter', () => { @@ -67,20 +67,14 @@ describe('profiling OTLP exporter', () => { }); describe('exporting', () => { - const sandbox = sinon.createSandbox(); - - beforeEach(() => { - sandbox.restore(); - }); - - it('attaches common attributes when exporting CPU profiles', (done) => { + it('attaches common attributes when exporting CPU profiles', () => { const exporter = new OTLPProfilingExporter({ endpoint: 'http://foobar:8181', callstackInterval: 1000, resource: new Resource({ service: 'foo' }), }); - sandbox.replace(exporter['_client'], 'export', (payload: unknown) => { + mock.method(exporter['_client'], 'export', (payload: unknown) => { const { resourceLogs } = payload as any; assert.deepStrictEqual(resourceLogs.length, 1); const { instrumentationLibraryLogs, resource } = resourceLogs[0]; @@ -107,7 +101,7 @@ describe('profiling OTLP exporter', () => { { key: 'profiling.data.total.frame.count', value: { intValue: 2 } }, ]); - done(); + // done(); }); exporter.send(cpuProfile); @@ -120,7 +114,7 @@ describe('profiling OTLP exporter', () => { resource: new Resource({ service: 'foo' }), }); - sandbox.replace(exporter['_client'], 'export', (payload: unknown) => { + mock.method(exporter['_client'], 'export', (payload: unknown) => { const { resourceLogs } = payload as any; assert.deepStrictEqual(resourceLogs.length, 1); const { instrumentationLibraryLogs, resource } = resourceLogs[0]; @@ -147,7 +141,7 @@ describe('profiling OTLP exporter', () => { { key: 'profiling.data.total.frame.count', value: { intValue: 3 } }, ]); - done(); + // done(); }); exporter.sendHeapProfile(heapProfile); diff --git a/test/profiling/extension.test.ts b/test/profiling/extension.test.ts index fbd22b59..078e1bac 100644 --- a/test/profiling/extension.test.ts +++ b/test/profiling/extension.test.ts @@ -15,6 +15,7 @@ */ import { strict as assert } from 'assert'; +import { afterEach, describe, it } from 'node:test'; import { AllocationSample, HeapProfileNode, diff --git a/test/profiling/profiling.test.ts b/test/profiling/profiling.test.ts index 7562695a..e0faeadf 100644 --- a/test/profiling/profiling.test.ts +++ b/test/profiling/profiling.test.ts @@ -14,27 +14,26 @@ * limitations under the License. */ -import * as assert from 'assert'; -import { hrtime } from 'process'; +import { strict as assert } from 'assert'; +import { beforeEach, describe, it } from 'node:test'; import { inspect } from 'util'; -import { context, trace, propagation } from '@opentelemetry/api'; +import { context, trace } from '@opentelemetry/api'; import { Resource } from '@opentelemetry/resources'; -import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions'; import { InMemorySpanExporter } from '@opentelemetry/sdk-trace-base'; +import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions'; +import { start, stop } from '../../src'; import { - defaultExporterFactory, - startProfiling, _setDefaultOptions, + defaultExporterFactory, } from '../../src/profiling'; -import { start, stop } from '../../src'; +import { ProfilingContextManager } from '../../src/profiling/ProfilingContextManager'; import { CpuProfile, HeapProfile, ProfilingExporter, } from '../../src/profiling/types'; -import { ProfilingContextManager } from '../../src/profiling/ProfilingContextManager'; import { detect as detectResource } from '../../src/resource'; import * as utils from '../utils'; @@ -49,20 +48,30 @@ describe('profiling', () => { utils.cleanEnvironment(); }); - it('sets default options when no options are provided', () => { + it('sets default options when no options are provided', async () => { const options = _setDefaultOptions(); - assert.deepStrictEqual(options, { + await options.resource.waitForAsyncAttributes(); + const testResource = new Resource({ + [SemanticResourceAttributes.SERVICE_NAME]: '@splunk/otel', + }).merge(detectResource()); + await testResource.waitForAsyncAttributes(); + + const { resource: defaultResource, ...defaultOtherAttrs } = options; + + assert.deepStrictEqual(defaultOtherAttrs, { serviceName: '@splunk/otel', endpoint: 'http://localhost:4317', callstackInterval: 1_000, collectionDuration: 30_000, - resource: new Resource({ - [SemanticResourceAttributes.SERVICE_NAME]: '@splunk/otel', - }).merge(detectResource()), exporterFactory: defaultExporterFactory, memoryProfilingEnabled: false, memoryProfilingOptions: undefined, }); + + assert.deepStrictEqual( + defaultResource._attributes, + testResource._attributes + ); }); it('uses options from environment', () => { diff --git a/test/profiling/serialization.test.ts b/test/profiling/serialization.test.ts index 6de1dd1a..da1ced17 100644 --- a/test/profiling/serialization.test.ts +++ b/test/profiling/serialization.test.ts @@ -14,12 +14,13 @@ * limitations under the License. */ import { strict as assert } from 'assert'; +import { describe, it } from 'node:test'; +import { perftools } from '../../src/profiling/proto/profile.js'; import { + StringTable, serialize, serializeHeapProfile, - StringTable, } from '../../src/profiling/utils'; -import { perftools } from '../../src/profiling/proto/profile.js'; import { cpuProfile, heapProfile } from './profiles'; const proto = perftools.profiles; diff --git a/test/separate_process/debug_metrics.test.ts b/test/separate_process/debug_metrics.test.ts index 74ed190b..2dc8a203 100644 --- a/test/separate_process/debug_metrics.test.ts +++ b/test/separate_process/debug_metrics.test.ts @@ -14,14 +14,11 @@ * limitations under the License. */ -import * as assert from 'assert'; -import { cleanEnvironment, TestMetricReader } from '../utils'; -import { - AggregationTemporality, - MetricReader, -} from '@opentelemetry/sdk-metrics'; -import { startMetrics } from '../../src/metrics'; +import { AggregationTemporality } from '@opentelemetry/sdk-metrics'; +import { strict as assert } from 'assert'; +import { afterEach, beforeEach, describe, it } from 'node:test'; import { start, stop } from '../../src'; +import { TestMetricReader, cleanEnvironment } from '../utils'; describe('debug metrics', () => { let reader: TestMetricReader; diff --git a/test/servertiming.test.ts b/test/servertiming.test.ts index 850125ab..b9fd4371 100644 --- a/test/servertiming.test.ts +++ b/test/servertiming.test.ts @@ -14,6 +14,8 @@ * limitations under the License. */ +import * as utils from './utils'; +utils.mockMocha(); import { strict as assert } from 'assert'; import { beforeEach, describe, it, afterEach } from 'node:test'; @@ -21,7 +23,6 @@ import { context, trace } from '@opentelemetry/api'; import { HttpInstrumentation } from '@opentelemetry/instrumentation-http'; import { parseOptionsAndConfigureInstrumentations } from '../src/instrumentations'; import { startTracing, stopTracing } from '../src/tracing'; -import * as utils from './utils'; const PORT = 9111; const SERVER_URL = `http://localhost:${PORT}`; @@ -43,16 +44,6 @@ describe('servertiming', () => { beforeEach(utils.cleanEnvironment); afterEach(async () => { - console.log('closing server'); - // if (server) { - // // Await server closing to ensure it's fully stopped - // await new Promise((resolve, reject) => { - // server.close((err) => { - // if (err) reject(err); - // else resolve(); - // }); - // }); - // } server.close(); stopTracing(); }); @@ -62,15 +53,12 @@ describe('servertiming', () => { const http = require('http'); server = http.createServer((req, res) => { spanContext = trace.getSpanContext(context.active()); - console.log('got request', spanContext); res.end('ok'); }); server.listen(PORT); - // await new Promise((resolve) => server.listen(PORT, resolve)); await new Promise((resolve) => { http.get(SERVER_URL, (res) => { - console.log('got response', spanContext); assertHeaders(spanContext, res); resolve(); }); @@ -81,69 +69,66 @@ describe('servertiming', () => { const { tracingOptions } = parseOptionsAndConfigureInstrumentations(); startTracing(tracingOptions); await testHeadersAdded(); - console.log('test 1 done'); }); it('can be enabled via environment variables', async () => { process.env.SPLUNK_TRACE_RESPONSE_HEADER_ENABLED = 'true'; const { tracingOptions } = parseOptionsAndConfigureInstrumentations(); startTracing(tracingOptions); - // await new Promise((resolve) => setTimeout(resolve, 500)); await testHeadersAdded(); - console.log('test 2 done'); }); - // it('injects server timing header with current context', async () => { - // const { tracingOptions } = parseOptionsAndConfigureInstrumentations({ - // tracing: { serverTimingEnabled: true }, - // }); - // startTracing(tracingOptions); - // await testHeadersAdded(); - // }); - - // it('works with user provided http instrumentation config', async () => { - // const { tracingOptions } = parseOptionsAndConfigureInstrumentations({ - // tracing: { - // serverTimingEnabled: true, - // instrumentations: [new HttpInstrumentation({})], - // }, - // }); - // startTracing(tracingOptions); - // await testHeadersAdded(); - // }); - - // it('leaves user hooks unchanged', async () => { - // let userHookCalled = false; - // const { tracingOptions } = parseOptionsAndConfigureInstrumentations({ - // tracing: { - // serverTimingEnabled: true, - // instrumentations: [ - // new HttpInstrumentation({ - // responseHook: (span, response) => { - // userHookCalled = true; - // }, - // }), - // ], - // }, - // }); - // startTracing(tracingOptions); - - // const http = require('http'); - // let spanContext; - - // server = http.createServer((req, res) => { - // spanContext = trace.getSpanContext(context.active()); - // res.end('ok'); - // }); - - // server.listen(PORT); - - // await new Promise((resolve) => { - // http.get(SERVER_URL, (res) => { - // assertHeaders(spanContext, res); - // assert.ok(userHookCalled); - // resolve(); - // }); - // }); - // }); + it('injects server timing header with current context', async () => { + const { tracingOptions } = parseOptionsAndConfigureInstrumentations({ + tracing: { serverTimingEnabled: true }, + }); + startTracing(tracingOptions); + await testHeadersAdded(); + }); + + it('works with user provided http instrumentation config', async () => { + const { tracingOptions } = parseOptionsAndConfigureInstrumentations({ + tracing: { + serverTimingEnabled: true, + instrumentations: [new HttpInstrumentation({})], + }, + }); + startTracing(tracingOptions); + await testHeadersAdded(); + }); + + it('leaves user hooks unchanged', async () => { + let userHookCalled = false; + const { tracingOptions } = parseOptionsAndConfigureInstrumentations({ + tracing: { + serverTimingEnabled: true, + instrumentations: [ + new HttpInstrumentation({ + responseHook: (span, response) => { + userHookCalled = true; + }, + }), + ], + }, + }); + startTracing(tracingOptions); + + const http = require('http'); + let spanContext; + + server = http.createServer((req, res) => { + spanContext = trace.getSpanContext(context.active()); + res.end('ok'); + }); + + server.listen(PORT); + + await new Promise((resolve) => { + http.get(SERVER_URL, (res) => { + assertHeaders(spanContext, res); + assert.ok(userHookCalled); + resolve(); + }); + }); + }); }); diff --git a/test/service_name.test.ts b/test/service_name.test.ts index 389941a6..77d76084 100644 --- a/test/service_name.test.ts +++ b/test/service_name.test.ts @@ -13,7 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import * as assert from 'assert'; + +import { strict as assert } from 'assert'; +import { beforeEach, describe, it } from 'node:test'; import * as fs from 'fs'; import * as os from 'os'; import * as path from 'path'; diff --git a/test/start.test.ts b/test/start.test.ts index ac994ddf..95c8b445 100644 --- a/test/start.test.ts +++ b/test/start.test.ts @@ -13,8 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import * as assert from 'assert'; -import * as sinon from 'sinon'; + +import { strict as assert } from 'assert'; +import { afterEach, beforeEach, describe, it, mock } from 'node:test'; import { diag } from '@opentelemetry/api'; import { Resource } from '@opentelemetry/resources'; @@ -81,24 +82,32 @@ describe('start', () => { const logging = signals.includes('logging'); if (metrics) { - sinon.assert.calledOnce(fns.metrics); + assert(fns.metrics.mock.callCount() === 1); + // sinon.assert.calledOnce(fns.metrics); } else { - sinon.assert.notCalled(fns.metrics); + assert(fns.metrics.mock.callCount() === 0); + // sinon.assert.notCalled(fns.metrics); } if (profiling) { - sinon.assert.calledOnce(fns.profiling); + assert(fns.profiling.mock.callCount() === 1); + // sinon.assert.calledOnce(fns.profiling); } else { - sinon.assert.notCalled(fns.profiling); + assert(fns.profiling.mock.callCount() === 0); + // sinon.assert.notCalled(fns.profiling); } if (tracing) { - sinon.assert.calledOnce(fns.tracing); + assert(fns.tracing.mock.callCount() === 1); + // sinon.assert.calledOnce(fns.tracing); } else { - sinon.assert.notCalled(fns.tracing); + assert(fns.tracing.mock.callCount() === 0); + // sinon.assert.notCalled(fns.tracing); } if (logging) { - sinon.assert.calledOnce(fns.logging); + assert(fns.logging.mock.callCount() === 1); + // sinon.assert.calledOnce(fns.logging); } else { - sinon.assert.notCalled(fns.logging); + assert(fns.logging.mock.callCount() === 0); + // sinon.assert.notCalled(fns.logging); } }; @@ -106,29 +115,29 @@ describe('start', () => { beforeEach(() => { signals.stop = { - logging: sinon.spy(), - metrics: sinon.spy(), - profiling: sinon.spy(), - tracing: sinon.stub(tracing, 'stopTracing').callsFake(() => {}), + logging: mock.fn(), + metrics: mock.fn(), + profiling: mock.fn(), + tracing: mock.method(tracing, 'stopTracing', () => {}), }; signals.start = { - logging: sinon.stub(logging, 'startLogging').callsFake(() => { + logging: mock.method(logging, 'startLogging', () => { return { stop: signals.stop.logging }; }), - metrics: sinon.stub(metrics, 'startMetrics').callsFake(() => { + metrics: mock.method(metrics, 'startMetrics', () => { return { stop: signals.stop.metrics }; }), - profiling: sinon.stub(profiling, 'startProfiling').callsFake(() => { + profiling: mock.method(profiling, 'startProfiling', () => { return { stop: signals.stop.profiling }; }), - tracing: sinon.stub(tracing, 'startTracing').callsFake(() => true), + tracing: mock.method(tracing, 'startTracing', () => true), }; }); afterEach(() => { stop(); - sinon.restore(); + // sinon.restore(); //FIXME hmmm }); describe('toggling signals', () => { @@ -187,7 +196,7 @@ describe('start', () => { logging: true, }); - sinon.assert.calledOnceWithMatch(signals.start.tracing, { + utils.calledOnceWithMatch(signals.start.tracing, { accessToken: 'xyz', endpoint: 'localhost:1111', serviceName: 'test', @@ -195,19 +204,19 @@ describe('start', () => { captureHttpRequestUriParams: [], }); - sinon.assert.calledOnceWithMatch(signals.start.profiling, { + utils.calledOnceWithMatch(signals.start.profiling, { endpoint: 'localhost:1111', serviceName: 'test', }); - sinon.assert.calledOnceWithMatch(signals.start.metrics, { + utils.calledOnceWithMatch(signals.start.metrics, { accessToken: 'xyz', endpoint: 'localhost:1111', serviceName: 'test', }); - sinon.assert.calledOnceWithMatch(signals.start.logging, { - // accessToken: 'xyz', // FIXME logging doesn't use accessToken atm cause no ingest + utils.calledOnceWithMatch(signals.start.logging, { + //accessToken: 'xyz',// FIXME logging doesn't use accessToken atm cause no ingest endpoint: 'localhost:1111', serviceName: 'test', }); @@ -267,48 +276,53 @@ describe('start', () => { }); describe('diagnostic logging', () => { - const sandbox = sinon.createSandbox(); - let c; + let logSpy; + let infoSpy; + let debugSpy; beforeEach(() => { utils.cleanEnvironment(); - c = sandbox.spy(console); + logSpy = mock.method(console, 'log'); + infoSpy = mock.method(console, 'info'); + debugSpy = mock.method(console, 'debug'); }); afterEach(() => { - sandbox.restore(); + logSpy.mock.resetCalls(); + infoSpy.mock.resetCalls(); + debugSpy.mock.resetCalls(); }); it('does not enable diagnostic logging by default', () => { start(); diag.info('42'); - assert(c.log.notCalled); + assert(logSpy.mock.callCount() === 0); }); it('does not enable diagnostic logging via explicit config', () => { start({ logLevel: 'none' }); diag.info('42'); - assert(c.log.notCalled); + assert(logSpy.mock.callCount() === 0); }); it('is possible to enable diag logging via config', () => { start({ logLevel: 'debug' }); diag.debug('42'); - assert(c.debug.calledWithExactly('42')); + utils.calledWithExactly(debugSpy, '42'); }); it('is possible to enable diag logging via env vars', () => { process.env.OTEL_LOG_LEVEL = 'info'; start(); diag.info('42'); - assert(c.info.calledWithExactly('42')); + utils.calledWithExactly(infoSpy, '42'); }); it('prefers programmatic config over env var', () => { process.env.OTEL_LOG_LEVEL = 'debug'; start({ logLevel: 'info' }); diag.debug('42'); - assert(c.debug.notCalled); + assert(debugSpy.mock.callCount() === 0); }); }); }); diff --git a/test/tracing/tracing.test.ts b/test/tracing/tracing.test.ts index 6e144ac2..84b001e8 100644 --- a/test/tracing/tracing.test.ts +++ b/test/tracing/tracing.test.ts @@ -14,18 +14,18 @@ * limitations under the License. */ -import * as assert from 'assert'; -import * as sinon from 'sinon'; +import { strict as assert } from 'assert'; +import { after, before, beforeEach, describe, it, mock } from 'node:test'; import { trace } from '@opentelemetry/api'; +import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc'; import { BatchSpanProcessor, - SimpleSpanProcessor, ConsoleSpanExporter, InMemorySpanExporter, + SimpleSpanProcessor, } from '@opentelemetry/sdk-trace-base'; import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node'; -import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc'; import { parseOptionsAndConfigureInstrumentations } from '../../src/instrumentations'; import { startTracing, stopTracing } from '../../src/tracing'; @@ -35,7 +35,7 @@ describe('tracing:otlp', () => { let addSpanProcessorMock; before(() => { - addSpanProcessorMock = sinon.spy( + addSpanProcessorMock = mock.method( NodeTracerProvider.prototype, 'addSpanProcessor' ); @@ -43,11 +43,11 @@ describe('tracing:otlp', () => { beforeEach(() => { utils.cleanEnvironment(); - addSpanProcessorMock.resetHistory(); + addSpanProcessorMock.mock.resetCalls(); }); after(() => { - addSpanProcessorMock.restore(); + // addSpanProcessorMock.restore(); }); function assertTracingPipeline( @@ -55,9 +55,8 @@ describe('tracing:otlp', () => { serviceName: string, accessToken?: string ) { - sinon.assert.calledOnce(addSpanProcessorMock); - const processor = addSpanProcessorMock.getCall(0).args[0]; - + assert(addSpanProcessorMock.mock.callCount() === 1); + const processor = addSpanProcessorMock.mock.calls[0].arguments[0]; assert(processor instanceof BatchSpanProcessor); const exporter = processor['_exporter']; assert(exporter instanceof OTLPTraceExporter); @@ -65,9 +64,10 @@ describe('tracing:otlp', () => { assert.deepEqual(exporter.url, exportURL); if (accessToken) { - // gRPC not yet supported in ingest assert.equal( - exporter['_transport']['_parameters']['metadata']().get('x-sf-token'), + exporter['_transport']['_parameters'] + ['metadata']() + .get('x-sf-token')[0], accessToken ); } @@ -123,8 +123,8 @@ describe('tracing:otlp', () => { startTracing(tracingOptions); - sinon.assert.calledOnce(addSpanProcessorMock); - const p1 = addSpanProcessorMock.getCall(0).args[0]; + assert(addSpanProcessorMock.mock.callCount() === 1); + const p1 = addSpanProcessorMock.mock.calls[0].arguments[0]; assert(p1 instanceof SimpleSpanProcessor); const exp1 = p1['_exporter']; @@ -146,14 +146,14 @@ describe('tracing:otlp', () => { startTracing(tracingOptions); - sinon.assert.calledTwice(addSpanProcessorMock); - const p1 = addSpanProcessorMock.getCall(0).args[0]; + assert(addSpanProcessorMock.mock.callCount() === 2); + const p1 = addSpanProcessorMock.mock.calls[0].arguments[0]; assert(p1 instanceof SimpleSpanProcessor); const exp1 = p1['_exporter']; assert(exp1 instanceof ConsoleSpanExporter); - const p2 = addSpanProcessorMock.getCall(1).args[0]; + const p2 = addSpanProcessorMock.mock.calls[1].arguments[0]; assert(p2 instanceof BatchSpanProcessor); const exp2 = p2['_exporter']; assert(exp2 instanceof InMemorySpanExporter); @@ -171,8 +171,8 @@ describe('tracing:otlp', () => { span.end(); }; const exporter = new InMemorySpanExporter(); - const exportFn = sinon.spy(exporter, 'export'); - const shutdownFn = sinon.spy(exporter, 'shutdown'); + const exportFn = mock.method(exporter, 'export'); + const shutdownFn = mock.method(exporter, 'shutdown'); const { tracingOptions } = parseOptionsAndConfigureInstrumentations({ tracing: { @@ -185,8 +185,8 @@ describe('tracing:otlp', () => { const storedTracer = trace.getTracer('test-tracer'); createSpan(); - assert.equal(exportFn.callCount, 0); - assert.equal(shutdownFn.callCount, 0); + assert.equal(exportFn.mock.callCount(), 0); + assert.equal(shutdownFn.mock.callCount(), 0); await stopTracing(); createSpan(false); @@ -194,10 +194,10 @@ describe('tracing:otlp', () => { // are "recorded", but the SpanProcessor which is now shut down will just dump them. createSpan(true, storedTracer); - assert.equal(exportFn.callCount, 1); - assert.equal(shutdownFn.callCount, 1); + assert.equal(exportFn.mock.callCount(), 1); + assert.equal(shutdownFn.mock.callCount(), 1); - exportFn.restore(); - shutdownFn.restore(); + exportFn.mock.restore(); + shutdownFn.mock.restore(); }); }); diff --git a/test/uri_parameter_capture.test.ts b/test/uri_parameter_capture.test.ts index 7d0a2ffd..a41bea0b 100644 --- a/test/uri_parameter_capture.test.ts +++ b/test/uri_parameter_capture.test.ts @@ -14,16 +14,18 @@ * limitations under the License. */ -import * as assert from 'assert'; -import { startTracing, stopTracing } from '../src/tracing'; -import { defaultSpanProcessorFactory } from '../src/tracing/options'; -import { parseOptionsAndConfigureInstrumentations } from '../src/instrumentations'; import * as utils from './utils'; +utils.mockMocha(); import { InMemorySpanExporter, ReadableSpan, SpanProcessor, } from '@opentelemetry/sdk-trace-base'; +import { strict as assert } from 'assert'; +import { afterEach, beforeEach, before, describe, it } from 'node:test'; +import { parseOptionsAndConfigureInstrumentations } from '../src/instrumentations'; +import { startTracing, stopTracing } from '../src/tracing'; +import { defaultSpanProcessorFactory } from '../src/tracing/options'; const PORT = 9112; const SERVER_URL = `http://localhost:${PORT}`; diff --git a/test/utils.test.ts b/test/utils.test.ts index 7ea649e4..39af2673 100644 --- a/test/utils.test.ts +++ b/test/utils.test.ts @@ -13,13 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import * as assert from 'assert'; -import * as sinon from 'sinon'; import * as api from '@opentelemetry/api'; +import { strict as assert } from 'assert'; +import { afterEach, beforeEach, describe, it, mock } from 'node:test'; -import { getNonEmptyEnvVar, parseLogLevel } from '../src/utils'; -import { cleanEnvironment } from './utils'; import { DiagLogLevel } from '@opentelemetry/api'; +import { getNonEmptyEnvVar, parseLogLevel } from '../src/utils'; +import { calledWithExactly, cleanEnvironment } from './utils'; describe('utils', () => { describe('logLevel', () => { @@ -37,20 +37,18 @@ describe('utils', () => { }); describe('getNonEmptyEnvVar', () => { - const sandbox = sinon.createSandbox(); let logger; beforeEach(() => { cleanEnvironment(); logger = { - warn: sandbox.spy(), + warn: mock.fn(), }; api.diag.setLogger(logger, api.DiagLogLevel.ALL); - logger.warn.resetHistory(); }); afterEach(() => { - sandbox.restore(); + logger.warn.mock.resetCalls(); }); it('returns an empty environment variable as undefined', () => { @@ -77,7 +75,7 @@ describe('utils', () => { process.env.OTEL_SERVICE_NAME = ''; assert.deepStrictEqual(getNonEmptyEnvVar('OTEL_SERVICE_NAME'), undefined); - sinon.assert.calledWith( + calledWithExactly( logger.warn, `Defined, but empty environment variable: 'OTEL_SERVICE_NAME'. The value will be considered as undefined.` ); diff --git a/test/utils.ts b/test/utils.ts index fb661829..c1dae84e 100644 --- a/test/utils.ts +++ b/test/utils.ts @@ -106,3 +106,44 @@ export function assertInjection( ); } } + +export function calledWithExactly(mocked, expected) { + const match = mocked.mock.calls.some((call) => { + try { + assert.deepStrictEqual(call.arguments[0], expected); + return true; + } catch (error) { + return false; + } + }); + + assert(match, `Expected call with: ${JSON.stringify(expected)} not found`); +} + +export function calledOnceWithMatch(mocked, match: Object) { + assert.strictEqual( + mocked.mock.calls.length, + 1, + 'calledOnceWithMatch can only be used with a single call' + ); + + const callArgs = mocked.mock.calls[0].arguments[0]; + for (const key in match) { + assert.deepEqual(callArgs[key], match[key], `key ${key} does not match`); + } +} + +export function mockMocha() { + const isMocha = [ + 'afterEach', + 'after', + 'beforeEach', + 'before', + 'describe', + 'it', + ].forEach((fn) => { + global[fn] = () => { + console.error(`Attempted to call mock global mocha function`); + }; + }); +}