diff --git a/.github.amrom.workers.devponent_owners.yml b/.github.amrom.workers.devponent_owners.yml index c53adad9af..382ddb7f11 100644 --- a/.github.amrom.workers.devponent_owners.yml +++ b/.github.amrom.workers.devponent_owners.yml @@ -30,6 +30,8 @@ components: - pichlermarc - legendecas - blumamir + packages/baggage-log-record-processor: + - maryliag packages/baggage-span-processor: - mikegoldsmith - jamiedanielson diff --git a/.github/workflows/ossf-scorecard.yml b/.github/workflows/ossf-scorecard.yml new file mode 100644 index 0000000000..1750c54f03 --- /dev/null +++ b/.github/workflows/ossf-scorecard.yml @@ -0,0 +1,47 @@ +name: OSSF Scorecard + +on: + push: + branches: + - main + schedule: + - cron: "31 18 * * 4" # once a week + workflow_dispatch: + +permissions: read-all + +jobs: + analysis: + runs-on: ubuntu-latest + permissions: + # Needed for Code scanning upload + security-events: write + # Needed for GitHub OIDC token if publish_results is true + id-token: write + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + + - uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1 + with: + results_file: results.sarif + results_format: sarif + publish_results: true + + # Upload the results as artifacts (optional). Commenting out will disable + # uploads of run results in SARIF format to the repository Actions tab. + # https://docs.github.com/en/actions/advanced-guides/storing-workflow-data-as-artifacts + - name: "Upload artifact" + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + # Upload the results to GitHub's code scanning dashboard (optional). + # Commenting out will disable upload of results to your repo's Code Scanning dashboard + - name: "Upload to code-scanning" + uses: github/codeql-action/upload-sarif@5f8171a638ada777af81d42b55959a643bb29017 # v3.28.12 + with: + sarif_file: results.sarif diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 5def797d4d..582c9eb32c 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -7,9 +7,10 @@ "detectors/node/opentelemetry-resource-detector-github": "0.31.0", "detectors/node/opentelemetry-resource-detector-instana": "0.19.0", "metapackages/auto-configuration-propagators": "0.4.0", - "metapackages/auto-instrumentations-node": "0.57.0", + "metapackages/auto-instrumentations-node": "0.57.1", "metapackages/auto-instrumentations-web": "0.46.0", "packages/baggage-span-processor": "0.4.0", + "packages/baggage-log-record-processor": "0.1.0", "packages/opentelemetry-host-metrics": "0.36.0", "packages/opentelemetry-id-generator-aws-xray": "2.0.0", "packages/opentelemetry-propagation-utils": "0.31.0", @@ -21,7 +22,7 @@ "plugins/node/instrumentation-cucumber": "0.15.0", "plugins/node/instrumentation-dataloader": "0.17.0", "plugins/node/instrumentation-fs": "0.20.0", - "plugins/node/instrumentation-kafkajs": "0.8.0", + "plugins/node/instrumentation-kafkajs": "0.9.0", "plugins/node/instrumentation-lru-memoizer": "0.45.0", "plugins/node/instrumentation-mongoose": "0.47.0", "plugins/node/instrumentation-runtime-node": "0.13.0", @@ -29,7 +30,7 @@ "plugins/node/instrumentation-tedious": "0.19.0", "plugins/node/instrumentation-undici": "0.11.0", "plugins/node/opentelemetry-instrumentation-aws-lambda": "0.51.0", - "plugins/node/opentelemetry-instrumentation-aws-sdk": "0.50.0", + "plugins/node/opentelemetry-instrumentation-aws-sdk": "0.51.0", "plugins/node/opentelemetry-instrumentation-bunyan": "0.46.0", "plugins/node/opentelemetry-instrumentation-cassandra": "0.46.0", "plugins/node/opentelemetry-instrumentation-connect": "0.44.0", @@ -46,7 +47,7 @@ "plugins/node/opentelemetry-instrumentation-mongodb": "0.53.0", "plugins/node/opentelemetry-instrumentation-mysql": "0.46.0", "plugins/node/opentelemetry-instrumentation-mysql2": "0.46.0", - "plugins/node/opentelemetry-instrumentation-nestjs-core": "0.45.0", + "plugins/node/opentelemetry-instrumentation-nestjs-core": "0.46.0", "plugins/node/opentelemetry-instrumentation-net": "0.44.0", "plugins/node/opentelemetry-instrumentation-pg": "0.52.0", "plugins/node/opentelemetry-instrumentation-pino": "0.47.0", diff --git a/metapackages/auto-instrumentations-node/CHANGELOG.md b/metapackages/auto-instrumentations-node/CHANGELOG.md index ac852e4b96..2cb265e519 100644 --- a/metapackages/auto-instrumentations-node/CHANGELOG.md +++ b/metapackages/auto-instrumentations-node/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## [0.57.1](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/auto-instrumentations-node-v0.57.0...auto-instrumentations-node-v0.57.1) (2025-04-08) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @opentelemetry/instrumentation-aws-sdk bumped from ^0.50.0 to ^0.51.0 + * @opentelemetry/instrumentation-kafkajs bumped from ^0.8.0 to ^0.9.0 + * @opentelemetry/instrumentation-nestjs-core bumped from ^0.45.0 to ^0.46.0 + ## [0.57.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/auto-instrumentations-node-v0.56.1...auto-instrumentations-node-v0.57.0) (2025-03-18) diff --git a/metapackages/auto-instrumentations-node/README.md b/metapackages/auto-instrumentations-node/README.md index c44ab45269..01af995f54 100644 --- a/metapackages/auto-instrumentations-node/README.md +++ b/metapackages/auto-instrumentations-node/README.md @@ -11,7 +11,7 @@ The net result is the ability to gather telemetry data from a Node application w This module also provides a simple way to manually initialize multiple Node instrumentations for use with the OpenTelemetry SDK. -Compatible with OpenTelemetry JS API and SDK `1.0+`. +Compatible with OpenTelemetry JS API and SDK `2.0+`. ## Installation diff --git a/metapackages/auto-instrumentations-node/package.json b/metapackages/auto-instrumentations-node/package.json index 948eb68d7a..fd8980b8d8 100644 --- a/metapackages/auto-instrumentations-node/package.json +++ b/metapackages/auto-instrumentations-node/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/auto-instrumentations-node", - "version": "0.57.0", + "version": "0.57.1", "description": "Metapackage which bundles opentelemetry node core and contrib instrumentations", "author": "OpenTelemetry Authors", "homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/metapackages/auto-instrumentations-node#readme", @@ -33,10 +33,12 @@ "url": "https://github.com/open-telemetry/opentelemetry-js-contrib/issues" }, "peerDependencies": { - "@opentelemetry/api": "^1.4.1" + "@opentelemetry/api": "^1.4.1", + "@opentelemetry/core": "^2.0.0" }, "devDependencies": { "@opentelemetry/api": "^1.4.1", + "@opentelemetry/core": "^2.0.0", "@types/mocha": "10.0.10", "@types/node": "18.18.14", "@types/sinon": "17.0.4", @@ -49,7 +51,7 @@ "@opentelemetry/instrumentation": "^0.200.0", "@opentelemetry/instrumentation-amqplib": "^0.47.0", "@opentelemetry/instrumentation-aws-lambda": "^0.51.0", - "@opentelemetry/instrumentation-aws-sdk": "^0.50.0", + "@opentelemetry/instrumentation-aws-sdk": "^0.51.0", "@opentelemetry/instrumentation-bunyan": "^0.46.0", "@opentelemetry/instrumentation-cassandra-driver": "^0.46.0", "@opentelemetry/instrumentation-connect": "^0.44.0", @@ -65,7 +67,7 @@ "@opentelemetry/instrumentation-hapi": "^0.46.0", "@opentelemetry/instrumentation-http": "^0.200.0", "@opentelemetry/instrumentation-ioredis": "^0.48.0", - "@opentelemetry/instrumentation-kafkajs": "^0.8.0", + "@opentelemetry/instrumentation-kafkajs": "^0.9.0", "@opentelemetry/instrumentation-knex": "^0.45.0", "@opentelemetry/instrumentation-koa": "^0.48.0", "@opentelemetry/instrumentation-lru-memoizer": "^0.45.0", @@ -74,7 +76,7 @@ "@opentelemetry/instrumentation-mongoose": "^0.47.0", "@opentelemetry/instrumentation-mysql": "^0.46.0", "@opentelemetry/instrumentation-mysql2": "^0.46.0", - "@opentelemetry/instrumentation-nestjs-core": "^0.45.0", + "@opentelemetry/instrumentation-nestjs-core": "^0.46.0", "@opentelemetry/instrumentation-net": "^0.44.0", "@opentelemetry/instrumentation-pg": "^0.52.0", "@opentelemetry/instrumentation-pino": "^0.47.0", diff --git a/metapackages/auto-instrumentations-node/src/register.ts b/metapackages/auto-instrumentations-node/src/register.ts index 3a4ae6cd5a..5ffeb2c32e 100644 --- a/metapackages/auto-instrumentations-node/src/register.ts +++ b/metapackages/auto-instrumentations-node/src/register.ts @@ -15,13 +15,18 @@ */ import * as opentelemetry from '@opentelemetry/sdk-node'; import { diag, DiagConsoleLogger } from '@opentelemetry/api'; +import { getStringFromEnv, diagLogLevelFromString } from '@opentelemetry/core'; import { - getLogLevelFromEnv, getNodeAutoInstrumentations, getResourceDetectorsFromEnv, } from './utils'; -diag.setLogger(new DiagConsoleLogger(), getLogLevelFromEnv()); +const logLevel = getStringFromEnv('OTEL_LOG_LEVEL'); +if (logLevel != null) { + diag.setLogger(new DiagConsoleLogger(), { + logLevel: diagLogLevelFromString(logLevel), + }); +} const sdk = new opentelemetry.NodeSDK({ instrumentations: getNodeAutoInstrumentations(), diff --git a/metapackages/auto-instrumentations-node/src/utils.ts b/metapackages/auto-instrumentations-node/src/utils.ts index ae5349a0fc..e43ee7c32a 100644 --- a/metapackages/auto-instrumentations-node/src/utils.ts +++ b/metapackages/auto-instrumentations-node/src/utils.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { diag, DiagLogLevel } from '@opentelemetry/api'; +import { diag } from '@opentelemetry/api'; import { Instrumentation } from '@opentelemetry/instrumentation'; import { AmqplibInstrumentation } from '@opentelemetry/instrumentation-amqplib'; @@ -135,17 +135,6 @@ const InstrumentationMap = { '@opentelemetry/instrumentation-winston': WinstonInstrumentation, }; -// The support string -> DiagLogLevel mappings -const logLevelMap: { [key: string]: DiagLogLevel } = { - ALL: DiagLogLevel.ALL, - VERBOSE: DiagLogLevel.VERBOSE, - DEBUG: DiagLogLevel.DEBUG, - INFO: DiagLogLevel.INFO, - WARN: DiagLogLevel.WARN, - ERROR: DiagLogLevel.ERROR, - NONE: DiagLogLevel.NONE, -}; - const defaultExcludedInstrumentations = [ '@opentelemetry/instrumentation-fs', '@opentelemetry/instrumentation-fastify', @@ -303,16 +292,3 @@ export function getResourceDetectorsFromEnv(): Array { return resourceDetector || []; }); } - -export function getLogLevelFromEnv(): DiagLogLevel { - const rawLogLevel = process.env.OTEL_LOG_LEVEL; - - // NOTE: as per specification we should actually only register if something is set, but our previous implementation - // always registered a logger, even when nothing was set. Falling back to 'INFO' here to keep the same behavior as - // with previous implementations. - // Also: no point in warning - no logger is registered yet - return ( - logLevelMap[rawLogLevel?.trim().toUpperCase() ?? 'INFO'] ?? - DiagLogLevel.INFO - ); -} diff --git a/metapackages/auto-instrumentations-node/test/utils.test.ts b/metapackages/auto-instrumentations-node/test/utils.test.ts index 7fac6762fc..1241ca6cce 100644 --- a/metapackages/auto-instrumentations-node/test/utils.test.ts +++ b/metapackages/auto-instrumentations-node/test/utils.test.ts @@ -14,12 +14,12 @@ * limitations under the License. */ -import { diag, DiagLogLevel } from '@opentelemetry/api'; +import { diag } from '@opentelemetry/api'; import { HttpInstrumentationConfig } from '@opentelemetry/instrumentation-http'; import * as assert from 'assert'; import * as sinon from 'sinon'; import { getNodeAutoInstrumentations } from '../src'; -import { getLogLevelFromEnv, getResourceDetectorsFromEnv } from '../src/utils'; +import { getResourceDetectorsFromEnv } from '../src/utils'; describe('utils', () => { describe('getNodeAutoInstrumentations', () => { @@ -223,44 +223,4 @@ describe('utils', () => { delete process.env.OTEL_NODE_RESOURCE_DETECTORS; }); }); - - describe('getLogLevelFromEnv', function () { - afterEach(function () { - delete process.env.OTEL_LOG_LEVEL; - }); - - it('should select log level based on env var', function () { - process.env.OTEL_LOG_LEVEL = 'NONE'; - assert.strictEqual(getLogLevelFromEnv(), DiagLogLevel.NONE); - process.env.OTEL_LOG_LEVEL = 'VERBOSE'; - assert.strictEqual(getLogLevelFromEnv(), DiagLogLevel.VERBOSE); - process.env.OTEL_LOG_LEVEL = 'DEBUG'; - assert.strictEqual(getLogLevelFromEnv(), DiagLogLevel.DEBUG); - process.env.OTEL_LOG_LEVEL = 'INFO'; - assert.strictEqual(getLogLevelFromEnv(), DiagLogLevel.INFO); - process.env.OTEL_LOG_LEVEL = 'WARN'; - assert.strictEqual(getLogLevelFromEnv(), DiagLogLevel.WARN); - process.env.OTEL_LOG_LEVEL = 'ERROR'; - assert.strictEqual(getLogLevelFromEnv(), DiagLogLevel.ERROR); - process.env.OTEL_LOG_LEVEL = 'ALL'; - assert.strictEqual(getLogLevelFromEnv(), DiagLogLevel.ALL); - }); - - it('should ignore casing', function () { - process.env.OTEL_LOG_LEVEL = 'warn'; - assert.strictEqual(getLogLevelFromEnv(), DiagLogLevel.WARN); - process.env.OTEL_LOG_LEVEL = 'WaRN'; - assert.strictEqual(getLogLevelFromEnv(), DiagLogLevel.WARN); - }); - - it('should fall back to INFO on bogus input', function () { - process.env.OTEL_LOG_LEVEL = 'bogus'; - assert.strictEqual(getLogLevelFromEnv(), DiagLogLevel.INFO); - }); - - it('should use INFO when unset', function () { - delete process.env.OTEL_LOG_LEVEL; - assert.strictEqual(getLogLevelFromEnv(), DiagLogLevel.INFO); - }); - }); }); diff --git a/package-lock.json b/package-lock.json index 1e2922179d..6039666989 100644 --- a/package-lock.json +++ b/package-lock.json @@ -345,13 +345,13 @@ }, "metapackages/auto-instrumentations-node": { "name": "@opentelemetry/auto-instrumentations-node", - "version": "0.57.0", + "version": "0.57.1", "license": "Apache-2.0", "dependencies": { "@opentelemetry/instrumentation": "^0.200.0", "@opentelemetry/instrumentation-amqplib": "^0.47.0", "@opentelemetry/instrumentation-aws-lambda": "^0.51.0", - "@opentelemetry/instrumentation-aws-sdk": "^0.50.0", + "@opentelemetry/instrumentation-aws-sdk": "^0.51.0", "@opentelemetry/instrumentation-bunyan": "^0.46.0", "@opentelemetry/instrumentation-cassandra-driver": "^0.46.0", "@opentelemetry/instrumentation-connect": "^0.44.0", @@ -367,7 +367,7 @@ "@opentelemetry/instrumentation-hapi": "^0.46.0", "@opentelemetry/instrumentation-http": "^0.200.0", "@opentelemetry/instrumentation-ioredis": "^0.48.0", - "@opentelemetry/instrumentation-kafkajs": "^0.8.0", + "@opentelemetry/instrumentation-kafkajs": "^0.9.0", "@opentelemetry/instrumentation-knex": "^0.45.0", "@opentelemetry/instrumentation-koa": "^0.48.0", "@opentelemetry/instrumentation-lru-memoizer": "^0.45.0", @@ -376,7 +376,7 @@ "@opentelemetry/instrumentation-mongoose": "^0.47.0", "@opentelemetry/instrumentation-mysql": "^0.46.0", "@opentelemetry/instrumentation-mysql2": "^0.46.0", - "@opentelemetry/instrumentation-nestjs-core": "^0.45.0", + "@opentelemetry/instrumentation-nestjs-core": "^0.46.0", "@opentelemetry/instrumentation-net": "^0.44.0", "@opentelemetry/instrumentation-pg": "^0.52.0", "@opentelemetry/instrumentation-pino": "^0.47.0", @@ -398,6 +398,7 @@ }, "devDependencies": { "@opentelemetry/api": "^1.4.1", + "@opentelemetry/core": "^2.0.0", "@types/mocha": "10.0.10", "@types/node": "18.18.14", "@types/sinon": "17.0.4", @@ -410,7 +411,8 @@ "node": "^18.19.0 || >=20.6.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.4.1" + "@opentelemetry/api": "^1.4.1", + "@opentelemetry/core": "^2.0.0" } }, "metapackages/auto-instrumentations-node/node_modules/@types/node": { @@ -710,47 +712,103 @@ "node": ">=14.0.0" } }, - "node_modules/@aws-sdk/client-cognito-identity": { - "version": "3.750.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.750.0.tgz", - "integrity": "sha512-ia5+l7U1ludU/YqQAnEMj5DIp1kfMTu14lUOMG3uTIwTcj8OjkCvAe6BuM0OY6zd8enrJYWLqIqxuKPOWw4I7Q==", + "node_modules/@aws-sdk/client-bedrock-runtime": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-bedrock-runtime/-/client-bedrock-runtime-3.758.0.tgz", + "integrity": "sha512-T7s+fULUxN3AcJP+lgoUKLawzVEtyCTi+5Ga+wrHnqEPwAsM/wg7VctsZfow1fCgARLT/lzmP2LTCi8ycRnQWg==", "dev": true, - "optional": true, + "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.750.0", - "@aws-sdk/credential-provider-node": "3.750.0", + "@aws-sdk/core": "3.758.0", + "@aws-sdk/credential-provider-node": "3.758.0", "@aws-sdk/middleware-host-header": "3.734.0", "@aws-sdk/middleware-logger": "3.734.0", "@aws-sdk/middleware-recursion-detection": "3.734.0", - "@aws-sdk/middleware-user-agent": "3.750.0", + "@aws-sdk/middleware-user-agent": "3.758.0", "@aws-sdk/region-config-resolver": "3.734.0", "@aws-sdk/types": "3.734.0", "@aws-sdk/util-endpoints": "3.743.0", "@aws-sdk/util-user-agent-browser": "3.734.0", - "@aws-sdk/util-user-agent-node": "3.750.0", + "@aws-sdk/util-user-agent-node": "3.758.0", "@smithy/config-resolver": "^4.0.1", - "@smithy/core": "^3.1.4", + "@smithy/core": "^3.1.5", + "@smithy/eventstream-serde-browser": "^4.0.1", + "@smithy/eventstream-serde-config-resolver": "^4.0.1", + "@smithy/eventstream-serde-node": "^4.0.1", "@smithy/fetch-http-handler": "^5.0.1", "@smithy/hash-node": "^4.0.1", "@smithy/invalid-dependency": "^4.0.1", "@smithy/middleware-content-length": "^4.0.1", - "@smithy/middleware-endpoint": "^4.0.5", - "@smithy/middleware-retry": "^4.0.6", + "@smithy/middleware-endpoint": "^4.0.6", + "@smithy/middleware-retry": "^4.0.7", "@smithy/middleware-serde": "^4.0.2", "@smithy/middleware-stack": "^4.0.1", "@smithy/node-config-provider": "^4.0.1", - "@smithy/node-http-handler": "^4.0.2", + "@smithy/node-http-handler": "^4.0.3", "@smithy/protocol-http": "^5.0.1", - "@smithy/smithy-client": "^4.1.5", + "@smithy/smithy-client": "^4.1.6", "@smithy/types": "^4.1.0", "@smithy/url-parser": "^4.0.1", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.6", - "@smithy/util-defaults-mode-node": "^4.0.6", + "@smithy/util-defaults-mode-browser": "^4.0.7", + "@smithy/util-defaults-mode-node": "^4.0.7", + "@smithy/util-endpoints": "^3.0.1", + "@smithy/util-middleware": "^4.0.1", + "@smithy/util-retry": "^4.0.1", + "@smithy/util-stream": "^4.1.2", + "@smithy/util-utf8": "^4.0.0", + "@types/uuid": "^9.0.1", + "tslib": "^2.6.2", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/client-sso": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.758.0.tgz", + "integrity": "sha512-BoGO6IIWrLyLxQG6txJw6RT2urmbtlwfggapNCrNPyYjlXpzTSJhBYjndg7TpDATFd0SXL0zm8y/tXsUXNkdYQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.758.0", + "@aws-sdk/middleware-host-header": "3.734.0", + "@aws-sdk/middleware-logger": "3.734.0", + "@aws-sdk/middleware-recursion-detection": "3.734.0", + "@aws-sdk/middleware-user-agent": "3.758.0", + "@aws-sdk/region-config-resolver": "3.734.0", + "@aws-sdk/types": "3.734.0", + "@aws-sdk/util-endpoints": "3.743.0", + "@aws-sdk/util-user-agent-browser": "3.734.0", + "@aws-sdk/util-user-agent-node": "3.758.0", + "@smithy/config-resolver": "^4.0.1", + "@smithy/core": "^3.1.5", + "@smithy/fetch-http-handler": "^5.0.1", + "@smithy/hash-node": "^4.0.1", + "@smithy/invalid-dependency": "^4.0.1", + "@smithy/middleware-content-length": "^4.0.1", + "@smithy/middleware-endpoint": "^4.0.6", + "@smithy/middleware-retry": "^4.0.7", + "@smithy/middleware-serde": "^4.0.2", + "@smithy/middleware-stack": "^4.0.1", + "@smithy/node-config-provider": "^4.0.1", + "@smithy/node-http-handler": "^4.0.3", + "@smithy/protocol-http": "^5.0.1", + "@smithy/smithy-client": "^4.1.6", + "@smithy/types": "^4.1.0", + "@smithy/url-parser": "^4.0.1", + "@smithy/util-base64": "^4.0.0", + "@smithy/util-body-length-browser": "^4.0.0", + "@smithy/util-body-length-node": "^4.0.0", + "@smithy/util-defaults-mode-browser": "^4.0.7", + "@smithy/util-defaults-mode-node": "^4.0.7", "@smithy/util-endpoints": "^3.0.1", "@smithy/util-middleware": "^4.0.1", "@smithy/util-retry": "^4.0.1", @@ -761,44 +819,86 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/abort-controller": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.1.tgz", - "integrity": "sha512-fiUIYgIgRjMWznk6iLJz35K2YxSLHzLBA/RC6lBrKfQ8fHbPfvk7Pk9UvpKoHgJjI18MnbPuEju53zcVy6KF1g==", + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/core": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.758.0.tgz", + "integrity": "sha512-0RswbdR9jt/XKemaLNuxi2gGr4xGlHyGxkTdhSQzCyUe9A9OPCoLl3rIESRguQEech+oJnbHk/wuiwHqTuP9sg==", "dev": true, - "optional": true, + "license": "Apache-2.0", "dependencies": { + "@aws-sdk/types": "3.734.0", + "@smithy/core": "^3.1.5", + "@smithy/node-config-provider": "^4.0.1", + "@smithy/property-provider": "^4.0.1", + "@smithy/protocol-http": "^5.0.1", + "@smithy/signature-v4": "^5.0.1", + "@smithy/smithy-client": "^4.1.6", "@smithy/types": "^4.1.0", + "@smithy/util-middleware": "^4.0.1", + "fast-xml-parser": "4.4.1", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/node-http-handler": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.0.2.tgz", - "integrity": "sha512-X66H9aah9hisLLSnGuzRYba6vckuFtGE+a5DcHLliI/YlqKrGoxhisD5XbX44KyoeRzoNlGr94eTsMVHFAzPOw==", + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/credential-provider-env": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.758.0.tgz", + "integrity": "sha512-N27eFoRrO6MeUNumtNHDW9WOiwfd59LPXPqDrIa3kWL/s+fOKFHb9xIcF++bAwtcZnAxKkgpDCUP+INNZskE+w==", "dev": true, - "optional": true, + "license": "Apache-2.0", "dependencies": { - "@smithy/abort-controller": "^4.0.1", + "@aws-sdk/core": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@smithy/property-provider": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/credential-provider-http": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.758.0.tgz", + "integrity": "sha512-Xt9/U8qUCiw1hihztWkNeIR+arg6P+yda10OuCHX6kFVx3auTlU7+hCqs3UxqniGU4dguHuftf3mRpi5/GJ33Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@smithy/fetch-http-handler": "^5.0.1", + "@smithy/node-http-handler": "^4.0.3", + "@smithy/property-provider": "^4.0.1", "@smithy/protocol-http": "^5.0.1", - "@smithy/querystring-builder": "^4.0.1", + "@smithy/smithy-client": "^4.1.6", "@smithy/types": "^4.1.0", + "@smithy/util-stream": "^4.1.2", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/protocol-http": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.0.1.tgz", - "integrity": "sha512-TE4cpj49jJNB/oHyh/cRVEgNZaoPaxd4vteJNB0yGidOCVR0jCw/hjPVsT8Q8FRmj8Bd3bFZt8Dh7xGCT+xMBQ==", + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.758.0.tgz", + "integrity": "sha512-cymSKMcP5d+OsgetoIZ5QCe1wnp2Q/tq+uIxVdh9MbfdBBEnl9Ecq6dH6VlYS89sp4QKuxHxkWXVnbXU3Q19Aw==", "dev": true, - "optional": true, + "license": "Apache-2.0", "dependencies": { + "@aws-sdk/core": "3.758.0", + "@aws-sdk/credential-provider-env": "3.758.0", + "@aws-sdk/credential-provider-http": "3.758.0", + "@aws-sdk/credential-provider-process": "3.758.0", + "@aws-sdk/credential-provider-sso": "3.758.0", + "@aws-sdk/credential-provider-web-identity": "3.758.0", + "@aws-sdk/nested-clients": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@smithy/credential-provider-imds": "^4.0.1", + "@smithy/property-provider": "^4.0.1", + "@smithy/shared-ini-file-loader": "^4.0.1", "@smithy/types": "^4.1.0", "tslib": "^2.6.2" }, @@ -806,106 +906,204 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/querystring-builder": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.0.1.tgz", - "integrity": "sha512-wU87iWZoCbcqrwszsOewEIuq+SU2mSoBE2CcsLwE0I19m0B2gOJr1MVjxWcDQYOzHbR1xCk7AcOBbGFUYOKvdg==", + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/credential-provider-node": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.758.0.tgz", + "integrity": "sha512-+DaMv63wiq7pJrhIQzZYMn4hSarKiizDoJRvyR7WGhnn0oQ/getX9Z0VNCV3i7lIFoLNTb7WMmQ9k7+z/uD5EQ==", "dev": true, - "optional": true, + "license": "Apache-2.0", "dependencies": { + "@aws-sdk/credential-provider-env": "3.758.0", + "@aws-sdk/credential-provider-http": "3.758.0", + "@aws-sdk/credential-provider-ini": "3.758.0", + "@aws-sdk/credential-provider-process": "3.758.0", + "@aws-sdk/credential-provider-sso": "3.758.0", + "@aws-sdk/credential-provider-web-identity": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@smithy/credential-provider-imds": "^4.0.1", + "@smithy/property-provider": "^4.0.1", + "@smithy/shared-ini-file-loader": "^4.0.1", "@smithy/types": "^4.1.0", - "@smithy/util-uri-escape": "^4.0.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/types": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz", - "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==", + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/credential-provider-process": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.758.0.tgz", + "integrity": "sha512-AzcY74QTPqcbXWVgjpPZ3HOmxQZYPROIBz2YINF0OQk0MhezDWV/O7Xec+K1+MPGQO3qS6EDrUUlnPLjsqieHA==", "dev": true, - "optional": true, + "license": "Apache-2.0", "dependencies": { + "@aws-sdk/core": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@smithy/property-provider": "^4.0.1", + "@smithy/shared-ini-file-loader": "^4.0.1", + "@smithy/types": "^4.1.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/util-uri-escape": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.0.0.tgz", - "integrity": "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg==", + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.758.0.tgz", + "integrity": "sha512-x0FYJqcOLUCv8GLLFDYMXRAQKGjoM+L0BG4BiHYZRDf24yQWFCAZsCQAYKo6XZYh2qznbsW6f//qpyJ5b0QVKQ==", "dev": true, - "optional": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/client-sso": "3.758.0", + "@aws-sdk/core": "3.758.0", + "@aws-sdk/token-providers": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@smithy/property-provider": "^4.0.1", + "@smithy/shared-ini-file-loader": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.758.0.tgz", + "integrity": "sha512-XGguXhBqiCXMXRxcfCAVPlMbm3VyJTou79r/3mxWddHWF0XbhaQiBIbUz6vobVTD25YQRbWSmSch7VA8kI5Lrw==", + "dev": true, + "license": "Apache-2.0", "dependencies": { + "@aws-sdk/core": "3.758.0", + "@aws-sdk/nested-clients": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@smithy/property-provider": "^4.0.1", + "@smithy/types": "^4.1.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-dynamodb": { - "version": "3.751.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.751.0.tgz", - "integrity": "sha512-U7hbXiuePbfmH7wstnCvOmUxwrWRV3/FMK2WuZU7wQZfBrIsPdmMh8XMGyXJ7VZ4dSq66Skqs0U2OBpB+9sO5w==", + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.758.0.tgz", + "integrity": "sha512-iNyehQXtQlj69JCgfaOssgZD4HeYGOwxcaKeG6F+40cwBjTAi0+Ph1yfDwqk2qiBPIRWJ/9l2LodZbxiBqgrwg==", "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@aws-sdk/util-endpoints": "3.743.0", + "@smithy/core": "^3.1.5", + "@smithy/protocol-http": "^5.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/nested-clients": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.758.0.tgz", + "integrity": "sha512-YZ5s7PSvyF3Mt2h1EQulCG93uybprNGbBkPmVuy/HMMfbFTt4iL3SbKjxqvOZelm86epFfj7pvK7FliI2WOEcg==", + "dev": true, + "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.750.0", - "@aws-sdk/credential-provider-node": "3.750.0", - "@aws-sdk/middleware-endpoint-discovery": "3.734.0", + "@aws-sdk/core": "3.758.0", "@aws-sdk/middleware-host-header": "3.734.0", "@aws-sdk/middleware-logger": "3.734.0", "@aws-sdk/middleware-recursion-detection": "3.734.0", - "@aws-sdk/middleware-user-agent": "3.750.0", + "@aws-sdk/middleware-user-agent": "3.758.0", "@aws-sdk/region-config-resolver": "3.734.0", "@aws-sdk/types": "3.734.0", "@aws-sdk/util-endpoints": "3.743.0", "@aws-sdk/util-user-agent-browser": "3.734.0", - "@aws-sdk/util-user-agent-node": "3.750.0", + "@aws-sdk/util-user-agent-node": "3.758.0", "@smithy/config-resolver": "^4.0.1", - "@smithy/core": "^3.1.4", + "@smithy/core": "^3.1.5", "@smithy/fetch-http-handler": "^5.0.1", "@smithy/hash-node": "^4.0.1", "@smithy/invalid-dependency": "^4.0.1", "@smithy/middleware-content-length": "^4.0.1", - "@smithy/middleware-endpoint": "^4.0.5", - "@smithy/middleware-retry": "^4.0.6", + "@smithy/middleware-endpoint": "^4.0.6", + "@smithy/middleware-retry": "^4.0.7", "@smithy/middleware-serde": "^4.0.2", "@smithy/middleware-stack": "^4.0.1", "@smithy/node-config-provider": "^4.0.1", - "@smithy/node-http-handler": "^4.0.2", + "@smithy/node-http-handler": "^4.0.3", "@smithy/protocol-http": "^5.0.1", - "@smithy/smithy-client": "^4.1.5", + "@smithy/smithy-client": "^4.1.6", "@smithy/types": "^4.1.0", "@smithy/url-parser": "^4.0.1", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.6", - "@smithy/util-defaults-mode-node": "^4.0.6", + "@smithy/util-defaults-mode-browser": "^4.0.7", + "@smithy/util-defaults-mode-node": "^4.0.7", "@smithy/util-endpoints": "^3.0.1", "@smithy/util-middleware": "^4.0.1", "@smithy/util-retry": "^4.0.1", "@smithy/util-utf8": "^4.0.0", - "@smithy/util-waiter": "^4.0.2", - "@types/uuid": "^9.0.1", - "tslib": "^2.6.2", - "uuid": "^9.0.1" + "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-dynamodb/node_modules/@smithy/abort-controller": { + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/token-providers": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.758.0.tgz", + "integrity": "sha512-ckptN1tNrIfQUaGWm/ayW1ddG+imbKN7HHhjFdS4VfItsP0QQOB0+Ov+tpgb4MoNR4JaUghMIVStjIeHN2ks1w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/nested-clients": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@smithy/property-provider": "^4.0.1", + "@smithy/shared-ini-file-loader": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.758.0.tgz", + "integrity": "sha512-A5EZw85V6WhoKMV2hbuFRvb9NPlxEErb4HPO6/SPXYY4QrjprIzScHxikqcWv1w4J3apB1wto9LPU3IMsYtfrw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/middleware-user-agent": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@smithy/node-config-provider": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/abort-controller": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.1.tgz", "integrity": "sha512-fiUIYgIgRjMWznk6iLJz35K2YxSLHzLBA/RC6lBrKfQ8fHbPfvk7Pk9UvpKoHgJjI18MnbPuEju53zcVy6KF1g==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@smithy/types": "^4.1.0", "tslib": "^2.6.2" @@ -914,11 +1112,12 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-dynamodb/node_modules/@smithy/node-http-handler": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.0.2.tgz", - "integrity": "sha512-X66H9aah9hisLLSnGuzRYba6vckuFtGE+a5DcHLliI/YlqKrGoxhisD5XbX44KyoeRzoNlGr94eTsMVHFAzPOw==", + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/node-http-handler": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.0.3.tgz", + "integrity": "sha512-dYCLeINNbYdvmMLtW0VdhW1biXt+PPCGazzT5ZjKw46mOtdgToQEwjqZSS9/EN8+tNs/RO0cEWG044+YZs97aA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@smithy/abort-controller": "^4.0.1", "@smithy/protocol-http": "^5.0.1", @@ -930,11 +1129,12 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-dynamodb/node_modules/@smithy/protocol-http": { + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/protocol-http": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.0.1.tgz", "integrity": "sha512-TE4cpj49jJNB/oHyh/cRVEgNZaoPaxd4vteJNB0yGidOCVR0jCw/hjPVsT8Q8FRmj8Bd3bFZt8Dh7xGCT+xMBQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@smithy/types": "^4.1.0", "tslib": "^2.6.2" @@ -943,11 +1143,12 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-dynamodb/node_modules/@smithy/querystring-builder": { + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/querystring-builder": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.0.1.tgz", "integrity": "sha512-wU87iWZoCbcqrwszsOewEIuq+SU2mSoBE2CcsLwE0I19m0B2gOJr1MVjxWcDQYOzHbR1xCk7AcOBbGFUYOKvdg==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@smithy/types": "^4.1.0", "@smithy/util-uri-escape": "^4.0.0", @@ -957,11 +1158,12 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-dynamodb/node_modules/@smithy/types": { + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/types": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz", "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" }, @@ -969,11 +1171,12 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-dynamodb/node_modules/@smithy/util-uri-escape": { + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/util-uri-escape": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.0.0.tgz", "integrity": "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg==", "dev": true, + "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" }, @@ -981,7 +1184,7 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-dynamodb/node_modules/uuid": { + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/uuid": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", @@ -990,15 +1193,17 @@ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" ], + "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } }, - "node_modules/@aws-sdk/client-kinesis": { + "node_modules/@aws-sdk/client-cognito-identity": { "version": "3.750.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-kinesis/-/client-kinesis-3.750.0.tgz", - "integrity": "sha512-b+Io2aWR12q+l0j1XtSks7pSmLTErt+ExyMamtFQF7vwM6KtSzh3NQHdiRpSQbDwAcLsns7yJgH3HUfyKKfuLg==", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.750.0.tgz", + "integrity": "sha512-ia5+l7U1ludU/YqQAnEMj5DIp1kfMTu14lUOMG3uTIwTcj8OjkCvAe6BuM0OY6zd8enrJYWLqIqxuKPOWw4I7Q==", "dev": true, + "optional": true, "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", @@ -1015,9 +1220,6 @@ "@aws-sdk/util-user-agent-node": "3.750.0", "@smithy/config-resolver": "^4.0.1", "@smithy/core": "^3.1.4", - "@smithy/eventstream-serde-browser": "^4.0.1", - "@smithy/eventstream-serde-config-resolver": "^4.0.1", - "@smithy/eventstream-serde-node": "^4.0.1", "@smithy/fetch-http-handler": "^5.0.1", "@smithy/hash-node": "^4.0.1", "@smithy/invalid-dependency": "^4.0.1", @@ -1041,18 +1243,18 @@ "@smithy/util-middleware": "^4.0.1", "@smithy/util-retry": "^4.0.1", "@smithy/util-utf8": "^4.0.0", - "@smithy/util-waiter": "^4.0.2", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-kinesis/node_modules/@smithy/abort-controller": { + "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/abort-controller": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.1.tgz", "integrity": "sha512-fiUIYgIgRjMWznk6iLJz35K2YxSLHzLBA/RC6lBrKfQ8fHbPfvk7Pk9UvpKoHgJjI18MnbPuEju53zcVy6KF1g==", "dev": true, + "optional": true, "dependencies": { "@smithy/types": "^4.1.0", "tslib": "^2.6.2" @@ -1061,11 +1263,12 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-kinesis/node_modules/@smithy/node-http-handler": { + "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/node-http-handler": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.0.2.tgz", "integrity": "sha512-X66H9aah9hisLLSnGuzRYba6vckuFtGE+a5DcHLliI/YlqKrGoxhisD5XbX44KyoeRzoNlGr94eTsMVHFAzPOw==", "dev": true, + "optional": true, "dependencies": { "@smithy/abort-controller": "^4.0.1", "@smithy/protocol-http": "^5.0.1", @@ -1077,11 +1280,12 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-kinesis/node_modules/@smithy/protocol-http": { + "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/protocol-http": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.0.1.tgz", "integrity": "sha512-TE4cpj49jJNB/oHyh/cRVEgNZaoPaxd4vteJNB0yGidOCVR0jCw/hjPVsT8Q8FRmj8Bd3bFZt8Dh7xGCT+xMBQ==", "dev": true, + "optional": true, "dependencies": { "@smithy/types": "^4.1.0", "tslib": "^2.6.2" @@ -1090,11 +1294,12 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-kinesis/node_modules/@smithy/querystring-builder": { + "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/querystring-builder": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.0.1.tgz", "integrity": "sha512-wU87iWZoCbcqrwszsOewEIuq+SU2mSoBE2CcsLwE0I19m0B2gOJr1MVjxWcDQYOzHbR1xCk7AcOBbGFUYOKvdg==", "dev": true, + "optional": true, "dependencies": { "@smithy/types": "^4.1.0", "@smithy/util-uri-escape": "^4.0.0", @@ -1104,11 +1309,12 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-kinesis/node_modules/@smithy/types": { + "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/types": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz", "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==", "dev": true, + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -1116,11 +1322,12 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-kinesis/node_modules/@smithy/util-uri-escape": { + "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/util-uri-escape": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.0.0.tgz", "integrity": "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg==", "dev": true, + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -1128,16 +1335,17 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-lambda": { - "version": "3.750.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-lambda/-/client-lambda-3.750.0.tgz", - "integrity": "sha512-lSfKdMBXaSQOh48hleRJEKuVO1wQBOgPIonRkCPU5bpagZckWyeD8p8XSgdF6p22lZZUPuasS6+PEJ6knSYNDQ==", + "node_modules/@aws-sdk/client-dynamodb": { + "version": "3.751.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.751.0.tgz", + "integrity": "sha512-U7hbXiuePbfmH7wstnCvOmUxwrWRV3/FMK2WuZU7wQZfBrIsPdmMh8XMGyXJ7VZ4dSq66Skqs0U2OBpB+9sO5w==", "dev": true, "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.750.0", "@aws-sdk/credential-provider-node": "3.750.0", + "@aws-sdk/middleware-endpoint-discovery": "3.734.0", "@aws-sdk/middleware-host-header": "3.734.0", "@aws-sdk/middleware-logger": "3.734.0", "@aws-sdk/middleware-recursion-detection": "3.734.0", @@ -1149,9 +1357,289 @@ "@aws-sdk/util-user-agent-node": "3.750.0", "@smithy/config-resolver": "^4.0.1", "@smithy/core": "^3.1.4", - "@smithy/eventstream-serde-browser": "^4.0.1", - "@smithy/eventstream-serde-config-resolver": "^4.0.1", - "@smithy/eventstream-serde-node": "^4.0.1", + "@smithy/fetch-http-handler": "^5.0.1", + "@smithy/hash-node": "^4.0.1", + "@smithy/invalid-dependency": "^4.0.1", + "@smithy/middleware-content-length": "^4.0.1", + "@smithy/middleware-endpoint": "^4.0.5", + "@smithy/middleware-retry": "^4.0.6", + "@smithy/middleware-serde": "^4.0.2", + "@smithy/middleware-stack": "^4.0.1", + "@smithy/node-config-provider": "^4.0.1", + "@smithy/node-http-handler": "^4.0.2", + "@smithy/protocol-http": "^5.0.1", + "@smithy/smithy-client": "^4.1.5", + "@smithy/types": "^4.1.0", + "@smithy/url-parser": "^4.0.1", + "@smithy/util-base64": "^4.0.0", + "@smithy/util-body-length-browser": "^4.0.0", + "@smithy/util-body-length-node": "^4.0.0", + "@smithy/util-defaults-mode-browser": "^4.0.6", + "@smithy/util-defaults-mode-node": "^4.0.6", + "@smithy/util-endpoints": "^3.0.1", + "@smithy/util-middleware": "^4.0.1", + "@smithy/util-retry": "^4.0.1", + "@smithy/util-utf8": "^4.0.0", + "@smithy/util-waiter": "^4.0.2", + "@types/uuid": "^9.0.1", + "tslib": "^2.6.2", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-dynamodb/node_modules/@smithy/abort-controller": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.1.tgz", + "integrity": "sha512-fiUIYgIgRjMWznk6iLJz35K2YxSLHzLBA/RC6lBrKfQ8fHbPfvk7Pk9UvpKoHgJjI18MnbPuEju53zcVy6KF1g==", + "dev": true, + "dependencies": { + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-dynamodb/node_modules/@smithy/node-http-handler": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.0.2.tgz", + "integrity": "sha512-X66H9aah9hisLLSnGuzRYba6vckuFtGE+a5DcHLliI/YlqKrGoxhisD5XbX44KyoeRzoNlGr94eTsMVHFAzPOw==", + "dev": true, + "dependencies": { + "@smithy/abort-controller": "^4.0.1", + "@smithy/protocol-http": "^5.0.1", + "@smithy/querystring-builder": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-dynamodb/node_modules/@smithy/protocol-http": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.0.1.tgz", + "integrity": "sha512-TE4cpj49jJNB/oHyh/cRVEgNZaoPaxd4vteJNB0yGidOCVR0jCw/hjPVsT8Q8FRmj8Bd3bFZt8Dh7xGCT+xMBQ==", + "dev": true, + "dependencies": { + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-dynamodb/node_modules/@smithy/querystring-builder": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.0.1.tgz", + "integrity": "sha512-wU87iWZoCbcqrwszsOewEIuq+SU2mSoBE2CcsLwE0I19m0B2gOJr1MVjxWcDQYOzHbR1xCk7AcOBbGFUYOKvdg==", + "dev": true, + "dependencies": { + "@smithy/types": "^4.1.0", + "@smithy/util-uri-escape": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-dynamodb/node_modules/@smithy/types": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz", + "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==", + "dev": true, + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-dynamodb/node_modules/@smithy/util-uri-escape": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.0.0.tgz", + "integrity": "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg==", + "dev": true, + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-dynamodb/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@aws-sdk/client-kinesis": { + "version": "3.750.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-kinesis/-/client-kinesis-3.750.0.tgz", + "integrity": "sha512-b+Io2aWR12q+l0j1XtSks7pSmLTErt+ExyMamtFQF7vwM6KtSzh3NQHdiRpSQbDwAcLsns7yJgH3HUfyKKfuLg==", + "dev": true, + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.750.0", + "@aws-sdk/credential-provider-node": "3.750.0", + "@aws-sdk/middleware-host-header": "3.734.0", + "@aws-sdk/middleware-logger": "3.734.0", + "@aws-sdk/middleware-recursion-detection": "3.734.0", + "@aws-sdk/middleware-user-agent": "3.750.0", + "@aws-sdk/region-config-resolver": "3.734.0", + "@aws-sdk/types": "3.734.0", + "@aws-sdk/util-endpoints": "3.743.0", + "@aws-sdk/util-user-agent-browser": "3.734.0", + "@aws-sdk/util-user-agent-node": "3.750.0", + "@smithy/config-resolver": "^4.0.1", + "@smithy/core": "^3.1.4", + "@smithy/eventstream-serde-browser": "^4.0.1", + "@smithy/eventstream-serde-config-resolver": "^4.0.1", + "@smithy/eventstream-serde-node": "^4.0.1", + "@smithy/fetch-http-handler": "^5.0.1", + "@smithy/hash-node": "^4.0.1", + "@smithy/invalid-dependency": "^4.0.1", + "@smithy/middleware-content-length": "^4.0.1", + "@smithy/middleware-endpoint": "^4.0.5", + "@smithy/middleware-retry": "^4.0.6", + "@smithy/middleware-serde": "^4.0.2", + "@smithy/middleware-stack": "^4.0.1", + "@smithy/node-config-provider": "^4.0.1", + "@smithy/node-http-handler": "^4.0.2", + "@smithy/protocol-http": "^5.0.1", + "@smithy/smithy-client": "^4.1.5", + "@smithy/types": "^4.1.0", + "@smithy/url-parser": "^4.0.1", + "@smithy/util-base64": "^4.0.0", + "@smithy/util-body-length-browser": "^4.0.0", + "@smithy/util-body-length-node": "^4.0.0", + "@smithy/util-defaults-mode-browser": "^4.0.6", + "@smithy/util-defaults-mode-node": "^4.0.6", + "@smithy/util-endpoints": "^3.0.1", + "@smithy/util-middleware": "^4.0.1", + "@smithy/util-retry": "^4.0.1", + "@smithy/util-utf8": "^4.0.0", + "@smithy/util-waiter": "^4.0.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-kinesis/node_modules/@smithy/abort-controller": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.1.tgz", + "integrity": "sha512-fiUIYgIgRjMWznk6iLJz35K2YxSLHzLBA/RC6lBrKfQ8fHbPfvk7Pk9UvpKoHgJjI18MnbPuEju53zcVy6KF1g==", + "dev": true, + "dependencies": { + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-kinesis/node_modules/@smithy/node-http-handler": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.0.2.tgz", + "integrity": "sha512-X66H9aah9hisLLSnGuzRYba6vckuFtGE+a5DcHLliI/YlqKrGoxhisD5XbX44KyoeRzoNlGr94eTsMVHFAzPOw==", + "dev": true, + "dependencies": { + "@smithy/abort-controller": "^4.0.1", + "@smithy/protocol-http": "^5.0.1", + "@smithy/querystring-builder": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-kinesis/node_modules/@smithy/protocol-http": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.0.1.tgz", + "integrity": "sha512-TE4cpj49jJNB/oHyh/cRVEgNZaoPaxd4vteJNB0yGidOCVR0jCw/hjPVsT8Q8FRmj8Bd3bFZt8Dh7xGCT+xMBQ==", + "dev": true, + "dependencies": { + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-kinesis/node_modules/@smithy/querystring-builder": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.0.1.tgz", + "integrity": "sha512-wU87iWZoCbcqrwszsOewEIuq+SU2mSoBE2CcsLwE0I19m0B2gOJr1MVjxWcDQYOzHbR1xCk7AcOBbGFUYOKvdg==", + "dev": true, + "dependencies": { + "@smithy/types": "^4.1.0", + "@smithy/util-uri-escape": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-kinesis/node_modules/@smithy/types": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz", + "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==", + "dev": true, + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-kinesis/node_modules/@smithy/util-uri-escape": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.0.0.tgz", + "integrity": "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg==", + "dev": true, + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-lambda": { + "version": "3.750.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-lambda/-/client-lambda-3.750.0.tgz", + "integrity": "sha512-lSfKdMBXaSQOh48hleRJEKuVO1wQBOgPIonRkCPU5bpagZckWyeD8p8XSgdF6p22lZZUPuasS6+PEJ6knSYNDQ==", + "dev": true, + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.750.0", + "@aws-sdk/credential-provider-node": "3.750.0", + "@aws-sdk/middleware-host-header": "3.734.0", + "@aws-sdk/middleware-logger": "3.734.0", + "@aws-sdk/middleware-recursion-detection": "3.734.0", + "@aws-sdk/middleware-user-agent": "3.750.0", + "@aws-sdk/region-config-resolver": "3.734.0", + "@aws-sdk/types": "3.734.0", + "@aws-sdk/util-endpoints": "3.743.0", + "@aws-sdk/util-user-agent-browser": "3.734.0", + "@aws-sdk/util-user-agent-node": "3.750.0", + "@smithy/config-resolver": "^4.0.1", + "@smithy/core": "^3.1.4", + "@smithy/eventstream-serde-browser": "^4.0.1", + "@smithy/eventstream-serde-config-resolver": "^4.0.1", + "@smithy/eventstream-serde-node": "^4.0.1", "@smithy/fetch-http-handler": "^5.0.1", "@smithy/hash-node": "^4.0.1", "@smithy/invalid-dependency": "^4.0.1", @@ -1848,28 +2336,6 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/core/node_modules/fast-xml-parser": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", - "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - }, - { - "type": "paypal", - "url": "https://paypal.me/naturalintelligence" - } - ], - "dependencies": { - "strnum": "^1.0.5" - }, - "bin": { - "fxparser": "src/cli/cli.js" - } - }, "node_modules/@aws-sdk/credential-provider-cognito-identity": { "version": "3.750.0", "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.750.0.tgz", @@ -7331,317 +7797,6 @@ "sparse-bitfield": "^3.0.3" } }, - "node_modules/@nestjs/common": { - "version": "9.4.3", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-9.4.3.tgz", - "integrity": "sha512-Gd6D4IaYj01o14Bwv81ukidn4w3bPHCblMUq+SmUmWLyosK+XQmInCS09SbDDZyL8jy86PngtBLTdhJ2bXSUig==", - "dev": true, - "dependencies": { - "iterare": "1.2.1", - "tslib": "2.5.3", - "uid": "2.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nest" - }, - "peerDependencies": { - "cache-manager": "<=5", - "class-transformer": "*", - "class-validator": "*", - "reflect-metadata": "^0.1.12", - "rxjs": "^7.1.0" - }, - "peerDependenciesMeta": { - "cache-manager": { - "optional": true - }, - "class-transformer": { - "optional": true - }, - "class-validator": { - "optional": true - } - } - }, - "node_modules/@nestjs/common/node_modules/tslib": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz", - "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==", - "dev": true - }, - "node_modules/@nestjs/core": { - "version": "9.4.3", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-9.4.3.tgz", - "integrity": "sha512-Qi63+wi55Jh4sDyaj5Hhx2jOpKqT386aeo+VOKsxnd+Ql9VvkO/FjmuwBGUyzkJt29ENYc+P0Sx/k5LtstNpPQ==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@nuxtjs/opencollective": "0.3.2", - "fast-safe-stringify": "2.1.1", - "iterare": "1.2.1", - "path-to-regexp": "3.2.0", - "tslib": "2.5.3", - "uid": "2.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nest" - }, - "peerDependencies": { - "@nestjs/common": "^9.0.0", - "@nestjs/microservices": "^9.0.0", - "@nestjs/platform-express": "^9.0.0", - "@nestjs/websockets": "^9.0.0", - "reflect-metadata": "^0.1.12", - "rxjs": "^7.1.0" - }, - "peerDependenciesMeta": { - "@nestjs/microservices": { - "optional": true - }, - "@nestjs/platform-express": { - "optional": true - }, - "@nestjs/websockets": { - "optional": true - } - } - }, - "node_modules/@nestjs/core/node_modules/path-to-regexp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.2.0.tgz", - "integrity": "sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA==", - "dev": true - }, - "node_modules/@nestjs/core/node_modules/tslib": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz", - "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==", - "dev": true - }, - "node_modules/@nestjs/platform-express": { - "version": "9.4.3", - "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-9.4.3.tgz", - "integrity": "sha512-FpdczWoRSC0zz2dNL9u2AQLXKXRVtq4HgHklAhbL59X0uy+mcxhlSThG7DHzDMkoSnuuHY8ojDVf7mDxk+GtCw==", - "dev": true, - "dependencies": { - "body-parser": "1.20.2", - "cors": "2.8.5", - "express": "4.18.2", - "multer": "1.4.4-lts.1", - "tslib": "2.5.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nest" - }, - "peerDependencies": { - "@nestjs/common": "^9.0.0", - "@nestjs/core": "^9.0.0" - } - }, - "node_modules/@nestjs/platform-express/node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@nestjs/platform-express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/@nestjs/platform-express/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/@nestjs/platform-express/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@nestjs/platform-express/node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", - "dev": true, - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.1", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.11.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/@nestjs/platform-express/node_modules/express/node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/@nestjs/platform-express/node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@nestjs/platform-express/node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "dev": true - }, - "node_modules/@nestjs/platform-express/node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@nestjs/platform-express/node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", - "dev": true - }, - "node_modules/@nestjs/platform-express/node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@nestjs/platform-express/node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/@nestjs/platform-express/node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "dev": true, - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/@nestjs/platform-express/node_modules/tslib": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz", - "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==", - "dev": true - }, "node_modules/@netflix/nerror": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@netflix/nerror/-/nerror-1.1.3.tgz", @@ -8408,22 +8563,31 @@ "tao": "index.js" } }, - "node_modules/@nuxtjs/opencollective": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz", - "integrity": "sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==", + "node_modules/@nuxt/opencollective": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@nuxt/opencollective/-/opencollective-0.4.1.tgz", + "integrity": "sha512-GXD3wy50qYbxCJ652bDrDzgMr3NFEkIS374+IgFQKkCvk9yiYcLvX2XDYr7UyQxf4wK0e+yqDYRubZ0DtOxnmQ==", "dev": true, + "license": "MIT", "dependencies": { - "chalk": "^4.1.0", - "consola": "^2.15.0", - "node-fetch": "^2.6.1" + "consola": "^3.2.3" }, "bin": { "opencollective": "bin/opencollective.js" }, "engines": { - "node": ">=8.0.0", - "npm": ">=5.0.0" + "node": "^14.18.0 || >=16.10.0", + "npm": ">=5.10.0" + } + }, + "node_modules/@nuxt/opencollective/node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" } }, "node_modules/@octokit/auth-token": { @@ -8649,6 +8813,10 @@ "resolved": "metapackages/auto-instrumentations-web", "link": true }, + "node_modules/@opentelemetry/baggage-log-record-processor": { + "resolved": "packages/baggage-log-record-processor", + "link": true + }, "node_modules/@opentelemetry/baggage-span-processor": { "resolved": "packages/baggage-span-processor", "link": true @@ -9446,6 +9614,7 @@ "version": "1.30.0", "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.30.0.tgz", "integrity": "sha512-4VlGgo32k2EQ2wcCY3vEU28A0O13aOtHz3Xt2/2U5FAh9EfhD6t6DqL5Z6yAnRCntbTFDU4YfbpyzSlHNWycPw==", + "license": "Apache-2.0", "engines": { "node": ">=14" } @@ -10336,17 +10505,18 @@ } }, "node_modules/@smithy/core": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.1.4.tgz", - "integrity": "sha512-wFExFGK+7r2wYriOqe7RRIBNpvxwiS95ih09+GSLRBdoyK/O1uZA7K7pKesj5CBvwJuSBeXwLyR88WwIAY+DGA==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.1.5.tgz", + "integrity": "sha512-HLclGWPkCsekQgsyzxLhCQLa8THWXtB5PxyYN+2O6nkyLt550KQKTlbV2D1/j5dNIQapAZM1+qFnpBFxZQkgCA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@smithy/middleware-serde": "^4.0.2", "@smithy/protocol-http": "^5.0.1", "@smithy/types": "^4.1.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-middleware": "^4.0.1", - "@smithy/util-stream": "^4.1.1", + "@smithy/util-stream": "^4.1.2", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, @@ -10787,12 +10957,13 @@ } }, "node_modules/@smithy/middleware-endpoint": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.0.5.tgz", - "integrity": "sha512-cPzGZV7qStHwboFrm6GfrzQE+YDiCzWcTh4+7wKrP/ZQ4gkw+r7qDjV8GjM4N0UYsuUyLfpzLGg5hxsYTU11WA==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.0.6.tgz", + "integrity": "sha512-ftpmkTHIFqgaFugcjzLZv3kzPEFsBFSnq1JsIkr2mwFzCraZVhQk2gqN51OOeRxqhbPTkRFj39Qd2V91E/mQxg==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.1.4", + "@smithy/core": "^3.1.5", "@smithy/middleware-serde": "^4.0.2", "@smithy/node-config-provider": "^4.0.1", "@smithy/shared-ini-file-loader": "^4.0.1", @@ -10818,15 +10989,16 @@ } }, "node_modules/@smithy/middleware-retry": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.0.6.tgz", - "integrity": "sha512-s8QzuOQnbdvRymD9Gt9c9zMq10wUQAHQ3z72uirrBHCwZcLTrL5iCOuVTMdka2IXOYhQE890WD5t6G24+F+Qcg==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.0.7.tgz", + "integrity": "sha512-58j9XbUPLkqAcV1kHzVX/kAR16GT+j7DUZJqwzsxh1jtz7G82caZiGyyFgUvogVfNTg3TeAOIJepGc8TXF4AVQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@smithy/node-config-provider": "^4.0.1", "@smithy/protocol-http": "^5.0.1", "@smithy/service-error-classification": "^4.0.1", - "@smithy/smithy-client": "^4.1.5", + "@smithy/smithy-client": "^4.1.6", "@smithy/types": "^4.1.0", "@smithy/util-middleware": "^4.0.1", "@smithy/util-retry": "^4.0.1", @@ -11151,17 +11323,18 @@ } }, "node_modules/@smithy/smithy-client": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.1.5.tgz", - "integrity": "sha512-DMXYoYeL4QkElr216n1yodTFeATbfb4jwYM9gKn71Rw/FNA1/Sm36tkTSCsZEs7mgpG3OINmkxL9vgVFzyGPaw==", + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.1.6.tgz", + "integrity": "sha512-UYDolNg6h2O0L+cJjtgSyKKvEKCOa/8FHYJnBobyeoeWDmNpXjwOAtw16ezyeu1ETuuLEOZbrynK0ZY1Lx9Jbw==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.1.4", - "@smithy/middleware-endpoint": "^4.0.5", + "@smithy/core": "^3.1.5", + "@smithy/middleware-endpoint": "^4.0.6", "@smithy/middleware-stack": "^4.0.1", "@smithy/protocol-http": "^5.0.1", "@smithy/types": "^4.1.0", - "@smithy/util-stream": "^4.1.1", + "@smithy/util-stream": "^4.1.2", "tslib": "^2.6.2" }, "engines": { @@ -11295,13 +11468,14 @@ } }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.6.tgz", - "integrity": "sha512-N8+VCt+piupH1A7DgSVDNrVHqRLz8r6DvBkpS7EWHiIxsUk4jqGuQLjqC/gnCzmwGkVBdNruHoYAzzaSQ8e80w==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.7.tgz", + "integrity": "sha512-CZgDDrYHLv0RUElOsmZtAnp1pIjwDVCSuZWOPhIOBvG36RDfX1Q9+6lS61xBf+qqvHoqRjHxgINeQz47cYFC2Q==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@smithy/property-provider": "^4.0.1", - "@smithy/smithy-client": "^4.1.5", + "@smithy/smithy-client": "^4.1.6", "@smithy/types": "^4.1.0", "bowser": "^2.11.0", "tslib": "^2.6.2" @@ -11323,16 +11497,17 @@ } }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.6.tgz", - "integrity": "sha512-9zhx1shd1VwSSVvLZB8CM3qQ3RPD3le7A3h/UPuyh/PC7g4OaWDi2xUNzamsVoSmCGtmUBONl56lM2EU6LcH7A==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.7.tgz", + "integrity": "sha512-79fQW3hnfCdrfIi1soPbK3zmooRFnLpSx3Vxi6nUlqaaQeC5dm8plt4OTNDNqEEEDkvKghZSaoti684dQFVrGQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@smithy/config-resolver": "^4.0.1", "@smithy/credential-provider-imds": "^4.0.1", "@smithy/node-config-provider": "^4.0.1", "@smithy/property-provider": "^4.0.1", - "@smithy/smithy-client": "^4.1.5", + "@smithy/smithy-client": "^4.1.6", "@smithy/types": "^4.1.0", "tslib": "^2.6.2" }, @@ -11442,13 +11617,14 @@ } }, "node_modules/@smithy/util-stream": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.1.1.tgz", - "integrity": "sha512-+Xvh8nhy0Wjv1y71rBVyV3eJU3356XsFQNI8dEZVNrQju7Eib8G31GWtO+zMa9kTCGd41Mflu+ZKfmQL/o2XzQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.1.2.tgz", + "integrity": "sha512-44PKEqQ303d3rlQuiDpcCcu//hV8sn+u2JBo84dWCE0rvgeiVl0IlLMagbU++o0jCWhYCsHaAt9wZuZqNe05Hw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@smithy/fetch-http-handler": "^5.0.1", - "@smithy/node-http-handler": "^4.0.2", + "@smithy/node-http-handler": "^4.0.3", "@smithy/types": "^4.1.0", "@smithy/util-base64": "^4.0.0", "@smithy/util-buffer-from": "^4.0.0", @@ -11465,6 +11641,7 @@ "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.1.tgz", "integrity": "sha512-fiUIYgIgRjMWznk6iLJz35K2YxSLHzLBA/RC6lBrKfQ8fHbPfvk7Pk9UvpKoHgJjI18MnbPuEju53zcVy6KF1g==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@smithy/types": "^4.1.0", "tslib": "^2.6.2" @@ -11474,10 +11651,11 @@ } }, "node_modules/@smithy/util-stream/node_modules/@smithy/node-http-handler": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.0.2.tgz", - "integrity": "sha512-X66H9aah9hisLLSnGuzRYba6vckuFtGE+a5DcHLliI/YlqKrGoxhisD5XbX44KyoeRzoNlGr94eTsMVHFAzPOw==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.0.3.tgz", + "integrity": "sha512-dYCLeINNbYdvmMLtW0VdhW1biXt+PPCGazzT5ZjKw46mOtdgToQEwjqZSS9/EN8+tNs/RO0cEWG044+YZs97aA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@smithy/abort-controller": "^4.0.1", "@smithy/protocol-http": "^5.0.1", @@ -11494,6 +11672,7 @@ "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.0.1.tgz", "integrity": "sha512-TE4cpj49jJNB/oHyh/cRVEgNZaoPaxd4vteJNB0yGidOCVR0jCw/hjPVsT8Q8FRmj8Bd3bFZt8Dh7xGCT+xMBQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@smithy/types": "^4.1.0", "tslib": "^2.6.2" @@ -11507,6 +11686,7 @@ "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.0.1.tgz", "integrity": "sha512-wU87iWZoCbcqrwszsOewEIuq+SU2mSoBE2CcsLwE0I19m0B2gOJr1MVjxWcDQYOzHbR1xCk7AcOBbGFUYOKvdg==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@smithy/types": "^4.1.0", "@smithy/util-uri-escape": "^4.0.0", @@ -11521,6 +11701,7 @@ "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz", "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" }, @@ -11533,6 +11714,7 @@ "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.0.0.tgz", "integrity": "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg==", "dev": true, + "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" }, @@ -13758,37 +13940,6 @@ "fastq": "^1.17.1" } }, - "node_modules/aws-sdk": { - "version": "2.1008.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1008.0.tgz", - "integrity": "sha512-wBEon+ARCuMcwEPpOFZqRT3elBLfLtPqv8jMql3Hsr7Ua5toPlgKMmjf368iTzBNaY7TOZsjLAT9nAhvtSZ++g==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "buffer": "4.9.2", - "events": "1.1.1", - "ieee754": "1.1.13", - "jmespath": "0.15.0", - "querystring": "0.2.0", - "sax": "1.2.1", - "url": "0.10.3", - "uuid": "3.3.2", - "xml2js": "0.4.19" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/aws-sdk/node_modules/uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, "node_modules/aws-ssl-profiles": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz", @@ -14371,17 +14522,6 @@ "ieee754": "^1.1.13" } }, - "node_modules/buffer": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", - "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", - "dev": true, - "dependencies": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, "node_modules/buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", @@ -15410,12 +15550,6 @@ "integrity": "sha512-bTTG28diWg7R7/+qE5NZumwPbCiJOT8uPdZYu674brDjBWQctbaQbYlDKhalS+4i5HxIx+G8dZsnBHKzWpp01A==", "dev": true }, - "node_modules/consola": { - "version": "2.15.3", - "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", - "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==", - "dev": true - }, "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", @@ -17718,15 +17852,6 @@ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", "dev": true }, - "node_modules/events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==", - "dev": true, - "engines": { - "node": ">=0.4.x" - } - }, "node_modules/ewma": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/ewma/-/ewma-2.0.1.tgz", @@ -18179,6 +18304,29 @@ "integrity": "sha512-ypuAmmMKInk5q7XcepxlnUWDLWv4GFtaJqAzWKqn62IpQ3pejtr5dTVbt3vwqVaMKmkNR55sTT+CqUKIaT21BA==", "dev": true }, + "node_modules/fast-xml-parser": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "license": "MIT", + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, "node_modules/fastest-levenshtein": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", @@ -20684,6 +20832,13 @@ "node": ">=0.10.0" } }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "dev": true, + "license": "MIT" + }, "node_modules/is-property": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", @@ -21357,15 +21512,6 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/jmespath": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", - "integrity": "sha512-+kHj8HXArPfpPEKGLZ+kB5ONRTCiGQXo8RQYL0hH8t6pWXUBBK5KkkQmTNOwKK4LEsd0yTsgtjJVm4UBSZea4w==", - "dev": true, - "engines": { - "node": ">= 0.6.0" - } - }, "node_modules/joi": { "version": "17.12.2", "resolved": "https://registry.npmjs.org/joi/-/joi-17.12.2.tgz", @@ -25273,81 +25419,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, - "node_modules/multer": { - "version": "1.4.4-lts.1", - "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4-lts.1.tgz", - "integrity": "sha512-WeSGziVj6+Z2/MwQo3GvqzgR+9Uc+qt8SwHKh3gvNPiISKfsMfG4SvCOFYlxxgkXt7yIV2i1yczehm0EOKIxIg==", - "dev": true, - "dependencies": { - "append-field": "^1.0.0", - "busboy": "^1.0.0", - "concat-stream": "^1.5.2", - "mkdirp": "^0.5.4", - "object-assign": "^4.1.1", - "type-is": "^1.6.4", - "xtend": "^4.0.0" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/multer/node_modules/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "engines": [ - "node >= 0.8" - ], - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/multer/node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/multer/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/multer/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/multer/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/multimatch": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-5.0.0.tgz", @@ -28785,16 +28856,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", - "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", - "dev": true, - "engines": { - "node": ">=0.4.x" - } - }, "node_modules/querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", @@ -30274,12 +30335,6 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "devOptional": true }, - "node_modules/sax": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", - "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==", - "dev": true - }, "node_modules/scheduler": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", @@ -33684,16 +33739,6 @@ "node": ">=6" } }, - "node_modules/url": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", - "integrity": "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==", - "dev": true, - "dependencies": { - "punycode": "1.3.2", - "querystring": "0.2.0" - } - }, "node_modules/url-parse": { "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", @@ -33704,12 +33749,6 @@ "requires-port": "^1.0.0" } }, - "node_modules/url/node_modules/punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==", - "dev": true - }, "node_modules/urlpattern-polyfill": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", @@ -34590,25 +34629,6 @@ } } }, - "node_modules/xml2js": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", - "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", - "dev": true, - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~9.0.1" - } - }, - "node_modules/xml2js/node_modules/xmlbuilder": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", - "integrity": "sha512-7YXTQc3P2l9+0rjaUbLwMKRhtmwg1M1eDf6nag7urC7pIPYLD9W/jmzQ4ptRSUbodw5S0jfoGTflLemQibSpeQ==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/xmlbuilder": { "version": "15.1.1", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", @@ -34843,6 +34863,38 @@ "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.15.0.tgz", "integrity": "sha512-9oxn0IIjbCZkJ67L+LkhYWRyAy7axphb3VgE2MBDlOqnmHMPWGYMxJxBYFueFq/JGY2GMwS0rU+UCLunEmy5UA==" }, + "packages/baggage-log-record-processor": { + "name": "@opentelemetry/baggage-log-record-processor", + "version": "0.1.0", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/sdk-logs": "^0.200.0" + }, + "devDependencies": { + "@opentelemetry/api": "^1.0.0", + "@types/mocha": "10.0.10", + "@types/node": "18.18.14", + "expect": "29.2.0", + "nyc": "15.1.0", + "rimraf": "5.0.10", + "typescript": "5.0.4" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "packages/baggage-log-record-processor/node_modules/@types/node": { + "version": "18.18.14", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.14.tgz", + "integrity": "sha512-iSOeNeXYNYNLLOMDSVPvIFojclvMZ/HDY2dU17kUlcsOsSQETbWIslJbYLZgA+ox8g2XQwSHKTkght1a5X26lQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, "packages/baggage-span-processor": { "name": "@opentelemetry/baggage-span-processor", "version": "0.4.0", @@ -35288,11 +35340,11 @@ }, "plugins/node/instrumentation-kafkajs": { "name": "@opentelemetry/instrumentation-kafkajs", - "version": "0.8.0", + "version": "0.9.0", "license": "Apache-2.0", "dependencies": { "@opentelemetry/instrumentation": "^0.200.0", - "@opentelemetry/semantic-conventions": "^1.27.0" + "@opentelemetry/semantic-conventions": "^1.30.0" }, "devDependencies": { "@opentelemetry/api": "^1.3.0", @@ -35305,6 +35357,7 @@ "nyc": "15.1.0", "rimraf": "5.0.10", "sinon": "15.2.0", + "test-all-versions": "6.1.0", "typescript": "5.0.4" }, "engines": { @@ -35736,7 +35789,7 @@ }, "plugins/node/opentelemetry-instrumentation-aws-sdk": { "name": "@opentelemetry/instrumentation-aws-sdk", - "version": "0.50.0", + "version": "0.51.0", "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "^2.0.0", @@ -35745,6 +35798,7 @@ "@opentelemetry/semantic-conventions": "^1.27.0" }, "devDependencies": { + "@aws-sdk/client-bedrock-runtime": "^3.587.0", "@aws-sdk/client-dynamodb": "^3.85.0", "@aws-sdk/client-kinesis": "^3.85.0", "@aws-sdk/client-lambda": "^3.85.0", @@ -35759,7 +35813,6 @@ "@types/mocha": "10.0.10", "@types/node": "18.18.14", "@types/sinon": "17.0.4", - "aws-sdk": "2.1008.0", "eslint": "8.7.0", "expect": "29.2.0", "nock": "13.3.3", @@ -36348,7 +36401,7 @@ "@types/bson": "4.0.5", "@types/mocha": "10.0.10", "@types/node": "18.18.14", - "mongodb": "6.8.0", + "mongodb": "6.15.0", "nyc": "15.1.0", "rimraf": "5.0.10", "test-all-versions": "6.1.0", @@ -36450,13 +36503,13 @@ } }, "plugins/node/opentelemetry-instrumentation-mongodb/node_modules/mongodb": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.8.0.tgz", - "integrity": "sha512-HGQ9NWDle5WvwMnrvUxsFYPd3JEbqD3RgABHBQRuoCEND0qzhsd0iH5ypHsf1eJ+sXmvmyKpP+FLOKY8Il7jMw==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.15.0.tgz", + "integrity": "sha512-ifBhQ0rRzHDzqp9jAQP6OwHSH7dbYIQjD3SbJs9YYk9AikKEettW/9s/tbSFDTpXcRbF+u1aLrhHxDFaYtZpFQ==", "dev": true, "dependencies": { - "@mongodb-js/saslprep": "^1.1.5", - "bson": "^6.7.0", + "@mongodb-js/saslprep": "^1.1.9", + "bson": "^6.10.3", "mongodb-connection-string-url": "^3.0.0" }, "engines": { @@ -36464,7 +36517,7 @@ }, "peerDependencies": { "@aws-sdk/credential-providers": "^3.188.0", - "@mongodb-js/zstd": "^1.1.0", + "@mongodb-js/zstd": "^1.1.0 || ^2.0.0", "gcp-metadata": "^5.2.0", "kerberos": "^2.0.1", "mongodb-client-encryption": ">=6.0.0 <7", @@ -36587,16 +36640,16 @@ }, "plugins/node/opentelemetry-instrumentation-nestjs-core": { "name": "@opentelemetry/instrumentation-nestjs-core", - "version": "0.45.0", + "version": "0.46.0", "license": "Apache-2.0", "dependencies": { "@opentelemetry/instrumentation": "^0.200.0", - "@opentelemetry/semantic-conventions": "^1.27.0" + "@opentelemetry/semantic-conventions": "^1.30.0" }, "devDependencies": { - "@nestjs/common": "9.4.3", - "@nestjs/core": "9.4.3", - "@nestjs/platform-express": "9.4.3", + "@nestjs/common": "11.0.10", + "@nestjs/core": "11.0.10", + "@nestjs/platform-express": "11.0.10", "@opentelemetry/api": "^1.3.0", "@opentelemetry/context-async-hooks": "^2.0.0", "@opentelemetry/sdk-trace-base": "^2.0.0", @@ -36606,7 +36659,7 @@ "@types/semver": "7.5.8", "cross-env": "7.0.3", "nyc": "15.1.0", - "reflect-metadata": "0.1.13", + "reflect-metadata": "0.2.2", "rimraf": "5.0.10", "rxjs": "7.8.2", "rxjs-compat": "6.6.7", @@ -36621,6 +36674,100 @@ "@opentelemetry/api": "^1.3.0" } }, + "plugins/node/opentelemetry-instrumentation-nestjs-core/node_modules/@nestjs/common": { + "version": "11.0.10", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-11.0.10.tgz", + "integrity": "sha512-pzGXp14KF2Q4CDZGQgPK4l8zEg7i6cNkb+10yc8ZA5K41cLe3ZbWW1YxtY2e/glHauOJwTLSVjH4tiRVtOTizg==", + "dev": true, + "license": "MIT", + "dependencies": { + "iterare": "1.2.1", + "tslib": "2.8.1", + "uid": "2.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "class-transformer": "*", + "class-validator": "*", + "reflect-metadata": "^0.1.12 || ^0.2.0", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } + } + }, + "plugins/node/opentelemetry-instrumentation-nestjs-core/node_modules/@nestjs/core": { + "version": "11.0.10", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-11.0.10.tgz", + "integrity": "sha512-f0qB8ztNWZeAD4E4fUdHConmNYCa/A78U7WJu5mX9OLYfOAs3ESYCDfsH9MRUvkA4Ft4Y1uMmyJo5L4fg4+beg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@nuxt/opencollective": "0.4.1", + "fast-safe-stringify": "2.1.1", + "iterare": "1.2.1", + "path-to-regexp": "8.2.0", + "tslib": "2.8.1", + "uid": "2.0.2" + }, + "engines": { + "node": ">= 20" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^11.0.0", + "@nestjs/microservices": "^11.0.0", + "@nestjs/platform-express": "^11.0.0", + "@nestjs/websockets": "^11.0.0", + "reflect-metadata": "^0.1.12 || ^0.2.0", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "@nestjs/microservices": { + "optional": true + }, + "@nestjs/platform-express": { + "optional": true + }, + "@nestjs/websockets": { + "optional": true + } + } + }, + "plugins/node/opentelemetry-instrumentation-nestjs-core/node_modules/@nestjs/platform-express": { + "version": "11.0.10", + "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-11.0.10.tgz", + "integrity": "sha512-UVSf0yaWFBC2Zn2FOWABXxCnyG8XNIXrNnvTFpbUFqaJu1YDdwJ7wQBBqxq9CtJT7ILqSmfhOU7HS0d/0EAxpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cors": "2.8.5", + "express": "5.0.1", + "multer": "1.4.5-lts.1", + "path-to-regexp": "8.2.0", + "tslib": "2.8.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^11.0.0", + "@nestjs/core": "^11.0.0" + } + }, "plugins/node/opentelemetry-instrumentation-nestjs-core/node_modules/@types/node": { "version": "18.18.14", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.14.tgz", @@ -36630,6 +36777,514 @@ "undici-types": "~5.26.4" } }, + "plugins/node/opentelemetry-instrumentation-nestjs-core/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-nestjs-core/node_modules/body-parser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.1.0.tgz", + "integrity": "sha512-/hPxh61E+ll0Ujp24Ilm64cykicul1ypfwjVttduAiEdtnJFvLePSrIPk+HMImtNv5270wOGCb1Tns2rybMkoQ==", + "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.5.2", + "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-nestjs-core/node_modules/body-parser/node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "plugins/node/opentelemetry-instrumentation-nestjs-core/node_modules/body-parser/node_modules/type-is": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.0.tgz", + "integrity": "sha512-gd0sGezQYCbWSbkZr75mln4YBidWUN60+devscpLF5mtRDUpiaTvKpBNrdaCvel1NdR2k6vclXybU5fBd2i+nw==", + "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-nestjs-core/node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "engines": [ + "node >= 0.8" + ], + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "plugins/node/opentelemetry-instrumentation-nestjs-core/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-nestjs-core/node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "plugins/node/opentelemetry-instrumentation-nestjs-core/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-nestjs-core/node_modules/express": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/express/-/express-5.0.1.tgz", + "integrity": "sha512-ORF7g6qGnD+YtUG9yx4DFoqCShNMmUKiXuT5oWMHiOvt/4WFbHC6yCwQMTSBMno7AqntNCAzzcnnjowRkTL9eQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.0.1", + "content-disposition": "^1.0.0", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "^1.2.1", + "debug": "4.3.6", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "^2.0.0", + "fresh": "2.0.0", + "http-errors": "2.0.0", + "merge-descriptors": "^2.0.0", + "methods": "~1.1.2", + "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.13.0", + "range-parser": "~1.2.1", + "router": "^2.0.0", + "safe-buffer": "5.2.1", + "send": "^1.1.0", + "serve-static": "^2.1.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "^2.0.0", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "plugins/node/opentelemetry-instrumentation-nestjs-core/node_modules/express/node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "plugins/node/opentelemetry-instrumentation-nestjs-core/node_modules/express/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true, + "license": "MIT" + }, + "plugins/node/opentelemetry-instrumentation-nestjs-core/node_modules/express/node_modules/type-is": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.0.tgz", + "integrity": "sha512-gd0sGezQYCbWSbkZr75mln4YBidWUN60+devscpLF5mtRDUpiaTvKpBNrdaCvel1NdR2k6vclXybU5fBd2i+nw==", + "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-nestjs-core/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-nestjs-core/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-nestjs-core/node_modules/iconv-lite": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.2.tgz", + "integrity": "sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "plugins/node/opentelemetry-instrumentation-nestjs-core/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-nestjs-core/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-nestjs-core/node_modules/mime-types": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.0.tgz", + "integrity": "sha512-XqoSHeCGjVClAmoGFG3lVFqQFRIrTVw2OH3axRqAcfaw+gHWIfnASS92AV+Rl/mk0MupgZTRHQOjxY6YVnzK5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "^1.53.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "plugins/node/opentelemetry-instrumentation-nestjs-core/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "plugins/node/opentelemetry-instrumentation-nestjs-core/node_modules/multer": { + "version": "1.4.5-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", + "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "plugins/node/opentelemetry-instrumentation-nestjs-core/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-nestjs-core/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-nestjs-core/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "plugins/node/opentelemetry-instrumentation-nestjs-core/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-nestjs-core/node_modules/raw-body/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-nestjs-core/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "plugins/node/opentelemetry-instrumentation-nestjs-core/node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "plugins/node/opentelemetry-instrumentation-nestjs-core/node_modules/reflect-metadata": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", + "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", + "dev": true, + "license": "Apache-2.0" + }, + "plugins/node/opentelemetry-instrumentation-nestjs-core/node_modules/router": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.1.0.tgz", + "integrity": "sha512-/m/NSLxeYEgWNtyC+WtNHCF7jbGxOibVWKnn+1Psff4dJGOfoXP+MuC/f2CwSmyiHdOIzYnYFp4W6GxWfekaLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "plugins/node/opentelemetry-instrumentation-nestjs-core/node_modules/send": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.1.0.tgz", + "integrity": "sha512-v67WcEouB5GxbTWL/4NeToqcZiAWEq90N888fczVArY8A79J0L4FD7vj5hm3eUMua5EpoQ59wa/oovY6TLvRUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "destroy": "^1.2.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^0.5.2", + "http-errors": "^2.0.0", + "mime-types": "^2.1.35", + "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-nestjs-core/node_modules/send/node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "plugins/node/opentelemetry-instrumentation-nestjs-core/node_modules/send/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "plugins/node/opentelemetry-instrumentation-nestjs-core/node_modules/send/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "plugins/node/opentelemetry-instrumentation-nestjs-core/node_modules/serve-static": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.1.0.tgz", + "integrity": "sha512-A3We5UfEjG8Z7VkDv6uItWw6HY2bBSBJT1KtVESn6EOoOr2jAxNhxWCLY3jDE2WcuHXByWju74ck3ZgLwL8xmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "plugins/node/opentelemetry-instrumentation-nestjs-core/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "plugins/node/opentelemetry-instrumentation-nestjs-core/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, "plugins/node/opentelemetry-instrumentation-net": { "name": "@opentelemetry/instrumentation-net", "version": "0.44.0", @@ -37775,6 +38430,398 @@ } } }, + "@aws-sdk/client-bedrock-runtime": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-bedrock-runtime/-/client-bedrock-runtime-3.758.0.tgz", + "integrity": "sha512-T7s+fULUxN3AcJP+lgoUKLawzVEtyCTi+5Ga+wrHnqEPwAsM/wg7VctsZfow1fCgARLT/lzmP2LTCi8ycRnQWg==", + "dev": true, + "requires": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.758.0", + "@aws-sdk/credential-provider-node": "3.758.0", + "@aws-sdk/middleware-host-header": "3.734.0", + "@aws-sdk/middleware-logger": "3.734.0", + "@aws-sdk/middleware-recursion-detection": "3.734.0", + "@aws-sdk/middleware-user-agent": "3.758.0", + "@aws-sdk/region-config-resolver": "3.734.0", + "@aws-sdk/types": "3.734.0", + "@aws-sdk/util-endpoints": "3.743.0", + "@aws-sdk/util-user-agent-browser": "3.734.0", + "@aws-sdk/util-user-agent-node": "3.758.0", + "@smithy/config-resolver": "^4.0.1", + "@smithy/core": "^3.1.5", + "@smithy/eventstream-serde-browser": "^4.0.1", + "@smithy/eventstream-serde-config-resolver": "^4.0.1", + "@smithy/eventstream-serde-node": "^4.0.1", + "@smithy/fetch-http-handler": "^5.0.1", + "@smithy/hash-node": "^4.0.1", + "@smithy/invalid-dependency": "^4.0.1", + "@smithy/middleware-content-length": "^4.0.1", + "@smithy/middleware-endpoint": "^4.0.6", + "@smithy/middleware-retry": "^4.0.7", + "@smithy/middleware-serde": "^4.0.2", + "@smithy/middleware-stack": "^4.0.1", + "@smithy/node-config-provider": "^4.0.1", + "@smithy/node-http-handler": "^4.0.3", + "@smithy/protocol-http": "^5.0.1", + "@smithy/smithy-client": "^4.1.6", + "@smithy/types": "^4.1.0", + "@smithy/url-parser": "^4.0.1", + "@smithy/util-base64": "^4.0.0", + "@smithy/util-body-length-browser": "^4.0.0", + "@smithy/util-body-length-node": "^4.0.0", + "@smithy/util-defaults-mode-browser": "^4.0.7", + "@smithy/util-defaults-mode-node": "^4.0.7", + "@smithy/util-endpoints": "^3.0.1", + "@smithy/util-middleware": "^4.0.1", + "@smithy/util-retry": "^4.0.1", + "@smithy/util-stream": "^4.1.2", + "@smithy/util-utf8": "^4.0.0", + "@types/uuid": "^9.0.1", + "tslib": "^2.6.2", + "uuid": "^9.0.1" + }, + "dependencies": { + "@aws-sdk/client-sso": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.758.0.tgz", + "integrity": "sha512-BoGO6IIWrLyLxQG6txJw6RT2urmbtlwfggapNCrNPyYjlXpzTSJhBYjndg7TpDATFd0SXL0zm8y/tXsUXNkdYQ==", + "dev": true, + "requires": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.758.0", + "@aws-sdk/middleware-host-header": "3.734.0", + "@aws-sdk/middleware-logger": "3.734.0", + "@aws-sdk/middleware-recursion-detection": "3.734.0", + "@aws-sdk/middleware-user-agent": "3.758.0", + "@aws-sdk/region-config-resolver": "3.734.0", + "@aws-sdk/types": "3.734.0", + "@aws-sdk/util-endpoints": "3.743.0", + "@aws-sdk/util-user-agent-browser": "3.734.0", + "@aws-sdk/util-user-agent-node": "3.758.0", + "@smithy/config-resolver": "^4.0.1", + "@smithy/core": "^3.1.5", + "@smithy/fetch-http-handler": "^5.0.1", + "@smithy/hash-node": "^4.0.1", + "@smithy/invalid-dependency": "^4.0.1", + "@smithy/middleware-content-length": "^4.0.1", + "@smithy/middleware-endpoint": "^4.0.6", + "@smithy/middleware-retry": "^4.0.7", + "@smithy/middleware-serde": "^4.0.2", + "@smithy/middleware-stack": "^4.0.1", + "@smithy/node-config-provider": "^4.0.1", + "@smithy/node-http-handler": "^4.0.3", + "@smithy/protocol-http": "^5.0.1", + "@smithy/smithy-client": "^4.1.6", + "@smithy/types": "^4.1.0", + "@smithy/url-parser": "^4.0.1", + "@smithy/util-base64": "^4.0.0", + "@smithy/util-body-length-browser": "^4.0.0", + "@smithy/util-body-length-node": "^4.0.0", + "@smithy/util-defaults-mode-browser": "^4.0.7", + "@smithy/util-defaults-mode-node": "^4.0.7", + "@smithy/util-endpoints": "^3.0.1", + "@smithy/util-middleware": "^4.0.1", + "@smithy/util-retry": "^4.0.1", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/core": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.758.0.tgz", + "integrity": "sha512-0RswbdR9jt/XKemaLNuxi2gGr4xGlHyGxkTdhSQzCyUe9A9OPCoLl3rIESRguQEech+oJnbHk/wuiwHqTuP9sg==", + "dev": true, + "requires": { + "@aws-sdk/types": "3.734.0", + "@smithy/core": "^3.1.5", + "@smithy/node-config-provider": "^4.0.1", + "@smithy/property-provider": "^4.0.1", + "@smithy/protocol-http": "^5.0.1", + "@smithy/signature-v4": "^5.0.1", + "@smithy/smithy-client": "^4.1.6", + "@smithy/types": "^4.1.0", + "@smithy/util-middleware": "^4.0.1", + "fast-xml-parser": "4.4.1", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-env": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.758.0.tgz", + "integrity": "sha512-N27eFoRrO6MeUNumtNHDW9WOiwfd59LPXPqDrIa3kWL/s+fOKFHb9xIcF++bAwtcZnAxKkgpDCUP+INNZskE+w==", + "dev": true, + "requires": { + "@aws-sdk/core": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@smithy/property-provider": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-http": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.758.0.tgz", + "integrity": "sha512-Xt9/U8qUCiw1hihztWkNeIR+arg6P+yda10OuCHX6kFVx3auTlU7+hCqs3UxqniGU4dguHuftf3mRpi5/GJ33Q==", + "dev": true, + "requires": { + "@aws-sdk/core": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@smithy/fetch-http-handler": "^5.0.1", + "@smithy/node-http-handler": "^4.0.3", + "@smithy/property-provider": "^4.0.1", + "@smithy/protocol-http": "^5.0.1", + "@smithy/smithy-client": "^4.1.6", + "@smithy/types": "^4.1.0", + "@smithy/util-stream": "^4.1.2", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-ini": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.758.0.tgz", + "integrity": "sha512-cymSKMcP5d+OsgetoIZ5QCe1wnp2Q/tq+uIxVdh9MbfdBBEnl9Ecq6dH6VlYS89sp4QKuxHxkWXVnbXU3Q19Aw==", + "dev": true, + "requires": { + "@aws-sdk/core": "3.758.0", + "@aws-sdk/credential-provider-env": "3.758.0", + "@aws-sdk/credential-provider-http": "3.758.0", + "@aws-sdk/credential-provider-process": "3.758.0", + "@aws-sdk/credential-provider-sso": "3.758.0", + "@aws-sdk/credential-provider-web-identity": "3.758.0", + "@aws-sdk/nested-clients": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@smithy/credential-provider-imds": "^4.0.1", + "@smithy/property-provider": "^4.0.1", + "@smithy/shared-ini-file-loader": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-node": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.758.0.tgz", + "integrity": "sha512-+DaMv63wiq7pJrhIQzZYMn4hSarKiizDoJRvyR7WGhnn0oQ/getX9Z0VNCV3i7lIFoLNTb7WMmQ9k7+z/uD5EQ==", + "dev": true, + "requires": { + "@aws-sdk/credential-provider-env": "3.758.0", + "@aws-sdk/credential-provider-http": "3.758.0", + "@aws-sdk/credential-provider-ini": "3.758.0", + "@aws-sdk/credential-provider-process": "3.758.0", + "@aws-sdk/credential-provider-sso": "3.758.0", + "@aws-sdk/credential-provider-web-identity": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@smithy/credential-provider-imds": "^4.0.1", + "@smithy/property-provider": "^4.0.1", + "@smithy/shared-ini-file-loader": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-process": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.758.0.tgz", + "integrity": "sha512-AzcY74QTPqcbXWVgjpPZ3HOmxQZYPROIBz2YINF0OQk0MhezDWV/O7Xec+K1+MPGQO3qS6EDrUUlnPLjsqieHA==", + "dev": true, + "requires": { + "@aws-sdk/core": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@smithy/property-provider": "^4.0.1", + "@smithy/shared-ini-file-loader": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-sso": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.758.0.tgz", + "integrity": "sha512-x0FYJqcOLUCv8GLLFDYMXRAQKGjoM+L0BG4BiHYZRDf24yQWFCAZsCQAYKo6XZYh2qznbsW6f//qpyJ5b0QVKQ==", + "dev": true, + "requires": { + "@aws-sdk/client-sso": "3.758.0", + "@aws-sdk/core": "3.758.0", + "@aws-sdk/token-providers": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@smithy/property-provider": "^4.0.1", + "@smithy/shared-ini-file-loader": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-web-identity": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.758.0.tgz", + "integrity": "sha512-XGguXhBqiCXMXRxcfCAVPlMbm3VyJTou79r/3mxWddHWF0XbhaQiBIbUz6vobVTD25YQRbWSmSch7VA8kI5Lrw==", + "dev": true, + "requires": { + "@aws-sdk/core": "3.758.0", + "@aws-sdk/nested-clients": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@smithy/property-provider": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/middleware-user-agent": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.758.0.tgz", + "integrity": "sha512-iNyehQXtQlj69JCgfaOssgZD4HeYGOwxcaKeG6F+40cwBjTAi0+Ph1yfDwqk2qiBPIRWJ/9l2LodZbxiBqgrwg==", + "dev": true, + "requires": { + "@aws-sdk/core": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@aws-sdk/util-endpoints": "3.743.0", + "@smithy/core": "^3.1.5", + "@smithy/protocol-http": "^5.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/nested-clients": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.758.0.tgz", + "integrity": "sha512-YZ5s7PSvyF3Mt2h1EQulCG93uybprNGbBkPmVuy/HMMfbFTt4iL3SbKjxqvOZelm86epFfj7pvK7FliI2WOEcg==", + "dev": true, + "requires": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.758.0", + "@aws-sdk/middleware-host-header": "3.734.0", + "@aws-sdk/middleware-logger": "3.734.0", + "@aws-sdk/middleware-recursion-detection": "3.734.0", + "@aws-sdk/middleware-user-agent": "3.758.0", + "@aws-sdk/region-config-resolver": "3.734.0", + "@aws-sdk/types": "3.734.0", + "@aws-sdk/util-endpoints": "3.743.0", + "@aws-sdk/util-user-agent-browser": "3.734.0", + "@aws-sdk/util-user-agent-node": "3.758.0", + "@smithy/config-resolver": "^4.0.1", + "@smithy/core": "^3.1.5", + "@smithy/fetch-http-handler": "^5.0.1", + "@smithy/hash-node": "^4.0.1", + "@smithy/invalid-dependency": "^4.0.1", + "@smithy/middleware-content-length": "^4.0.1", + "@smithy/middleware-endpoint": "^4.0.6", + "@smithy/middleware-retry": "^4.0.7", + "@smithy/middleware-serde": "^4.0.2", + "@smithy/middleware-stack": "^4.0.1", + "@smithy/node-config-provider": "^4.0.1", + "@smithy/node-http-handler": "^4.0.3", + "@smithy/protocol-http": "^5.0.1", + "@smithy/smithy-client": "^4.1.6", + "@smithy/types": "^4.1.0", + "@smithy/url-parser": "^4.0.1", + "@smithy/util-base64": "^4.0.0", + "@smithy/util-body-length-browser": "^4.0.0", + "@smithy/util-body-length-node": "^4.0.0", + "@smithy/util-defaults-mode-browser": "^4.0.7", + "@smithy/util-defaults-mode-node": "^4.0.7", + "@smithy/util-endpoints": "^3.0.1", + "@smithy/util-middleware": "^4.0.1", + "@smithy/util-retry": "^4.0.1", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/token-providers": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.758.0.tgz", + "integrity": "sha512-ckptN1tNrIfQUaGWm/ayW1ddG+imbKN7HHhjFdS4VfItsP0QQOB0+Ov+tpgb4MoNR4JaUghMIVStjIeHN2ks1w==", + "dev": true, + "requires": { + "@aws-sdk/nested-clients": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@smithy/property-provider": "^4.0.1", + "@smithy/shared-ini-file-loader": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/util-user-agent-node": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.758.0.tgz", + "integrity": "sha512-A5EZw85V6WhoKMV2hbuFRvb9NPlxEErb4HPO6/SPXYY4QrjprIzScHxikqcWv1w4J3apB1wto9LPU3IMsYtfrw==", + "dev": true, + "requires": { + "@aws-sdk/middleware-user-agent": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@smithy/node-config-provider": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + } + }, + "@smithy/abort-controller": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.1.tgz", + "integrity": "sha512-fiUIYgIgRjMWznk6iLJz35K2YxSLHzLBA/RC6lBrKfQ8fHbPfvk7Pk9UvpKoHgJjI18MnbPuEju53zcVy6KF1g==", + "dev": true, + "requires": { + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + } + }, + "@smithy/node-http-handler": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.0.3.tgz", + "integrity": "sha512-dYCLeINNbYdvmMLtW0VdhW1biXt+PPCGazzT5ZjKw46mOtdgToQEwjqZSS9/EN8+tNs/RO0cEWG044+YZs97aA==", + "dev": true, + "requires": { + "@smithy/abort-controller": "^4.0.1", + "@smithy/protocol-http": "^5.0.1", + "@smithy/querystring-builder": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + } + }, + "@smithy/protocol-http": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.0.1.tgz", + "integrity": "sha512-TE4cpj49jJNB/oHyh/cRVEgNZaoPaxd4vteJNB0yGidOCVR0jCw/hjPVsT8Q8FRmj8Bd3bFZt8Dh7xGCT+xMBQ==", + "dev": true, + "requires": { + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + } + }, + "@smithy/querystring-builder": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.0.1.tgz", + "integrity": "sha512-wU87iWZoCbcqrwszsOewEIuq+SU2mSoBE2CcsLwE0I19m0B2gOJr1MVjxWcDQYOzHbR1xCk7AcOBbGFUYOKvdg==", + "dev": true, + "requires": { + "@smithy/types": "^4.1.0", + "@smithy/util-uri-escape": "^4.0.0", + "tslib": "^2.6.2" + } + }, + "@smithy/types": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz", + "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==", + "dev": true, + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-uri-escape": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.0.0.tgz", + "integrity": "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg==", + "dev": true, + "requires": { + "tslib": "^2.6.2" + } + }, + "uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true + } + } + }, "@aws-sdk/client-cognito-identity": { "version": "3.750.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.750.0.tgz", @@ -38744,15 +39791,6 @@ "requires": { "tslib": "^2.6.2" } - }, - "fast-xml-parser": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", - "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", - "dev": true, - "requires": { - "strnum": "^1.0.5" - } } } }, @@ -42923,242 +43961,6 @@ "sparse-bitfield": "^3.0.3" } }, - "@nestjs/common": { - "version": "9.4.3", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-9.4.3.tgz", - "integrity": "sha512-Gd6D4IaYj01o14Bwv81ukidn4w3bPHCblMUq+SmUmWLyosK+XQmInCS09SbDDZyL8jy86PngtBLTdhJ2bXSUig==", - "dev": true, - "requires": { - "iterare": "1.2.1", - "tslib": "2.5.3", - "uid": "2.0.2" - }, - "dependencies": { - "tslib": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz", - "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==", - "dev": true - } - } - }, - "@nestjs/core": { - "version": "9.4.3", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-9.4.3.tgz", - "integrity": "sha512-Qi63+wi55Jh4sDyaj5Hhx2jOpKqT386aeo+VOKsxnd+Ql9VvkO/FjmuwBGUyzkJt29ENYc+P0Sx/k5LtstNpPQ==", - "dev": true, - "requires": { - "@nuxtjs/opencollective": "0.3.2", - "fast-safe-stringify": "2.1.1", - "iterare": "1.2.1", - "path-to-regexp": "3.2.0", - "tslib": "2.5.3", - "uid": "2.0.2" - }, - "dependencies": { - "path-to-regexp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.2.0.tgz", - "integrity": "sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA==", - "dev": true - }, - "tslib": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz", - "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==", - "dev": true - } - } - }, - "@nestjs/platform-express": { - "version": "9.4.3", - "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-9.4.3.tgz", - "integrity": "sha512-FpdczWoRSC0zz2dNL9u2AQLXKXRVtq4HgHklAhbL59X0uy+mcxhlSThG7DHzDMkoSnuuHY8ojDVf7mDxk+GtCw==", - "dev": true, - "requires": { - "body-parser": "1.20.2", - "cors": "2.8.5", - "express": "4.18.2", - "multer": "1.4.4-lts.1", - "tslib": "2.5.3" - }, - "dependencies": { - "cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - } - } - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "dev": true - }, - "express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", - "dev": true, - "requires": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.1", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.11.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "dev": true, - "requires": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - } - } - } - }, - "finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - } - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "dev": true - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", - "dev": true - }, - "raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "dev": true, - "requires": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "dev": true, - "requires": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - } - }, - "serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "dev": true, - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - } - }, - "tslib": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz", - "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==", - "dev": true - } - } - }, "@netflix/nerror": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@netflix/nerror/-/nerror-1.1.3.tgz", @@ -43702,15 +44504,21 @@ "nx": "15.9.7" } }, - "@nuxtjs/opencollective": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz", - "integrity": "sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==", + "@nuxt/opencollective": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@nuxt/opencollective/-/opencollective-0.4.1.tgz", + "integrity": "sha512-GXD3wy50qYbxCJ652bDrDzgMr3NFEkIS374+IgFQKkCvk9yiYcLvX2XDYr7UyQxf4wK0e+yqDYRubZ0DtOxnmQ==", "dev": true, "requires": { - "chalk": "^4.1.0", - "consola": "^2.15.0", - "node-fetch": "^2.6.1" + "consola": "^3.2.3" + }, + "dependencies": { + "consola": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "dev": true + } } }, "@octokit/auth-token": { @@ -43921,10 +44729,11 @@ "version": "file:metapackages/auto-instrumentations-node", "requires": { "@opentelemetry/api": "^1.4.1", + "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.200.0", "@opentelemetry/instrumentation-amqplib": "^0.47.0", "@opentelemetry/instrumentation-aws-lambda": "^0.51.0", - "@opentelemetry/instrumentation-aws-sdk": "^0.50.0", + "@opentelemetry/instrumentation-aws-sdk": "^0.51.0", "@opentelemetry/instrumentation-bunyan": "^0.46.0", "@opentelemetry/instrumentation-cassandra-driver": "^0.46.0", "@opentelemetry/instrumentation-connect": "^0.44.0", @@ -43940,7 +44749,7 @@ "@opentelemetry/instrumentation-hapi": "^0.46.0", "@opentelemetry/instrumentation-http": "^0.200.0", "@opentelemetry/instrumentation-ioredis": "^0.48.0", - "@opentelemetry/instrumentation-kafkajs": "^0.8.0", + "@opentelemetry/instrumentation-kafkajs": "^0.9.0", "@opentelemetry/instrumentation-knex": "^0.45.0", "@opentelemetry/instrumentation-koa": "^0.48.0", "@opentelemetry/instrumentation-lru-memoizer": "^0.45.0", @@ -43949,7 +44758,7 @@ "@opentelemetry/instrumentation-mongoose": "^0.47.0", "@opentelemetry/instrumentation-mysql": "^0.46.0", "@opentelemetry/instrumentation-mysql2": "^0.46.0", - "@opentelemetry/instrumentation-nestjs-core": "^0.45.0", + "@opentelemetry/instrumentation-nestjs-core": "^0.46.0", "@opentelemetry/instrumentation-net": "^0.44.0", "@opentelemetry/instrumentation-pg": "^0.52.0", "@opentelemetry/instrumentation-pino": "^0.47.0", @@ -44047,6 +44856,30 @@ } } }, + "@opentelemetry/baggage-log-record-processor": { + "version": "file:packages/baggage-log-record-processor", + "requires": { + "@opentelemetry/api": "^1.0.0", + "@opentelemetry/sdk-logs": "^0.200.0", + "@types/mocha": "10.0.10", + "@types/node": "18.18.14", + "expect": "29.2.0", + "nyc": "15.1.0", + "rimraf": "5.0.10", + "typescript": "5.0.4" + }, + "dependencies": { + "@types/node": { + "version": "18.18.14", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.14.tgz", + "integrity": "sha512-iSOeNeXYNYNLLOMDSVPvIFojclvMZ/HDY2dU17kUlcsOsSQETbWIslJbYLZgA+ox8g2XQwSHKTkght1a5X26lQ==", + "dev": true, + "requires": { + "undici-types": "~5.26.4" + } + } + } + }, "@opentelemetry/baggage-span-processor": { "version": "file:packages/baggage-span-processor", "requires": { @@ -44436,6 +45269,7 @@ "@opentelemetry/instrumentation-aws-sdk": { "version": "file:plugins/node/opentelemetry-instrumentation-aws-sdk", "requires": { + "@aws-sdk/client-bedrock-runtime": "^3.587.0", "@aws-sdk/client-dynamodb": "^3.85.0", "@aws-sdk/client-kinesis": "^3.85.0", "@aws-sdk/client-lambda": "^3.85.0", @@ -44454,7 +45288,6 @@ "@types/mocha": "10.0.10", "@types/node": "18.18.14", "@types/sinon": "17.0.4", - "aws-sdk": "2.1008.0", "eslint": "8.7.0", "expect": "29.2.0", "nock": "13.3.3", @@ -45014,7 +45847,7 @@ "@opentelemetry/contrib-test-utils": "^0.46.0", "@opentelemetry/instrumentation": "^0.200.0", "@opentelemetry/sdk-trace-base": "^2.0.0", - "@opentelemetry/semantic-conventions": "^1.27.0", + "@opentelemetry/semantic-conventions": "^1.30.0", "@types/mocha": "10.0.10", "@types/node": "18.18.14", "@types/sinon": "^17.0.0", @@ -45022,6 +45855,7 @@ "nyc": "15.1.0", "rimraf": "5.0.10", "sinon": "15.2.0", + "test-all-versions": "6.1.0", "typescript": "5.0.4" }, "dependencies": { @@ -45236,7 +46070,7 @@ "@types/bson": "4.0.5", "@types/mocha": "10.0.10", "@types/node": "18.18.14", - "mongodb": "6.8.0", + "mongodb": "6.15.0", "nyc": "15.1.0", "rimraf": "5.0.10", "test-all-versions": "6.1.0", @@ -45317,13 +46151,13 @@ } }, "mongodb": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.8.0.tgz", - "integrity": "sha512-HGQ9NWDle5WvwMnrvUxsFYPd3JEbqD3RgABHBQRuoCEND0qzhsd0iH5ypHsf1eJ+sXmvmyKpP+FLOKY8Il7jMw==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.15.0.tgz", + "integrity": "sha512-ifBhQ0rRzHDzqp9jAQP6OwHSH7dbYIQjD3SbJs9YYk9AikKEettW/9s/tbSFDTpXcRbF+u1aLrhHxDFaYtZpFQ==", "dev": true, "requires": { - "@mongodb-js/saslprep": "^1.1.5", - "bson": "^6.7.0", + "@mongodb-js/saslprep": "^1.1.9", + "bson": "^6.10.3", "mongodb-connection-string-url": "^3.0.0" } }, @@ -45436,21 +46270,21 @@ "@opentelemetry/instrumentation-nestjs-core": { "version": "file:plugins/node/opentelemetry-instrumentation-nestjs-core", "requires": { - "@nestjs/common": "9.4.3", - "@nestjs/core": "9.4.3", - "@nestjs/platform-express": "9.4.3", + "@nestjs/common": "11.0.10", + "@nestjs/core": "11.0.10", + "@nestjs/platform-express": "11.0.10", "@opentelemetry/api": "^1.3.0", "@opentelemetry/context-async-hooks": "^2.0.0", "@opentelemetry/instrumentation": "^0.200.0", "@opentelemetry/sdk-trace-base": "^2.0.0", "@opentelemetry/sdk-trace-node": "^2.0.0", - "@opentelemetry/semantic-conventions": "^1.27.0", + "@opentelemetry/semantic-conventions": "^1.30.0", "@types/mocha": "10.0.10", "@types/node": "18.18.14", "@types/semver": "7.5.8", "cross-env": "7.0.3", "nyc": "15.1.0", - "reflect-metadata": "0.1.13", + "reflect-metadata": "0.2.2", "rimraf": "5.0.10", "rxjs": "7.8.2", "rxjs-compat": "6.6.7", @@ -45459,6 +46293,44 @@ "typescript": "5.0.4" }, "dependencies": { + "@nestjs/common": { + "version": "11.0.10", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-11.0.10.tgz", + "integrity": "sha512-pzGXp14KF2Q4CDZGQgPK4l8zEg7i6cNkb+10yc8ZA5K41cLe3ZbWW1YxtY2e/glHauOJwTLSVjH4tiRVtOTizg==", + "dev": true, + "requires": { + "iterare": "1.2.1", + "tslib": "2.8.1", + "uid": "2.0.2" + } + }, + "@nestjs/core": { + "version": "11.0.10", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-11.0.10.tgz", + "integrity": "sha512-f0qB8ztNWZeAD4E4fUdHConmNYCa/A78U7WJu5mX9OLYfOAs3ESYCDfsH9MRUvkA4Ft4Y1uMmyJo5L4fg4+beg==", + "dev": true, + "requires": { + "@nuxt/opencollective": "0.4.1", + "fast-safe-stringify": "2.1.1", + "iterare": "1.2.1", + "path-to-regexp": "8.2.0", + "tslib": "2.8.1", + "uid": "2.0.2" + } + }, + "@nestjs/platform-express": { + "version": "11.0.10", + "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-11.0.10.tgz", + "integrity": "sha512-UVSf0yaWFBC2Zn2FOWABXxCnyG8XNIXrNnvTFpbUFqaJu1YDdwJ7wQBBqxq9CtJT7ILqSmfhOU7HS0d/0EAxpw==", + "dev": true, + "requires": { + "cors": "2.8.5", + "express": "5.0.1", + "multer": "1.4.5-lts.1", + "path-to-regexp": "8.2.0", + "tslib": "2.8.1" + } + }, "@types/node": { "version": "18.18.14", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.14.tgz", @@ -45467,6 +46339,386 @@ "requires": { "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.1.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.1.0.tgz", + "integrity": "sha512-/hPxh61E+ll0Ujp24Ilm64cykicul1ypfwjVttduAiEdtnJFvLePSrIPk+HMImtNv5270wOGCb1Tns2rybMkoQ==", + "dev": true, + "requires": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.5.2", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" + }, + "dependencies": { + "qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "dev": true, + "requires": { + "side-channel": "^1.1.0" + } + }, + "type-is": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.0.tgz", + "integrity": "sha512-gd0sGezQYCbWSbkZr75mln4YBidWUN60+devscpLF5mtRDUpiaTvKpBNrdaCvel1NdR2k6vclXybU5fBd2i+nw==", + "dev": true, + "requires": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + } + } + } + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "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.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "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.0.1", + "resolved": "https://registry.npmjs.org/express/-/express-5.0.1.tgz", + "integrity": "sha512-ORF7g6qGnD+YtUG9yx4DFoqCShNMmUKiXuT5oWMHiOvt/4WFbHC6yCwQMTSBMno7AqntNCAzzcnnjowRkTL9eQ==", + "dev": true, + "requires": { + "accepts": "^2.0.0", + "body-parser": "^2.0.1", + "content-disposition": "^1.0.0", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "^1.2.1", + "debug": "4.3.6", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "^2.0.0", + "fresh": "2.0.0", + "http-errors": "2.0.0", + "merge-descriptors": "^2.0.0", + "methods": "~1.1.2", + "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.13.0", + "range-parser": "~1.2.1", + "router": "^2.0.0", + "safe-buffer": "5.2.1", + "send": "^1.1.0", + "serve-static": "^2.1.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "^2.0.0", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "type-is": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.0.tgz", + "integrity": "sha512-gd0sGezQYCbWSbkZr75mln4YBidWUN60+devscpLF5mtRDUpiaTvKpBNrdaCvel1NdR2k6vclXybU5fBd2i+nw==", + "dev": true, + "requires": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + } + } + } + }, + "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.5.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.2.tgz", + "integrity": "sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "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.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.0.tgz", + "integrity": "sha512-XqoSHeCGjVClAmoGFG3lVFqQFRIrTVw2OH3axRqAcfaw+gHWIfnASS92AV+Rl/mk0MupgZTRHQOjxY6YVnzK5w==", + "dev": true, + "requires": { + "mime-db": "^1.53.0" + } + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + }, + "multer": { + "version": "1.4.5-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", + "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "dev": true, + "requires": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.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 + }, + "qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dev": true, + "requires": { + "side-channel": "^1.0.6" + } + }, + "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" + }, + "dependencies": { + "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" + } + } + } + }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "reflect-metadata": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", + "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", + "dev": true + }, + "router": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.1.0.tgz", + "integrity": "sha512-/m/NSLxeYEgWNtyC+WtNHCF7jbGxOibVWKnn+1Psff4dJGOfoXP+MuC/f2CwSmyiHdOIzYnYFp4W6GxWfekaLA==", + "dev": true, + "requires": { + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + } + }, + "send": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.1.0.tgz", + "integrity": "sha512-v67WcEouB5GxbTWL/4NeToqcZiAWEq90N888fczVArY8A79J0L4FD7vj5hm3eUMua5EpoQ59wa/oovY6TLvRUA==", + "dev": true, + "requires": { + "debug": "^4.3.5", + "destroy": "^1.2.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^0.5.2", + "http-errors": "^2.0.0", + "mime-types": "^2.1.35", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + }, + "dependencies": { + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "requires": { + "mime-db": "1.52.0" + } + } + } + }, + "serve-static": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.1.0.tgz", + "integrity": "sha512-A3We5UfEjG8Z7VkDv6uItWw6HY2bBSBJT1KtVESn6EOoOr2jAxNhxWCLY3jDE2WcuHXByWju74ck3ZgLwL8xmA==", + "dev": true, + "requires": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } } } }, @@ -47435,9 +48687,9 @@ } }, "@smithy/core": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.1.4.tgz", - "integrity": "sha512-wFExFGK+7r2wYriOqe7RRIBNpvxwiS95ih09+GSLRBdoyK/O1uZA7K7pKesj5CBvwJuSBeXwLyR88WwIAY+DGA==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.1.5.tgz", + "integrity": "sha512-HLclGWPkCsekQgsyzxLhCQLa8THWXtB5PxyYN+2O6nkyLt550KQKTlbV2D1/j5dNIQapAZM1+qFnpBFxZQkgCA==", "dev": true, "requires": { "@smithy/middleware-serde": "^4.0.2", @@ -47445,7 +48697,7 @@ "@smithy/types": "^4.1.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-middleware": "^4.0.1", - "@smithy/util-stream": "^4.1.1", + "@smithy/util-stream": "^4.1.2", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, @@ -47812,12 +49064,12 @@ } }, "@smithy/middleware-endpoint": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.0.5.tgz", - "integrity": "sha512-cPzGZV7qStHwboFrm6GfrzQE+YDiCzWcTh4+7wKrP/ZQ4gkw+r7qDjV8GjM4N0UYsuUyLfpzLGg5hxsYTU11WA==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.0.6.tgz", + "integrity": "sha512-ftpmkTHIFqgaFugcjzLZv3kzPEFsBFSnq1JsIkr2mwFzCraZVhQk2gqN51OOeRxqhbPTkRFj39Qd2V91E/mQxg==", "dev": true, "requires": { - "@smithy/core": "^3.1.4", + "@smithy/core": "^3.1.5", "@smithy/middleware-serde": "^4.0.2", "@smithy/node-config-provider": "^4.0.1", "@smithy/shared-ini-file-loader": "^4.0.1", @@ -47839,15 +49091,15 @@ } }, "@smithy/middleware-retry": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.0.6.tgz", - "integrity": "sha512-s8QzuOQnbdvRymD9Gt9c9zMq10wUQAHQ3z72uirrBHCwZcLTrL5iCOuVTMdka2IXOYhQE890WD5t6G24+F+Qcg==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.0.7.tgz", + "integrity": "sha512-58j9XbUPLkqAcV1kHzVX/kAR16GT+j7DUZJqwzsxh1jtz7G82caZiGyyFgUvogVfNTg3TeAOIJepGc8TXF4AVQ==", "dev": true, "requires": { "@smithy/node-config-provider": "^4.0.1", "@smithy/protocol-http": "^5.0.1", "@smithy/service-error-classification": "^4.0.1", - "@smithy/smithy-client": "^4.1.5", + "@smithy/smithy-client": "^4.1.6", "@smithy/types": "^4.1.0", "@smithy/util-middleware": "^4.0.1", "@smithy/util-retry": "^4.0.1", @@ -48111,17 +49363,17 @@ } }, "@smithy/smithy-client": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.1.5.tgz", - "integrity": "sha512-DMXYoYeL4QkElr216n1yodTFeATbfb4jwYM9gKn71Rw/FNA1/Sm36tkTSCsZEs7mgpG3OINmkxL9vgVFzyGPaw==", + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.1.6.tgz", + "integrity": "sha512-UYDolNg6h2O0L+cJjtgSyKKvEKCOa/8FHYJnBobyeoeWDmNpXjwOAtw16ezyeu1ETuuLEOZbrynK0ZY1Lx9Jbw==", "dev": true, "requires": { - "@smithy/core": "^3.1.4", - "@smithy/middleware-endpoint": "^4.0.5", + "@smithy/core": "^3.1.5", + "@smithy/middleware-endpoint": "^4.0.6", "@smithy/middleware-stack": "^4.0.1", "@smithy/protocol-http": "^5.0.1", "@smithy/types": "^4.1.0", - "@smithy/util-stream": "^4.1.1", + "@smithy/util-stream": "^4.1.2", "tslib": "^2.6.2" }, "dependencies": { @@ -48226,13 +49478,13 @@ } }, "@smithy/util-defaults-mode-browser": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.6.tgz", - "integrity": "sha512-N8+VCt+piupH1A7DgSVDNrVHqRLz8r6DvBkpS7EWHiIxsUk4jqGuQLjqC/gnCzmwGkVBdNruHoYAzzaSQ8e80w==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.7.tgz", + "integrity": "sha512-CZgDDrYHLv0RUElOsmZtAnp1pIjwDVCSuZWOPhIOBvG36RDfX1Q9+6lS61xBf+qqvHoqRjHxgINeQz47cYFC2Q==", "dev": true, "requires": { "@smithy/property-provider": "^4.0.1", - "@smithy/smithy-client": "^4.1.5", + "@smithy/smithy-client": "^4.1.6", "@smithy/types": "^4.1.0", "bowser": "^2.11.0", "tslib": "^2.6.2" @@ -48250,16 +49502,16 @@ } }, "@smithy/util-defaults-mode-node": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.6.tgz", - "integrity": "sha512-9zhx1shd1VwSSVvLZB8CM3qQ3RPD3le7A3h/UPuyh/PC7g4OaWDi2xUNzamsVoSmCGtmUBONl56lM2EU6LcH7A==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.7.tgz", + "integrity": "sha512-79fQW3hnfCdrfIi1soPbK3zmooRFnLpSx3Vxi6nUlqaaQeC5dm8plt4OTNDNqEEEDkvKghZSaoti684dQFVrGQ==", "dev": true, "requires": { "@smithy/config-resolver": "^4.0.1", "@smithy/credential-provider-imds": "^4.0.1", "@smithy/node-config-provider": "^4.0.1", "@smithy/property-provider": "^4.0.1", - "@smithy/smithy-client": "^4.1.5", + "@smithy/smithy-client": "^4.1.6", "@smithy/types": "^4.1.0", "tslib": "^2.6.2" }, @@ -48350,13 +49602,13 @@ } }, "@smithy/util-stream": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.1.1.tgz", - "integrity": "sha512-+Xvh8nhy0Wjv1y71rBVyV3eJU3356XsFQNI8dEZVNrQju7Eib8G31GWtO+zMa9kTCGd41Mflu+ZKfmQL/o2XzQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.1.2.tgz", + "integrity": "sha512-44PKEqQ303d3rlQuiDpcCcu//hV8sn+u2JBo84dWCE0rvgeiVl0IlLMagbU++o0jCWhYCsHaAt9wZuZqNe05Hw==", "dev": true, "requires": { "@smithy/fetch-http-handler": "^5.0.1", - "@smithy/node-http-handler": "^4.0.2", + "@smithy/node-http-handler": "^4.0.3", "@smithy/types": "^4.1.0", "@smithy/util-base64": "^4.0.0", "@smithy/util-buffer-from": "^4.0.0", @@ -48376,9 +49628,9 @@ } }, "@smithy/node-http-handler": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.0.2.tgz", - "integrity": "sha512-X66H9aah9hisLLSnGuzRYba6vckuFtGE+a5DcHLliI/YlqKrGoxhisD5XbX44KyoeRzoNlGr94eTsMVHFAzPOw==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.0.3.tgz", + "integrity": "sha512-dYCLeINNbYdvmMLtW0VdhW1biXt+PPCGazzT5ZjKw46mOtdgToQEwjqZSS9/EN8+tNs/RO0cEWG044+YZs97aA==", "dev": true, "requires": { "@smithy/abort-controller": "^4.0.1", @@ -50280,31 +51532,6 @@ "fastq": "^1.17.1" } }, - "aws-sdk": { - "version": "2.1008.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1008.0.tgz", - "integrity": "sha512-wBEon+ARCuMcwEPpOFZqRT3elBLfLtPqv8jMql3Hsr7Ua5toPlgKMmjf368iTzBNaY7TOZsjLAT9nAhvtSZ++g==", - "dev": true, - "requires": { - "buffer": "4.9.2", - "events": "1.1.1", - "ieee754": "1.1.13", - "jmespath": "0.15.0", - "querystring": "0.2.0", - "sax": "1.2.1", - "url": "0.10.3", - "uuid": "3.3.2", - "xml2js": "0.4.19" - }, - "dependencies": { - "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "dev": true - } - } - }, "aws-ssl-profiles": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz", @@ -50746,17 +51973,6 @@ } } }, - "buffer": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", - "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, "buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", @@ -51570,12 +52786,6 @@ "integrity": "sha512-bTTG28diWg7R7/+qE5NZumwPbCiJOT8uPdZYu674brDjBWQctbaQbYlDKhalS+4i5HxIx+G8dZsnBHKzWpp01A==", "dev": true }, - "consola": { - "version": "2.15.3", - "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", - "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==", - "dev": true - }, "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", @@ -53313,12 +54523,6 @@ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", "dev": true }, - "events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==", - "dev": true - }, "ewma": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/ewma/-/ewma-2.0.1.tgz", @@ -53701,6 +54905,15 @@ "integrity": "sha512-ypuAmmMKInk5q7XcepxlnUWDLWv4GFtaJqAzWKqn62IpQ3pejtr5dTVbt3vwqVaMKmkNR55sTT+CqUKIaT21BA==", "dev": true }, + "fast-xml-parser": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", + "dev": true, + "requires": { + "strnum": "^1.0.5" + } + }, "fastest-levenshtein": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", @@ -55578,6 +56791,12 @@ "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", "dev": true }, + "is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "dev": true + }, "is-property": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", @@ -56075,12 +57294,6 @@ } } }, - "jmespath": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", - "integrity": "sha512-+kHj8HXArPfpPEKGLZ+kB5ONRTCiGQXo8RQYL0hH8t6pWXUBBK5KkkQmTNOwKK4LEsd0yTsgtjJVm4UBSZea4w==", - "dev": true - }, "joi": { "version": "17.12.2", "resolved": "https://registry.npmjs.org/joi/-/joi-17.12.2.tgz", @@ -59174,74 +60387,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, - "multer": { - "version": "1.4.4-lts.1", - "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4-lts.1.tgz", - "integrity": "sha512-WeSGziVj6+Z2/MwQo3GvqzgR+9Uc+qt8SwHKh3gvNPiISKfsMfG4SvCOFYlxxgkXt7yIV2i1yczehm0EOKIxIg==", - "dev": true, - "requires": { - "append-field": "^1.0.0", - "busboy": "^1.0.0", - "concat-stream": "^1.5.2", - "mkdirp": "^0.5.4", - "object-assign": "^4.1.1", - "type-is": "^1.6.4", - "xtend": "^4.0.0" - }, - "dependencies": { - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "requires": { - "minimist": "^1.2.6" - } - }, - "readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, "multimatch": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-5.0.0.tgz", @@ -61907,12 +63052,6 @@ "side-channel": "^1.0.4" } }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", - "dev": true - }, "querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", @@ -63039,12 +64178,6 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "devOptional": true }, - "sax": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", - "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==", - "dev": true - }, "scheduler": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", @@ -65596,24 +66729,6 @@ } } }, - "url": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", - "integrity": "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==", - "dev": true, - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==", - "dev": true - } - } - }, "url-parse": { "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", @@ -66307,24 +67422,6 @@ "dev": true, "requires": {} }, - "xml2js": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", - "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", - "dev": true, - "requires": { - "sax": ">=0.6.0", - "xmlbuilder": "~9.0.1" - }, - "dependencies": { - "xmlbuilder": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", - "integrity": "sha512-7YXTQc3P2l9+0rjaUbLwMKRhtmwg1M1eDf6nag7urC7pIPYLD9W/jmzQ4ptRSUbodw5S0jfoGTflLemQibSpeQ==", - "dev": true - } - } - }, "xmlbuilder": { "version": "15.1.1", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", diff --git a/packages/baggage-log-record-processor/.eslintignore b/packages/baggage-log-record-processor/.eslintignore new file mode 100644 index 0000000000..378eac25d3 --- /dev/null +++ b/packages/baggage-log-record-processor/.eslintignore @@ -0,0 +1 @@ +build diff --git a/packages/baggage-log-record-processor/.eslintrc.js b/packages/baggage-log-record-processor/.eslintrc.js new file mode 100644 index 0000000000..f726f3becb --- /dev/null +++ b/packages/baggage-log-record-processor/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + "env": { + "mocha": true, + "node": true + }, + ...require('../../eslint.config.js') +} diff --git a/packages/baggage-log-record-processor/CHANGELOG.md b/packages/baggage-log-record-processor/CHANGELOG.md new file mode 100644 index 0000000000..76dab3a823 --- /dev/null +++ b/packages/baggage-log-record-processor/CHANGELOG.md @@ -0,0 +1,12 @@ +# Changelog + +## [0.1.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/baggage-log-record-processor-v0.0.1...baggage-log-record-processor-v0.1.0) (2025-04-08) + + +### Features + +* **baggage-log-record-processor:** add package baggage log record processor ([#2754](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/2754)) ([03350ef](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/03350efea65a9c13dcb32d01fc9d41b008723152)) + +## 0.0.1 + +Initial version. diff --git a/packages/baggage-log-record-processor/LICENSE b/packages/baggage-log-record-processor/LICENSE new file mode 100644 index 0000000000..261eeb9e9f --- /dev/null +++ b/packages/baggage-log-record-processor/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/baggage-log-record-processor/README.md b/packages/baggage-log-record-processor/README.md new file mode 100644 index 0000000000..52403ad398 --- /dev/null +++ b/packages/baggage-log-record-processor/README.md @@ -0,0 +1,73 @@ +# OpenTelemetry Baggage Log Record Processor + +[![NPM Published Version][npm-img]][npm-url] +[![Apache License][license-image]][license-url] + +The BaggageLogRecordProcessor reads entries stored in Baggage from the parent context and adds the [baggage](https://opentelemetry.io/docs/concepts/signals/baggage) entries' keys and +values to the log record as attributes on log emit. + +⚠ Warning ⚠️ + +Do not put sensitive information in Baggage. + +To repeat: a consequence of adding data to Baggage is that the keys and values will appear in all outgoing HTTP headers from the application. + +Compatible with OpenTelemetry JS API and SDK `1.0+`. + +## Installation + +```bash +npm install --save @opentelemetry/baggage-log-record-processor +``` + +### Usage + +Add to the log record processors that copies all baggage entries during configuration: + +```javascript +import { NodeSDK, logs } from '@opentelemetry/sdk-node'; +import { ALLOW_ALL_BAGGAGE_KEYS, BaggageLogRecordProcessor } from '@opentelemetry/baggage-log-record-processor'; + +const logRecordProcessor = [ + new logs.SimpleLogRecordProcessor( + new logs.ConsoleLogRecordExporter()), + new BaggageLogRecordProcessor(ALLOW_ALL_BAGGAGE_KEYS)]; + +const sdk = new NodeSDK({ + serviceName: "example-service", + logRecordProcessor +}); + +sdk.start(); +``` + +Alternatively, you can provide a custom baggage key predicate to select which baggage keys you want to copy. + +For example, to only copy baggage entries that start with `my-key`: + +```javascript +new BaggageLogRecordProcessor((baggageKey: string) => key.startsWith('my-key')) +``` + +For example, to only copy baggage entries that matches the regex `^key.+`: + +```javascript +const regex = new RegExp("^key.+") +new BaggageLogRecordProcessor((baggageKey: string) => regex.test(baggageKey)) +``` + +## Useful links + +- For more information on OpenTelemetry, visit: +- For more about OpenTelemetry JavaScript: +- For help or feedback on this project, join us in [GitHub Discussions][discussions-url] + +## License + +APACHE 2.0 - See [LICENSE][license-url] for more information. + +[discussions-url]: https://github.com/open-telemetry/opentelemetry-js/discussions +[license-url]: https://github.com/open-telemetry/opentelemetry-js-contrib/blob/main/LICENSE +[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat +[npm-url]: https://www.npmjs.com/package/@opentelemetry/baggage-log-record-processor +[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fbaggage-log-record-processor.svg diff --git a/packages/baggage-log-record-processor/package.json b/packages/baggage-log-record-processor/package.json new file mode 100644 index 0000000000..6c2bf44b92 --- /dev/null +++ b/packages/baggage-log-record-processor/package.json @@ -0,0 +1,56 @@ +{ + "name": "@opentelemetry/baggage-log-record-processor", + "version": "0.1.0", + "description": "OpenTelemetry Baggage Log Record Processor", + "main": "build/src/index.js", + "types": "build/src/index.d.ts", + "repository": "open-telemetry/opentelemetry-js-contrib", + "scripts": { + "clean": "rimraf build/*", + "compile": "tsc -p .", + "lint": "eslint . --ext .ts", + "lint:fix": "eslint . --ext .ts --fix", + "prewatch": "npm run precompile", + "prepublishOnly": "npm run compile", + "tdd": "npm run test -- --watch-extensions ts --watch", + "test": "nyc mocha test/**/*.test.ts", + "version:update": "node ../../scripts/version-update.js", + "watch": "tsc -w" + }, + "keywords": [ + "opentelemetry", + "nodejs", + "log", + "baggage", + "plugin" + ], + "author": "OpenTelemetry Authors", + "license": "Apache-2.0", + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "files": [ + "build/src/**/*.js", + "build/src/**/*.js.map", + "build/src/**/*.d.ts" + ], + "publishConfig": { + "access": "public" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "dependencies": { + "@opentelemetry/sdk-logs": "^0.200.0" + }, + "devDependencies": { + "@opentelemetry/api": "^1.0.0", + "@types/mocha": "10.0.10", + "@types/node": "18.18.14", + "expect": "29.2.0", + "nyc": "15.1.0", + "rimraf": "5.0.10", + "typescript": "5.0.4" + }, + "homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/packages/baggage-log-record-processor#readme" +} diff --git a/packages/baggage-log-record-processor/src/baggage-log-record-processor.ts b/packages/baggage-log-record-processor/src/baggage-log-record-processor.ts new file mode 100644 index 0000000000..610b0ec10f --- /dev/null +++ b/packages/baggage-log-record-processor/src/baggage-log-record-processor.ts @@ -0,0 +1,73 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { BaggageKeyPredicate } from './types'; +import { Context, propagation } from '@opentelemetry/api'; +import { LogRecord, LogRecordProcessor } from '@opentelemetry/sdk-logs'; + +/** + * BaggageLogRecordProcessor is a {@link LogRecordProcessor} that reads entries stored in {@link Baggage} + * from the parent context and adds the baggage entries' keys and + * values to the log as attributes on log emit. + * + * ⚠ Warning ⚠️ + * + * Do not put sensitive information in Baggage. + * + * To repeat: a consequence of adding data to Baggage is that the keys and + * values will appear in all outgoing HTTP headers from the application. + */ +export class BaggageLogRecordProcessor implements LogRecordProcessor { + private _keyPredicate: BaggageKeyPredicate; + + /** + * Constructs a new BaggageLogRecordProcessor instance. + * @param keyPredicate A predicate that determines whether a baggage key-value pair should be added to new log as a log attribute. + */ + constructor(keyPredicate: BaggageKeyPredicate) { + this._keyPredicate = keyPredicate; + } + + /** + * Forces to export all finished log records. + */ + forceFlush(): Promise { + // no-op + return Promise.resolve(); + } + + /** + * Called when a {@link LogRecord} is emit + * @param logRecord the ReadWriteLogRecord that just emitted. + * @param context the current Context, or an empty Context if the Logger was obtained with include_trace_context=false + */ + onEmit(logRecord: LogRecord, context?: Context): void { + if (context) { + (propagation.getBaggage(context)?.getAllEntries() ?? []) + .filter(entry => this._keyPredicate(entry[0])) + .forEach(entry => logRecord.setAttribute(entry[0], entry[1].value)); + } + } + + /** + * Shuts down the processor. Called when SDK is shut down. This is an + * opportunity for processor to do any cleanup required. + */ + shutdown(): Promise { + // no-op + return Promise.resolve(); + } +} diff --git a/packages/baggage-log-record-processor/src/index.ts b/packages/baggage-log-record-processor/src/index.ts new file mode 100644 index 0000000000..afdea6c6f8 --- /dev/null +++ b/packages/baggage-log-record-processor/src/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { BaggageLogRecordProcessor } from './baggage-log-record-processor'; +export { ALLOW_ALL_BAGGAGE_KEYS, BaggageKeyPredicate } from './types'; diff --git a/packages/baggage-log-record-processor/src/types.ts b/packages/baggage-log-record-processor/src/types.ts new file mode 100644 index 0000000000..62abb59f47 --- /dev/null +++ b/packages/baggage-log-record-processor/src/types.ts @@ -0,0 +1,26 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * A function that determines whether a baggage key-value pair should be added to new + * log record as a log attribute. + */ +export type BaggageKeyPredicate = (baggageKey: string) => boolean; + +/** + * A {@link BaggageKeyPredicate} that includes all baggage keys. + */ +export const ALLOW_ALL_BAGGAGE_KEYS: BaggageKeyPredicate = (_: string) => true; diff --git a/packages/baggage-log-record-processor/test/baggage-log-record-processor.test.ts b/packages/baggage-log-record-processor/test/baggage-log-record-processor.test.ts new file mode 100644 index 0000000000..3fcfba16e4 --- /dev/null +++ b/packages/baggage-log-record-processor/test/baggage-log-record-processor.test.ts @@ -0,0 +1,143 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { BaggageLogRecordProcessor } from '../src/baggage-log-record-processor'; +import { ALLOW_ALL_BAGGAGE_KEYS } from '../src/types'; +import { propagation, ROOT_CONTEXT } from '@opentelemetry/api'; +import { + InMemoryLogRecordExporter, + LoggerProvider, + SimpleLogRecordProcessor, +} from '@opentelemetry/sdk-logs'; +import { expect } from 'expect'; + +describe('BaggageLogRecordProcessor with all keys', () => { + const baggageProcessor = new BaggageLogRecordProcessor( + ALLOW_ALL_BAGGAGE_KEYS + ); + const bag = propagation.createBaggage({ + brand: { value: 'samsonite' }, + color: { value: 'blue' }, + }); + + it('onEmit adds current Baggage entries to a log record as attributes', () => { + const loggerProvider = new LoggerProvider(); + const exporter = new InMemoryLogRecordExporter(); + loggerProvider.addLogRecordProcessor(baggageProcessor); + loggerProvider.addLogRecordProcessor( + new SimpleLogRecordProcessor(exporter) + ); + const logger = loggerProvider.getLogger('my-logger'); + const ctx = propagation.setBaggage(ROOT_CONTEXT, bag); + + logger.emit({ + body: 'my log body', + context: ctx, + }); + + const logRecords = exporter.getFinishedLogRecords(); + expect(logRecords.length).toBe(1); + expect(logRecords[0].attributes).toEqual({ + brand: 'samsonite', + color: 'blue', + }); + }); + + it('forceFlush is a no-op and does not throw error', async () => { + await expect(baggageProcessor.forceFlush()).resolves.not.toThrow(); + }); + + it('shutdown is a no-op and does not throw error', async () => { + await expect(baggageProcessor.shutdown()).resolves.not.toThrow(); + }); +}); + +describe('BaggageLogRecordProcessor startWith key filter', () => { + const baggageProcessor = new BaggageLogRecordProcessor((key: string) => + key.startsWith('brand') + ); + const bag = propagation.createBaggage({ + brand: { value: 'samsonite' }, + color: { value: 'blue' }, + }); + + it('onEmit adds current filtered by startWith Baggage entries to a log record as attributes', () => { + const loggerProvider = new LoggerProvider(); + const exporter = new InMemoryLogRecordExporter(); + loggerProvider.addLogRecordProcessor(baggageProcessor); + loggerProvider.addLogRecordProcessor( + new SimpleLogRecordProcessor(exporter) + ); + const logger = loggerProvider.getLogger('my-logger'); + const ctx = propagation.setBaggage(ROOT_CONTEXT, bag); + + logger.emit({ + body: 'my log body', + context: ctx, + }); + + const logRecords = exporter.getFinishedLogRecords(); + expect(logRecords.length).toBe(1); + expect(logRecords[0].attributes).toEqual({ brand: 'samsonite' }); + }); + + it('forceFlush is a no-op and does not throw error', async () => { + await expect(baggageProcessor.forceFlush()).resolves.not.toThrow(); + }); + + it('shutdown is a no-op and does not throw error', async () => { + await expect(baggageProcessor.shutdown()).resolves.not.toThrow(); + }); +}); + +describe('BaggageLogRecordProcessor with regex key filter', () => { + const regex = new RegExp('^col.+'); + const baggageProcessor = new BaggageLogRecordProcessor((key: string) => + regex.test(key) + ); + const bag = propagation.createBaggage({ + brand: { value: 'samsonite' }, + color: { value: 'blue' }, + }); + + it('onEmit adds current filtered by regex Baggage entries to a log record as attributes', () => { + const loggerProvider = new LoggerProvider(); + const exporter = new InMemoryLogRecordExporter(); + loggerProvider.addLogRecordProcessor(baggageProcessor); + loggerProvider.addLogRecordProcessor( + new SimpleLogRecordProcessor(exporter) + ); + const logger = loggerProvider.getLogger('my-logger'); + const ctx = propagation.setBaggage(ROOT_CONTEXT, bag); + + logger.emit({ + body: 'my log body', + context: ctx, + }); + + const logRecords = exporter.getFinishedLogRecords(); + expect(logRecords.length).toBe(1); + expect(logRecords[0].attributes).toEqual({ color: 'blue' }); + }); + + it('forceFlush is a no-op and does not throw error', async () => { + await expect(baggageProcessor.forceFlush()).resolves.not.toThrow(); + }); + + it('shutdown is a no-op and does not throw error', async () => { + await expect(baggageProcessor.shutdown()).resolves.not.toThrow(); + }); +}); diff --git a/packages/baggage-log-record-processor/tsconfig.json b/packages/baggage-log-record-processor/tsconfig.json new file mode 100644 index 0000000000..4078877ce6 --- /dev/null +++ b/packages/baggage-log-record-processor/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.base", + "compilerOptions": { + "rootDir": ".", + "outDir": "build" + }, + "include": [ + "src/**/*.ts", + "test/**/*.ts" + ] +} diff --git a/packages/opentelemetry-host-metrics/src/BaseMetrics.ts b/packages/opentelemetry-host-metrics/src/BaseMetrics.ts index ff39b8475f..a320a6c552 100644 --- a/packages/opentelemetry-host-metrics/src/BaseMetrics.ts +++ b/packages/opentelemetry-host-metrics/src/BaseMetrics.ts @@ -43,9 +43,6 @@ export abstract class BaseMetrics { // Do not use `??` operator to allow falling back to default when the // specified name is an empty string. this._name = config?.name || DEFAULT_NAME; - if (config?.meterProvider == null) { - this._logger.warn('No meter provider, using default'); - } const meterProvider = config?.meterProvider ?? metrics.getMeterProvider(); this._meter = meterProvider.getMeter(this._name, PACKAGE_VERSION); } diff --git a/plugins/node/instrumentation-kafkajs/.tav.yml b/plugins/node/instrumentation-kafkajs/.tav.yml new file mode 100644 index 0000000000..a9359dcd1b --- /dev/null +++ b/plugins/node/instrumentation-kafkajs/.tav.yml @@ -0,0 +1,5 @@ +kafkajs: + - versions: + include: ">=0.3.0 <3" + mode: latest-minors + commands: npm run test diff --git a/plugins/node/instrumentation-kafkajs/CHANGELOG.md b/plugins/node/instrumentation-kafkajs/CHANGELOG.md index 7748f36631..1ede724e21 100644 --- a/plugins/node/instrumentation-kafkajs/CHANGELOG.md +++ b/plugins/node/instrumentation-kafkajs/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [0.9.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-kafkajs-v0.8.0...instrumentation-kafkajs-v0.9.0) (2025-04-08) + + +### ⚠ BREAKING CHANGES + +* **instrumentation-kafkajs:** add .tav.yml and narrow support range to (>=0.3.0 <3) ([#2758](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/2758)) + +### Features + +* **instrumentation-kafkajs:** add .tav.yml and narrow support range to (>=0.3.0 <3) ([#2758](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/2758)) ([5837997](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/5837997dfb42a6ea6482999c0ca3e00cf68cdb8d)) +* **instrumentation-kafkajs:** update semantic conventions ([#2752](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/2752)) ([407f615](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/407f61591ba69a39a6908264379d4d98a48dbec4)) + ## [0.8.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-kafkajs-v0.7.1...instrumentation-kafkajs-v0.8.0) (2025-03-18) diff --git a/plugins/node/instrumentation-kafkajs/README.md b/plugins/node/instrumentation-kafkajs/README.md index a5f54ee2ee..6bf6185505 100644 --- a/plugins/node/instrumentation-kafkajs/README.md +++ b/plugins/node/instrumentation-kafkajs/README.md @@ -17,13 +17,15 @@ npm install --save @opentelemetry/instrumentation-kafkajs ### Supported versions -- [`kafkajs`](https://www.npmjs.com/package/kafkajs) versions `>=0.1.0 <3` +- [`kafkajs`](https://www.npmjs.com/package/kafkajs) versions `>=0.3.0 <3` ## Usage ```js const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node'); -const { KafkaJsInstrumentation } = require('@opentelemetry/instrumentation-kafkajs'); +const { + KafkaJsInstrumentation, +} = require('@opentelemetry/instrumentation-kafkajs'); const { registerInstrumentations } = require('@opentelemetry/instrumentation'); const provider = new NodeTracerProvider(); @@ -42,22 +44,51 @@ registerInstrumentations({ You can set the following: -| Options | Type | Description | -| ---------------------------- | -------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | -| `producerHook` | `KafkaProducerCustomAttributeFunction` | Function called before a producer message is sent. Allows for adding custom attributes to the span. | -| `consumerHook` | `KafkaConsumerCustomAttributeFunction` | Function called before a consumer message is processed. Allows for adding custom attributes to the span. | +| Options | Type | Description | +| -------------- | -------------------------------------- | -------------------------------------------------------------------------------------------------------- | +| `producerHook` | `KafkaProducerCustomAttributeFunction` | Function called before a producer message is sent. Allows for adding custom attributes to the span. | +| `consumerHook` | `KafkaConsumerCustomAttributeFunction` | Function called before a consumer message is processed. Allows for adding custom attributes to the span. | ## Semantic Conventions -This package uses `@opentelemetry/semantic-conventions` version `1.24+`, which implements Semantic Convention [Version 1.7.0](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.7.0/semantic_conventions/README.md) +This package uses `@opentelemetry/semantic-conventions` version `1.30+`, which implements Semantic Convention [Version 1.30.0](https://github.com/open-telemetry/semantic-conventions/blob/v1.30.0/docs/README.md) -Attributes collected: +### Spans Emitted -| Attribute | Short Description | -| -----------------------------| ----------------------------------------------------- | -| `messaging.system` | An identifier for the messaging system being used. | -| `messaging.destination` | The message destination name. | -| `messaging.operation` | A string identifying the kind of messaging operation. | +| KafkaJS Object | Action | Span Kind | Span Name | Operation Type / Name | +| -------------- | -------------------------- | --------- | -------------------------- | --------------------- | +| Consumer | `eachBatch` | Client | `poll ` | `receive` / `poll` | +| Consumer | `eachBatch`, `eachMessage` | Consumer | `process ` [1] | `process` / `process` | +| Producer | `send` | Producer | `send ` | `send` / `send` | + +**[1] `process `:** In the context of `eachBatch`, this span will be emitted for each message in the batch but the timing (start, end, duration) will reflect the timing of the batch. + +### Metrics Emitted + +| KafkaJS Object | Metric Name | Short Description | +| --------------------- | ------------------------------------- | ------------------------------------------------------------ | +| Consumer | `messaging.process.duration` | Duration of processing operation. [1] | +| Consumer | `messaging.client.consumed.messages` | Number of messages that were delivered to the application. | +| Consumer and Producer | `messaging.client.operation.duration` | Number of messages that were delivered to the application. | +| Producer | `messaging.client.sent.messages` | Number of messages producer attempted to send to the broker. | + +**[1] `messaging.process.duration`:** In the context of `eachBatch`, this metric will be emitted once for each message but the value reflects the duration of the entire batch. + +### Attributes Collected + +These attributes are added to both spans and metrics, where possible. + +| Attribute | Short Description | +| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `messaging.system` | An identifier for the messaging system being used (i.e. `"kafka"`). | +| `messaging.destination.name` | The message destination name. | +| `messaging.operation.type` | A string identifying the type of messaging operation. | +| `messaging.operation.name` | The system-specific name of the messaging operation. | +| `messaging.operation.name` | The system-specific name of the messaging operation. | +| `messaging.kafka.message.key` | A stringified value representing the key of the Kafka message (if present). | +| `messaging.kafka.message.tombstone` | A boolean that is true if the message is a tombstone. | +| `messaging.kafka.offset` | The offset of a record in the corresponding Kafka partition. | +| `messaging.destination.partition.id` | The identifier of the partition messages are sent to or received from, unique within the `messaging.destination.name`. **Note:** only available on producer spans. | ## Useful links diff --git a/plugins/node/instrumentation-kafkajs/package.json b/plugins/node/instrumentation-kafkajs/package.json index 2e3d170bf2..5e48db6192 100644 --- a/plugins/node/instrumentation-kafkajs/package.json +++ b/plugins/node/instrumentation-kafkajs/package.json @@ -1,12 +1,13 @@ { "name": "@opentelemetry/instrumentation-kafkajs", - "version": "0.8.0", + "version": "0.9.0", "description": "OpenTelemetry instrumentation for `kafkajs` messaging client for Apache Kafka", "main": "build/src/index.js", "types": "build/src/index.d.ts", "repository": "open-telemetry/opentelemetry-js-contrib", "scripts": { - "test": "mocha --require @opentelemetry/contrib-test-utils 'test/**/*.test.ts'", + "test": "nyc mocha --require @opentelemetry/contrib-test-utils 'test/**/*.test.ts'", + "test-all-versions": "tav", "tdd": "npm run test -- --watch-extensions ts --watch", "clean": "rimraf build/*", "lint": "eslint . --ext .ts", @@ -52,11 +53,12 @@ "nyc": "15.1.0", "rimraf": "5.0.10", "sinon": "15.2.0", + "test-all-versions": "6.1.0", "typescript": "5.0.4" }, "dependencies": { "@opentelemetry/instrumentation": "^0.200.0", - "@opentelemetry/semantic-conventions": "^1.27.0" + "@opentelemetry/semantic-conventions": "^1.30.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/instrumentation-kafkajs#readme" } diff --git a/plugins/node/instrumentation-kafkajs/src/instrumentation.ts b/plugins/node/instrumentation-kafkajs/src/instrumentation.ts index 1dacb4351c..4ea12bd502 100644 --- a/plugins/node/instrumentation-kafkajs/src/instrumentation.ts +++ b/plugins/node/instrumentation-kafkajs/src/instrumentation.ts @@ -15,50 +15,180 @@ */ import { - SpanKind, - Span, - SpanStatusCode, + Attributes, Context, - propagation, - Link, - trace, context, + Counter, + Histogram, + Link, + propagation, ROOT_CONTEXT, + Span, + SpanKind, + SpanStatusCode, + trace, } from '@opentelemetry/api'; import { - MESSAGINGOPERATIONVALUES_PROCESS, - MESSAGINGOPERATIONVALUES_RECEIVE, - SEMATTRS_MESSAGING_SYSTEM, - SEMATTRS_MESSAGING_DESTINATION, - SEMATTRS_MESSAGING_OPERATION, + InstrumentationBase, + InstrumentationNodeModuleDefinition, + isWrapped, + safeExecuteInTheMiddle, +} from '@opentelemetry/instrumentation'; +import { + ATTR_ERROR_TYPE, + ATTR_SERVER_ADDRESS, + ATTR_SERVER_PORT, + ERROR_TYPE_VALUE_OTHER, } from '@opentelemetry/semantic-conventions'; import type * as kafkaJs from 'kafkajs'; import type { + Consumer, + ConsumerRunConfig, EachBatchHandler, EachMessageHandler, + KafkaMessage, + Message, Producer, RecordMetadata, - Message, - ConsumerRunConfig, - KafkaMessage, - Consumer, } from 'kafkajs'; +import { EVENT_LISTENERS_SET } from './internal-types'; +import { bufferTextMapGetter } from './propagator'; +import { + ATTR_MESSAGING_BATCH_MESSAGE_COUNT, + ATTR_MESSAGING_DESTINATION_NAME, + ATTR_MESSAGING_DESTINATION_PARTITION_ID, + ATTR_MESSAGING_KAFKA_MESSAGE_KEY, + ATTR_MESSAGING_KAFKA_MESSAGE_TOMBSTONE, + ATTR_MESSAGING_KAFKA_OFFSET, + ATTR_MESSAGING_OPERATION_NAME, + ATTR_MESSAGING_OPERATION_TYPE, + ATTR_MESSAGING_SYSTEM, + MESSAGING_OPERATION_TYPE_VALUE_PROCESS, + MESSAGING_OPERATION_TYPE_VALUE_RECEIVE, + MESSAGING_OPERATION_TYPE_VALUE_SEND, + MESSAGING_SYSTEM_VALUE_KAFKA, + METRIC_MESSAGING_CLIENT_CONSUMED_MESSAGES, + METRIC_MESSAGING_CLIENT_OPERATION_DURATION, + METRIC_MESSAGING_CLIENT_SENT_MESSAGES, + METRIC_MESSAGING_PROCESS_DURATION, +} from './semconv'; import { KafkaJsInstrumentationConfig } from './types'; /** @knipignore */ import { PACKAGE_NAME, PACKAGE_VERSION } from './version'; -import { bufferTextMapGetter } from './propagator'; -import { - InstrumentationBase, - InstrumentationNodeModuleDefinition, - safeExecuteInTheMiddle, - isWrapped, -} from '@opentelemetry/instrumentation'; +interface ConsumerSpanOptions { + topic: string; + message: KafkaMessage | undefined; + operationType: string; + attributes: Attributes; + ctx?: Context | undefined; + link?: Link; +} +// This interface acts as a strict subset of the KafkaJS Consumer and +// Producer interfaces (just for the event we're needing) +interface KafkaEventEmitter { + on( + eventName: + | kafkaJs.ConsumerEvents['REQUEST'] + | kafkaJs.ProducerEvents['REQUEST'], + listener: (event: kafkaJs.RequestEvent) => void + ): void; + events: { + REQUEST: + | kafkaJs.ConsumerEvents['REQUEST'] + | kafkaJs.ProducerEvents['REQUEST']; + }; + [EVENT_LISTENERS_SET]?: boolean; +} + +interface StandardAttributes extends Attributes { + [ATTR_MESSAGING_SYSTEM]: string; + [ATTR_MESSAGING_OPERATION_NAME]: OP; + [ATTR_ERROR_TYPE]?: string; +} +interface TopicAttributes { + [ATTR_MESSAGING_DESTINATION_NAME]: string; + [ATTR_MESSAGING_DESTINATION_PARTITION_ID]?: string; +} + +interface ClientDurationAttributes + extends StandardAttributes, + Partial { + [ATTR_SERVER_ADDRESS]: string; + [ATTR_SERVER_PORT]: number; + [ATTR_MESSAGING_OPERATION_TYPE]?: string; +} +interface SentMessagesAttributes + extends StandardAttributes<'send'>, + TopicAttributes { + [ATTR_ERROR_TYPE]?: string; +} +type ConsumedMessagesAttributes = StandardAttributes<'receive' | 'process'>; +interface MessageProcessDurationAttributes + extends StandardAttributes<'process'>, + TopicAttributes { + [ATTR_MESSAGING_SYSTEM]: string; + [ATTR_MESSAGING_OPERATION_NAME]: 'process'; + [ATTR_ERROR_TYPE]?: string; +} +type RecordPendingMetric = (errorType?: string | undefined) => void; + +function prepareCounter( + meter: Counter, + value: number, + attributes: T +): RecordPendingMetric { + return (errorType?: string | undefined) => { + meter.add(value, { + ...attributes, + ...(errorType ? { [ATTR_ERROR_TYPE]: errorType } : {}), + }); + }; +} + +function prepareDurationHistogram( + meter: Histogram, + value: number, + attributes: T +): RecordPendingMetric { + return (errorType?: string | undefined) => { + meter.record((Date.now() - value) / 1000, { + ...attributes, + ...(errorType ? { [ATTR_ERROR_TYPE]: errorType } : {}), + }); + }; +} + +const HISTOGRAM_BUCKET_BOUNDARIES = [ + 0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1, 2.5, 5, 7.5, 10, +]; export class KafkaJsInstrumentation extends InstrumentationBase { + private _clientDuration!: Histogram; + private _sentMessages!: Counter; + private _consumedMessages!: Counter; + private _processDuration!: Histogram; + constructor(config: KafkaJsInstrumentationConfig = {}) { super(PACKAGE_NAME, PACKAGE_VERSION, config); } + override _updateMetricInstruments() { + this._clientDuration = this.meter.createHistogram( + METRIC_MESSAGING_CLIENT_OPERATION_DURATION, + { advice: { explicitBucketBoundaries: HISTOGRAM_BUCKET_BOUNDARIES } } + ); + this._sentMessages = this.meter.createCounter( + METRIC_MESSAGING_CLIENT_SENT_MESSAGES + ); + this._consumedMessages = this.meter.createCounter( + METRIC_MESSAGING_CLIENT_CONSUMED_MESSAGES + ); + this._processDuration = this.meter.createHistogram( + METRIC_MESSAGING_PROCESS_DURATION, + { advice: { explicitBucketBoundaries: HISTOGRAM_BUCKET_BOUNDARIES } } + ); + } + protected init() { const unpatch = (moduleExports: typeof kafkaJs) => { if (isWrapped(moduleExports?.Kafka?.prototype.producer)) { @@ -71,7 +201,7 @@ export class KafkaJsInstrumentation extends InstrumentationBase=0.1.0 <3'], + ['>=0.3.0 <3'], (moduleExports: typeof kafkaJs) => { unpatch(moduleExports); this._wrap( @@ -111,11 +241,36 @@ export class KafkaJsInstrumentation extends InstrumentationBase + ) { + const [address, port] = event.payload.broker.split(':'); + this._clientDuration.record(event.payload.duration / 1000, { + [ATTR_MESSAGING_SYSTEM]: MESSAGING_SYSTEM_VALUE_KAFKA, + [ATTR_MESSAGING_OPERATION_NAME]: `${event.payload.apiName}`, // potentially suffix with @v${event.payload.apiVersion}? + [ATTR_SERVER_ADDRESS]: address, + [ATTR_SERVER_PORT]: Number.parseInt(port, 10), + }); + } + private _getProducerPatch() { const instrumentation = this; return (original: kafkaJs.Kafka['producer']) => { @@ -143,6 +298,8 @@ export class KafkaJsInstrumentation extends InstrumentationBase { const payload = args[0]; // https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/messaging.md#topic-with-multiple-consumers - const receivingSpan = instrumentation._startConsumerSpan( - payload.batch.topic, - undefined, - MESSAGINGOPERATIONVALUES_RECEIVE, - ROOT_CONTEXT - ); + const receivingSpan = instrumentation._startConsumerSpan({ + topic: payload.batch.topic, + message: undefined, + operationType: MESSAGING_OPERATION_TYPE_VALUE_RECEIVE, + ctx: ROOT_CONTEXT, + attributes: { + [ATTR_MESSAGING_BATCH_MESSAGE_COUNT]: payload.batch.messages.length, + [ATTR_MESSAGING_DESTINATION_PARTITION_ID]: String( + payload.batch.partition + ), + }, + }); return context.with( trace.setSpan(context.active(), receivingSpan), () => { - const spans = payload.batch.messages.map( - (message: KafkaMessage) => { - const propagatedContext: Context = propagation.extract( - ROOT_CONTEXT, - message.headers, - bufferTextMapGetter - ); - const spanContext = trace - .getSpan(propagatedContext) - ?.spanContext(); - let origSpanLink: Link | undefined; - if (spanContext) { - origSpanLink = { - context: spanContext, - }; + const startTime = Date.now(); + const spans: Span[] = []; + const pendingMetrics: RecordPendingMetric[] = [ + prepareCounter( + instrumentation._consumedMessages, + payload.batch.messages.length, + { + [ATTR_MESSAGING_SYSTEM]: MESSAGING_SYSTEM_VALUE_KAFKA, + [ATTR_MESSAGING_OPERATION_NAME]: 'process', + [ATTR_MESSAGING_DESTINATION_NAME]: payload.batch.topic, + [ATTR_MESSAGING_DESTINATION_PARTITION_ID]: String( + payload.batch.partition + ), } - return instrumentation._startConsumerSpan( - payload.batch.topic, - message, - MESSAGINGOPERATIONVALUES_PROCESS, - undefined, - origSpanLink - ); + ), + ]; + payload.batch.messages.forEach(message => { + const propagatedContext: Context = propagation.extract( + ROOT_CONTEXT, + message.headers, + bufferTextMapGetter + ); + const spanContext = trace + .getSpan(propagatedContext) + ?.spanContext(); + let origSpanLink: Link | undefined; + if (spanContext) { + origSpanLink = { + context: spanContext, + }; } - ); + spans.push( + instrumentation._startConsumerSpan({ + topic: payload.batch.topic, + message, + operationType: MESSAGING_OPERATION_TYPE_VALUE_PROCESS, + link: origSpanLink, + attributes: { + [ATTR_MESSAGING_DESTINATION_PARTITION_ID]: String( + payload.batch.partition + ), + }, + }) + ); + pendingMetrics.push( + prepareDurationHistogram( + instrumentation._processDuration, + startTime, + { + [ATTR_MESSAGING_SYSTEM]: MESSAGING_SYSTEM_VALUE_KAFKA, + [ATTR_MESSAGING_OPERATION_NAME]: 'process', + [ATTR_MESSAGING_DESTINATION_NAME]: payload.batch.topic, + [ATTR_MESSAGING_DESTINATION_PARTITION_ID]: String( + payload.batch.partition + ), + } + ) + ); + }); const batchMessagePromise: Promise = original!.apply( this, args @@ -262,6 +491,7 @@ export class KafkaJsInstrumentation extends InstrumentationBase { const batch = args[0]; const messages = batch.topicMessages || []; - const spans: Span[] = messages - .map(topicMessage => - topicMessage.messages.map(message => - instrumentation._startProducerSpan(topicMessage.topic, message) - ) - ) - .reduce((acc, val) => acc.concat(val), []); + const spans: Span[] = []; + const pendingMetrics: RecordPendingMetric[] = []; + + messages.forEach(topicMessage => { + topicMessage.messages.forEach(message => { + spans.push( + instrumentation._startProducerSpan(topicMessage.topic, message) + ); + pendingMetrics.push( + prepareCounter(instrumentation._sentMessages, 1, { + [ATTR_MESSAGING_SYSTEM]: MESSAGING_SYSTEM_VALUE_KAFKA, + [ATTR_MESSAGING_OPERATION_NAME]: 'send', + [ATTR_MESSAGING_DESTINATION_NAME]: topicMessage.topic, + ...(message.partition !== undefined + ? { + [ATTR_MESSAGING_DESTINATION_PARTITION_ID]: String( + message.partition + ), + } + : {}), + }) + ); + }); + }); const origSendResult: Promise = original.apply( this, args ); - return instrumentation._endSpansOnPromise(spans, origSendResult); + return instrumentation._endSpansOnPromise( + spans, + pendingMetrics, + origSendResult + ); }; }; } @@ -308,35 +559,64 @@ export class KafkaJsInstrumentation extends InstrumentationBase + prepareCounter(instrumentation._sentMessages, 1, { + [ATTR_MESSAGING_SYSTEM]: MESSAGING_SYSTEM_VALUE_KAFKA, + [ATTR_MESSAGING_OPERATION_NAME]: 'send', + [ATTR_MESSAGING_DESTINATION_NAME]: record.topic, + ...(m.partition !== undefined + ? { + [ATTR_MESSAGING_DESTINATION_PARTITION_ID]: String( + m.partition + ), + } + : {}), + }) + ); const origSendResult: Promise = original.apply( this, args ); - return instrumentation._endSpansOnPromise(spans, origSendResult); + return instrumentation._endSpansOnPromise( + spans, + pendingMetrics, + origSendResult + ); }; }; } private _endSpansOnPromise( spans: Span[], + pendingMetrics: RecordPendingMetric[], sendPromise: Promise ): Promise { return Promise.resolve(sendPromise) + .then(result => { + pendingMetrics.forEach(m => m()); + return result; + }) .catch(reason => { - let errorMessage: string; - if (typeof reason === 'string') errorMessage = reason; - else if ( + let errorMessage: string | undefined; + let errorType: string = ERROR_TYPE_VALUE_OTHER; + if (typeof reason === 'string' || reason === undefined) { + errorMessage = reason; + } else if ( typeof reason === 'object' && Object.prototype.hasOwnProperty.call(reason, 'message') - ) + ) { errorMessage = reason.message; + errorType = reason.constructor.name; + } + pendingMetrics.forEach(m => m(errorType)); - spans.forEach(span => + spans.forEach(span => { + span.setAttribute(ATTR_ERROR_TYPE, errorType); span.setStatus({ code: SpanStatusCode.ERROR, message: errorMessage, - }) - ); + }); + }); throw reason; }) @@ -345,25 +625,42 @@ export class KafkaJsInstrumentation extends InstrumentationBase; + attributes: Attributes; + }[] + > +) { + assert.strictEqual(errors.length, 0); + const { metrics } = resourceMetrics.scopeMetrics[0]; + assert.strictEqual( + Object.keys(expected).length, + metrics.length, + 'A different number of metrics were found than expected' + ); + Object.entries(expected).forEach(([name, values]) => { + const match = metrics.find(metric => metric.descriptor.name === name); + assert.ok(match, `metric ${name} not found`); + + if (match.dataPointType === DataPointType.HISTOGRAM) { + assert.deepStrictEqual( + match.dataPoints.map(d => d.value.count), + values.map(v => v.count), + `${name} datapoints do not have the same count` + ); + values.forEach(({ buckets }, i) => { + if (buckets) { + const { boundaries, counts } = match.dataPoints[i].value.buckets; + const actualBuckets = counts.reduce((acc, n, j) => { + if (n > 0) { + acc[boundaries[j]] = n; + } + return acc; + }, {} as Record); + assert.deepStrictEqual(actualBuckets, buckets); + } + }); + } else { + assert.deepStrictEqual( + match.dataPoints.map(d => d.value), + values.map(v => v.value), + `${name} datapoint values do not match` + ); + } + assert.deepStrictEqual( + match.dataPoints.map(d => d.attributes), + values.map(v => v.attributes) + ); + }); +} describe('instrumentation-kafkajs', () => { propagation.setGlobalPropagator( @@ -107,8 +181,10 @@ describe('instrumentation-kafkajs', () => { }; }; + let metricReader: TestMetricReader; beforeEach(() => { messagesSent = []; + metricReader = initMeterProvider(instrumentation); }); describe('producer', () => { @@ -127,21 +203,29 @@ describe('instrumentation-kafkajs', () => { }; describe('successful send', () => { - beforeEach(async () => { - patchProducerSend(async (): Promise => { - return [ - { - topicName: 'topic-name-1', - partition: 0, - errorCode: 123, - offset: '18', - timestamp: '123456', - }, - ]; - }); + const defaultRecordMetadata = [ + { + topicName: 'topic-name-1', + partition: 0, + errorCode: 123, + offset: '18', + timestamp: '123456', + }, + ]; + function initializeProducer( + recordMetadata: RecordMetadata[] = defaultRecordMetadata + ) { + patchProducerSend( + async (): Promise => recordMetadata + ); instrumentation.disable(); instrumentation.enable(); - producer = kafka.producer(); + producer = kafka.producer({ + createPartitioner: kafkajs.Partitioners.LegacyPartitioner, + }); + } + beforeEach(() => { + initializeProducer(); }); it('simple send create span with right attributes, pass return value correctly and propagate context', async () => { @@ -149,6 +233,8 @@ describe('instrumentation-kafkajs', () => { topic: 'topic-name-1', messages: [ { + partition: 42, + key: 'message-key-0', value: 'testing message content', }, ], @@ -161,29 +247,109 @@ describe('instrumentation-kafkajs', () => { assert.strictEqual(spans.length, 1); const span = spans[0]; assert.strictEqual(span.kind, SpanKind.PRODUCER); - assert.strictEqual(span.name, 'topic-name-1'); + assert.strictEqual(span.name, 'send topic-name-1'); assert.strictEqual(span.status.code, SpanStatusCode.UNSET); - assert.strictEqual(span.attributes[SEMATTRS_MESSAGING_SYSTEM], 'kafka'); + assert.strictEqual(span.attributes[ATTR_MESSAGING_SYSTEM], 'kafka'); assert.strictEqual( - span.attributes[SEMATTRS_MESSAGING_DESTINATION], + span.attributes[ATTR_MESSAGING_DESTINATION_NAME], 'topic-name-1' ); + assert.strictEqual( + span.attributes[ATTR_MESSAGING_DESTINATION_PARTITION_ID], + '42' + ); + assert.strictEqual( + span.attributes[ATTR_MESSAGING_KAFKA_MESSAGE_TOMBSTONE], + undefined + ); + assert.strictEqual( + span.attributes[ATTR_MESSAGING_KAFKA_MESSAGE_KEY], + 'message-key-0' + ); assert.strictEqual(messagesSent.length, 1); expectKafkaHeadersToMatchSpanContext( messagesSent[0], span as ReadableSpan ); + + assertMetricCollection(await metricReader.collect(), { + [METRIC_MESSAGING_CLIENT_SENT_MESSAGES]: [ + { + value: 1, + attributes: { + [ATTR_MESSAGING_SYSTEM]: MESSAGING_SYSTEM_VALUE_KAFKA, + [ATTR_MESSAGING_DESTINATION_NAME]: 'topic-name-1', + [ATTR_MESSAGING_DESTINATION_PARTITION_ID]: '42', + [ATTR_MESSAGING_OPERATION_NAME]: 'send', + }, + }, + ], + }); + }); + + it('simple send create span with tombstone attribute', async () => { + await producer.send({ + topic: 'topic-name-1', + messages: [ + { + partition: 42, + key: 'message-key-1', + value: null, + }, + ], + }); + + const spans = getTestSpans(); + assert.strictEqual(spans.length, 1); + const span = spans[0]; + assert.strictEqual(span.kind, SpanKind.PRODUCER); + assert.strictEqual(span.name, 'send topic-name-1'); + assert.strictEqual( + span.attributes[ATTR_MESSAGING_KAFKA_MESSAGE_TOMBSTONE], + true + ); + assertMetricCollection(await metricReader.collect(), { + [METRIC_MESSAGING_CLIENT_SENT_MESSAGES]: [ + { + value: 1, + attributes: { + [ATTR_MESSAGING_SYSTEM]: MESSAGING_SYSTEM_VALUE_KAFKA, + [ATTR_MESSAGING_DESTINATION_NAME]: 'topic-name-1', + [ATTR_MESSAGING_OPERATION_NAME]: 'send', + [ATTR_MESSAGING_DESTINATION_PARTITION_ID]: '42', + }, + }, + ], + }); }); it('send two messages', async () => { + initializeProducer([ + { + topicName: 'topic-name-1', + partition: 0, + errorCode: 123, + offset: '18', + timestamp: '123456', + }, + { + topicName: 'topic-name-1', + partition: 0, + errorCode: 123, + offset: '19', + timestamp: '123456', + }, + ]); await producer.send({ topic: 'topic-name-1', messages: [ { + partition: 0, value: 'message1', }, { + partition: 0, value: 'message2', }, ], @@ -191,8 +357,8 @@ describe('instrumentation-kafkajs', () => { const spans = getTestSpans(); assert.strictEqual(spans.length, 2); - assert.strictEqual(spans[0].name, 'topic-name-1'); - assert.strictEqual(spans[1].name, 'topic-name-1'); + assert.strictEqual(spans[0].name, 'send topic-name-1'); + assert.strictEqual(spans[1].name, 'send topic-name-1'); assert.strictEqual(messagesSent.length, 2); expectKafkaHeadersToMatchSpanContext( @@ -203,9 +369,45 @@ describe('instrumentation-kafkajs', () => { messagesSent[1], spans[1] as ReadableSpan ); + assertMetricCollection(await metricReader.collect(), { + [METRIC_MESSAGING_CLIENT_SENT_MESSAGES]: [ + { + value: 2, + attributes: { + [ATTR_MESSAGING_SYSTEM]: MESSAGING_SYSTEM_VALUE_KAFKA, + [ATTR_MESSAGING_DESTINATION_NAME]: 'topic-name-1', + [ATTR_MESSAGING_DESTINATION_PARTITION_ID]: '0', + [ATTR_MESSAGING_OPERATION_NAME]: 'send', + }, + }, + ], + }); }); it('send batch', async () => { + initializeProducer([ + { + topicName: 'topic-name-1', + partition: 0, + errorCode: 123, + offset: '18', + timestamp: '123456', + }, + { + topicName: 'topic-name-1', + partition: 0, + errorCode: 123, + offset: '19', + timestamp: '123456', + }, + { + topicName: 'topic-name-2', + partition: 1, + errorCode: 123, + offset: '19', + timestamp: '123456', + }, + ]); await producer.sendBatch({ topicMessages: [ { @@ -223,6 +425,7 @@ describe('instrumentation-kafkajs', () => { topic: 'topic-name-2', messages: [ { + partition: 1, value: 'message2-1', }, ], @@ -232,9 +435,9 @@ describe('instrumentation-kafkajs', () => { const spans = getTestSpans(); assert.strictEqual(spans.length, 3); - assert.strictEqual(spans[0].name, 'topic-name-1'); - assert.strictEqual(spans[1].name, 'topic-name-1'); - assert.strictEqual(spans[2].name, 'topic-name-2'); + assert.strictEqual(spans[0].name, 'send topic-name-1'); + assert.strictEqual(spans[1].name, 'send topic-name-1'); + assert.strictEqual(spans[2].name, 'send topic-name-2'); assert.strictEqual(messagesSent.length, 3); for (let i = 0; i < 3; i++) { @@ -243,6 +446,27 @@ describe('instrumentation-kafkajs', () => { spans[i] as ReadableSpan ); } + assertMetricCollection(await metricReader.collect(), { + [METRIC_MESSAGING_CLIENT_SENT_MESSAGES]: [ + { + value: 2, + attributes: { + [ATTR_MESSAGING_SYSTEM]: MESSAGING_SYSTEM_VALUE_KAFKA, + [ATTR_MESSAGING_DESTINATION_NAME]: 'topic-name-1', + [ATTR_MESSAGING_OPERATION_NAME]: 'send', + }, + }, + { + value: 1, + attributes: { + [ATTR_MESSAGING_SYSTEM]: MESSAGING_SYSTEM_VALUE_KAFKA, + [ATTR_MESSAGING_DESTINATION_NAME]: 'topic-name-2', + [ATTR_MESSAGING_DESTINATION_PARTITION_ID]: '1', + [ATTR_MESSAGING_OPERATION_NAME]: 'send', + }, + }, + ], + }); }); }); @@ -255,7 +479,9 @@ describe('instrumentation-kafkajs', () => { }); instrumentation.disable(); instrumentation.enable(); - producer = kafka.producer(); + producer = kafka.producer({ + createPartitioner: kafkajs.Partitioners.LegacyPartitioner, + }); }); it('error in send create failed span', async () => { @@ -278,6 +504,19 @@ describe('instrumentation-kafkajs', () => { span.status.message, 'error thrown from kafka client send' ); + assertMetricCollection(await metricReader.collect(), { + [METRIC_MESSAGING_CLIENT_SENT_MESSAGES]: [ + { + value: 1, + attributes: { + [ATTR_MESSAGING_SYSTEM]: MESSAGING_SYSTEM_VALUE_KAFKA, + [ATTR_MESSAGING_DESTINATION_NAME]: 'topic-name-1', + [ATTR_MESSAGING_OPERATION_NAME]: 'send', + [ATTR_ERROR_TYPE]: 'Error', + }, + }, + ], + }); }); it('error in send with multiple messages create failed spans', async () => { @@ -304,6 +543,19 @@ describe('instrumentation-kafkajs', () => { 'error thrown from kafka client send' ); }); + assertMetricCollection(await metricReader.collect(), { + [METRIC_MESSAGING_CLIENT_SENT_MESSAGES]: [ + { + value: 2, + attributes: { + [ATTR_MESSAGING_SYSTEM]: MESSAGING_SYSTEM_VALUE_KAFKA, + [ATTR_MESSAGING_DESTINATION_NAME]: 'topic-name-1', + [ATTR_MESSAGING_OPERATION_NAME]: 'send', + [ATTR_ERROR_TYPE]: 'Error', + }, + }, + ], + }); }); it('error in sendBatch should set error to all spans', async () => { @@ -342,6 +594,28 @@ describe('instrumentation-kafkajs', () => { 'error thrown from kafka client send' ); }); + assertMetricCollection(await metricReader.collect(), { + [METRIC_MESSAGING_CLIENT_SENT_MESSAGES]: [ + { + value: 2, + attributes: { + [ATTR_MESSAGING_SYSTEM]: MESSAGING_SYSTEM_VALUE_KAFKA, + [ATTR_MESSAGING_DESTINATION_NAME]: 'topic-name-1', + [ATTR_MESSAGING_OPERATION_NAME]: 'send', + [ATTR_ERROR_TYPE]: 'Error', + }, + }, + { + value: 1, + attributes: { + [ATTR_MESSAGING_SYSTEM]: MESSAGING_SYSTEM_VALUE_KAFKA, + [ATTR_MESSAGING_DESTINATION_NAME]: 'topic-name-2', + [ATTR_MESSAGING_OPERATION_NAME]: 'send', + [ATTR_ERROR_TYPE]: 'Error', + }, + }, + ], + }); }); }); @@ -360,7 +634,9 @@ describe('instrumentation-kafkajs', () => { instrumentation.disable(); instrumentation.setConfig(config); instrumentation.enable(); - producer = kafka.producer(); + producer = kafka.producer({ + createPartitioner: kafkajs.Partitioners.LegacyPartitioner, + }); }); it('producer hook add span attribute with value from message', async () => { @@ -395,7 +671,9 @@ describe('instrumentation-kafkajs', () => { instrumentation.disable(); instrumentation.setConfig(config); instrumentation.enable(); - producer = kafka.producer(); + producer = kafka.producer({ + createPartitioner: kafkajs.Partitioners.LegacyPartitioner, + }); }); it('producer hook add span attribute with value from message', async () => { @@ -417,22 +695,34 @@ describe('instrumentation-kafkajs', () => { }); describe('consumer', () => { - const createKafkaMessage = (offset: string): KafkaMessage => { + interface CreateMessageParams { + offset: string; + key?: string | null; + tombstone?: boolean; + } + + const createKafkaMessage = ({ + offset, + key = 'message-key', + tombstone = false, + }: CreateMessageParams): KafkaMessage => { return { - key: Buffer.from('message-key', 'utf8'), - value: Buffer.from('message content', 'utf8'), + key: typeof key === 'string' ? Buffer.from(key, 'utf8') : key, + value: tombstone ? null : Buffer.from('message content', 'utf8'), timestamp: '1234', size: 10, attributes: 1, - offset: offset, + offset, }; }; - const createEachMessagePayload = (): EachMessagePayload => { + const createEachMessagePayload = ( + params: Partial = {} + ): EachMessagePayload => { return { topic: 'topic-name-1', - partition: 0, - message: createKafkaMessage('123'), + partition: 1, + message: createKafkaMessage({ offset: '123', ...params }), heartbeat: async () => {}, pause: () => () => {}, }; @@ -444,7 +734,10 @@ describe('instrumentation-kafkajs', () => { topic: 'topic-name-1', partition: 1234, highWatermark: '4567', - messages: [createKafkaMessage('124'), createKafkaMessage('125')], + messages: [ + createKafkaMessage({ offset: '124' }), + createKafkaMessage({ offset: '125' }), + ], }, } as EachBatchPayload; }; @@ -468,25 +761,104 @@ describe('instrumentation-kafkajs', () => { _payload: EachMessagePayload ): Promise => {}, }); - const payload: EachMessagePayload = createEachMessagePayload(); + const payload = createEachMessagePayload(); await runConfig?.eachMessage!(payload); const spans = getTestSpans(); assert.strictEqual(spans.length, 1); const span = spans[0]; - assert.strictEqual(span.name, 'topic-name-1'); + assert.strictEqual(span.name, 'process topic-name-1'); assert.strictEqual(span.parentSpanContext?.spanId, undefined); assert.strictEqual(span.kind, SpanKind.CONSUMER); assert.strictEqual(span.status.code, SpanStatusCode.UNSET); - assert.strictEqual(span.attributes[SEMATTRS_MESSAGING_SYSTEM], 'kafka'); + assert.strictEqual(span.attributes[ATTR_MESSAGING_SYSTEM], 'kafka'); assert.strictEqual( - span.attributes[SEMATTRS_MESSAGING_DESTINATION], + span.attributes[ATTR_MESSAGING_DESTINATION_NAME], 'topic-name-1' ); assert.strictEqual( - span.attributes[SEMATTRS_MESSAGING_OPERATION], + span.attributes[ATTR_MESSAGING_OPERATION_TYPE], 'process' ); + assert.strictEqual( + span.attributes[ATTR_MESSAGING_DESTINATION_PARTITION_ID], + '1' + ); + assert.strictEqual( + span.attributes[ATTR_MESSAGING_KAFKA_MESSAGE_KEY], + 'message-key' + ); + assert.strictEqual( + span.attributes[ATTR_MESSAGING_KAFKA_MESSAGE_TOMBSTONE], + undefined + ); + assert.strictEqual(span.attributes[ATTR_MESSAGING_KAFKA_OFFSET], '123'); + assertMetricCollection(await metricReader.collect(), { + [METRIC_MESSAGING_PROCESS_DURATION]: [ + { + count: 1, + attributes: { + [ATTR_MESSAGING_SYSTEM]: MESSAGING_SYSTEM_VALUE_KAFKA, + [ATTR_MESSAGING_DESTINATION_NAME]: 'topic-name-1', + [ATTR_MESSAGING_DESTINATION_PARTITION_ID]: '1', + [ATTR_MESSAGING_OPERATION_NAME]: 'process', + }, + }, + ], + [METRIC_MESSAGING_CLIENT_CONSUMED_MESSAGES]: [ + { + value: 1, + attributes: { + [ATTR_MESSAGING_SYSTEM]: MESSAGING_SYSTEM_VALUE_KAFKA, + [ATTR_MESSAGING_DESTINATION_NAME]: 'topic-name-1', + [ATTR_MESSAGING_DESTINATION_PARTITION_ID]: '1', + [ATTR_MESSAGING_OPERATION_NAME]: 'process', + }, + }, + ], + }); + }); + + it('consume eachMessage tombstone', async () => { + consumer.run({ + eachMessage: async ( + _payload: EachMessagePayload + ): Promise => {}, + }); + const payload = createEachMessagePayload({ tombstone: true }); + await runConfig?.eachMessage!(payload); + + const spans = getTestSpans(); + assert.strictEqual(spans.length, 1); + const span = spans[0]; + assert.strictEqual(span.name, 'process topic-name-1'); + assert.strictEqual( + span.attributes[ATTR_MESSAGING_KAFKA_MESSAGE_KEY], + 'message-key' + ); + assert.strictEqual( + span.attributes[ATTR_MESSAGING_KAFKA_MESSAGE_TOMBSTONE], + true + ); + }); + + it('consume eachMessage with null key', async () => { + consumer.run({ + eachMessage: async ( + _payload: EachMessagePayload + ): Promise => {}, + }); + const payload = createEachMessagePayload({ key: null }); + await runConfig?.eachMessage!(payload); + + const spans = getTestSpans(); + assert.strictEqual(spans.length, 1); + const span = spans[0]; + assert.strictEqual(span.name, 'process topic-name-1'); + assert.strictEqual( + span.attributes[ATTR_MESSAGING_KAFKA_MESSAGE_KEY], + undefined + ); }); it('consumer eachMessage with non promise return value', async () => { @@ -607,6 +979,32 @@ describe('instrumentation-kafkajs', () => { span.status.message, 'error thrown from eachMessage callback' ); + assertMetricCollection(await metricReader.collect(), { + [METRIC_MESSAGING_PROCESS_DURATION]: [ + { + count: 1, + attributes: { + [ATTR_MESSAGING_SYSTEM]: MESSAGING_SYSTEM_VALUE_KAFKA, + [ATTR_MESSAGING_DESTINATION_NAME]: 'topic-name-1', + [ATTR_MESSAGING_DESTINATION_PARTITION_ID]: '1', + [ATTR_MESSAGING_OPERATION_NAME]: 'process', + [ATTR_ERROR_TYPE]: 'Error', + }, + }, + ], + [METRIC_MESSAGING_CLIENT_CONSUMED_MESSAGES]: [ + { + value: 1, + attributes: { + [ATTR_MESSAGING_SYSTEM]: MESSAGING_SYSTEM_VALUE_KAFKA, + [ATTR_MESSAGING_DESTINATION_NAME]: 'topic-name-1', + [ATTR_MESSAGING_DESTINATION_PARTITION_ID]: '1', + [ATTR_MESSAGING_OPERATION_NAME]: 'process', + [ATTR_ERROR_TYPE]: 'Error', + }, + }, + ], + }); }); it('throwing object with no message', async () => { @@ -633,6 +1031,32 @@ describe('instrumentation-kafkajs', () => { const span = spans[0]; assert.strictEqual(span.status.code, SpanStatusCode.ERROR); assert.strictEqual(span.status.message, undefined); + assertMetricCollection(await metricReader.collect(), { + [METRIC_MESSAGING_PROCESS_DURATION]: [ + { + count: 1, + attributes: { + [ATTR_MESSAGING_SYSTEM]: MESSAGING_SYSTEM_VALUE_KAFKA, + [ATTR_MESSAGING_DESTINATION_NAME]: 'topic-name-1', + [ATTR_MESSAGING_DESTINATION_PARTITION_ID]: '1', + [ATTR_MESSAGING_OPERATION_NAME]: 'process', + [ATTR_ERROR_TYPE]: '_OTHER', + }, + }, + ], + [METRIC_MESSAGING_CLIENT_CONSUMED_MESSAGES]: [ + { + value: 1, + attributes: { + [ATTR_MESSAGING_SYSTEM]: MESSAGING_SYSTEM_VALUE_KAFKA, + [ATTR_MESSAGING_DESTINATION_NAME]: 'topic-name-1', + [ATTR_MESSAGING_DESTINATION_PARTITION_ID]: '1', + [ATTR_MESSAGING_OPERATION_NAME]: 'process', + [ATTR_ERROR_TYPE]: '_OTHER', + }, + }, + ], + }); }); it('throwing non object', async () => { @@ -656,6 +1080,32 @@ describe('instrumentation-kafkajs', () => { const span = spans[0]; assert.strictEqual(span.status.code, SpanStatusCode.ERROR); assert.strictEqual(span.status.message, undefined); + assertMetricCollection(await metricReader.collect(), { + [METRIC_MESSAGING_PROCESS_DURATION]: [ + { + count: 1, + attributes: { + [ATTR_MESSAGING_SYSTEM]: MESSAGING_SYSTEM_VALUE_KAFKA, + [ATTR_MESSAGING_DESTINATION_NAME]: 'topic-name-1', + [ATTR_MESSAGING_DESTINATION_PARTITION_ID]: '1', + [ATTR_MESSAGING_OPERATION_NAME]: 'process', + [ATTR_ERROR_TYPE]: '_OTHER', + }, + }, + ], + [METRIC_MESSAGING_CLIENT_CONSUMED_MESSAGES]: [ + { + value: 1, + attributes: { + [ATTR_MESSAGING_SYSTEM]: MESSAGING_SYSTEM_VALUE_KAFKA, + [ATTR_MESSAGING_DESTINATION_NAME]: 'topic-name-1', + [ATTR_MESSAGING_DESTINATION_PARTITION_ID]: '1', + [ATTR_MESSAGING_OPERATION_NAME]: 'process', + [ATTR_ERROR_TYPE]: '_OTHER', + }, + }, + ], + }); }); }); @@ -678,32 +1128,40 @@ describe('instrumentation-kafkajs', () => { const spans = getTestSpans(); assert.strictEqual(spans.length, 3); spans.forEach(span => { - assert.strictEqual(span.name, 'topic-name-1'); assert.strictEqual(span.status.code, SpanStatusCode.UNSET); + assert.strictEqual(span.attributes[ATTR_MESSAGING_SYSTEM], 'kafka'); assert.strictEqual( - span.attributes[SEMATTRS_MESSAGING_SYSTEM], - 'kafka' - ); - assert.strictEqual( - span.attributes[SEMATTRS_MESSAGING_DESTINATION], + span.attributes[ATTR_MESSAGING_DESTINATION_NAME], 'topic-name-1' ); }); const [recvSpan, msg1Span, msg2Span] = spans; + assert.strictEqual(recvSpan.kind, SpanKind.CLIENT); + assert.strictEqual(recvSpan.name, 'poll topic-name-1'); assert.strictEqual(recvSpan.parentSpanContext?.spanId, undefined); assert.strictEqual( - recvSpan.attributes[SEMATTRS_MESSAGING_OPERATION], + recvSpan.attributes[ATTR_MESSAGING_OPERATION_TYPE], 'receive' ); + assert.strictEqual( + recvSpan.attributes[ATTR_MESSAGING_OPERATION_NAME], + 'poll' + ); + assert.strictEqual(msg1Span.kind, SpanKind.CONSUMER); + assert.strictEqual(msg1Span.name, 'process topic-name-1'); assert.strictEqual( msg1Span.parentSpanContext?.spanId, recvSpan.spanContext().spanId ); assert.strictEqual( - msg1Span.attributes[SEMATTRS_MESSAGING_OPERATION], + msg1Span.attributes[ATTR_MESSAGING_OPERATION_TYPE], + 'process' + ); + assert.strictEqual( + msg1Span.attributes[ATTR_MESSAGING_OPERATION_NAME], 'process' ); @@ -712,9 +1170,37 @@ describe('instrumentation-kafkajs', () => { recvSpan.spanContext().spanId ); assert.strictEqual( - msg2Span.attributes[SEMATTRS_MESSAGING_OPERATION], + msg2Span.attributes[ATTR_MESSAGING_OPERATION_TYPE], 'process' ); + assert.strictEqual( + msg2Span.attributes[ATTR_MESSAGING_OPERATION_NAME], + 'process' + ); + assertMetricCollection(await metricReader.collect(), { + [METRIC_MESSAGING_PROCESS_DURATION]: [ + { + count: 2, + attributes: { + [ATTR_MESSAGING_SYSTEM]: MESSAGING_SYSTEM_VALUE_KAFKA, + [ATTR_MESSAGING_DESTINATION_NAME]: 'topic-name-1', + [ATTR_MESSAGING_DESTINATION_PARTITION_ID]: '1234', + [ATTR_MESSAGING_OPERATION_NAME]: 'process', + }, + }, + ], + [METRIC_MESSAGING_CLIENT_CONSUMED_MESSAGES]: [ + { + value: 2, + attributes: { + [ATTR_MESSAGING_SYSTEM]: MESSAGING_SYSTEM_VALUE_KAFKA, + [ATTR_MESSAGING_DESTINATION_NAME]: 'topic-name-1', + [ATTR_MESSAGING_DESTINATION_PARTITION_ID]: '1234', + [ATTR_MESSAGING_OPERATION_NAME]: 'process', + }, + }, + ], + }); }); it('consumer eachBatch with non promise return value', async () => { @@ -741,7 +1227,9 @@ describe('instrumentation-kafkajs', () => { storeRunConfig(); instrumentation.disable(); instrumentation.enable(); - producer = kafka.producer(); + producer = kafka.producer({ + createPartitioner: kafkajs.Partitioners.LegacyPartitioner, + }); consumer = kafka.consumer({ groupId: 'testing-group-id' }); }); @@ -868,6 +1356,39 @@ describe('instrumentation-kafkajs', () => { ); }); }); + describe('client duration metric', () => { + it('records the metric', async () => { + instrumentation['_recordClientDurationMetric']({ + payload: { + broker: 'kafka.host:4789', + duration: 250, + apiName: 'some-operation', + apiKey: 123, + apiVersion: 1, + clientId: 'client-id', + correlationId: 456, + createdAt: Date.now(), + pendingDuration: 0, + sentAt: Date.now(), + size: 1024, + }, + }); + assertMetricCollection(await metricReader.collect(), { + [METRIC_MESSAGING_CLIENT_OPERATION_DURATION]: [ + { + count: 1, + buckets: { '0.25': 1 }, + attributes: { + [ATTR_MESSAGING_SYSTEM]: MESSAGING_SYSTEM_VALUE_KAFKA, + [ATTR_MESSAGING_OPERATION_NAME]: 'some-operation', + [ATTR_SERVER_ADDRESS]: 'kafka.host', + [ATTR_SERVER_PORT]: 4789, + }, + }, + ], + }); + }); + }); describe('bufferTextMapGetter', () => { it('is possible to retrieve keys case insensitively', () => { @@ -881,5 +1402,11 @@ describe('instrumentation-kafkajs', () => { '123' ); }); + it('exposes a keys method', () => { + assert.deepStrictEqual(bufferTextMapGetter.keys({ a: 1, b: 2 }), [ + 'a', + 'b', + ]); + }); }); }); diff --git a/plugins/node/instrumentation-tedious/tsconfig.json b/plugins/node/instrumentation-tedious/tsconfig.json index 403245c3ac..28be80d266 100644 --- a/plugins/node/instrumentation-tedious/tsconfig.json +++ b/plugins/node/instrumentation-tedious/tsconfig.json @@ -2,12 +2,7 @@ "extends": "../../../tsconfig.base", "compilerOptions": { "rootDir": ".", - "outDir": "build", - // When testing with tedious@18, skipLibCheck:true is needed to avoid - // checking its types. They require AggregateError that is only available - // with `"target": "es2022"`, which, IIUC we don't want with our regular TS - // v4 build for release. - "skipLibCheck": true + "outDir": "build" }, "include": [ "src/**/*.ts", diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/.tav.yml b/plugins/node/opentelemetry-instrumentation-aws-sdk/.tav.yml index 31ec962f35..0ec6e8b36b 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-sdk/.tav.yml +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/.tav.yml @@ -1,23 +1,18 @@ -# Note: tests must set `SKIP_TEST_IF_DISABLE=true` to override usage of -# `mocha --require '../../../scripts/skip-test-if.js' ...` if calling `npm test`. - -"aws-sdk": - env: - - SKIP_TEST_IF_DISABLE=true - # A small subset of releases in the range [2.308.0, 3) to reduce testing time. - versions: - include: "^2.308.0" - mode: max-7 - commands: - - mocha --require '@opentelemetry/contrib-test-utils' test/aws-sdk-v2.test.ts - # Versions [3.363.0, 3.377.0] of all @aws-sdk/client-* were bad releases. See: # - https://github.com/open-telemetry/opentelemetry-js-contrib/pull/2464#issuecomment-2403652552 # - https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1828#issuecomment-1834276719 -# node version support in JS SDK v3: -# - 14.x dropped in v3.567.0 https://github.com/aws/aws-sdk-js-v3/pull/6034 -# - 16.x dropped in v3.723.0 https://github.com/aws/aws-sdk-js-v3/pull/6775 +"@aws-sdk/client-bedrock-runtime": + env: + - SKIP_TEST_IF_DISABLE=true + jobs: + - node: ">=18" + versions: + include: "^3.587.0" + exclude: ">=3.363.0 <=3.377.0" + mode: "max-7" + commands: + - mocha --require '@opentelemetry/contrib-test-utils' test/bedrock-runtime.test.ts "@aws-sdk/client-s3": env: @@ -32,22 +27,6 @@ commands: - mocha --require '@opentelemetry/contrib-test-utils' test/aws-sdk-v3-s3.test.ts - mocha --require '@opentelemetry/contrib-test-utils' test/s3.test.ts - - node: "16" - versions: - include: ">=3.6.1 <3.723.0" - exclude: "3.529.0 || >=3.363.0 <=3.377.0" - mode: "max-7" - commands: - - mocha --require '@opentelemetry/contrib-test-utils' test/aws-sdk-v3-s3.test.ts - - mocha --require '@opentelemetry/contrib-test-utils' test/s3.test.ts - - node: "14" - versions: - include: ">=3.6.1 <3.567.0" - exclude: "3.529.0 || >=3.363.0 <=3.377.0" - mode: "max-7" - commands: - - mocha --require '@opentelemetry/contrib-test-utils' test/aws-sdk-v3-s3.test.ts - - mocha --require '@opentelemetry/contrib-test-utils' test/s3.test.ts "@aws-sdk/client-sqs": env: @@ -60,21 +39,3 @@ mode: "max-7" commands: - mocha --require '@opentelemetry/contrib-test-utils' test/aws-sdk-v3-sqs.test.ts - - mocha --require '@opentelemetry/contrib-test-utils' test/sqs.test.ts - - node: "16" - versions: - include: ">=3.24.0 <3.723.0" - exclude: ">=3.363.0 <=3.377.0" - mode: "max-7" - commands: - - mocha --require '@opentelemetry/contrib-test-utils' test/aws-sdk-v3-sqs.test.ts - - mocha --require '@opentelemetry/contrib-test-utils' test/sqs.test.ts - - node: "14" - versions: - include: ">=3.24.0 <3.567.0" - exclude: ">=3.363.0 <=3.377.0" - mode: "max-7" - commands: - - mocha --require '@opentelemetry/contrib-test-utils' test/aws-sdk-v3-sqs.test.ts - - mocha --require '@opentelemetry/contrib-test-utils' test/sqs.test.ts - diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/CHANGELOG.md b/plugins/node/opentelemetry-instrumentation-aws-sdk/CHANGELOG.md index 993f24625a..557ae490d0 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-sdk/CHANGELOG.md +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [0.51.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-aws-sdk-v0.50.0...instrumentation-aws-sdk-v0.51.0) (2025-04-08) + + +### ⚠ BREAKING CHANGES + +* **aws-sdk:** drop support for AWS SDK for JavaScript v2 ([#2623](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/2623)) + +### Features + +* **aws-sdk:** drop support for AWS SDK for JavaScript v2 ([#2623](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/2623)) ([37d8ce1](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/37d8ce16faf4d3d3b45eaa0f7bdeddcfa47f139d)) +* **instrumentation-aws-sdk:** add bedrock-runtime extension to apply gen ai conventions ([#2700](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/2700)) ([2b7feac](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/2b7feac92489d35d69824a51a1c3b462c7c2912b)) + ## [0.50.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-aws-sdk-v0.49.1...instrumentation-aws-sdk-v0.50.0) (2025-03-18) diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/README.md b/plugins/node/opentelemetry-instrumentation-aws-sdk/README.md index ea51d907d4..82e877d03b 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-sdk/README.md +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/README.md @@ -5,7 +5,7 @@ [component owners](https://github.com/open-telemetry/opentelemetry-js-contrib/blob/main/.github.amrom.workers.devponent_owners.yml): @blumamir @jj22ee @trivikr -This module provides automatic instrumentation for the [`aws-sdk` v2](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/) and [`@aws-sdk` v3](https://github.com/aws/aws-sdk-js-v3) modules, which may be loaded using the [`@opentelemetry/sdk-trace-node`](https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-sdk-trace-node) package and is included in the [`@opentelemetry/auto-instrumentations-node`](https://www.npmjs.com/package/@opentelemetry/auto-instrumentations-node) bundle. +This module provides automatic instrumentation for the [AWS SDK for JavaScript v3](https://github.com/aws/aws-sdk-js-v3) modules, which may be loaded using the [`@opentelemetry/sdk-trace-node`](https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-sdk-trace-node) package and is included in the [`@opentelemetry/auto-instrumentations-node`](https://www.npmjs.com/package/@opentelemetry/auto-instrumentations-node) bundle. If total installation size is not constrained, it is recommended to use the [`@opentelemetry/auto-instrumentations-node`](https://www.npmjs.com/package/@opentelemetry/auto-instrumentations-node) bundle with [@opentelemetry/sdk-node](`https://www.npmjs.com/package/@opentelemetry/sdk-node`) for the most seamless instrumentation experience. @@ -19,7 +19,6 @@ npm install --save @opentelemetry/instrumentation-aws-sdk ## Supported Versions -- [`aws-sdk`](https://www.npmjs.com/package/aws-sdk) versions `>=2.308.0 <3` - `@aws-sdk/client-*` versions `>=3.0.0 <4` ## Usage @@ -60,7 +59,7 @@ aws-sdk instrumentation has few options available to choose from. You can set th ## Span Attributes -Both V2 and V3 instrumentations are collecting the following attributes: +The instrumentations are collecting the following attributes: | Attribute Name | Type | Description | Example | | -------------- | ---- | ----------- | ------- | | `rpc.system` | string | Always equals "aws-api" | | @@ -68,21 +67,9 @@ Both V2 and V3 instrumentations are collecting the following attributes: | `rpc.service` | string | The name of the service to which a request is made, as returned by the AWS SDK. If the SDK does not provide a away to retrieve a name, the name of the SDK's client interface for a service SHOULD be used, removing the suffix `Client` if present, resulting in a PascalCase name with no spaces. | `S3`, `DynamoDB`, `Route53` | | `aws.region` | string | Region name for the request | "eu-west-1" | -### V2 attributes - -In addition to the above attributes, the instrumentation also collect the following for V2 ONLY: -| Attribute Name | Type | Description | Example | -| -------------- | ---- | ----------- | ------- | -| `aws.operation` | string | The method name for the request. | for `SQS.sendMessage(...)` the operation is "sendMessage" | -| `aws.signature.version` | string | AWS version of authentication signature on the request. | "v4" | -| `aws.service.api` | string | The SDK class name for the service | "SQS" | -| `aws.service.identifier` | string | Identifier for the service in the SDK | "sqs" | -| `aws.service.name` | string | Abbreviation name for the service | "Amazon SQS" | -| `aws.request.id` | uuid | Request unique id, as returned from aws on response | "01234567-89ab-cdef-0123-456789abcdef" | - ### Custom User Attributes -The instrumentation user can configure a `preRequestHook` function which will be called before each request, with a normalized request object (across v2 and v3) and the corresponding span. +The instrumentation user can configure a `preRequestHook` function which will be called before each request, with a normalized request object and the corresponding span. This hook can be used to add custom attributes to the span with any logic. For example, user can add interesting attributes from the `request.params`, and write custom logic based on the service and operation. Usage example: @@ -107,6 +94,7 @@ Specific service logic currently implemented for: - [SNS](./doc/sns.md) - [Lambda](./doc/lambda.md) - DynamoDb +- Amazon Bedrock Runtime (See the [GenAI semantic conventions](https://opentelemetry.io/docs/specs/semconv/gen-ai/).) ## Potential Side Effects diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/package.json b/plugins/node/opentelemetry-instrumentation-aws-sdk/package.json index 1f060c441f..5cc5bdea3a 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-sdk/package.json +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/instrumentation-aws-sdk", - "version": "0.50.0", + "version": "0.51.0", "description": "OpenTelemetry instrumentation for `aws-sdk` and `@aws-sdk/client-*` clients for various AWS services", "keywords": [ "aws", @@ -35,7 +35,7 @@ "prewatch": "npm run precompile", "prepublishOnly": "npm run compile", "tdd": "npm run test -- --watch-extensions ts --watch", - "test": "SKIP_TEST_IF_NODE_OLDER_THAN=18 nyc mocha --require '../../../scripts/skip-test-if.js' --require '@opentelemetry/contrib-test-utils' 'test/**/*.test.ts'", + "test": "nyc mocha --require '@opentelemetry/contrib-test-utils' 'test/**/*.test.ts'", "test-all-versions": "tav", "version:update": "node ../../../scripts/version-update.js", "watch": "tsc -w" @@ -50,6 +50,7 @@ "@opentelemetry/semantic-conventions": "^1.27.0" }, "devDependencies": { + "@aws-sdk/client-bedrock-runtime": "^3.587.0", "@aws-sdk/client-dynamodb": "^3.85.0", "@aws-sdk/client-kinesis": "^3.85.0", "@aws-sdk/client-lambda": "^3.85.0", @@ -64,7 +65,6 @@ "@types/mocha": "10.0.10", "@types/node": "18.18.14", "@types/sinon": "17.0.4", - "aws-sdk": "2.1008.0", "eslint": "8.7.0", "expect": "29.2.0", "nock": "13.3.3", diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/src/aws-sdk.ts b/plugins/node/opentelemetry-instrumentation-aws-sdk/src/aws-sdk.ts index a3040a15a9..f894e28458 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-sdk/src/aws-sdk.ts +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/src/aws-sdk.ts @@ -18,12 +18,10 @@ import { SpanKind, context, trace, - Context, diag, SpanStatusCode, } from '@opentelemetry/api'; import { suppressTracing } from '@opentelemetry/core'; -import type * as AWS from 'aws-sdk'; import { AttributeNames } from './enums'; import { ServicesExtensions } from './services'; import { @@ -53,7 +51,6 @@ import type { import { bindPromise, extractAttributesFromNormalizedRequest, - normalizeV2Request, normalizeV3Request, removeSuffixFromStringIfExists, } from './utils'; @@ -68,11 +65,6 @@ type V3PluginCommand = AwsV3Command & { [V3_CLIENT_CONFIG_KEY]?: any; }; -const REQUEST_SPAN_KEY = Symbol('opentelemetry.instrumentation.aws-sdk.span'); -type V2PluginRequest = AWS.Request & { - [REQUEST_SPAN_KEY]?: Span; -}; - export class AwsInstrumentation extends InstrumentationBase { static readonly component = 'aws-sdk'; private servicesExtensions: ServicesExtensions = new ServicesExtensions(); @@ -141,23 +133,7 @@ export class AwsInstrumentation extends InstrumentationBase, - metadata: RequestMetadata, - normalizedRequest: NormalizedRequest - ): Span { - const operation = (request as any).operation; - const service = (request as any).service; - const serviceIdentifier = service?.serviceIdentifier; - const name = - metadata.spanName ?? - `${normalizedRequest.serviceName}.${normalizedRequest.commandName}`; - - const newSpan = this.tracer.startSpan(name, { - kind: metadata.spanKind ?? SpanKind.CLIENT, - attributes: { - [AttributeNames.AWS_OPERATION]: operation, - [AttributeNames.AWS_SIGNATURE_VERSION]: - service?.config?.signatureVersion, - [AttributeNames.AWS_SERVICE_API]: service?.api?.className, - [AttributeNames.AWS_SERVICE_IDENTIFIER]: serviceIdentifier, - [AttributeNames.AWS_SERVICE_NAME]: service?.api?.abbreviation, - ...extractAttributesFromNormalizedRequest(normalizedRequest), - ...metadata.spanAttributes, - }, - }); - - return newSpan; - } - private _callUserPreRequestHook( span: Span, request: NormalizedRequest, @@ -310,51 +232,6 @@ export class AwsInstrumentation extends InstrumentationBase { - // read issue https://github.com/aspecto-io/opentelemetry-ext-js/issues/60 - context.with(completedEventContext, () => { - if (!v2Request[REQUEST_SPAN_KEY]) { - return; - } - delete v2Request[REQUEST_SPAN_KEY]; - - const requestId = response.requestId; - const normalizedResponse: NormalizedResponse = { - data: response.data, - request: normalizedRequest, - requestId: requestId, - }; - - self._callUserResponseHook(span, normalizedResponse); - if (response.error) { - span.recordException(response.error); - } else { - this.servicesExtensions.responseHook( - normalizedResponse, - span, - self.tracer, - self.getConfig() - ); - } - - span.setAttribute(AttributeNames.AWS_REQUEST_ID, requestId); - - const httpStatusCode = response.httpResponse?.statusCode; - if (httpStatusCode) { - span.setAttribute(SEMATTRS_HTTP_STATUS_CODE, httpStatusCode); - } - span.end(); - }); - }); - } - private _getV3ConstructStackPatch( moduleVersion: string | undefined, original: (...args: unknown[]) => MiddlewareStack @@ -446,7 +323,9 @@ export class AwsInstrumentation extends InstrumentationBase void) => void - ) { - const self = this; - return function ( - this: V2PluginRequest, - callback?: (err: any, data: any) => void - ) { - /* - if the span was already started, we don't want to start a new one - when Request.promise() is called - */ - if (this[REQUEST_SPAN_KEY]) { - return original.call(this, callback); - } - - const normalizedRequest = normalizeV2Request(this); - const requestMetadata = self.servicesExtensions.requestPreSpanHook( - normalizedRequest, - self.getConfig(), - self._diag - ); - const span = self._startAwsV2Span( - this, - requestMetadata, - normalizedRequest - ); - this[REQUEST_SPAN_KEY] = span; - const activeContextWithSpan = trace.setSpan(context.active(), span); - const callbackWithContext = context.bind(activeContextWithSpan, callback); - - self._callUserPreRequestHook(span, normalizedRequest, moduleVersion); - self._registerV2CompletedEvent( - span, - this, - normalizedRequest, - activeContextWithSpan - ); - - return context.with(activeContextWithSpan, () => { - self.servicesExtensions.requestPostSpanHook(normalizedRequest); - return self._callOriginalFunction(() => - original.call(this, callbackWithContext) - ); - }); - }; - } - - private _getRequestPromisePatch( - moduleVersion: string | undefined, - original: (...args: unknown[]) => Promise - ) { - const self = this; - return function (this: V2PluginRequest, ...args: unknown[]): Promise { - // if the span was already started, we don't want to start a new one when Request.promise() is called - if (this[REQUEST_SPAN_KEY]) { - return original.apply(this, args); - } - - const normalizedRequest = normalizeV2Request(this); - const requestMetadata = self.servicesExtensions.requestPreSpanHook( - normalizedRequest, - self.getConfig(), - self._diag - ); - const span = self._startAwsV2Span( - this, - requestMetadata, - normalizedRequest - ); - this[REQUEST_SPAN_KEY] = span; - - const activeContextWithSpan = trace.setSpan(context.active(), span); - self._callUserPreRequestHook(span, normalizedRequest, moduleVersion); - self._registerV2CompletedEvent( - span, - this, - normalizedRequest, - activeContextWithSpan - ); - - const origPromise: Promise = context.with( - activeContextWithSpan, - () => { - self.servicesExtensions.requestPostSpanHook(normalizedRequest); - return self._callOriginalFunction(() => - original.call(this, arguments) - ); - } - ); - - return requestMetadata.isIncoming - ? bindPromise(origPromise, activeContextWithSpan) - : origPromise; - }; - } - private _callOriginalFunction(originalFunction: (...args: any[]) => T): T { if (this.getConfig().suppressInternalInstrumentation) { return context.with(suppressTracing(context.active()), originalFunction); diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/src/semconv.ts b/plugins/node/opentelemetry-instrumentation-aws-sdk/src/semconv.ts new file mode 100644 index 0000000000..480541614c --- /dev/null +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/src/semconv.ts @@ -0,0 +1,140 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file contains a copy of unstable semantic convention definitions + * used by this package. + * @see https://github.com/open-telemetry/opentelemetry-js/tree/main/semantic-conventions#unstable-semconv + */ + +/** + * The name of the operation being performed. + * + * @note If one of the predefined values applies, but specific system uses a different name it's **RECOMMENDED** to document it in the semantic conventions for specific GenAI system and use system-specific name in the instrumentation. If a different name is not documented, instrumentation libraries **SHOULD** use applicable predefined value. + * + * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. + */ +export const ATTR_GEN_AI_OPERATION_NAME = 'gen_ai.operation.name' as const; + +/** + * The maximum number of tokens the model generates for a request. + * + * @example 100 + * + * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. + */ +export const ATTR_GEN_AI_REQUEST_MAX_TOKENS = + 'gen_ai.request.max_tokens' as const; + +/** + * The name of the GenAI model a request is being made to. + * + * @example "gpt-4" + * + * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. + */ +export const ATTR_GEN_AI_REQUEST_MODEL = 'gen_ai.request.model' as const; + +/** + * List of sequences that the model will use to stop generating further tokens. + * + * @example ["forest", "lived"] + * + * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. + */ +export const ATTR_GEN_AI_REQUEST_STOP_SEQUENCES = + 'gen_ai.request.stop_sequences' as const; + +/** + * The temperature setting for the GenAI request. + * + * @example 0.0 + * + * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. + */ +export const ATTR_GEN_AI_REQUEST_TEMPERATURE = + 'gen_ai.request.temperature' as const; + +/** + * The top_p sampling setting for the GenAI request. + * + * @example 1.0 + * + * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. + */ +export const ATTR_GEN_AI_REQUEST_TOP_P = 'gen_ai.request.top_p' as const; + +/** + * Array of reasons the model stopped generating tokens, corresponding to each generation received. + * + * @example ["stop"] + * @example ["stop", "length"] + * + * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. + */ +export const ATTR_GEN_AI_RESPONSE_FINISH_REASONS = + 'gen_ai.response.finish_reasons' as const; + +/** + * The Generative AI product as identified by the client or server instrumentation. + * + * @example "openai" + * + * @note The `gen_ai.system` describes a family of GenAI models with specific model identified + * by `gen_ai.request.model` and `gen_ai.response.model` attributes. + * + * The actual GenAI product may differ from the one identified by the client. + * Multiple systems, including Azure OpenAI and Gemini, are accessible by OpenAI client + * libraries. In such cases, the `gen_ai.system` is set to `openai` based on the + * instrumentation's best knowledge, instead of the actual system. The `server.address` + * attribute may help identify the actual system in use for `openai`. + * + * For custom model, a custom friendly name **SHOULD** be used. + * If none of these options apply, the `gen_ai.system` **SHOULD** be set to `_OTHER`. + * + * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. + */ +export const ATTR_GEN_AI_SYSTEM = 'gen_ai.system' as const; + +/** + * The number of tokens used in the GenAI input (prompt). + * + * @example 100 + * + * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. + */ +export const ATTR_GEN_AI_USAGE_INPUT_TOKENS = + 'gen_ai.usage.input_tokens' as const; + +/** + * The number of tokens used in the GenAI response (completion). + * + * @example 180 + * + * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. + */ +export const ATTR_GEN_AI_USAGE_OUTPUT_TOKENS = + 'gen_ai.usage.output_tokens' as const; + +/** + * Enum value "chat" for attribute {@link ATTR_GEN_AI_OPERATION_NAME}. + */ +export const GEN_AI_OPERATION_NAME_VALUE_CHAT = 'chat' as const; + +/** + * Enum value "aws.bedrock" for attribute {@link ATTR_GEN_AI_SYSTEM}. + */ +export const GEN_AI_SYSTEM_VALUE_AWS_BEDROCK = 'aws.bedrock' as const; diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/src/services/ServicesExtensions.ts b/plugins/node/opentelemetry-instrumentation-aws-sdk/src/services/ServicesExtensions.ts index 609ed7f7a0..edf18bdaea 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-sdk/src/services/ServicesExtensions.ts +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/src/services/ServicesExtensions.ts @@ -21,6 +21,7 @@ import { NormalizedRequest, NormalizedResponse, } from '../types'; +import { BedrockRuntimeServiceExtension } from './bedrock-runtime'; import { DynamodbServiceExtension } from './dynamodb'; import { SnsServiceExtension } from './sns'; import { LambdaServiceExtension } from './lambda'; @@ -37,6 +38,7 @@ export class ServicesExtensions implements ServiceExtension { this.services.set('Lambda', new LambdaServiceExtension()); this.services.set('S3', new S3ServiceExtension()); this.services.set('Kinesis', new KinesisServiceExtension()); + this.services.set('BedrockRuntime', new BedrockRuntimeServiceExtension()); } requestPreSpanHook( diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/src/services/bedrock-runtime.ts b/plugins/node/opentelemetry-instrumentation-aws-sdk/src/services/bedrock-runtime.ts new file mode 100644 index 0000000000..3c3e88c813 --- /dev/null +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/src/services/bedrock-runtime.ts @@ -0,0 +1,134 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { Attributes, DiagLogger, Span, Tracer } from '@opentelemetry/api'; +import { RequestMetadata, ServiceExtension } from './ServiceExtension'; +import { + ATTR_GEN_AI_SYSTEM, + ATTR_GEN_AI_OPERATION_NAME, + ATTR_GEN_AI_REQUEST_MODEL, + ATTR_GEN_AI_REQUEST_MAX_TOKENS, + ATTR_GEN_AI_REQUEST_TEMPERATURE, + ATTR_GEN_AI_REQUEST_TOP_P, + ATTR_GEN_AI_REQUEST_STOP_SEQUENCES, + ATTR_GEN_AI_USAGE_INPUT_TOKENS, + ATTR_GEN_AI_USAGE_OUTPUT_TOKENS, + ATTR_GEN_AI_RESPONSE_FINISH_REASONS, + GEN_AI_OPERATION_NAME_VALUE_CHAT, + GEN_AI_SYSTEM_VALUE_AWS_BEDROCK, +} from '../semconv'; +import { + AwsSdkInstrumentationConfig, + NormalizedRequest, + NormalizedResponse, +} from '../types'; + +export class BedrockRuntimeServiceExtension implements ServiceExtension { + requestPreSpanHook( + request: NormalizedRequest, + config: AwsSdkInstrumentationConfig, + diag: DiagLogger + ): RequestMetadata { + switch (request.commandName) { + case 'Converse': + return this.requestPreSpanHookConverse(request, config, diag); + } + + return { + isIncoming: false, + }; + } + + private requestPreSpanHookConverse( + request: NormalizedRequest, + config: AwsSdkInstrumentationConfig, + diag: DiagLogger + ): RequestMetadata { + let spanName = GEN_AI_OPERATION_NAME_VALUE_CHAT; + const spanAttributes: Attributes = { + [ATTR_GEN_AI_SYSTEM]: GEN_AI_SYSTEM_VALUE_AWS_BEDROCK, + [ATTR_GEN_AI_OPERATION_NAME]: GEN_AI_OPERATION_NAME_VALUE_CHAT, + }; + + const modelId = request.commandInput.modelId; + if (modelId) { + spanAttributes[ATTR_GEN_AI_REQUEST_MODEL] = modelId; + if (spanName) { + spanName += ` ${modelId}`; + } + } + + const inferenceConfig = request.commandInput.inferenceConfig; + if (inferenceConfig) { + const { maxTokens, temperature, topP, stopSequences } = inferenceConfig; + if (maxTokens !== undefined) { + spanAttributes[ATTR_GEN_AI_REQUEST_MAX_TOKENS] = maxTokens; + } + if (temperature !== undefined) { + spanAttributes[ATTR_GEN_AI_REQUEST_TEMPERATURE] = temperature; + } + if (topP !== undefined) { + spanAttributes[ATTR_GEN_AI_REQUEST_TOP_P] = topP; + } + if (stopSequences !== undefined) { + spanAttributes[ATTR_GEN_AI_REQUEST_STOP_SEQUENCES] = stopSequences; + } + } + + return { + spanName, + isIncoming: false, + spanAttributes, + }; + } + + responseHook( + response: NormalizedResponse, + span: Span, + tracer: Tracer, + config: AwsSdkInstrumentationConfig + ) { + if (!span.isRecording()) { + return; + } + + switch (response.request.commandName) { + case 'Converse': + return this.responseHookConverse(response, span, tracer, config); + } + } + + private responseHookConverse( + response: NormalizedResponse, + span: Span, + tracer: Tracer, + config: AwsSdkInstrumentationConfig + ) { + const { stopReason, usage } = response.data; + if (usage) { + const { inputTokens, outputTokens } = usage; + if (inputTokens !== undefined) { + span.setAttribute(ATTR_GEN_AI_USAGE_INPUT_TOKENS, inputTokens); + } + if (outputTokens !== undefined) { + span.setAttribute(ATTR_GEN_AI_USAGE_OUTPUT_TOKENS, outputTokens); + } + } + + if (stopReason !== undefined) { + span.setAttribute(ATTR_GEN_AI_RESPONSE_FINISH_REASONS, [stopReason]); + } + } +} diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/src/types.ts b/plugins/node/opentelemetry-instrumentation-aws-sdk/src/types.ts index ce99e8c441..03c30ca4e0 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-sdk/src/types.ts +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/src/types.ts @@ -20,7 +20,7 @@ import { SQS } from './aws-sdk.types'; export type CommandInput = Record; /** - * These are normalized request and response, which are used by both sdk v2 and v3. + * These are normalized request and response. * They organize the relevant data in one interface which can be processed in a * uniform manner in hooks */ diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/src/utils.ts b/plugins/node/opentelemetry-instrumentation-aws-sdk/src/utils.ts index cb8aaa6591..99295f0a06 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-sdk/src/utils.ts +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/src/utils.ts @@ -22,9 +22,6 @@ import { import { AttributeNames } from './enums'; import { NormalizedRequest } from './types'; -const toPascalCase = (str: string): string => - typeof str === 'string' ? str.charAt(0).toUpperCase() + str.slice(1) : str; - export const removeSuffixFromStringIfExists = ( str: string, suffixToRemove: string @@ -35,16 +32,6 @@ export const removeSuffixFromStringIfExists = ( : str; }; -export const normalizeV2Request = (awsV2Request: any): NormalizedRequest => { - const service = awsV2Request?.service; - return { - serviceName: service?.api?.serviceId?.replace(/\s+/g, ''), - commandName: toPascalCase(awsV2Request?.operation), - commandInput: awsV2Request.params, - region: service?.config?.region, - }; -}; - export const normalizeV3Request = ( serviceName: string, commandNameWithSuffix: string, diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/MessageAttributes.test.ts b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/MessageAttributes.test.ts index 826fa3f15e..0c1f20f669 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/MessageAttributes.test.ts +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/MessageAttributes.test.ts @@ -14,7 +14,9 @@ * limitations under the License. */ +import { propagation } from '@opentelemetry/api'; import { expect } from 'expect'; +import * as sinon from 'sinon'; import { MAX_MESSAGE_ATTRIBUTES, contextGetter, @@ -71,6 +73,7 @@ describe('MessageAttributes', () => { describe('injectPropagationContext', () => { it('should inject context if there are available attributes', () => { + sinon.spy(propagation, 'inject'); const contextAttributes = { key1: { DataType: 'String', StringValue: 'value1' }, key2: { DataType: 'String', StringValue: 'value2' }, @@ -79,12 +82,14 @@ describe('MessageAttributes', () => { key5: { DataType: 'String', StringValue: 'value5' }, }; - expect(Object.keys(contextAttributes).length).toBe(5); injectPropagationContext(contextAttributes); - expect(Object.keys(contextAttributes).length).toBeGreaterThan(5); + // @ts-expect-error Property 'calledOnce' does not exist on type + expect(propagation.inject.calledOnce).toBe(true); + sinon.restore(); }); it('should not inject context if there not enough available attributes', () => { + sinon.spy(propagation, 'inject'); const contextAttributes = { key1: { DataType: 'String', StringValue: 'value1' }, key2: { DataType: 'String', StringValue: 'value2' }, @@ -98,9 +103,10 @@ describe('MessageAttributes', () => { key10: { DataType: 'String', StringValue: 'value10' }, }; - expect(Object.keys(contextAttributes).length).toBe(10); injectPropagationContext(contextAttributes); - expect(Object.keys(contextAttributes).length).toBe(10); + // @ts-expect-error Property 'calledOnce' does not exist on type + expect(propagation.inject.calledOnce).toBe(false); + sinon.restore(); }); }); diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/aws-sdk-v2.test.ts b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/aws-sdk-v2.test.ts deleted file mode 100644 index 96a082ddb3..0000000000 --- a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/aws-sdk-v2.test.ts +++ /dev/null @@ -1,430 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { - AwsInstrumentation, - AwsSdkRequestHookInformation, - AwsSdkResponseHookInformation, -} from '../src'; -import { - getTestSpans, - registerInstrumentationTesting, -} from '@opentelemetry/contrib-test-utils'; -const instrumentation = registerInstrumentationTesting( - new AwsInstrumentation() -); -import * as AWS from 'aws-sdk'; - -import { ReadableSpan } from '@opentelemetry/sdk-trace-base'; -import { SpanStatusCode, Span, SpanKind } from '@opentelemetry/api'; -import { AttributeNames } from '../src/enums'; -import { mockV2AwsSend } from './testing-utils'; -import { expect } from 'expect'; -import { SEMATTRS_HTTP_STATUS_CODE } from '@opentelemetry/semantic-conventions'; -import { AWSError } from 'aws-sdk'; -import { HttpResponse } from 'aws-sdk/lib/http_response'; - -describe('instrumentation-aws-sdk-v2', () => { - const responseMockSuccess = { - requestId: '0000000000000', - error: null, - httpResponse: { - statusCode: 200, - }, - }; - - const error: AWSError = { - name: 'error', - message: 'something went wrong', - stack: 'fakeStack', - code: 'errorCode', - time: new Date(), - }; - - const responseMockWithError: Pick< - AWS.Response, - 'requestId' | 'error' - > & { httpResponse: Partial } = { - requestId: '0000000000000', - error, - httpResponse: { - statusCode: 400, - }, - }; - - const getAwsSpans = (): ReadableSpan[] => { - return getTestSpans().filter(s => - s.instrumentationScope.name.includes('aws-sdk') - ); - }; - - before(() => { - AWS.config.credentials = { - accessKeyId: 'test key id', - expired: false, - expireTime: new Date(), - secretAccessKey: 'test acc key', - sessionToken: 'test token', - }; - }); - - describe('functional', () => { - describe('successful send', () => { - before(() => { - mockV2AwsSend(responseMockSuccess); - }); - - it('adds proper number of spans with correct attributes', async () => { - const s3 = new AWS.S3(); - const bucketName = 'aws-test-bucket'; - const keyName = 'aws-test-object.txt'; - await new Promise(resolve => { - // span 1 - s3.createBucket({ Bucket: bucketName }, async (err, data) => { - const params = { - Bucket: bucketName, - Key: keyName, - Body: 'Hello World!', - }; - // span 2 - s3.putObject(params, (err, data) => { - if (err) console.log(err); - resolve({}); - }); - }); - }); - - const awsSpans = getAwsSpans(); - expect(awsSpans.length).toBe(2); - const [spanCreateBucket, spanPutObject] = awsSpans; - - expect(spanCreateBucket.attributes[AttributeNames.AWS_OPERATION]).toBe( - 'createBucket' - ); - expect( - spanCreateBucket.attributes[AttributeNames.AWS_SIGNATURE_VERSION] - ).toBe('s3'); - expect( - spanCreateBucket.attributes[AttributeNames.AWS_SERVICE_API] - ).toBe('S3'); - expect( - spanCreateBucket.attributes[AttributeNames.AWS_SERVICE_IDENTIFIER] - ).toBe('s3'); - expect( - spanCreateBucket.attributes[AttributeNames.AWS_SERVICE_NAME] - ).toBe('Amazon S3'); - expect(spanCreateBucket.attributes[AttributeNames.AWS_REQUEST_ID]).toBe( - responseMockSuccess.requestId - ); - expect(spanCreateBucket.attributes[AttributeNames.AWS_REGION]).toBe( - 'us-east-1' - ); - expect(spanCreateBucket.attributes[SEMATTRS_HTTP_STATUS_CODE]).toBe( - 200 - ); - - expect(spanCreateBucket.name).toBe('S3.CreateBucket'); - expect(spanCreateBucket.kind).toEqual(SpanKind.CLIENT); - expect(spanPutObject.attributes[AttributeNames.AWS_OPERATION]).toBe( - 'putObject' - ); - expect( - spanPutObject.attributes[AttributeNames.AWS_SIGNATURE_VERSION] - ).toBe('s3'); - expect(spanPutObject.attributes[AttributeNames.AWS_SERVICE_API]).toBe( - 'S3' - ); - expect( - spanPutObject.attributes[AttributeNames.AWS_SERVICE_IDENTIFIER] - ).toBe('s3'); - expect(spanPutObject.attributes[AttributeNames.AWS_SERVICE_NAME]).toBe( - 'Amazon S3' - ); - expect(spanPutObject.attributes[AttributeNames.AWS_REQUEST_ID]).toBe( - responseMockSuccess.requestId - ); - expect(spanPutObject.attributes[AttributeNames.AWS_REGION]).toBe( - 'us-east-1' - ); - expect(spanPutObject.name).toBe('S3.PutObject'); - expect(spanPutObject.attributes[SEMATTRS_HTTP_STATUS_CODE]).toBe(200); - }); - - it('adds proper number of spans with correct attributes if both, promise and callback were used', async () => { - const s3 = new AWS.S3(); - const bucketName = 'aws-test-bucket'; - const keyName = 'aws-test-object.txt'; - await new Promise(resolve => { - // span 1 - s3.createBucket({ Bucket: bucketName }, async (err, data) => { - const params = { - Bucket: bucketName, - Key: keyName, - Body: 'Hello World!', - }; - - let reqPromise: Promise | null = null; - let numberOfCalls = 0; - const cbPromise = new Promise(resolveCb => { - // span 2 - const request = s3.putObject(params, (err, data) => { - if (err) console.log(err); - numberOfCalls++; - if (numberOfCalls === 2) { - resolveCb({}); - } - }); - // NO span - reqPromise = request.promise(); - }); - - await Promise.all([cbPromise, reqPromise]).then(() => { - resolve({}); - }); - }); - }); - - const awsSpans = getAwsSpans(); - expect(awsSpans.length).toBe(2); - const [spanCreateBucket, spanPutObjectCb] = awsSpans; - expect(spanCreateBucket.attributes[AttributeNames.AWS_OPERATION]).toBe( - 'createBucket' - ); - expect(spanPutObjectCb.attributes[AttributeNames.AWS_OPERATION]).toBe( - 'putObject' - ); - expect(spanPutObjectCb.attributes[AttributeNames.AWS_REGION]).toBe( - 'us-east-1' - ); - expect(spanPutObjectCb.attributes[SEMATTRS_HTTP_STATUS_CODE]).toBe(200); - }); - - it('adds proper number of spans with correct attributes if only promise was used', async () => { - const s3 = new AWS.S3(); - const bucketName = 'aws-test-bucket'; - const keyName = 'aws-test-object.txt'; - await new Promise(resolve => { - // span 1 - s3.createBucket({ Bucket: bucketName }, async (err, data) => { - const params = { - Bucket: bucketName, - Key: keyName, - Body: 'Hello World!', - }; - - // NO span - const request = s3.putObject(params); - // span 2 - await request.promise(); - resolve({}); - }); - }); - - const awsSpans = getAwsSpans(); - expect(awsSpans.length).toBe(2); - const [spanCreateBucket, spanPutObjectCb] = awsSpans; - expect(spanCreateBucket.attributes[AttributeNames.AWS_OPERATION]).toBe( - 'createBucket' - ); - expect(spanPutObjectCb.attributes[AttributeNames.AWS_OPERATION]).toBe( - 'putObject' - ); - expect(spanPutObjectCb.attributes[AttributeNames.AWS_REGION]).toBe( - 'us-east-1' - ); - expect(spanPutObjectCb.attributes[SEMATTRS_HTTP_STATUS_CODE]).toBe(200); - }); - - it('should create span if no callback is supplied', done => { - const s3 = new AWS.S3(); - const bucketName = 'aws-test-bucket'; - - s3.putObject({ - Bucket: bucketName, - Key: 'key name from tests', - Body: 'Hello World!', - }).send(); - - setImmediate(() => { - const awsSpans = getAwsSpans(); - expect(awsSpans.length).toBe(1); - done(); - }); - }); - }); - - describe('send return error', () => { - before(() => { - mockV2AwsSend(responseMockWithError); - }); - - it('adds error attribute properly', async () => { - const s3 = new AWS.S3(); - const bucketName = 'aws-test-bucket'; - await new Promise(resolve => { - s3.createBucket({ Bucket: bucketName }, async () => { - resolve({}); - }); - }); - - const awsSpans = getAwsSpans(); - expect(awsSpans.length).toBe(1); - const [spanCreateBucket] = awsSpans; - const exceptionEvent = spanCreateBucket.events.filter( - event => event.name === 'exception' - ); - expect(exceptionEvent.length).toBe(1); - - expect(exceptionEvent[0]).toStrictEqual( - expect.objectContaining({ - name: 'exception', - attributes: { - 'exception.message': 'something went wrong', - 'exception.stacktrace': 'fakeStack', - 'exception.type': 'errorCode', - }, - }) - ); - - expect(spanCreateBucket.attributes[SEMATTRS_HTTP_STATUS_CODE]).toBe( - 400 - ); - }); - }); - }); - - describe('instrumentation config', () => { - it('preRequestHook called and add request attribute to span', done => { - mockV2AwsSend(responseMockSuccess, 'data returned from operation'); - const config = { - preRequestHook: ( - span: Span, - requestInfo: AwsSdkRequestHookInformation - ) => { - span.setAttribute( - 'attribute from hook', - requestInfo.request.commandInput['Bucket'] - ); - }, - }; - - instrumentation.disable(); - instrumentation.setConfig(config); - instrumentation.enable(); - - const s3 = new AWS.S3(); - const bucketName = 'aws-test-bucket'; - - s3.createBucket({ Bucket: bucketName }, async (err, data) => { - const awsSpans = getAwsSpans(); - expect(awsSpans.length).toBe(1); - expect(awsSpans[0].attributes['attribute from hook']).toStrictEqual( - bucketName - ); - done(); - }); - }); - - it('preRequestHook throws does not fail span', done => { - mockV2AwsSend(responseMockSuccess, 'data returned from operation'); - const config = { - preRequestHook: (span: Span, request: any) => { - throw new Error('error from request hook'); - }, - }; - - instrumentation.disable(); - instrumentation.setConfig(config); - instrumentation.enable(); - - const s3 = new AWS.S3(); - const bucketName = 'aws-test-bucket'; - - s3.createBucket({ Bucket: bucketName }, async (err, data) => { - const awsSpans = getAwsSpans(); - expect(awsSpans.length).toBe(1); - expect(awsSpans[0].status.code).toStrictEqual(SpanStatusCode.UNSET); - done(); - }); - }); - - it('responseHook called and add response attribute to span', done => { - mockV2AwsSend(responseMockSuccess, 'data returned from operation'); - const config = { - responseHook: ( - span: Span, - responseInfo: AwsSdkResponseHookInformation - ) => { - span.setAttribute( - 'attribute from response hook', - responseInfo.response['data'] - ); - }, - }; - - instrumentation.disable(); - instrumentation.setConfig(config); - instrumentation.enable(); - - const s3 = new AWS.S3(); - const bucketName = 'aws-test-bucket'; - - s3.createBucket({ Bucket: bucketName }, async (err, data) => { - const awsSpans = getAwsSpans(); - expect(awsSpans.length).toBe(1); - expect( - awsSpans[0].attributes['attribute from response hook'] - ).toStrictEqual('data returned from operation'); - done(); - }); - }); - - it('suppressInternalInstrumentation set to true with send()', done => { - mockV2AwsSend(responseMockSuccess, 'data returned from operation', true); - const config = { - suppressInternalInstrumentation: true, - }; - - instrumentation.disable(); - instrumentation.setConfig(config); - instrumentation.enable(); - - const s3 = new AWS.S3(); - - s3.createBucket({ Bucket: 'aws-test-bucket' }, (err, data) => { - const awsSpans = getAwsSpans(); - expect(awsSpans.length).toBe(1); - done(); - }); - }); - - it('suppressInternalInstrumentation set to true with promise()', async () => { - mockV2AwsSend(responseMockSuccess, 'data returned from operation', true); - const config = { - suppressInternalInstrumentation: true, - }; - - instrumentation.disable(); - instrumentation.setConfig(config); - instrumentation.enable(); - - const s3 = new AWS.S3(); - - await s3.createBucket({ Bucket: 'aws-test-bucket' }).promise(); - const awsSpans = getAwsSpans(); - expect(awsSpans.length).toBe(1); - }); - }); -}); diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/bedrock-runtime.test.ts b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/bedrock-runtime.test.ts new file mode 100644 index 0000000000..43bf1abd47 --- /dev/null +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/bedrock-runtime.test.ts @@ -0,0 +1,193 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * These tests verify telemetry created against actual API responses + * which can be difficult to mock for LLMs. The responses are recorded + * automatically using nock's nock-back feature. Responses are recorded + * to the mock-responses directory with the name of the test - by default + * if a response is available for the current test it is used, and + * otherwise a real request is made and the response is recorded. + * To re-record all responses, set the NOCK_BACK_MODE environment variable + * to 'update' - when recording responses, valid AWS credentials for + * accessing bedrock are also required. To record for new tests while + * keeping existing recordings, set NOCK_BACK_MODE to 'record'. + */ + +import { + getTestSpans, + registerInstrumentationTesting, +} from '@opentelemetry/contrib-test-utils'; +import { AwsInstrumentation } from '../src'; +registerInstrumentationTesting(new AwsInstrumentation()); + +import { + BedrockRuntimeClient, + ConverseCommand, + ConversationRole, + InvokeModelCommand, +} from '@aws-sdk/client-bedrock-runtime'; +import { AwsCredentialIdentity } from '@aws-sdk/types'; +import * as path from 'path'; +import { Definition, back as nockBack } from 'nock'; + +import { ReadableSpan } from '@opentelemetry/sdk-trace-base'; +import { + ATTR_GEN_AI_SYSTEM, + ATTR_GEN_AI_OPERATION_NAME, + ATTR_GEN_AI_REQUEST_MODEL, + ATTR_GEN_AI_REQUEST_MAX_TOKENS, + ATTR_GEN_AI_REQUEST_TEMPERATURE, + ATTR_GEN_AI_REQUEST_TOP_P, + ATTR_GEN_AI_REQUEST_STOP_SEQUENCES, + ATTR_GEN_AI_USAGE_INPUT_TOKENS, + ATTR_GEN_AI_USAGE_OUTPUT_TOKENS, + ATTR_GEN_AI_RESPONSE_FINISH_REASONS, + GEN_AI_SYSTEM_VALUE_AWS_BEDROCK, + GEN_AI_OPERATION_NAME_VALUE_CHAT, +} from '../src/semconv'; +import { expect } from 'expect'; + +const region = 'us-east-1'; + +// Remove any data from recorded responses that could have sensitive data +// and that we don't need for testing. +const sanitizeRecordings = (scopes: Definition[]) => { + for (const scope of scopes) { + // Type definition seems to be incorrect of headers. + const headers: string[] = (scope as any).rawHeaders; + for (let i = 0; i < headers.length; i += 2) { + if (headers[i].toLowerCase() === 'set-cookie') { + headers.splice(i, 2); + } + } + } + return scopes; +}; + +describe('Bedrock', () => { + nockBack.fixtures = path.join(__dirname, 'mock-responses'); + let credentials: AwsCredentialIdentity | undefined; + if (nockBack.currentMode === 'dryrun') { + credentials = { + accessKeyId: 'testing', + secretAccessKey: 'testing', + }; + } + + const client = new BedrockRuntimeClient({ region, credentials }); + + let nockDone: () => void; + beforeEach(async function () { + const filename = `${this.currentTest + ?.fullTitle() + .toLowerCase() + .replace(/\s/g, '-')}.json`; + const { nockDone: nd } = await nockBack(filename, { + afterRecord: sanitizeRecordings, + }); + nockDone = nd; + }); + + afterEach(async function () { + nockDone(); + }); + + describe('Converse', () => { + it('adds genai conventions', async () => { + const modelId = 'amazon.titan-text-lite-v1'; + const messages = [ + { + role: ConversationRole.USER, + content: [{ text: 'Say this is a test' }], + }, + ]; + const inferenceConfig = { + maxTokens: 10, + temperature: 0.8, + topP: 1, + stopSequences: ['|'], + }; + + const command = new ConverseCommand({ + modelId, + messages, + inferenceConfig, + }); + const response = await client.send(command); + expect(response.output?.message?.content?.[0].text).toBe( + "Hi. I'm not sure what" + ); + + const testSpans: ReadableSpan[] = getTestSpans(); + const converseSpans: ReadableSpan[] = testSpans.filter( + (s: ReadableSpan) => { + return s.name === 'chat amazon.titan-text-lite-v1'; + } + ); + expect(converseSpans.length).toBe(1); + expect(converseSpans[0].attributes).toMatchObject({ + [ATTR_GEN_AI_SYSTEM]: GEN_AI_SYSTEM_VALUE_AWS_BEDROCK, + [ATTR_GEN_AI_OPERATION_NAME]: GEN_AI_OPERATION_NAME_VALUE_CHAT, + [ATTR_GEN_AI_REQUEST_MODEL]: modelId, + [ATTR_GEN_AI_REQUEST_MAX_TOKENS]: 10, + [ATTR_GEN_AI_REQUEST_TEMPERATURE]: 0.8, + [ATTR_GEN_AI_REQUEST_TOP_P]: 1, + [ATTR_GEN_AI_REQUEST_STOP_SEQUENCES]: ['|'], + [ATTR_GEN_AI_USAGE_INPUT_TOKENS]: 8, + [ATTR_GEN_AI_USAGE_OUTPUT_TOKENS]: 10, + [ATTR_GEN_AI_RESPONSE_FINISH_REASONS]: ['max_tokens'], + }); + }); + }); + + // TODO: Instrument InvokeModel + describe('InvokeModel', () => { + it('does not currently add genai conventions', async () => { + const modelId = 'amazon.titan-text-express-v1'; + const inputText = 'Say this is a test'; + const textGenerationConfig = { + maxTokenCount: 10, + temperature: 0.8, + topP: 1, + stopSequences: ['|'], + }; + const body: any = { + inputText, + textGenerationConfig, + }; + + const command = new InvokeModelCommand({ + modelId, + body: JSON.stringify(body), + }); + const response = await client.send(command); + const output = JSON.parse(response.body.transformToString()); + expect(output.results[0].outputText).toBe( + '\nHello! I am a computer program designed to' + ); + + const testSpans: ReadableSpan[] = getTestSpans(); + const converseSpans: ReadableSpan[] = testSpans.filter( + (s: ReadableSpan) => { + return s.name === 'BedrockRuntime.InvokeModel'; + } + ); + expect(converseSpans.length).toBe(1); + expect(converseSpans[0].attributes[ATTR_GEN_AI_SYSTEM]).toBeUndefined(); + }); + }); +}); diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/dynamodb.test.ts b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/dynamodb.test.ts deleted file mode 100644 index de34fd8a84..0000000000 --- a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/dynamodb.test.ts +++ /dev/null @@ -1,1136 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { - AwsInstrumentation, - CommandInput, - AwsSdkDynamoDBStatementSerializer, -} from '../src'; -import { - getTestSpans, - registerInstrumentationTesting, -} from '@opentelemetry/contrib-test-utils'; -const instrumentation = registerInstrumentationTesting( - new AwsInstrumentation() -); -import * as AWS from 'aws-sdk'; -import { AWSError } from 'aws-sdk'; - -import { mockV2AwsSend } from './testing-utils'; -import { - DBSYSTEMVALUES_DYNAMODB, - SEMATTRS_AWS_DYNAMODB_ATTRIBUTE_DEFINITIONS, - SEMATTRS_AWS_DYNAMODB_CONSISTENT_READ, - SEMATTRS_AWS_DYNAMODB_CONSUMED_CAPACITY, - SEMATTRS_AWS_DYNAMODB_COUNT, - SEMATTRS_AWS_DYNAMODB_EXCLUSIVE_START_TABLE, - SEMATTRS_AWS_DYNAMODB_GLOBAL_SECONDARY_INDEX_UPDATES, - SEMATTRS_AWS_DYNAMODB_GLOBAL_SECONDARY_INDEXES, - SEMATTRS_AWS_DYNAMODB_INDEX_NAME, - SEMATTRS_AWS_DYNAMODB_ITEM_COLLECTION_METRICS, - SEMATTRS_AWS_DYNAMODB_LIMIT, - SEMATTRS_AWS_DYNAMODB_LOCAL_SECONDARY_INDEXES, - SEMATTRS_AWS_DYNAMODB_PROJECTION, - SEMATTRS_AWS_DYNAMODB_PROVISIONED_READ_CAPACITY, - SEMATTRS_AWS_DYNAMODB_PROVISIONED_WRITE_CAPACITY, - SEMATTRS_AWS_DYNAMODB_SCAN_FORWARD, - SEMATTRS_AWS_DYNAMODB_SCANNED_COUNT, - SEMATTRS_AWS_DYNAMODB_SEGMENT, - SEMATTRS_AWS_DYNAMODB_SELECT, - SEMATTRS_AWS_DYNAMODB_TABLE_COUNT, - SEMATTRS_AWS_DYNAMODB_TABLE_NAMES, - SEMATTRS_AWS_DYNAMODB_TOTAL_SEGMENTS, - SEMATTRS_DB_NAME, - SEMATTRS_DB_OPERATION, - SEMATTRS_DB_STATEMENT, - SEMATTRS_DB_SYSTEM, -} from '@opentelemetry/semantic-conventions'; -import { expect } from 'expect'; -import type { ConsumedCapacity as ConsumedCapacityV2 } from 'aws-sdk/clients/dynamodb'; -import type { ConsumedCapacity as ConsumedCapacityV3 } from '@aws-sdk/client-dynamodb'; -import * as sinon from 'sinon'; - -type ConsumedCapacity = ConsumedCapacityV2 | ConsumedCapacityV3; - -const responseMockSuccess = { - requestId: '0000000000000', - error: null, -}; - -describe('DynamoDB', () => { - before(() => { - AWS.config.credentials = { - accessKeyId: 'test key id', - expired: false, - expireTime: new Date(), - secretAccessKey: 'test acc key', - sessionToken: 'test token', - }; - }); - - describe('Query', () => { - beforeEach(() => { - mockV2AwsSend(responseMockSuccess, { - Items: [{ key1: 'val1' }, { key2: 'val2' }], - Count: 2, - ScannedCount: 5, - } as AWS.DynamoDB.Types.QueryOutput); - }); - - it('should populate specific Query attributes', done => { - const dynamodb = new AWS.DynamoDB.DocumentClient(); - const params = { - TableName: 'test-table', - KeyConditionExpression: '#k = :v', - ExpressionAttributeNames: { - '#k': 'key1', - }, - ExpressionAttributeValues: { - ':v': 'val1', - }, - ProjectionExpression: 'id', - ScanIndexForward: true, - ConsistentRead: true, - IndexName: 'name_to_group', - Limit: 10, - Select: 'ALL_ATTRIBUTES', - }; - - dynamodb.query( - params, - (err: AWSError, data: AWS.DynamoDB.DocumentClient.QueryOutput) => { - const spans = getTestSpans(); - expect(spans.length).toStrictEqual(1); - const attrs = spans[0].attributes; - expect(attrs[SEMATTRS_DB_SYSTEM]).toStrictEqual( - DBSYSTEMVALUES_DYNAMODB - ); - expect(attrs[SEMATTRS_DB_NAME]).toStrictEqual('test-table'); - expect(attrs[SEMATTRS_DB_OPERATION]).toStrictEqual('Query'); - expect(attrs[SEMATTRS_AWS_DYNAMODB_SCAN_FORWARD]).toStrictEqual(true); - expect(attrs[SEMATTRS_AWS_DYNAMODB_CONSISTENT_READ]).toStrictEqual( - true - ); - expect(attrs[SEMATTRS_AWS_DYNAMODB_INDEX_NAME]).toStrictEqual( - 'name_to_group' - ); - expect(attrs[SEMATTRS_AWS_DYNAMODB_SELECT]).toStrictEqual( - 'ALL_ATTRIBUTES' - ); - expect(attrs[SEMATTRS_AWS_DYNAMODB_LIMIT]).toStrictEqual(10); - expect(attrs[SEMATTRS_AWS_DYNAMODB_TABLE_NAMES]).toStrictEqual([ - 'test-table', - ]); - expect(attrs[SEMATTRS_AWS_DYNAMODB_PROJECTION]).toStrictEqual('id'); - expect(attrs).not.toHaveProperty(SEMATTRS_DB_STATEMENT); - expect(err).toBeFalsy(); - done(); - } - ); - }); - }); - - describe('Scan', () => { - beforeEach(() => - mockV2AwsSend(responseMockSuccess, { - ConsumedCapacity: { - TableName: 'test-table', - CapacityUnits: 0.5, - Table: { CapacityUnits: 0.5 }, - }, - Count: 10, - ScannedCount: 50, - } as AWS.DynamoDB.Types.ScanOutput) - ); - - it('should populate specific Scan attributes', done => { - const dynamodb = new AWS.DynamoDB.DocumentClient(); - const params = { - TableName: 'test-table', - Item: { key1: 'val1' }, - ProjectionExpression: 'id', - ConsistentRead: true, - Segment: 10, - TotalSegments: 100, - IndexName: 'index_name', - Limit: 10, - Select: 'ALL_ATTRIBUTES', - }; - - dynamodb.scan( - params, - (err: AWSError, data: AWS.DynamoDB.DocumentClient.ScanOutput) => { - const spans = getTestSpans(); - expect(spans.length).toStrictEqual(1); - const attrs = spans[0].attributes; - expect(attrs[SEMATTRS_DB_SYSTEM]).toStrictEqual( - DBSYSTEMVALUES_DYNAMODB - ); - expect(attrs[SEMATTRS_DB_NAME]).toStrictEqual('test-table'); - expect(attrs[SEMATTRS_DB_OPERATION]).toStrictEqual('Scan'); - expect(attrs[SEMATTRS_AWS_DYNAMODB_SEGMENT]).toStrictEqual(10); - expect(attrs[SEMATTRS_AWS_DYNAMODB_TOTAL_SEGMENTS]).toStrictEqual( - 100 - ); - expect(attrs[SEMATTRS_AWS_DYNAMODB_INDEX_NAME]).toStrictEqual( - 'index_name' - ); - expect(attrs[SEMATTRS_AWS_DYNAMODB_SELECT]).toStrictEqual( - 'ALL_ATTRIBUTES' - ); - expect(attrs[SEMATTRS_AWS_DYNAMODB_COUNT]).toStrictEqual(10); - expect(attrs[SEMATTRS_AWS_DYNAMODB_SCANNED_COUNT]).toStrictEqual(50); - expect(attrs[SEMATTRS_AWS_DYNAMODB_LIMIT]).toStrictEqual(10); - expect(attrs[SEMATTRS_AWS_DYNAMODB_TABLE_NAMES]).toStrictEqual([ - 'test-table', - ]); - expect(attrs[SEMATTRS_AWS_DYNAMODB_PROJECTION]).toStrictEqual('id'); - expect(attrs).not.toHaveProperty(SEMATTRS_DB_STATEMENT); - expect(err).toBeFalsy(); - done(); - } - ); - }); - }); - - describe('BatchWriteItem', () => { - beforeEach(() => - mockV2AwsSend(responseMockSuccess, { - UnprocessedItems: {}, - ItemCollectionMetrics: { - ItemCollectionKey: [], - SizeEstimateRangeGB: [0], - }, - ConsumedCapacity: undefined, - } as AWS.DynamoDB.Types.BatchWriteItemOutput) - ); - - it('should populate specific BatchWriteItem attributes', done => { - const dynamodb = new AWS.DynamoDB.DocumentClient(); - const params = { - RequestItems: {}, - ReturnConsumedCapacity: 'INDEXES', - ReturnItemCollectionMetrics: 'SIZE', - }; - - dynamodb.batchWrite( - params, - ( - err: AWSError, - data: AWS.DynamoDB.DocumentClient.BatchWriteItemOutput - ) => { - const spans = getTestSpans(); - expect(spans.length).toStrictEqual(1); - const attrs = spans[0].attributes; - expect(attrs[SEMATTRS_DB_SYSTEM]).toStrictEqual( - DBSYSTEMVALUES_DYNAMODB - ); - expect( - attrs[SEMATTRS_AWS_DYNAMODB_ITEM_COLLECTION_METRICS] - ).toStrictEqual([ - JSON.stringify({ ItemCollectionKey: [], SizeEstimateRangeGB: [0] }), - ]); - - expect(attrs).not.toHaveProperty(SEMATTRS_DB_STATEMENT); - expect(err).toBeFalsy(); - done(); - } - ); - }); - }); - - describe('CreateTable', () => { - beforeEach(() => - mockV2AwsSend(responseMockSuccess, { - TableName: 'test_table', - ItemCollectionMetrics: { - ItemCollectionKey: [], - SizeEstimateRangeGB: [0], - }, - ConsumedCapacity: undefined, - } as AWS.DynamoDB.Types.CreateTableOutput) - ); - - it('should populate specific CreateTable attributes', done => { - const globalSecondaryIndexMockData = { - IndexName: 'test_index', - KeySchema: [ - { - AttributeName: 'attribute1', - KeyType: 'HASH', - }, - ], - Projection: { - ProjectionType: 'ALL', - NonKeyAttributes: ['non_key_attr'], - }, - ProvisionedThroughput: { - ReadCapacityUnits: 5, - WriteCapacityUnits: 10, - }, - }; - - const localSecondaryIndexMockData = { - IndexName: 'test_index', - KeySchema: [ - { - AttributeName: 'test_attribute', - KeyType: 'HASH', - }, - ], - Projection: { - ProjectionType: 'ALL', - NonKeyAttributes: ['STRING_VALUE'], - }, - }; - - const dynamodb = new AWS.DynamoDB(); - const params = { - AttributeDefinitions: [ - { - AttributeName: 'test_attribute', - AttributeType: 'S', - }, - ], - TableName: 'test_table', - KeySchema: [ - { - AttributeName: 'test_attribute', - KeyType: 'HASH', - }, - ], - LocalSecondaryIndexes: [localSecondaryIndexMockData], - GlobalSecondaryIndexes: [globalSecondaryIndexMockData], - BillingMode: 'PROVISIONED', - ProvisionedThroughput: { - ReadCapacityUnits: 20, - WriteCapacityUnits: 30, - }, - }; - - dynamodb.createTable( - params, - ( - err: AWSError, - data: AWS.DynamoDB.DocumentClient.CreateTableOutput - ) => { - const spans = getTestSpans(); - expect(spans.length).toStrictEqual(1); - const attrs = spans[0].attributes; - expect(attrs[SEMATTRS_DB_SYSTEM]).toStrictEqual( - DBSYSTEMVALUES_DYNAMODB - ); - expect( - attrs[SEMATTRS_AWS_DYNAMODB_ITEM_COLLECTION_METRICS] - ).toStrictEqual([ - JSON.stringify({ ItemCollectionKey: [], SizeEstimateRangeGB: [0] }), - ]); - - expect( - attrs[SEMATTRS_AWS_DYNAMODB_GLOBAL_SECONDARY_INDEXES] - ).toStrictEqual([JSON.stringify(globalSecondaryIndexMockData)]); - - expect( - attrs[SEMATTRS_AWS_DYNAMODB_LOCAL_SECONDARY_INDEXES] - ).toStrictEqual([JSON.stringify(localSecondaryIndexMockData)]); - expect( - attrs[SEMATTRS_AWS_DYNAMODB_PROVISIONED_READ_CAPACITY] - ).toStrictEqual(20); - expect( - attrs[SEMATTRS_AWS_DYNAMODB_PROVISIONED_WRITE_CAPACITY] - ).toStrictEqual(30); - expect(attrs).not.toHaveProperty(SEMATTRS_DB_STATEMENT); - expect(err).toBeFalsy(); - done(); - } - ); - }); - }); - - describe('UpdateTable', () => { - beforeEach(() => - mockV2AwsSend(responseMockSuccess, { - TableName: 'test_table', - } as AWS.DynamoDB.Types.UpdateTableOutput) - ); - - it('should populate specific CreateTable attributes', done => { - const dynamodb = new AWS.DynamoDB(); - const params = { - AttributeDefinitions: [ - { - AttributeName: 'test_attr', - AttributeType: 'S', - }, - ], - TableName: 'test_table', - ProvisionedThroughput: { - ReadCapacityUnits: 10, - WriteCapacityUnits: 15, - }, - GlobalSecondaryIndexUpdates: [ - { - Update: { - IndexName: 'test_index', - ProvisionedThroughput: { - ReadCapacityUnits: 1, - WriteCapacityUnits: 5, - }, - }, - }, - ], - }; - - dynamodb.updateTable( - params, - ( - err: AWSError, - data: AWS.DynamoDB.DocumentClient.UpdateTableOutput - ) => { - const spans = getTestSpans(); - expect(spans.length).toStrictEqual(1); - const attrs = spans[0].attributes; - expect(attrs[SEMATTRS_DB_SYSTEM]).toStrictEqual( - DBSYSTEMVALUES_DYNAMODB - ); - - expect( - attrs[SEMATTRS_AWS_DYNAMODB_GLOBAL_SECONDARY_INDEX_UPDATES] - ).toStrictEqual([ - JSON.stringify({ - Update: { - IndexName: 'test_index', - ProvisionedThroughput: { - ReadCapacityUnits: 1, - WriteCapacityUnits: 5, - }, - }, - }), - ]); - expect( - attrs[SEMATTRS_AWS_DYNAMODB_ATTRIBUTE_DEFINITIONS] - ).toStrictEqual([ - JSON.stringify({ - AttributeName: 'test_attr', - AttributeType: 'S', - }), - ]); - expect( - attrs[SEMATTRS_AWS_DYNAMODB_PROVISIONED_READ_CAPACITY] - ).toStrictEqual(10); - expect( - attrs[SEMATTRS_AWS_DYNAMODB_PROVISIONED_WRITE_CAPACITY] - ).toStrictEqual(15); - expect(attrs).not.toHaveProperty(SEMATTRS_DB_STATEMENT); - expect(err).toBeFalsy(); - done(); - } - ); - }); - }); - - describe('ListTables', () => { - beforeEach(() => - mockV2AwsSend(responseMockSuccess, { - TableNames: ['test_table', 'test_table_2', 'start_table'], - } as AWS.DynamoDB.Types.ListTablesOutput) - ); - - it('should populate specific ListTables attributes', done => { - const dynamodb = new AWS.DynamoDB(); - const params = { - ExclusiveStartTableName: 'start_table', - Limit: 10, - }; - - dynamodb.listTables( - params, - (err: AWSError, data: AWS.DynamoDB.DocumentClient.ListTablesOutput) => { - const spans = getTestSpans(); - expect(spans.length).toStrictEqual(1); - const attrs = spans[0].attributes; - expect(attrs[SEMATTRS_DB_SYSTEM]).toStrictEqual( - DBSYSTEMVALUES_DYNAMODB - ); - - expect( - attrs[SEMATTRS_AWS_DYNAMODB_EXCLUSIVE_START_TABLE] - ).toStrictEqual('start_table'); - expect(attrs[SEMATTRS_AWS_DYNAMODB_LIMIT]).toStrictEqual(10); - expect(attrs[SEMATTRS_AWS_DYNAMODB_TABLE_COUNT]).toStrictEqual(3); - - expect(attrs).not.toHaveProperty(SEMATTRS_DB_STATEMENT); - expect(err).toBeFalsy(); - done(); - } - ); - }); - }); - - describe('BatchGetItem', () => { - const consumedCapacityResponseMockData: ConsumedCapacity[] = [ - { - TableName: 'test-table', - CapacityUnits: 0.5, - Table: { CapacityUnits: 0.5 }, - }, - ]; - - it('should populate BatchGetIem default attributes', done => { - mockV2AwsSend(responseMockSuccess, { - Responses: { 'test-table': [{ key1: { S: 'val1' } }] }, - UnprocessedKeys: {}, - } as AWS.DynamoDB.Types.BatchGetItemOutput); - - const dynamodb = new AWS.DynamoDB.DocumentClient(); - const dynamodb_params = { - RequestItems: { - 'test-table': { - Keys: [{ key1: { S: 'val1' } }], - ProjectionExpression: 'id', - }, - }, - ReturnConsumedCapacity: 'INDEXES', - }; - dynamodb.batchGet( - dynamodb_params, - ( - err: AWSError, - data: AWS.DynamoDB.DocumentClient.BatchGetItemOutput - ) => { - const spans = getTestSpans(); - expect(spans.length).toStrictEqual(1); - const attrs = spans[0].attributes; - expect(attrs[SEMATTRS_DB_SYSTEM]).toStrictEqual( - DBSYSTEMVALUES_DYNAMODB - ); - expect(attrs[SEMATTRS_DB_OPERATION]).toStrictEqual('BatchGetItem'); - expect(attrs[SEMATTRS_AWS_DYNAMODB_TABLE_NAMES]).toStrictEqual([ - 'test-table', - ]); - expect( - attrs[SEMATTRS_AWS_DYNAMODB_CONSUMED_CAPACITY] - ).toBeUndefined(); - expect(attrs).not.toHaveProperty(SEMATTRS_DB_STATEMENT); - expect(err).toBeFalsy(); - done(); - } - ); - }); - - it('should populate BatchGetIem optional attributes', done => { - mockV2AwsSend(responseMockSuccess, { - Responses: { 'test-table': [{ key1: { S: 'val1' } }] }, - UnprocessedKeys: {}, - ConsumedCapacity: consumedCapacityResponseMockData, - } as AWS.DynamoDB.Types.BatchGetItemOutput); - - const dynamodb = new AWS.DynamoDB.DocumentClient(); - const dynamodb_params = { - RequestItems: { - 'test-table': { - Keys: [{ key1: { S: 'val1' } }], - ProjectionExpression: 'id', - }, - }, - ReturnConsumedCapacity: 'INDEXES', - }; - dynamodb.batchGet( - dynamodb_params, - ( - err: AWSError, - data: AWS.DynamoDB.DocumentClient.BatchGetItemOutput - ) => { - const spans = getTestSpans(); - expect(spans.length).toStrictEqual(1); - const attrs = spans[0].attributes; - expect(attrs[SEMATTRS_DB_SYSTEM]).toStrictEqual( - DBSYSTEMVALUES_DYNAMODB - ); - expect(attrs[SEMATTRS_DB_OPERATION]).toStrictEqual('BatchGetItem'); - expect(attrs[SEMATTRS_AWS_DYNAMODB_TABLE_NAMES]).toStrictEqual([ - 'test-table', - ]); - expect(attrs[SEMATTRS_AWS_DYNAMODB_CONSUMED_CAPACITY]).toStrictEqual( - consumedCapacityResponseMockData.map((x: ConsumedCapacity) => - JSON.stringify(x) - ) - ); - expect(attrs).not.toHaveProperty(SEMATTRS_DB_STATEMENT); - expect(err).toBeFalsy(); - done(); - } - ); - }); - - it('should populate BatchGetIem when consumedCapacity is undefined', done => { - mockV2AwsSend(responseMockSuccess, { - Responses: { 'test-table': [{ key1: { S: 'val1' } }] }, - UnprocessedKeys: {}, - ConsumedCapacity: undefined, - } as AWS.DynamoDB.Types.BatchGetItemOutput); - - const dynamodb = new AWS.DynamoDB.DocumentClient(); - const dynamodb_params = { - RequestItems: { - 'test-table': { - Keys: [{ key1: { S: 'val1' } }], - ProjectionExpression: 'id', - }, - }, - ReturnConsumedCapacity: 'NONE', - }; - dynamodb.batchGet( - dynamodb_params, - ( - err: AWSError, - data: AWS.DynamoDB.DocumentClient.BatchGetItemOutput - ) => { - const spans = getTestSpans(); - expect(spans.length).toStrictEqual(1); - const attrs = spans[0].attributes; - expect(attrs[SEMATTRS_DB_SYSTEM]).toStrictEqual('dynamodb'); - expect(attrs[SEMATTRS_DB_OPERATION]).toStrictEqual('BatchGetItem'); - expect(attrs[SEMATTRS_AWS_DYNAMODB_TABLE_NAMES]).toStrictEqual([ - 'test-table', - ]); - expect( - attrs[SEMATTRS_AWS_DYNAMODB_CONSUMED_CAPACITY] - ).toBeUndefined(); - expect(attrs).not.toHaveProperty(SEMATTRS_DB_STATEMENT); - expect(err).toBeFalsy(); - done(); - } - ); - }); - }); - - describe('ConsumedCapacity', () => { - it('should populate ConsumedCapacity attributes when they exist', done => { - mockV2AwsSend(responseMockSuccess, { - ConsumedCapacity: { - TableName: 'test-table', - CapacityUnits: 0.5, - Table: { CapacityUnits: 0.5 }, - }, - } as AWS.DynamoDB.Types.PutItemOutput); - - const dynamodb = new AWS.DynamoDB.DocumentClient(); - dynamodb.put( - { - TableName: 'test-table', - Item: { key1: 'val1' }, - ReturnConsumedCapacity: 'INDEXES', - }, - (err: AWSError, data: AWS.DynamoDB.DocumentClient.PutItemOutput) => { - const spans = getTestSpans(); - expect(spans.length).toStrictEqual(1); - const attrs = spans[0].attributes; - expect(attrs[SEMATTRS_DB_SYSTEM]).toStrictEqual( - DBSYSTEMVALUES_DYNAMODB - ); - expect(attrs[SEMATTRS_DB_OPERATION]).toStrictEqual('PutItem'); - expect(attrs[SEMATTRS_AWS_DYNAMODB_CONSUMED_CAPACITY]).toStrictEqual([ - JSON.stringify({ - TableName: 'test-table', - CapacityUnits: 0.5, - Table: { CapacityUnits: 0.5 }, - }), - ]); - expect(err).toBeFalsy(); - done(); - } - ); - }); - - it('should not populate ConsumedCapacity attributes when it is not returned', done => { - mockV2AwsSend(responseMockSuccess, { - ConsumedCapacity: undefined, - } as AWS.DynamoDB.Types.PutItemOutput); - - const dynamodb = new AWS.DynamoDB.DocumentClient(); - dynamodb.put( - { - TableName: 'test-table', - Item: { key1: 'val1' }, - ReturnConsumedCapacity: 'NONE', - }, - (err: AWSError, data: AWS.DynamoDB.DocumentClient.PutItemOutput) => { - const spans = getTestSpans(); - expect(spans.length).toStrictEqual(1); - const attrs = spans[0].attributes; - expect(attrs[SEMATTRS_DB_SYSTEM]).toStrictEqual( - DBSYSTEMVALUES_DYNAMODB - ); - expect(attrs[SEMATTRS_DB_OPERATION]).toStrictEqual('PutItem'); - expect(attrs).not.toHaveProperty( - SEMATTRS_AWS_DYNAMODB_CONSUMED_CAPACITY - ); - expect(err).toBeFalsy(); - done(); - } - ); - }); - }); - - describe('dbStatementSerializer config', () => { - const SERIALIZED_DB_STATEMENT = 'serialized statement'; - - const dynamoDBStatementSerializer: AwsSdkDynamoDBStatementSerializer = ( - _operation: string, - _command: CommandInput - ): string => { - return SERIALIZED_DB_STATEMENT; - }; - - beforeEach(() => { - instrumentation.disable(); - instrumentation.setConfig({ - dynamoDBStatementSerializer, - }); - instrumentation.enable(); - }); - - it('should not fail if serializer throws', done => { - instrumentation.disable(); - instrumentation.setConfig({ - dynamoDBStatementSerializer: () => { - throw new Error('Serializer failure'); - }, - }); - instrumentation.enable(); - mockV2AwsSend(responseMockSuccess, { - Items: [{ key1: 'val1' }, { key2: 'val2' }], - Count: 2, - ScannedCount: 5, - } as AWS.DynamoDB.Types.QueryOutput); - const dynamodb = new AWS.DynamoDB.DocumentClient(); - const params = { - TableName: 'test-table', - KeyConditionExpression: '#k = :v', - ExpressionAttributeNames: { - '#k': 'key1', - }, - ExpressionAttributeValues: { - ':v': 'val1', - }, - ProjectionExpression: 'id', - ScanIndexForward: true, - ConsistentRead: true, - IndexName: 'name_to_group', - Limit: 10, - Select: 'ALL_ATTRIBUTES', - }; - - dynamodb.query( - params, - (err: AWSError, _data: AWS.DynamoDB.DocumentClient.QueryOutput) => { - const spans = getTestSpans(); - expect(spans.length).toStrictEqual(1); - const attrs = spans[0].attributes; - - expect(attrs).not.toHaveProperty(SEMATTRS_DB_STATEMENT); - expect(err).toBeFalsy(); - done(); - } - ); - }); - - it('should omit DB statement if serializer is not configured', done => { - instrumentation.disable(); - instrumentation.setConfig({ - dynamoDBStatementSerializer: undefined, - }); - instrumentation.enable(); - mockV2AwsSend(responseMockSuccess, { - Items: [{ key1: 'val1' }, { key2: 'val2' }], - Count: 2, - ScannedCount: 5, - } as AWS.DynamoDB.Types.QueryOutput); - const dynamodb = new AWS.DynamoDB.DocumentClient(); - const params = { - TableName: 'test-table', - KeyConditionExpression: '#k = :v', - ExpressionAttributeNames: { - '#k': 'key1', - }, - ExpressionAttributeValues: { - ':v': 'val1', - }, - ProjectionExpression: 'id', - ScanIndexForward: true, - ConsistentRead: true, - IndexName: 'name_to_group', - Limit: 10, - Select: 'ALL_ATTRIBUTES', - }; - - dynamodb.query( - params, - (err: AWSError, _data: AWS.DynamoDB.DocumentClient.QueryOutput) => { - const spans = getTestSpans(); - expect(spans.length).toStrictEqual(1); - const attrs = spans[0].attributes; - - expect(attrs).not.toHaveProperty(SEMATTRS_DB_STATEMENT); - expect(err).toBeFalsy(); - done(); - } - ); - }); - - it('should omit DB statement if serializer returns undefined', done => { - instrumentation.disable(); - instrumentation.setConfig({ - dynamoDBStatementSerializer: () => undefined, - }); - instrumentation.enable(); - mockV2AwsSend(responseMockSuccess, { - Items: [{ key1: 'val1' }, { key2: 'val2' }], - Count: 2, - ScannedCount: 5, - } as AWS.DynamoDB.Types.QueryOutput); - const dynamodb = new AWS.DynamoDB.DocumentClient(); - const params = { - TableName: 'test-table', - KeyConditionExpression: '#k = :v', - ExpressionAttributeNames: { - '#k': 'key1', - }, - ExpressionAttributeValues: { - ':v': 'val1', - }, - ProjectionExpression: 'id', - ScanIndexForward: true, - ConsistentRead: true, - IndexName: 'name_to_group', - Limit: 10, - Select: 'ALL_ATTRIBUTES', - }; - - dynamodb.query( - params, - (err: AWSError, _data: AWS.DynamoDB.DocumentClient.QueryOutput) => { - const spans = getTestSpans(); - expect(spans.length).toStrictEqual(1); - const attrs = spans[0].attributes; - - expect(attrs).not.toHaveProperty(SEMATTRS_DB_STATEMENT); - expect(err).toBeFalsy(); - done(); - } - ); - }); - - it('should provide operation and command input to serializer', done => { - const dynamoDBStatementSerializerSpy = sinon.spy(); - instrumentation.disable(); - instrumentation.setConfig({ - dynamoDBStatementSerializer: dynamoDBStatementSerializerSpy, - }); - instrumentation.enable(); - mockV2AwsSend(responseMockSuccess, { - Items: [{ key1: 'val1' }, { key2: 'val2' }], - Count: 2, - ScannedCount: 5, - } as AWS.DynamoDB.Types.QueryOutput); - const dynamodb = new AWS.DynamoDB.DocumentClient(); - const params = { - TableName: 'test-table', - KeyConditionExpression: '#k = :v', - ExpressionAttributeNames: { - '#k': 'key1', - }, - ExpressionAttributeValues: { - ':v': 'val1', - }, - ProjectionExpression: 'id', - ScanIndexForward: true, - ConsistentRead: true, - IndexName: 'name_to_group', - Limit: 10, - Select: 'ALL_ATTRIBUTES', - }; - - dynamodb.query( - params, - (err: AWSError, _data: AWS.DynamoDB.DocumentClient.QueryOutput) => { - const spans = getTestSpans(); - expect(spans.length).toStrictEqual(1); - - expect(dynamoDBStatementSerializerSpy.callCount).toBe(1); - expect(dynamoDBStatementSerializerSpy.args[0][0]).toStrictEqual( - 'Query' - ); - expect(dynamoDBStatementSerializerSpy.args[0][1]).toStrictEqual({ - ConsistentRead: true, - ExpressionAttributeNames: { - '#k': 'key1', - }, - ExpressionAttributeValues: { - ':v': 'val1', - }, - IndexName: 'name_to_group', - KeyConditionExpression: '#k = :v', - Limit: 10, - ProjectionExpression: 'id', - ScanIndexForward: true, - Select: 'ALL_ATTRIBUTES', - TableName: 'test-table', - }); - - done(); - } - ); - }); - - it('should properly execute the db statement serializer for Query operation', done => { - mockV2AwsSend(responseMockSuccess, { - Items: [{ key1: 'val1' }, { key2: 'val2' }], - Count: 2, - ScannedCount: 5, - } as AWS.DynamoDB.Types.QueryOutput); - const dynamodb = new AWS.DynamoDB.DocumentClient(); - const params = { - TableName: 'test-table', - KeyConditionExpression: '#k = :v', - ExpressionAttributeNames: { - '#k': 'key1', - }, - ExpressionAttributeValues: { - ':v': 'val1', - }, - ProjectionExpression: 'id', - ScanIndexForward: true, - ConsistentRead: true, - IndexName: 'name_to_group', - Limit: 10, - Select: 'ALL_ATTRIBUTES', - }; - - dynamodb.query( - params, - (err: AWSError, _data: AWS.DynamoDB.DocumentClient.QueryOutput) => { - const spans = getTestSpans(); - expect(spans.length).toStrictEqual(1); - const attrs = spans[0].attributes; - - expect(attrs[SEMATTRS_DB_STATEMENT]).toStrictEqual( - SERIALIZED_DB_STATEMENT - ); - expect(err).toBeFalsy(); - done(); - } - ); - }); - - it('should properly execute the db statement serializer for CreateTable operation', done => { - mockV2AwsSend(responseMockSuccess, { - TableName: 'test_table', - ItemCollectionMetrics: { - ItemCollectionKey: [], - SizeEstimateRangeGB: [0], - }, - ConsumedCapacity: undefined, - } as AWS.DynamoDB.Types.CreateTableOutput); - const globalSecondaryIndexMockData = { - IndexName: 'test_index', - KeySchema: [ - { - AttributeName: 'attribute1', - KeyType: 'HASH', - }, - ], - Projection: { - ProjectionType: 'ALL', - NonKeyAttributes: ['non_key_attr'], - }, - ProvisionedThroughput: { - ReadCapacityUnits: 5, - WriteCapacityUnits: 10, - }, - }; - - const localSecondaryIndexMockData = { - IndexName: 'test_index', - KeySchema: [ - { - AttributeName: 'test_attribute', - KeyType: 'HASH', - }, - ], - Projection: { - ProjectionType: 'ALL', - NonKeyAttributes: ['STRING_VALUE'], - }, - }; - - const dynamodb = new AWS.DynamoDB(); - const params = { - AttributeDefinitions: [ - { - AttributeName: 'test_attribute', - AttributeType: 'S', - }, - ], - TableName: 'test_table', - KeySchema: [ - { - AttributeName: 'test_attribute', - KeyType: 'HASH', - }, - ], - LocalSecondaryIndexes: [localSecondaryIndexMockData], - GlobalSecondaryIndexes: [globalSecondaryIndexMockData], - BillingMode: 'PROVISIONED', - ProvisionedThroughput: { - ReadCapacityUnits: 20, - WriteCapacityUnits: 30, - }, - }; - - dynamodb.createTable( - params, - ( - err: AWSError, - _data: AWS.DynamoDB.DocumentClient.CreateTableOutput - ) => { - const spans = getTestSpans(); - expect(spans.length).toStrictEqual(1); - const attrs = spans[0].attributes; - - expect(attrs[SEMATTRS_DB_STATEMENT]).toStrictEqual( - SERIALIZED_DB_STATEMENT - ); - expect(err).toBeFalsy(); - done(); - } - ); - }); - - it('should properly execute the db statement serializer for UpdateTable operation', done => { - mockV2AwsSend(responseMockSuccess, { - TableName: 'test_table', - } as AWS.DynamoDB.Types.UpdateTableOutput); - const dynamodb = new AWS.DynamoDB(); - const params = { - AttributeDefinitions: [ - { - AttributeName: 'test_attr', - AttributeType: 'S', - }, - ], - TableName: 'test_table', - ProvisionedThroughput: { - ReadCapacityUnits: 10, - WriteCapacityUnits: 15, - }, - GlobalSecondaryIndexUpdates: [ - { - Update: { - IndexName: 'test_index', - ProvisionedThroughput: { - ReadCapacityUnits: 1, - WriteCapacityUnits: 5, - }, - }, - }, - ], - }; - - dynamodb.updateTable( - params, - ( - err: AWSError, - _data: AWS.DynamoDB.DocumentClient.UpdateTableOutput - ) => { - const spans = getTestSpans(); - expect(spans.length).toStrictEqual(1); - const attrs = spans[0].attributes; - - expect(attrs[SEMATTRS_DB_STATEMENT]).toStrictEqual( - SERIALIZED_DB_STATEMENT - ); - expect(err).toBeFalsy(); - done(); - } - ); - }); - - it('should properly execute the db statement serializer for ListTables operation', done => { - mockV2AwsSend(responseMockSuccess, { - TableNames: ['test_table', 'test_table_2', 'start_table'], - } as AWS.DynamoDB.Types.ListTablesOutput); - const dynamodb = new AWS.DynamoDB(); - const params = { - ExclusiveStartTableName: 'start_table', - Limit: 10, - }; - - dynamodb.listTables( - params, - ( - err: AWSError, - _data: AWS.DynamoDB.DocumentClient.ListTablesOutput - ) => { - const spans = getTestSpans(); - expect(spans.length).toStrictEqual(1); - const attrs = spans[0].attributes; - - expect(attrs[SEMATTRS_DB_STATEMENT]).toStrictEqual( - SERIALIZED_DB_STATEMENT - ); - expect(err).toBeFalsy(); - done(); - } - ); - }); - - it('should properly execute the db statement serializer for BatchWriteItem operation', done => { - mockV2AwsSend(responseMockSuccess, { - UnprocessedItems: {}, - ItemCollectionMetrics: { - ItemCollectionKey: [], - SizeEstimateRangeGB: [0], - }, - ConsumedCapacity: undefined, - } as AWS.DynamoDB.Types.BatchWriteItemOutput); - const dynamodb = new AWS.DynamoDB.DocumentClient(); - const params = { - RequestItems: {}, - ReturnConsumedCapacity: 'INDEXES', - ReturnItemCollectionMetrics: 'SIZE', - }; - - dynamodb.batchWrite( - params, - ( - err: AWSError, - _data: AWS.DynamoDB.DocumentClient.BatchWriteItemOutput - ) => { - const spans = getTestSpans(); - expect(spans.length).toStrictEqual(1); - const attrs = spans[0].attributes; - - expect(attrs[SEMATTRS_DB_STATEMENT]).toStrictEqual( - SERIALIZED_DB_STATEMENT - ); - expect(err).toBeFalsy(); - done(); - } - ); - }); - }); -}); diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/mock-responses/bedrock-converse-adds-genai-conventions.json b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/mock-responses/bedrock-converse-adds-genai-conventions.json new file mode 100644 index 0000000000..8f5e9f3c7c --- /dev/null +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/mock-responses/bedrock-converse-adds-genai-conventions.json @@ -0,0 +1,62 @@ +[ + { + "scope": "https://bedrock-runtime.us-east-1.amazonaws.com:443", + "method": "POST", + "path": "/model/amazon.titan-text-lite-v1/converse", + "body": { + "inferenceConfig": { + "maxTokens": 10, + "stopSequences": [ + "|" + ], + "temperature": 0.8, + "topP": 1 + }, + "messages": [ + { + "content": [ + { + "text": "Say this is a test" + } + ], + "role": "user" + } + ] + }, + "status": 200, + "response": { + "metrics": { + "latencyMs": 620 + }, + "output": { + "message": { + "content": [ + { + "text": "Hi. I'm not sure what" + } + ], + "role": "assistant" + } + }, + "stopReason": "max_tokens", + "usage": { + "inputTokens": 8, + "outputTokens": 10, + "totalTokens": 18 + } + }, + "rawHeaders": [ + "Date", + "Thu, 30 Jan 2025 06:45:08 GMT", + "Content-Type", + "application/json", + "Content-Length", + "203", + "Connection", + "keep-alive", + "x-amzn-RequestId", + "e6c824a2-3342-4707-ac1b-593670aae521" + ], + "responseIsBinary": false + } +] \ No newline at end of file diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/mock-responses/bedrock-invokemodel-does-not-currently-add-genai-conventions.json b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/mock-responses/bedrock-invokemodel-does-not-currently-add-genai-conventions.json new file mode 100644 index 0000000000..c013b5e7b3 --- /dev/null +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/mock-responses/bedrock-invokemodel-does-not-currently-add-genai-conventions.json @@ -0,0 +1,83 @@ +[ + { + "scope": "https://bedrock-runtime.us-east-1.amazonaws.com:443", + "method": "POST", + "path": "/model/amazon.titan-text-express-v1/invoke", + "body": { + "inputText": "Say this is a test", + "textGenerationConfig": { + "maxTokenCount": 10, + "temperature": 0.8, + "topP": 1, + "stopSequences": [ + "|" + ] + } + }, + "status": 403, + "response": { + "message": "Signature expired: 20250130T064508Z is now earlier than 20250210T013411Z (20250210T013911Z - 5 min.)" + }, + "rawHeaders": [ + "Date", + "Mon, 10 Feb 2025 01:39:11 GMT", + "Content-Type", + "application/json", + "Content-Length", + "114", + "Connection", + "keep-alive", + "x-amzn-RequestId", + "2737d2f5-442b-41b5-85bb-b7394008fbb7", + "x-amzn-ErrorType", + "InvalidSignatureException:http://internal.amazon.com/coral/com.amazon.coral.service/" + ], + "responseIsBinary": false + }, + { + "scope": "https://bedrock-runtime.us-east-1.amazonaws.com:443", + "method": "POST", + "path": "/model/amazon.titan-text-express-v1/invoke", + "body": { + "inputText": "Say this is a test", + "textGenerationConfig": { + "maxTokenCount": 10, + "temperature": 0.8, + "topP": 1, + "stopSequences": [ + "|" + ] + } + }, + "status": 200, + "response": { + "inputTextTokenCount": 5, + "results": [ + { + "tokenCount": 10, + "outputText": "\nHello! I am a computer program designed to", + "completionReason": "LENGTH" + } + ] + }, + "rawHeaders": [ + "Date", + "Mon, 10 Feb 2025 01:39:12 GMT", + "Content-Type", + "application/json", + "Content-Length", + "143", + "Connection", + "keep-alive", + "x-amzn-RequestId", + "81039412-bc01-4c17-a89f-12534a3aca0a", + "X-Amzn-Bedrock-Invocation-Latency", + "767", + "X-Amzn-Bedrock-Output-Token-Count", + "10", + "X-Amzn-Bedrock-Input-Token-Count", + "5" + ], + "responseIsBinary": false + } +] \ No newline at end of file diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/sns.test.ts b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/sns.test.ts index f8d4dd777f..64d9e9cab6 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/sns.test.ts +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/sns.test.ts @@ -13,23 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { AwsInstrumentation } from '../src'; -import { - getTestSpans, - registerInstrumentationTesting, -} from '@opentelemetry/contrib-test-utils'; -const instrumentation = registerInstrumentationTesting( - new AwsInstrumentation() -); -import * as AWSv2 from 'aws-sdk'; +import { getTestSpans } from '@opentelemetry/contrib-test-utils'; import { SNS as SNSv3 } from '@aws-sdk/client-sns'; import * as fs from 'fs'; import * as nock from 'nock'; -import { mockV2AwsSend } from './testing-utils'; import { expect } from 'expect'; import { ReadableSpan } from '@opentelemetry/sdk-trace-base'; -import * as sinon from 'sinon'; import { MESSAGINGDESTINATIONKINDVALUES_TOPIC, SEMATTRS_MESSAGING_DESTINATION, @@ -39,137 +29,6 @@ import { } from '@opentelemetry/semantic-conventions'; import { SpanKind } from '@opentelemetry/api'; -const responseMockSuccess = { - requestId: '0000000000000', - error: null, -}; - -const topicName = 'topic'; -const fakeARN = `arn:aws:sns:region:000000000:${topicName}`; - -describe('SNS - v2', () => { - before(() => { - AWSv2.config.credentials = { - accessKeyId: 'test key id', - expired: false, - expireTime: new Date(), - secretAccessKey: 'test acc key', - sessionToken: 'test token', - }; - }); - - beforeEach(() => { - mockV2AwsSend(responseMockSuccess, { - MessageId: '1', - } as AWS.SNS.Types.PublishResponse); - }); - - describe('publish', () => { - it('topic arn', async () => { - const sns = new AWSv2.SNS(); - - await sns - .publish({ - Message: 'sns message', - TopicArn: fakeARN, - }) - .promise(); - - const publishSpans = getTestSpans().filter( - (s: ReadableSpan) => s.name === `${topicName} send` - ); - expect(publishSpans.length).toBe(1); - - const publishSpan = publishSpans[0]; - expect(publishSpan.attributes[SEMATTRS_MESSAGING_DESTINATION_KIND]).toBe( - MESSAGINGDESTINATIONKINDVALUES_TOPIC - ); - expect(publishSpan.attributes[SEMATTRS_MESSAGING_DESTINATION]).toBe( - topicName - ); - expect(publishSpan.attributes['messaging.destination.name']).toBe( - fakeARN - ); - expect(publishSpan.attributes[SEMATTRS_RPC_METHOD]).toBe('Publish'); - expect(publishSpan.attributes[SEMATTRS_MESSAGING_SYSTEM]).toBe('aws.sns'); - expect(publishSpan.kind).toBe(SpanKind.PRODUCER); - }); - - it('phone number', async () => { - const sns = new AWSv2.SNS(); - const PhoneNumber = 'my phone number'; - await sns - .publish({ - Message: 'sns message', - PhoneNumber, - }) - .promise(); - - const publishSpans = getTestSpans().filter( - (s: ReadableSpan) => s.name === 'phone_number send' - ); - expect(publishSpans.length).toBe(1); - const publishSpan = publishSpans[0]; - expect(publishSpan.attributes[SEMATTRS_MESSAGING_DESTINATION]).toBe( - PhoneNumber - ); - expect(publishSpan.attributes['messaging.destination.name']).toBe( - PhoneNumber - ); - }); - - it('inject context propagation', async () => { - const sns = new AWSv2.SNS(); - const hookSpy = sinon.spy( - (instrumentation['servicesExtensions'] as any)['services'].get('SNS'), - 'requestPostSpanHook' - ); - - await sns - .publish({ - Message: 'sns message', - TopicArn: fakeARN, - }) - .promise(); - - const publishSpans = getTestSpans().filter( - (s: ReadableSpan) => s.name === `${topicName} send` - ); - expect(publishSpans.length).toBe(1); - expect( - hookSpy.args[0][0].commandInput.MessageAttributes.traceparent - ).toBeDefined(); - }); - }); - - describe('createTopic', () => { - it('basic createTopic creates a valid span', async () => { - const sns = new AWSv2.SNS(); - - const Name = 'my new topic'; - await sns.createTopic({ Name }).promise(); - - const spans = getTestSpans(); - const createTopicSpans = spans.filter( - (s: ReadableSpan) => s.name === 'SNS CreateTopic' - ); - expect(createTopicSpans.length).toBe(1); - - const createTopicSpan = createTopicSpans[0]; - expect( - createTopicSpan.attributes[SEMATTRS_MESSAGING_DESTINATION_KIND] - ).toBeUndefined(); - expect( - createTopicSpan.attributes[SEMATTRS_MESSAGING_DESTINATION] - ).toBeUndefined(); - expect( - createTopicSpan.attributes['messaging.destination.name'] - ).toBeUndefined(); - expect(createTopicSpan.kind).toBe(SpanKind.CLIENT); - }); - }); -}); - describe('SNS - v3', () => { let sns: any; beforeEach(() => { diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/sqs.test.ts b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/sqs.test.ts deleted file mode 100644 index 62ee776562..0000000000 --- a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/sqs.test.ts +++ /dev/null @@ -1,611 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { AwsInstrumentation, AwsSdkSqsProcessHookInformation } from '../src'; -import { - getTestSpans, - registerInstrumentationTesting, -} from '@opentelemetry/contrib-test-utils'; -const instrumentation = registerInstrumentationTesting( - new AwsInstrumentation() -); -import * as AWS from 'aws-sdk'; -import { AWSError } from 'aws-sdk'; -import type { SQS } from 'aws-sdk'; - -import { - MESSAGINGDESTINATIONKINDVALUES_QUEUE, - MESSAGINGOPERATIONVALUES_PROCESS, - MESSAGINGOPERATIONVALUES_RECEIVE, - SEMATTRS_HTTP_STATUS_CODE, - SEMATTRS_MESSAGING_DESTINATION, - SEMATTRS_MESSAGING_DESTINATION_KIND, - SEMATTRS_MESSAGING_MESSAGE_ID, - SEMATTRS_MESSAGING_OPERATION, - SEMATTRS_MESSAGING_SYSTEM, - SEMATTRS_MESSAGING_URL, - SEMATTRS_RPC_METHOD, - SEMATTRS_RPC_SERVICE, - SEMATTRS_RPC_SYSTEM, -} from '@opentelemetry/semantic-conventions'; -import { - context, - SpanKind, - SpanStatusCode, - trace, - Span, -} from '@opentelemetry/api'; -import { ReadableSpan } from '@opentelemetry/sdk-trace-base'; -import { mockV2AwsSend } from './testing-utils'; -import { Message } from 'aws-sdk/clients/sqs'; -import { expect } from 'expect'; -import * as sinon from 'sinon'; -import * as messageAttributes from '../src/services/MessageAttributes'; -import { AttributeNames } from '../src/enums'; - -// set aws environment variables, so tests in non aws environment are able to run -process.env.AWS_ACCESS_KEY_ID = 'testing'; -process.env.AWS_SECRET_ACCESS_KEY = 'testing'; - -const responseMockSuccess = { - requestId: '0000000000000', - error: null, - httpResponse: { statusCode: 200 }, -} as AWS.Response; - -const extractContextSpy = sinon.spy( - messageAttributes, - 'extractPropagationContext' -); - -describe('SQS', () => { - before(() => { - AWS.config.credentials = { - accessKeyId: 'test key id', - expired: false, - expireTime: new Date(), - secretAccessKey: 'test acc key', - sessionToken: 'test token', - }; - }); - - beforeEach(() => { - mockV2AwsSend(responseMockSuccess, { - Messages: [{ Body: 'msg 1 payload' }, { Body: 'msg 2 payload' }], - } as AWS.SQS.Types.ReceiveMessageResult); - }); - - describe('receive context', () => { - const createReceiveChildSpan = () => { - const childSpan = trace - .getTracerProvider() - .getTracer('default') - .startSpan('child span of SQS.ReceiveMessage'); - childSpan.end(); - }; - - const expectReceiverWithChildSpan = (spans: ReadableSpan[]) => { - const awsReceiveSpan = spans.filter(s => s.kind === SpanKind.CONSUMER); - expect(awsReceiveSpan.length).toBe(1); - const internalSpan = spans.filter(s => s.kind === SpanKind.INTERNAL); - expect(internalSpan.length).toBe(1); - expect(internalSpan[0].parentSpanContext?.spanId).toStrictEqual( - awsReceiveSpan[0].spanContext().spanId - ); - }; - - it('should set parent context in sqs receive callback', done => { - const sqs = new AWS.SQS(); - sqs.receiveMessage( - { - QueueUrl: 'queue/url/for/unittests', - }, - (err: AWSError, data: AWS.SQS.Types.ReceiveMessageResult) => { - expect(err).toBeFalsy(); - createReceiveChildSpan(); - expectReceiverWithChildSpan(getTestSpans()); - done(); - } - ); - }); - - it("should set parent context in sqs receive 'send' callback", done => { - const sqs = new AWS.SQS(); - sqs - .receiveMessage({ - QueueUrl: 'queue/url/for/unittests', - }) - .send((err: AWSError, data: AWS.SQS.Types.ReceiveMessageResult) => { - expect(err).toBeFalsy(); - createReceiveChildSpan(); - expectReceiverWithChildSpan(getTestSpans()); - done(); - }); - }); - - it('should set parent context in sqs receive promise then', async () => { - const sqs = new AWS.SQS(); - await sqs - .receiveMessage({ - QueueUrl: 'queue/url/for/unittests', - }) - .promise() - .then(() => { - createReceiveChildSpan(); - expectReceiverWithChildSpan(getTestSpans()); - }); - }); - - it.skip('should set parent context in sqs receive after await', async () => { - const sqs = new AWS.SQS(); - await sqs - .receiveMessage({ - QueueUrl: 'queue/url/for/unittests', - }) - .promise(); - - createReceiveChildSpan(); - expectReceiverWithChildSpan(getTestSpans()); - }); - - it.skip('should set parent context in sqs receive from async function', async () => { - const asycnReceive = async () => { - const sqs = new AWS.SQS(); - return await sqs - .receiveMessage({ - QueueUrl: 'queue/url/for/unittests', - }) - .promise(); - }; - - await asycnReceive(); - createReceiveChildSpan(); - expectReceiverWithChildSpan(getTestSpans()); - }); - }); - - describe('process spans', () => { - let receivedMessages: Message[]; - - const createProcessChildSpan = (msgContext: any) => { - const processChildSpan = trace - .getTracerProvider() - .getTracer('default') - .startSpan(`child span of sqs processing span of msg ${msgContext}`); - processChildSpan.end(); - }; - - const expectReceiver2ProcessWithNChildrenEach = ( - spans: ReadableSpan[], - numChildPerProcessSpan: number - ) => { - const awsReceiveSpan = spans.filter( - s => - s.attributes[SEMATTRS_MESSAGING_OPERATION] === - MESSAGINGOPERATIONVALUES_RECEIVE - ); - expect(awsReceiveSpan.length).toBe(1); - - const processSpans = spans.filter( - s => - s.attributes[SEMATTRS_MESSAGING_OPERATION] === - MESSAGINGOPERATIONVALUES_PROCESS - ); - expect(processSpans.length).toBe(2); - expect(processSpans[0].parentSpanContext?.spanId).toStrictEqual( - awsReceiveSpan[0].spanContext().spanId - ); - expect(processSpans[1].parentSpanContext?.spanId).toStrictEqual( - awsReceiveSpan[0].spanContext().spanId - ); - - const processChildSpans = spans.filter(s => s.kind === SpanKind.INTERNAL); - expect(processChildSpans.length).toBe(2 * numChildPerProcessSpan); - for (let i = 0; i < numChildPerProcessSpan; i++) { - expect( - processChildSpans[2 * i + 0].parentSpanContext?.spanId - ).toStrictEqual(processSpans[0].spanContext().spanId); - expect( - processChildSpans[2 * i + 1].parentSpanContext?.spanId - ).toStrictEqual(processSpans[1].spanContext().spanId); - } - }; - - const expectReceiver2ProcessWith1ChildEach = (spans: ReadableSpan[]) => { - expectReceiver2ProcessWithNChildrenEach(spans, 1); - }; - - const expectReceiver2ProcessWith2ChildEach = (spans: ReadableSpan[]) => { - expectReceiver2ProcessWithNChildrenEach(spans, 2); - }; - - const contextKeyFromTest = Symbol('context key from test'); - const contextValueFromTest = 'context value from test'; - - beforeEach(async () => { - const sqs = new AWS.SQS(); - await context.with( - context.active().setValue(contextKeyFromTest, contextValueFromTest), - async () => { - const res = await sqs - .receiveMessage({ - QueueUrl: 'queue/url/for/unittests', - }) - .promise(); - receivedMessages = res.Messages!; - } - ); - }); - - it('should create processing child with forEach', async () => { - receivedMessages.forEach(msg => { - createProcessChildSpan(msg.Body); - }); - expectReceiver2ProcessWith1ChildEach(getTestSpans()); - }); - - it('should create processing child with map', async () => { - receivedMessages.map(msg => { - createProcessChildSpan(msg.Body); - }); - expectReceiver2ProcessWith1ChildEach(getTestSpans()); - }); - - it('should not fail when mapping to non-object type', async () => { - receivedMessages - .map(msg => 'map result is string') - .map(s => 'some other string'); - }); - - it('should not fail when mapping to undefined type', async () => { - receivedMessages.map(msg => undefined).map(s => 'some other string'); - }); - - it('should create one processing child when throws in map', async () => { - try { - receivedMessages.map(msg => { - createProcessChildSpan(msg.Body); - throw Error('error from array.map'); - }); - } catch (err) {} - - const processChildSpans = getTestSpans().filter( - s => s.kind === SpanKind.INTERNAL - ); - expect(processChildSpans.length).toBe(1); - }); - - it('should create processing child with two forEach', async () => { - receivedMessages.forEach(msg => { - createProcessChildSpan(msg.Body); - }); - receivedMessages.forEach(msg => { - createProcessChildSpan(msg.Body); - }); - expectReceiver2ProcessWith2ChildEach(getTestSpans()); - }); - - it('should forward all parameters to forEach callback', async () => { - const objectForThis = {}; - receivedMessages.forEach(function (this: any, msg, index, array) { - expect(msg).not.toBeUndefined(); - expect(index).toBeLessThan(2); - expect(index).toBeGreaterThanOrEqual(0); - expect(array).toBe(receivedMessages); - expect(this).toBe(objectForThis); - }, objectForThis); - }); - - it('should create one processing child with forEach that throws', async () => { - try { - receivedMessages.forEach(msg => { - createProcessChildSpan(msg.Body); - throw Error('error from forEach'); - }); - } catch (err) {} - const processChildSpans = getTestSpans().filter( - s => s.kind === SpanKind.INTERNAL - ); - expect(processChildSpans.length).toBe(1); - }); - - it.skip('should create processing child with array index access', async () => { - for (let i = 0; i < receivedMessages.length; i++) { - const msg = receivedMessages[i]; - createProcessChildSpan(msg.Body); - } - expectReceiver2ProcessWith1ChildEach(getTestSpans()); - }); - - it('should create processing child with map and forEach calls', async () => { - receivedMessages - .map(msg => ({ payload: msg.Body })) - .forEach(msgBody => { - createProcessChildSpan(msgBody); - }); - expectReceiver2ProcessWith1ChildEach(getTestSpans()); - }); - - it('should create processing child with filter and forEach', async () => { - receivedMessages - .filter(msg => msg) - .forEach(msgBody => { - createProcessChildSpan(msgBody); - }); - expectReceiver2ProcessWith1ChildEach(getTestSpans()); - }); - - it.skip('should create processing child with for(msg of messages)', () => { - for (const msg of receivedMessages) { - createProcessChildSpan(msg.Body); - } - expectReceiver2ProcessWith1ChildEach(getTestSpans()); - }); - - it.skip('should create processing child with array.values() for loop', () => { - for (const msg of receivedMessages.values()) { - createProcessChildSpan(msg.Body); - } - expectReceiver2ProcessWith1ChildEach(getTestSpans()); - }); - - it.skip('should create processing child with array.values() for loop and awaits in process', async () => { - for (const msg of receivedMessages.values()) { - await new Promise(resolve => setImmediate(resolve)); - createProcessChildSpan(msg.Body); - } - expectReceiver2ProcessWith1ChildEach(getTestSpans()); - }); - - it('should propagate the context of the receive call in process spans loop', async () => { - receivedMessages.forEach(() => { - expect(context.active().getValue(contextKeyFromTest)).toStrictEqual( - contextValueFromTest - ); - }); - }); - }); - - describe('hooks', () => { - it('sqsResponseHook for sendMessage should add messaging attributes', async () => { - const region = 'us-east-1'; - const sqs = new AWS.SQS(); - sqs.config.update({ region }); - - const QueueName = 'unittest'; - const params = { - QueueUrl: `queue/url/for/${QueueName}`, - MessageBody: 'payload example from v2 without batch', - }; - - const response = await sqs.sendMessage(params).promise(); - - expect(getTestSpans().length).toBe(1); - const [span] = getTestSpans(); - - // make sure we have the general aws attributes: - expect(span.attributes[SEMATTRS_RPC_SYSTEM]).toEqual('aws-api'); - expect(span.attributes[SEMATTRS_RPC_METHOD]).toEqual('SendMessage'); - expect(span.attributes[SEMATTRS_RPC_SERVICE]).toEqual('SQS'); - expect(span.attributes[AttributeNames.AWS_REGION]).toEqual(region); - - // custom messaging attributes - expect(span.attributes[SEMATTRS_MESSAGING_SYSTEM]).toEqual('aws.sqs'); - expect(span.attributes[SEMATTRS_MESSAGING_DESTINATION_KIND]).toEqual( - MESSAGINGDESTINATIONKINDVALUES_QUEUE - ); - expect(span.attributes[SEMATTRS_MESSAGING_DESTINATION]).toEqual( - QueueName - ); - expect(span.attributes[SEMATTRS_MESSAGING_URL]).toEqual(params.QueueUrl); - expect(span.attributes[SEMATTRS_MESSAGING_MESSAGE_ID]).toEqual( - response.MessageId - ); - expect(span.attributes[SEMATTRS_HTTP_STATUS_CODE]).toEqual(200); - }); - - it('sqsProcessHook called and add message attribute to span', async () => { - const config = { - sqsProcessHook: ( - span: Span, - sqsProcessInfo: AwsSdkSqsProcessHookInformation - ) => { - span.setAttribute( - 'attribute from sqs process hook', - sqsProcessInfo.message.Body! - ); - }, - }; - - instrumentation.setConfig(config); - - const sqs = new AWS.SQS(); - const res = await sqs - .receiveMessage({ - QueueUrl: 'queue/url/for/unittests', - }) - .promise(); - res.Messages?.map( - message => 'some mapping to create child process spans' - ); - - const processSpans = getTestSpans().filter( - s => - s.attributes[SEMATTRS_MESSAGING_OPERATION] === - MESSAGINGOPERATIONVALUES_PROCESS - ); - expect(processSpans.length).toBe(2); - expect( - processSpans[0].attributes['attribute from sqs process hook'] - ).toBe('msg 1 payload'); - expect( - processSpans[1].attributes['attribute from sqs process hook'] - ).toBe('msg 2 payload'); - }); - - it('sqsProcessHook not set in config', async () => { - const sqs = new AWS.SQS(); - const res = await sqs - .receiveMessage({ - QueueUrl: 'queue/url/for/unittests', - }) - .promise(); - res.Messages?.map( - message => 'some mapping to create child process spans' - ); - const processSpans = getTestSpans().filter( - s => - s.attributes[SEMATTRS_MESSAGING_OPERATION] === - MESSAGINGOPERATIONVALUES_PROCESS - ); - expect(processSpans.length).toBe(2); - }); - - it('sqsProcessHook throws does not fail span', async () => { - const config = { - sqsProcessHook: ( - span: Span, - sqsProcessInfo: AwsSdkSqsProcessHookInformation - ) => { - throw new Error('error from sqsProcessHook hook'); - }, - }; - instrumentation.setConfig(config); - - const sqs = new AWS.SQS(); - const res = await sqs - .receiveMessage({ - QueueUrl: 'queue/url/for/unittests', - }) - .promise(); - res.Messages?.map( - message => 'some mapping to create child process spans' - ); - - const processSpans = getTestSpans().filter( - s => - s.attributes[SEMATTRS_MESSAGING_OPERATION] === - MESSAGINGOPERATIONVALUES_PROCESS - ); - expect(processSpans.length).toBe(2); - expect(processSpans[0].status.code).toStrictEqual(SpanStatusCode.UNSET); - expect(processSpans[1].status.code).toStrictEqual(SpanStatusCode.UNSET); - }); - - it('bogus sendMessageBatch input should not crash', async () => { - const region = 'us-east-1'; - const sqs = new AWS.SQS(); - sqs.config.update({ region }); - - const QueueName = 'unittest'; - const params = { - QueueUrl: `queue/url/for/${QueueName}`, - Entries: { Key1: { MessageBody: 'This is the first message' } }, - }; - await sqs - .sendMessageBatch(params as unknown as SQS.SendMessageBatchRequest) - .promise(); - - const spans = getTestSpans(); - expect(spans.length).toBe(1); - - // Spot check a single attribute as a sanity check. - expect(spans[0].attributes[SEMATTRS_RPC_METHOD]).toEqual( - 'SendMessageBatch' - ); - }); - }); - - describe('extract payload', () => { - beforeEach(() => { - extractContextSpy.resetHistory(); - }); - it('should not extract from payload even if set', async () => { - mockV2AwsSend(responseMockSuccess, { - Messages: [{ Body: JSON.stringify({ traceparent: 1 }) }], - } as AWS.SQS.Types.ReceiveMessageResult); - - const sqs = new AWS.SQS(); - await sqs - .receiveMessage({ - QueueUrl: 'queue/url/for/unittests1', - }) - .promise(); - expect(extractContextSpy.returnValues[0]?.traceparent).toBeUndefined(); - }); - - it('should extract from payload', async () => { - const traceparent = { - traceparent: { - Value: '00-a1d050b7c8ad93c405e7a0d94cda5b03-23a485dc98b24027-01', - Type: 'String', - }, - }; - instrumentation.setConfig({ - sqsExtractContextPropagationFromPayload: true, - }); - mockV2AwsSend(responseMockSuccess, { - Messages: [ - { Body: JSON.stringify({ MessageAttributes: { traceparent } }) }, - ], - } as AWS.SQS.Types.ReceiveMessageResult); - - const sqs = new AWS.SQS(); - await sqs - .receiveMessage({ - QueueUrl: 'queue/url/for/unittests', - }) - .promise(); - expect(extractContextSpy.returnValues[0]?.traceparent).toStrictEqual( - traceparent - ); - }); - - it('should not extract from payload but from attributes', async () => { - const traceparentInPayload = 'some-trace-parent-value'; - const traceparentInMessageAttributes = { - traceparent: { - StringValue: - '00-a1d050b7c8ad93c405e7a0d94cda5b03-23a485dc98b24027-01', - DataType: 'String', - }, - }; - instrumentation.setConfig({ - sqsExtractContextPropagationFromPayload: false, - }); - mockV2AwsSend(responseMockSuccess, { - Messages: [ - { - MessageAttributes: traceparentInMessageAttributes, - Body: JSON.stringify({ - MessageAttributes: { traceparentInPayload }, - }), - }, - ], - } as AWS.SQS.Types.ReceiveMessageResult); - - const sqs = new AWS.SQS(); - await sqs - .receiveMessage({ - QueueUrl: 'queue/url/for/unittests', - }) - .promise(); - - expect(extractContextSpy.returnValues[0]).toBe( - traceparentInMessageAttributes - ); - }); - }); -}); diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/testing-utils.ts b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/testing-utils.ts deleted file mode 100644 index 7ce6d373cc..0000000000 --- a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/testing-utils.ts +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { context } from '@opentelemetry/api'; -import { isTracingSuppressed } from '@opentelemetry/core'; -import { getInstrumentation } from '@opentelemetry/contrib-test-utils'; -import { expect } from 'expect'; -import * as AWS from 'aws-sdk'; - -// we want to mock the request object and trigger events on it's events emitter. -// the event emitter is not part of the public interface, so we create a type -// for the mock to use it. -type CompleteEventHandler = (response: AWS.Response) => void; -type RequestWithEvents = AWS.Request & { - _events: { complete: CompleteEventHandler[] }; -}; - -export const mockV2AwsSend = ( - sendResult: any, - data: any = undefined, - expectedInstrumentationSuppressed = false -) => { - // since we are setting a new value to a function being patched by the instrumentation, - // we need to disable and enable again to make the patch for the new function. - // I would like to see another pattern for this in the future, for example - patching only - // once and just setting the result and data, or patching the http layer instead with nock package. - getInstrumentation()?.disable(); - AWS.Request.prototype.send = function ( - this: RequestWithEvents, - cb?: (error: any, response: any) => void - ) { - expect(isTracingSuppressed(context.active())).toStrictEqual( - expectedInstrumentationSuppressed - ); - if (cb) { - (this as AWS.Request).on('complete', response => { - cb(response.error, response); - }); - } - const response = { - ...sendResult, - data, - request: this, - }; - setImmediate(() => { - this._events.complete.forEach( - (handler: (response: AWS.Response) => void) => - handler(response) - ); - }); - return response; - }; - - AWS.Request.prototype.promise = function (this: RequestWithEvents) { - expect(isTracingSuppressed(context.active())).toStrictEqual( - expectedInstrumentationSuppressed - ); - const response = { - ...sendResult, - data, - request: this, - }; - setImmediate(() => { - this._events.complete.forEach( - (handler: (response: AWS.Response) => void) => - handler(response) - ); - }); - return new Promise(resolve => - setImmediate(() => { - resolve(data); - }) - ); - }; - getInstrumentation()?.enable(); -}; diff --git a/plugins/node/opentelemetry-instrumentation-mongodb/package.json b/plugins/node/opentelemetry-instrumentation-mongodb/package.json index 120222a3c0..487eb2bdb4 100644 --- a/plugins/node/opentelemetry-instrumentation-mongodb/package.json +++ b/plugins/node/opentelemetry-instrumentation-mongodb/package.json @@ -7,7 +7,7 @@ "repository": "open-telemetry/opentelemetry-js-contrib", "scripts": { "docker:start": "docker run -e MONGODB_DB=opentelemetry-tests -e MONGODB_PORT=27017 -e MONGODB_HOST=127.0.0.1 -p 27017:27017 --rm mongo", - "test": "npm run test-v3 && npm run test-v4 && npm run test-v5-v6 && nyc merge .nyc_output ./coverage/coverage-final.json", + "test": "npm run test-v4 && npm run test-v5-v6", "test-v3": "tav mongodb 3.7.4 npm run test-v3-run", "test-v4": "tav mongodb 4.17.0 npm run test-v4-run", "test-v5-v6": "npm run test-v5-v6-run", @@ -60,7 +60,7 @@ "@types/bson": "4.0.5", "@types/mocha": "10.0.10", "@types/node": "18.18.14", - "mongodb": "6.8.0", + "mongodb": "6.15.0", "nyc": "15.1.0", "rimraf": "5.0.10", "test-all-versions": "6.1.0", diff --git a/plugins/node/opentelemetry-instrumentation-nestjs-core/.tav.yml b/plugins/node/opentelemetry-instrumentation-nestjs-core/.tav.yml index 4018e3d204..9cf60ed208 100644 --- a/plugins/node/opentelemetry-instrumentation-nestjs-core/.tav.yml +++ b/plugins/node/opentelemetry-instrumentation-nestjs-core/.tav.yml @@ -1,4 +1,17 @@ "@nestjs/core": + - versions: + include: ">=11.0.0 <12" + mode: latest-minors + # NestJS 11 requires Node.js v20 or later. + # https://docs.nestjs.com/migration-guide#nodejs-v16-and-v18-no-longer-supported + node: ">=20" + peerDependencies: + - "@nestjs/common@^11.0.0" + - "@nestjs/platform-express@^11.0.0" + - "reflect-metadata@^0.1.12" + - "rxjs@^7.1.0" + commands: npm run test + - versions: include: ">=10.0.0 <11" mode: latest-minors @@ -8,24 +21,37 @@ peerDependencies: - "@nestjs/common@^10.0.0" - "@nestjs/platform-express@^10.0.0" + - "reflect-metadata@^0.1.12" - "rxjs@^7.1.0" commands: npm run test - versions: include: ">=9.0.0 <10" mode: latest-minors + # NestJS 8.4.4+ requires Node.js v15 or later, + # because it's using "Nullish coalescing assignment" + # https://github.com/nestjs/nest/releases/tag/v8.4.4 + # https://github.com/nestjs/nest/pull/9435 + node: ">=15" peerDependencies: - "@nestjs/common@^9.0.0" - "@nestjs/platform-express@^9.0.0" + - "reflect-metadata@^0.1.12" - "rxjs@^7.1.0" commands: npm run test - versions: - include: ">=8.0.0 <9" + include: ">=8.0.0 <9.0.0" mode: latest-minors + # NestJS 8.4.4+ requires Node.js v15 or later, + # because it's using "Nullish coalescing assignment" + # https://github.com/nestjs/nest/releases/tag/v8.4.4 + # https://github.com/nestjs/nest/pull/9435 + node: ">=15" peerDependencies: - "@nestjs/common@^8.0.0" - "@nestjs/platform-express@^8.0.0" + - "reflect-metadata@^0.1.12" - "rxjs@^7.1.0" commands: npm run test @@ -36,6 +62,7 @@ peerDependencies: - "@nestjs/common@^7.0.0" - "@nestjs/platform-express@^7.0.0" + - "reflect-metadata@^0.1.12" - "rxjs@^6.0.0" commands: npm run test @@ -43,5 +70,6 @@ peerDependencies: - "@nestjs/common@^6.0.0" - "@nestjs/platform-express@^6.0.0" + - "reflect-metadata@^0.1.12" - "rxjs@^6.0.0" commands: npm run test diff --git a/plugins/node/opentelemetry-instrumentation-nestjs-core/CHANGELOG.md b/plugins/node/opentelemetry-instrumentation-nestjs-core/CHANGELOG.md index 84a4201e0a..4222faaea0 100644 --- a/plugins/node/opentelemetry-instrumentation-nestjs-core/CHANGELOG.md +++ b/plugins/node/opentelemetry-instrumentation-nestjs-core/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.46.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-nestjs-core-v0.45.0...instrumentation-nestjs-core-v0.46.0) (2025-04-08) + + +### Features + +* **instrumentation-nestjs-core:** add support for NestJS 11 ([#2685](https://github.com/open-telemetry/opentelemetry-js-contrib/issues/2685)) ([67e37b7](https://github.com/open-telemetry/opentelemetry-js-contrib/commit/67e37b78ab46273e937fb959b6c8cdcf9e16c8fb)) + ## [0.45.0](https://github.com/open-telemetry/opentelemetry-js-contrib/compare/instrumentation-nestjs-core-v0.44.1...instrumentation-nestjs-core-v0.45.0) (2025-03-18) diff --git a/plugins/node/opentelemetry-instrumentation-nestjs-core/package.json b/plugins/node/opentelemetry-instrumentation-nestjs-core/package.json index 9b21d61dbf..6639096e8f 100644 --- a/plugins/node/opentelemetry-instrumentation-nestjs-core/package.json +++ b/plugins/node/opentelemetry-instrumentation-nestjs-core/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/instrumentation-nestjs-core", - "version": "0.45.0", + "version": "0.46.0", "description": "OpenTelemetry instrumentation for NestJS server side applications framework", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -14,7 +14,8 @@ "prewatch": "npm run precompile", "prepublishOnly": "npm run compile", "tdd": "npm run test -- --watch-extensions ts --watch", - "test": "nyc mocha --timeout 5000 'test/**/*.test.ts'", + "test": "npm run test-required-node-version && nyc mocha --timeout 5000 'test/**/*.test.ts' || echo 'Node version is not supported for testing'", + "test-required-node-version": "node -e \"process.exit(parseInt(process.versions.node.split('.')[0], 10) >= 15 ? 0 : 1)\"", "test-all-versions": "tav", "version:update": "node ../../../scripts/version-update.js" }, @@ -44,9 +45,9 @@ "@opentelemetry/api": "^1.3.0" }, "devDependencies": { - "@nestjs/common": "9.4.3", - "@nestjs/core": "9.4.3", - "@nestjs/platform-express": "9.4.3", + "@nestjs/common": "11.0.10", + "@nestjs/core": "11.0.10", + "@nestjs/platform-express": "11.0.10", "@opentelemetry/api": "^1.3.0", "@opentelemetry/context-async-hooks": "^2.0.0", "@opentelemetry/sdk-trace-base": "^2.0.0", @@ -56,7 +57,7 @@ "@types/semver": "7.5.8", "cross-env": "7.0.3", "nyc": "15.1.0", - "reflect-metadata": "0.1.13", + "reflect-metadata": "0.2.2", "rimraf": "5.0.10", "rxjs": "7.8.2", "rxjs-compat": "6.6.7", @@ -66,7 +67,7 @@ }, "dependencies": { "@opentelemetry/instrumentation": "^0.200.0", - "@opentelemetry/semantic-conventions": "^1.27.0" + "@opentelemetry/semantic-conventions": "^1.30.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-nestjs-core#readme" } diff --git a/plugins/node/opentelemetry-instrumentation-nestjs-core/src/instrumentation.ts b/plugins/node/opentelemetry-instrumentation-nestjs-core/src/instrumentation.ts index edc7bc5d2f..680f246e52 100644 --- a/plugins/node/opentelemetry-instrumentation-nestjs-core/src/instrumentation.ts +++ b/plugins/node/opentelemetry-instrumentation-nestjs-core/src/instrumentation.ts @@ -34,7 +34,7 @@ import { } from '@opentelemetry/semantic-conventions'; import { AttributeNames, NestType } from './enums'; -const supportedVersions = ['>=4.0.0 <11']; +const supportedVersions = ['>=4.0.0 <12']; export class NestInstrumentation extends InstrumentationBase { static readonly COMPONENT = '@nestjs/core'; diff --git a/release-please-config.json b/release-please-config.json index b0993722d4..a55d06f9ec 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -17,6 +17,7 @@ "metapackages/auto-instrumentations-node": {}, "metapackages/auto-instrumentations-web": {}, "packages/baggage-span-processor": {}, + "packages/baggage-log-record-processor": {}, "packages/opentelemetry-host-metrics": {}, "packages/opentelemetry-id-generator-aws-xray": {}, "packages/opentelemetry-propagation-utils": {},