diff --git a/package-lock.json b/package-lock.json index ffd91915b4..9e3c4d50ac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35509,7 +35509,7 @@ "@types/mocha": "10.0.10", "@types/node": "18.18.14", "@types/sinon": "17.0.4", - "express": "4.20.0", + "express": "^5.1.0", "nyc": "17.1.0", "rimraf": "5.0.10", "sinon": "15.2.0", @@ -35532,6 +35532,301 @@ "undici-types": "~5.26.4" } }, + "plugins/node/opentelemetry-instrumentation-express/node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "plugins/node/opentelemetry-instrumentation-express/node_modules/body-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.6.3", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "plugins/node/opentelemetry-instrumentation-express/node_modules/content-disposition": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "plugins/node/opentelemetry-instrumentation-express/node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "plugins/node/opentelemetry-instrumentation-express/node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "plugins/node/opentelemetry-instrumentation-express/node_modules/express": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.0", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "plugins/node/opentelemetry-instrumentation-express/node_modules/finalhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "plugins/node/opentelemetry-instrumentation-express/node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "plugins/node/opentelemetry-instrumentation-express/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "plugins/node/opentelemetry-instrumentation-express/node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "plugins/node/opentelemetry-instrumentation-express/node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "plugins/node/opentelemetry-instrumentation-express/node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "plugins/node/opentelemetry-instrumentation-express/node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "plugins/node/opentelemetry-instrumentation-express/node_modules/path-to-regexp": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "plugins/node/opentelemetry-instrumentation-express/node_modules/raw-body": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", + "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.6.3", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "plugins/node/opentelemetry-instrumentation-express/node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "plugins/node/opentelemetry-instrumentation-express/node_modules/send": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18" + } + }, + "plugins/node/opentelemetry-instrumentation-express/node_modules/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + } + }, + "plugins/node/opentelemetry-instrumentation-express/node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "dev": true, + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "plugins/node/opentelemetry-instrumentation-express/node_modules/typescript": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", @@ -44090,7 +44385,7 @@ "@types/mocha": "10.0.10", "@types/node": "18.18.14", "@types/sinon": "17.0.4", - "express": "4.20.0", + "express": "^5.1.0", "nyc": "17.1.0", "rimraf": "5.0.10", "sinon": "15.2.0", @@ -44107,6 +44402,218 @@ "undici-types": "~5.26.4" } }, + "accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "dev": true, + "requires": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + } + }, + "body-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "dev": true, + "requires": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.6.3", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" + } + }, + "content-disposition": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "dev": true, + "requires": { + "safe-buffer": "5.2.1" + } + }, + "cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "dev": true + }, + "cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "dev": true + }, + "express": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "dev": true, + "requires": { + "accepts": "^2.0.0", + "body-parser": "^2.2.0", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + } + }, + "finalhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "dev": true, + "requires": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + } + }, + "fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "dev": true + }, + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, + "media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "dev": true + }, + "merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "dev": true + }, + "mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "dev": true, + "requires": { + "mime-db": "^1.54.0" + } + }, + "negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "dev": true + }, + "path-to-regexp": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "dev": true + }, + "raw-body": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", + "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", + "dev": true, + "requires": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.6.3", + "unpipe": "1.0.0" + } + }, + "router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "dev": true, + "requires": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + } + }, + "send": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "dev": true, + "requires": { + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + } + }, + "serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", + "dev": true, + "requires": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + } + }, + "type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "dev": true, + "requires": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + } + }, "typescript": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", diff --git a/plugins/node/opentelemetry-instrumentation-express/.tav.yml b/plugins/node/opentelemetry-instrumentation-express/.tav.yml index eeee57a593..a86f9fa41e 100644 --- a/plugins/node/opentelemetry-instrumentation-express/.tav.yml +++ b/plugins/node/opentelemetry-instrumentation-express/.tav.yml @@ -1,5 +1,5 @@ express: - versions: - include: "^4.16.2" + include: ">=4.16.2 <6" mode: latest-minors - commands: npm run test + commands: npm test diff --git a/plugins/node/opentelemetry-instrumentation-express/package.json b/plugins/node/opentelemetry-instrumentation-express/package.json index 18482b1832..d0adc56088 100644 --- a/plugins/node/opentelemetry-instrumentation-express/package.json +++ b/plugins/node/opentelemetry-instrumentation-express/package.json @@ -53,7 +53,7 @@ "@types/mocha": "10.0.10", "@types/node": "18.18.14", "@types/sinon": "17.0.4", - "express": "4.20.0", + "express": "^5.1.0", "nyc": "17.1.0", "rimraf": "5.0.10", "sinon": "15.2.0", diff --git a/plugins/node/opentelemetry-instrumentation-express/src/instrumentation.ts b/plugins/node/opentelemetry-instrumentation-express/src/instrumentation.ts index 55f137762d..4ae3d30925 100644 --- a/plugins/node/opentelemetry-instrumentation-express/src/instrumentation.ts +++ b/plugins/node/opentelemetry-instrumentation-express/src/instrumentation.ts @@ -60,9 +60,13 @@ export class ExpressInstrumentation extends InstrumentationBase=4.0.0 <5'], + ['>=4.0.0 <6'], moduleExports => { - const routerProto = moduleExports.Router as unknown as express.Router; + const isExpressWithRouterPrototype = + typeof moduleExports?.Router?.prototype?.route === 'function'; + const routerProto = isExpressWithRouterPrototype + ? moduleExports.Router.prototype // Express v5 + : moduleExports.Router; // Express v4 // patch express.Router.route if (isWrapped(routerProto.route)) { this._unwrap(routerProto, 'route'); @@ -82,13 +86,17 @@ export class ExpressInstrumentation extends InstrumentationBase { if (moduleExports === undefined) return; - const routerProto = moduleExports.Router as unknown as express.Router; + const isExpressWithRouterPrototype = + typeof moduleExports?.Router?.prototype?.route === 'function'; + const routerProto = isExpressWithRouterPrototype + ? moduleExports.Router.prototype + : moduleExports.Router; this._unwrap(routerProto, 'route'); this._unwrap(routerProto, 'use'); this._unwrap(moduleExports.application, 'use'); @@ -136,16 +144,24 @@ export class ExpressInstrumentation extends InstrumentationBase ) { + // If we access app.router in express 4.x we trigger an assertion error. + // This property existed in v3, was removed in v4 and then re-added in v5. + const router = isExpressWithRouterPrototype + ? this.router + : this._router; const route = original.apply(this, args); - const layer = this._router.stack[this._router.stack.length - 1]; - instrumentation._applyPatch(layer, getLayerPath(args)); + if (router) { + const layer = router.stack[router.stack.length - 1]; + instrumentation._applyPatch(layer, getLayerPath(args)); + } return route; }; }; diff --git a/plugins/node/opentelemetry-instrumentation-express/src/utils.ts b/plugins/node/opentelemetry-instrumentation-express/src/utils.ts index 325ce4eee1..69a20146b9 100644 --- a/plugins/node/opentelemetry-instrumentation-express/src/utils.ts +++ b/plugins/node/opentelemetry-instrumentation-express/src/utils.ts @@ -97,7 +97,7 @@ export const getLayerMetadata = ( }, name: `router - ${extractedRouterPath}`, }; - } else if (layer.name === 'bound dispatch') { + } else if (layer.name === 'bound dispatch' || layer.name === 'handle') { return { attributes: { [AttributeNames.EXPRESS_NAME]: diff --git a/plugins/node/opentelemetry-instrumentation-express/test/express.test.ts b/plugins/node/opentelemetry-instrumentation-express/test/express.test.ts index bc2b213ee5..e4a45d2e38 100644 --- a/plugins/node/opentelemetry-instrumentation-express/test/express.test.ts +++ b/plugins/node/opentelemetry-instrumentation-express/test/express.test.ts @@ -22,6 +22,7 @@ import { SimpleSpanProcessor, } from '@opentelemetry/sdk-trace-base'; import * as assert from 'assert'; +import * as semver from 'semver'; import { AttributeNames } from '../src/enums/AttributeNames'; import { ExpressInstrumentation } from '../src'; import { createServer, httpRequest, serverWithMiddleware } from './utils'; @@ -36,6 +37,9 @@ import * as express from 'express'; import { RPCMetadata, getRPCMetadata } from '@opentelemetry/core'; import { Server } from 'http'; +const LIB_VERSION = require('express/package.json').version; +const isExpressV5 = semver.satisfies(LIB_VERSION, '>=5.0.0'); + describe('ExpressInstrumentation', () => { const memoryExporter = new InMemorySpanExporter(); const spanProcessor = new SimpleSpanProcessor(memoryExporter); @@ -496,7 +500,7 @@ describe('ExpressInstrumentation', () => { const httpServer = await serverWithMiddleware(tracer, rootSpan, app => { app.use(express.json()); app.get('/bare_route', (req, res) => { - const stack = req.app._router.stack as any[]; + const stack = (req.app._router || req.app.router).stack as any[]; routerLayer = stack.find(layer => layer.name === 'router'); return res.status(200).end('test'); }); @@ -531,7 +535,7 @@ describe('ExpressInstrumentation', () => { next ) => router(req, res, next); router.use('/:slug', (req, res, next) => { - const stack = req.app._router.stack as any[]; + const stack = (req.app._router || req.app.router).stack as any[]; routerLayer = stack.find(router => router.name === 'CustomRouter'); return res.status(200).end('bar'); }); @@ -616,8 +620,8 @@ describe('ExpressInstrumentation', () => { // a `simpleMiddleware`, then makes a single 'GET /post/0' request. We // expect to see spans like this: // span 'GET /post/:id' - // `- span 'middleware - query' - // `- span 'middleware - expressInit' + // `- span 'middleware - query' // not in express@5 + // `- span 'middleware - expressInit' // not in express@5 // `- span 'middleware - simpleMiddleware' // `- span 'request handler - /post/:id' const spans = collector.sortedSpans; @@ -626,18 +630,21 @@ describe('ExpressInstrumentation', () => { assert.strictEqual(spans[1].name, 'GET /post/:id'); assert.strictEqual(spans[1].kind, testUtils.OtlpSpanKind.SERVER); assert.strictEqual(spans[1].parentSpanId, spans[0].spanId); - assert.strictEqual(spans[2].name, 'middleware - query'); - assert.strictEqual(spans[2].kind, testUtils.OtlpSpanKind.INTERNAL); - assert.strictEqual(spans[2].parentSpanId, spans[1].spanId); - assert.strictEqual(spans[3].name, 'middleware - expressInit'); - assert.strictEqual(spans[3].kind, testUtils.OtlpSpanKind.INTERNAL); - assert.strictEqual(spans[3].parentSpanId, spans[1].spanId); - assert.strictEqual(spans[4].name, 'middleware - simpleMiddleware'); - assert.strictEqual(spans[4].kind, testUtils.OtlpSpanKind.INTERNAL); - assert.strictEqual(spans[4].parentSpanId, spans[1].spanId); - assert.strictEqual(spans[5].name, 'request handler - /post/:id'); - assert.strictEqual(spans[5].kind, testUtils.OtlpSpanKind.INTERNAL); - assert.strictEqual(spans[5].parentSpanId, spans[1].spanId); + const expectedSpanNames = isExpressV5 + ? ['middleware - simpleMiddleware', 'request handler - /post/:id'] + : [ + 'middleware - query', + 'middleware - expressInit', + 'middleware - simpleMiddleware', + 'request handler - /post/:id', + ]; + const remainingSpans = spans.slice(2); + for (const expectedSpanName of expectedSpanNames) { + const span = remainingSpans.shift()!; + assert.strictEqual(span.name, expectedSpanName); + assert.strictEqual(span.kind, testUtils.OtlpSpanKind.INTERNAL); + assert.strictEqual(span.parentSpanId, spans[1].spanId); + } }, }); }); @@ -662,18 +669,26 @@ describe('ExpressInstrumentation', () => { assert.strictEqual(spans[1].name, 'GET /api/user/:id'); assert.strictEqual(spans[1].kind, testUtils.OtlpSpanKind.SERVER); assert.strictEqual(spans[1].parentSpanId, spans[0].spanId); - assert.strictEqual(spans[2].name, 'middleware - query'); - assert.strictEqual(spans[3].kind, testUtils.OtlpSpanKind.INTERNAL); - assert.strictEqual(spans[3].parentSpanId, spans[1].spanId); - assert.strictEqual(spans[4].name, 'middleware - simpleMiddleware'); - assert.strictEqual(spans[4].kind, testUtils.OtlpSpanKind.INTERNAL); - assert.strictEqual(spans[4].parentSpanId, spans[1].spanId); - assert.strictEqual(spans[5].name, 'router - /api/user/:id'); - assert.strictEqual(spans[5].kind, testUtils.OtlpSpanKind.INTERNAL); - assert.strictEqual(spans[5].parentSpanId, spans[1].spanId); - assert.strictEqual(spans[6].name, 'request handler - /api/user/:id'); - assert.strictEqual(spans[6].kind, testUtils.OtlpSpanKind.INTERNAL); - assert.strictEqual(spans[6].parentSpanId, spans[1].spanId); + const expectedSpanNames = isExpressV5 + ? [ + 'middleware - simpleMiddleware', + 'router - /api/user/:id', + 'request handler - /api/user/:id', + ] + : [ + 'middleware - query', + 'middleware - expressInit', + 'middleware - simpleMiddleware', + 'router - /api/user/:id', + 'request handler - /api/user/:id', + ]; + const remainingSpans = spans.slice(2); + for (const expectedSpanName of expectedSpanNames) { + const span = remainingSpans.shift()!; + assert.strictEqual(span.name, expectedSpanName); + assert.strictEqual(span.kind, testUtils.OtlpSpanKind.INTERNAL); + assert.strictEqual(span.parentSpanId, spans[1].spanId); + } }, }); }); @@ -697,30 +712,31 @@ describe('ExpressInstrumentation', () => { assert.strictEqual(spans[0].kind, testUtils.OtlpSpanKind.CLIENT); assert.strictEqual(spans[1].name, 'GET /api/user/:id/posts/:postId'); assert.strictEqual(spans[1].kind, testUtils.OtlpSpanKind.SERVER); - assert.strictEqual(spans[2].name, 'middleware - query'); - assert.strictEqual(spans[2].kind, testUtils.OtlpSpanKind.INTERNAL); - assert.strictEqual(spans[2].parentSpanId, spans[1].spanId); - assert.strictEqual(spans[3].name, 'middleware - expressInit'); - assert.strictEqual(spans[3].kind, testUtils.OtlpSpanKind.INTERNAL); - assert.strictEqual(spans[3].parentSpanId, spans[1].spanId); - assert.strictEqual(spans[4].name, 'middleware - simpleMiddleware'); - assert.strictEqual(spans[4].kind, testUtils.OtlpSpanKind.INTERNAL); - assert.strictEqual(spans[4].parentSpanId, spans[1].spanId); - assert.strictEqual(spans[5].name, 'router - /api/user/:id'); - assert.strictEqual(spans[5].kind, testUtils.OtlpSpanKind.INTERNAL); - assert.strictEqual(spans[5].parentSpanId, spans[1].spanId); - assert.strictEqual(spans[6].name, 'router - /api/user/:id/posts'); - assert.strictEqual(spans[6].kind, testUtils.OtlpSpanKind.INTERNAL); - assert.strictEqual(spans[6].parentSpanId, spans[1].spanId); - assert.strictEqual(spans[7].name, 'middleware - simpleMiddleware2'); - assert.strictEqual(spans[7].kind, testUtils.OtlpSpanKind.INTERNAL); - assert.strictEqual(spans[7].parentSpanId, spans[1].spanId); - assert.strictEqual( - spans[8].name, - 'request handler - /api/user/:id/posts/:postId' - ); - assert.strictEqual(spans[8].kind, testUtils.OtlpSpanKind.INTERNAL); - assert.strictEqual(spans[8].parentSpanId, spans[1].spanId); + const expectedSpanNames = isExpressV5 + ? [ + 'middleware - simpleMiddleware', + 'router - /api/user/:id', + 'router - /api/user/:id/posts', + 'middleware - simpleMiddleware2', + 'request handler - /api/user/:id/posts/:postId', + ] + : [ + 'middleware - query', + 'middleware - expressInit', + 'middleware - simpleMiddleware', + 'router - /api/user/:id', + 'router - /api/user/:id/posts', + 'middleware - simpleMiddleware2', + 'request handler - /api/user/:id/posts/:postId', + ]; + + const remainingSpans = spans.slice(2); + for (const expectedSpanName of expectedSpanNames) { + const span = remainingSpans.shift()!; + assert.strictEqual(span.name, expectedSpanName); + assert.strictEqual(span.kind, testUtils.OtlpSpanKind.INTERNAL); + assert.strictEqual(span.parentSpanId, spans[1].spanId); + } }, }); }); @@ -746,21 +762,24 @@ describe('ExpressInstrumentation', () => { assert.strictEqual(spans[1].name, 'GET /\\/test\\/regex/'); assert.strictEqual(spans[1].parentSpanId, spans[0].spanId); assert.strictEqual(spans[1].kind, testUtils.OtlpSpanKind.SERVER); - assert.strictEqual(spans[2].name, 'middleware - query'); - assert.strictEqual(spans[2].kind, testUtils.OtlpSpanKind.INTERNAL); - assert.strictEqual(spans[2].parentSpanId, spans[1].spanId); - assert.strictEqual(spans[3].name, 'middleware - expressInit'); - assert.strictEqual(spans[3].kind, testUtils.OtlpSpanKind.INTERNAL); - assert.strictEqual(spans[3].parentSpanId, spans[1].spanId); - assert.strictEqual(spans[4].name, 'middleware - simpleMiddleware'); - assert.strictEqual(spans[4].kind, testUtils.OtlpSpanKind.INTERNAL); - assert.strictEqual(spans[4].parentSpanId, spans[1].spanId); - assert.strictEqual( - spans[5].name, - 'request handler - /\\/test\\/regex/' - ); - assert.strictEqual(spans[5].kind, testUtils.OtlpSpanKind.INTERNAL); - assert.strictEqual(spans[5].parentSpanId, spans[1].spanId); + const expectedSpanNames = isExpressV5 + ? [ + 'middleware - simpleMiddleware', + 'request handler - /\\/test\\/regex/', + ] + : [ + 'middleware - query', + 'middleware - expressInit', + 'middleware - simpleMiddleware', + 'request handler - /\\/test\\/regex/', + ]; + const remainingSpans = spans.slice(2); + for (const expectedSpanName of expectedSpanNames) { + const span = remainingSpans.shift()!; + assert.strictEqual(span.name, expectedSpanName); + assert.strictEqual(span.kind, testUtils.OtlpSpanKind.INTERNAL); + assert.strictEqual(span.parentSpanId, spans[1].spanId); + } }, }); }); @@ -785,18 +804,24 @@ describe('ExpressInstrumentation', () => { assert.strictEqual(spans[0].kind, testUtils.OtlpSpanKind.CLIENT); assert.strictEqual(spans[1].name, 'GET /test,6,/test/'); assert.strictEqual(spans[1].kind, testUtils.OtlpSpanKind.SERVER); - assert.strictEqual(spans[2].name, 'middleware - query'); - assert.strictEqual(spans[2].kind, testUtils.OtlpSpanKind.INTERNAL); - assert.strictEqual(spans[2].parentSpanId, spans[1].spanId); - assert.strictEqual(spans[3].name, 'middleware - expressInit'); - assert.strictEqual(spans[3].kind, testUtils.OtlpSpanKind.INTERNAL); - assert.strictEqual(spans[3].parentSpanId, spans[1].spanId); - assert.strictEqual(spans[4].name, 'middleware - simpleMiddleware'); - assert.strictEqual(spans[4].kind, testUtils.OtlpSpanKind.INTERNAL); - assert.strictEqual(spans[4].parentSpanId, spans[1].spanId); - assert.strictEqual(spans[5].name, 'request handler - /test,6,/test/'); - assert.strictEqual(spans[5].kind, testUtils.OtlpSpanKind.INTERNAL); - assert.strictEqual(spans[5].parentSpanId, spans[1].spanId); + const expectedSpanNames = isExpressV5 + ? [ + 'middleware - simpleMiddleware', + 'request handler - /test,6,/test/', + ] + : [ + 'middleware - query', + 'middleware - expressInit', + 'middleware - simpleMiddleware', + 'request handler - /test,6,/test/', + ]; + const remainingSpans = spans.slice(2); + for (const expectedSpanName of expectedSpanNames) { + const span = remainingSpans.shift()!; + assert.strictEqual(span.name, expectedSpanName); + assert.strictEqual(span.kind, testUtils.OtlpSpanKind.INTERNAL); + assert.strictEqual(span.parentSpanId, spans[1].spanId); + } }, }); }); @@ -825,21 +850,24 @@ describe('ExpressInstrumentation', () => { 'GET /test/array1,/\\/test\\/array[2-9]/' ); assert.strictEqual(spans[1].kind, testUtils.OtlpSpanKind.SERVER); - assert.strictEqual(spans[2].name, 'middleware - query'); - assert.strictEqual(spans[2].kind, testUtils.OtlpSpanKind.INTERNAL); - assert.strictEqual(spans[2].parentSpanId, spans[1].spanId); - assert.strictEqual(spans[3].name, 'middleware - expressInit'); - assert.strictEqual(spans[3].kind, testUtils.OtlpSpanKind.INTERNAL); - assert.strictEqual(spans[3].parentSpanId, spans[1].spanId); - assert.strictEqual(spans[4].name, 'middleware - simpleMiddleware'); - assert.strictEqual(spans[4].kind, testUtils.OtlpSpanKind.INTERNAL); - assert.strictEqual(spans[4].parentSpanId, spans[1].spanId); - assert.strictEqual( - spans[5].name, - 'request handler - /test/array1,/\\/test\\/array[2-9]/' - ); - assert.strictEqual(spans[5].kind, testUtils.OtlpSpanKind.INTERNAL); - assert.strictEqual(spans[5].parentSpanId, spans[1].spanId); + const expectedSpanNames = isExpressV5 + ? [ + 'middleware - simpleMiddleware', + 'request handler - /test/array1,/\\/test\\/array[2-9]/', + ] + : [ + 'middleware - query', + 'middleware - expressInit', + 'middleware - simpleMiddleware', + 'request handler - /test/array1,/\\/test\\/array[2-9]/', + ]; + const remainingSpans = spans.slice(2); + for (const expectedSpanName of expectedSpanNames) { + const span = remainingSpans.shift()!; + assert.strictEqual(span.name, expectedSpanName); + assert.strictEqual(span.kind, testUtils.OtlpSpanKind.INTERNAL); + assert.strictEqual(span.parentSpanId, spans[1].spanId); + } }, }); }); @@ -852,8 +880,8 @@ describe('ExpressInstrumentation', () => { 'arr/requiredPath', 'arr/required/lastParam', 'arr55/required/lastParam', - 'arr/requiredPath/optionalPath/', - 'arr/requiredPath/optionalPath/lastParam', + 'arr/requiredpath/optionalPath/', + 'arr/requiredpath/optionalPath/lastParam', ]) { it('should handle more complex regexes in route arrays correctly', async () => { await testUtils.runTestFixture({ @@ -878,21 +906,25 @@ describe('ExpressInstrumentation', () => { 'GET /test/arr/:id,/\\/test\\/arr[0-9]*\\/required(path)?(\\/optionalPath)?\\/(lastParam)?/' ); assert.strictEqual(spans[1].kind, testUtils.OtlpSpanKind.SERVER); - assert.strictEqual(spans[2].name, 'middleware - query'); - assert.strictEqual(spans[2].kind, testUtils.OtlpSpanKind.INTERNAL); - assert.strictEqual(spans[2].parentSpanId, spans[1].spanId); - assert.strictEqual(spans[3].name, 'middleware - expressInit'); - assert.strictEqual(spans[3].kind, testUtils.OtlpSpanKind.INTERNAL); - assert.strictEqual(spans[3].parentSpanId, spans[1].spanId); - assert.strictEqual(spans[4].name, 'middleware - simpleMiddleware'); - assert.strictEqual(spans[4].kind, testUtils.OtlpSpanKind.INTERNAL); - assert.strictEqual(spans[4].parentSpanId, spans[1].spanId); - assert.strictEqual( - spans[5].name, - 'request handler - /test/arr/:id,/\\/test\\/arr[0-9]*\\/required(path)?(\\/optionalPath)?\\/(lastParam)?/' - ); - assert.strictEqual(spans[5].kind, testUtils.OtlpSpanKind.INTERNAL); - assert.strictEqual(spans[5].parentSpanId, spans[1].spanId); + + const expectedSpanNames = isExpressV5 + ? [ + 'middleware - simpleMiddleware', + 'request handler - /test/arr/:id,/\\/test\\/arr[0-9]*\\/required(path)?(\\/optionalPath)?\\/(lastParam)?/', + ] + : [ + 'middleware - query', + 'middleware - expressInit', + 'middleware - simpleMiddleware', + 'request handler - /test/arr/:id,/\\/test\\/arr[0-9]*\\/required(path)?(\\/optionalPath)?\\/(lastParam)?/', + ]; + const remainingSpans = spans.slice(2); + for (const expectedSpanName of expectedSpanNames) { + const span = remainingSpans.shift()!; + assert.strictEqual(span.name, expectedSpanName); + assert.strictEqual(span.kind, testUtils.OtlpSpanKind.INTERNAL); + assert.strictEqual(span.parentSpanId, spans[1].spanId); + } }, }); }); diff --git a/plugins/node/opentelemetry-instrumentation-express/test/hooks.test.ts b/plugins/node/opentelemetry-instrumentation-express/test/hooks.test.ts index 04af79540c..bc1ffcd2e4 100644 --- a/plugins/node/opentelemetry-instrumentation-express/test/hooks.test.ts +++ b/plugins/node/opentelemetry-instrumentation-express/test/hooks.test.ts @@ -67,7 +67,7 @@ describe('ExpressInstrumentation hooks', () => { rootSpan = tracer.startSpan('rootSpan'); const httpServer = await serverWithMiddleware(tracer, rootSpan, app => { - app.get('*', (req, res) => { + app.get(/.*/, (req, res) => { rpcMetadata = getRPCMetadata(context.active()); res.send('ok'); }); @@ -97,7 +97,7 @@ describe('ExpressInstrumentation hooks', () => { assert.strictEqual(spans.length, 2); assert.notStrictEqual( - spans.find(span => span.name === 'custom: request_handler - *'), + spans.find(span => span.name === 'custom: request_handler - /.*/'), undefined ); } @@ -120,9 +120,9 @@ describe('ExpressInstrumentation hooks', () => { const spans = memoryExporter.getFinishedSpans(); assert.strictEqual(spans.length, 2); - assert.strictEqual(rpcMetadata?.route, '*'); + assert.strictEqual(rpcMetadata?.route, '/.*/'); assert.notStrictEqual( - spans.find(span => span.name === 'request handler - *'), + spans.find(span => span.name === 'request handler - /.*/'), undefined ); } @@ -146,9 +146,9 @@ describe('ExpressInstrumentation hooks', () => { const spans = memoryExporter.getFinishedSpans(); assert.strictEqual(spans.length, 2); - assert.strictEqual(rpcMetadata?.route, '*'); + assert.strictEqual(rpcMetadata?.route, '/.*/'); assert.notStrictEqual( - spans.find(span => span.name === 'request handler - *'), + spans.find(span => span.name === 'request handler - /.*/'), undefined ); } @@ -165,7 +165,7 @@ describe('ExpressInstrumentation hooks', () => { rootSpan = tracer.startSpan('rootSpan'); const httpServer = await serverWithMiddleware(tracer, rootSpan, app => { - app.get('*', (req, res) => { + app.get(/.*/, (req, res) => { res.send('ok'); }); }); @@ -198,7 +198,7 @@ describe('ExpressInstrumentation hooks', () => { const spans = memoryExporter.getFinishedSpans(); const requestHandlerSpan = spans.find( - span => span.name === 'request handler - *' + span => span.name === 'request handler - /.*/' ); assert.strictEqual(spans.length, 2); @@ -234,7 +234,7 @@ describe('ExpressInstrumentation hooks', () => { const spans = memoryExporter.getFinishedSpans(); const requestHandlerSpan = spans.find( - span => span.name === 'request handler - *' + span => span.name === 'request handler - /.*/' ); assert.strictEqual(spans.length, 2);