diff --git a/.gitignore b/.gitignore index 6fc48da2..5b41478f 100644 --- a/.gitignore +++ b/.gitignore @@ -114,6 +114,7 @@ test/component/node/spans-test*.json .vscode test-spans*.json +test-logs*.json # ignore typescript build files test/helpers/*.d.ts diff --git a/README.md b/README.md index 85638430..b4787c79 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,10 @@ The Lumigo OpenTelemetry Distribution for Node.js is made of several upstream Op **Note:** If you are looking for the Lumigo Node.js tracer for AWS Lambda functions, [`@lumigo/tracer`](https://npm.io/package/@lumigo/tracer) is the package you should use instead. +## Logging support +The Lumigo OpenTelemetry Distribution also allows logging span-correlated records. See the [configuration](#logging-instrumentation) section for details on how to enable this feature. +When using the logging feature, the same set of rules for [secret masking](#lumigo-specific-configurations) applies on the content of the log message, with only `LUMIGO_SECRET_MASKING_REGEX` being considered. + ## Setup ### Add @lumigo/opentelemetry as dependency @@ -113,9 +117,27 @@ This setting is independent from `LUMIGO_DEBUG`, that is, `LUMIGO_DEBUG` does no * `LUMIGO_FILTER_HTTP_ENDPOINTS_REGEX='["regex1", "regex2"]'`: This option enables the filtering of client and server endpoints through regular expression searches. Fine-tune your settings via the following environment variables, which work in conjunction with `LUMIGO_FILTER_HTTP_ENDPOINTS_REGEX` for a specific span type: * `LUMIGO_FILTER_HTTP_ENDPOINTS_REGEX_SERVER` applies the regular expression search exclusively to server spans. Searching is performed against the following attributes on a span: `url.path` and `http.target`. * `LUMIGO_FILTER_HTTP_ENDPOINTS_REGEX_CLIENT` applies the regular expression search exclusively to client spans. Searching is performed against the following attributes on a span: `url.full` and `http.url`. - + For more information check out [Filtering http endpoints](#filtering-http-endpoints). +#### Logging instrumentation + +* `LUMIGO_ENABLE_LOGS` - Default: `false`. When set to `true`, turns on the logging instrumentations (currently for the [Winston](https://github.com/winstonjs/winston) and [Bunyan](https://github.com/trentm/node-bunyan) loggers) to capture log-records and send them to Lumigo. Emitted logs will also get injected with the active span context, e.g.: +```js + // ... + "body": "Hello Winston!", + "attributes": { + "trace_id": "1fce43bfd3fdde3f1a9ea1adc78b521d", + "span_id": "13c05292d3b5f5e8", + "trace_flags": "01" + } + "severityText": "info", + // ... +``` +Note that logging support is applicable only when using versions of the logging libraries listed [here](##supported-packages). + +* `LUMIGO_DEBUG_LOGDUMP` - similar to `LUMIGO_DEBUG_SPANDUMP`, only for logs instead of spans. Effective only when `LUMIGO_ENABLE_LOGS` is set to `true`. + ### Execution Tags [Execution Tags](https://docs.lumigo.io/docs/execution-tags) allow you to dynamically add dimensions to your invocations so that they can be identified, searched for, and filtered in Lumigo. @@ -491,7 +513,7 @@ For exclusive server (inbound) or client (outbound) span filtering, use the envi Notes: * the environment variable must be a valid JSON array of strings, so if you want to match endpoint with the hostname `google.com` the environment variable value should be `["google\\.com"]`. -* If we are filtering out an HTTP call to an opentelemetry traced component, every subsequent invocation made by that +* If we are filtering out an HTTP call to an opentelemetry traced component, every subsequent invocation made by that component won't be traced either. Examples: diff --git a/package-lock.json b/package-lock.json index ae70c0ae..a4136084 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,16 +6,18 @@ "packages": { "": { "name": "@lumigo/opentelemetry", - "version": "1.38.0", + "version": "1.39.1", "license": "Apache-2.0", "dependencies": { "@lumigo/node-core": "1.14.0", "@opentelemetry/api": "1.4.1", "@opentelemetry/core": "1.17.1", - "@opentelemetry/exporter-trace-otlp-http": "0.38.0", - "@opentelemetry/instrumentation": "0.38.0", + "@opentelemetry/exporter-logs-otlp-http": "0.51.0", + "@opentelemetry/exporter-trace-otlp-http": "0.51.0", + "@opentelemetry/instrumentation": "0.51.0", "@opentelemetry/instrumentation-amqplib": "0.33.2", "@opentelemetry/instrumentation-aws-sdk": "^0.38.1", + "@opentelemetry/instrumentation-bunyan": "0.37.0", "@opentelemetry/instrumentation-fastify": "^0.32.3", "@opentelemetry/instrumentation-grpc": "^0.41.0", "@opentelemetry/instrumentation-http": "0.38.0", @@ -24,11 +26,14 @@ "@opentelemetry/instrumentation-nestjs-core": "^0.34.0", "@opentelemetry/instrumentation-pg": "^0.38.0", "@opentelemetry/instrumentation-redis-4": "^0.35.3", + "@opentelemetry/instrumentation-winston": "0.36.0", "@opentelemetry/resource-detector-aws": "1.3.2", "@opentelemetry/resources": "1.17.1", + "@opentelemetry/sdk-logs": "^0.50.0", "@opentelemetry/sdk-trace-base": "1.9.1", "@opentelemetry/sdk-trace-node": "1.9.1", "@opentelemetry/semantic-conventions": "1.17.1", + "@opentelemetry/winston-transport": "0.2.0", "@prisma/instrumentation": "^4.14.0", "opentelemetry-instrumentation-express": "0.39.1", "opentelemetry-instrumentation-kafkajs": "^0.39.1", @@ -64,6 +69,7 @@ "eslint": "^8.40.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-prettier": "^3.4.0", + "express": "^4.19.2", "jest": "^29.4.0", "jest-chain": "^1.1.6", "jest-expect-message": "^1.1.3", @@ -76,6 +82,7 @@ "mock-http-server": "^1.4.5", "node-notifier": "^10.0.0", "npm-install-peers": "^1.2.2", + "p-retry": "^4.6.1", "prettier": "^2.2.1", "rimraf": "^3.0.2", "semantic-release": "^19.0.2", @@ -3138,6 +3145,17 @@ "node": ">=8.0.0" } }, + "node_modules/@opentelemetry/api-logs": { + "version": "0.50.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.50.0.tgz", + "integrity": "sha512-JdZuKrhOYggqOpUljAq4WWNi5nB10PmgoF0y2CvedLGXd0kSawb/UBnWT8gg1ND3bHCNHStAIVT0ELlxJJRqrA==", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/@opentelemetry/context-async-hooks": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-1.9.1.tgz", @@ -3163,16 +3181,98 @@ "@opentelemetry/api": ">=1.0.0 <1.7.0" } }, + "node_modules/@opentelemetry/exporter-logs-otlp-http": { + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.51.0.tgz", + "integrity": "sha512-7G+RUQ+HzLaQw5sl2hKLYmZ/pWuaZ3IR7+gLIZNS9RpLeEnG/mbNENM2YTWQYPwX/7YpSJUC1NAaiMYxQco0ow==", + "dependencies": { + "@opentelemetry/api-logs": "0.51.0", + "@opentelemetry/core": "1.24.0", + "@opentelemetry/otlp-exporter-base": "0.51.0", + "@opentelemetry/otlp-transformer": "0.51.0", + "@opentelemetry/sdk-logs": "0.51.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/exporter-logs-otlp-http/node_modules/@opentelemetry/api-logs": { + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.51.0.tgz", + "integrity": "sha512-m/jtfBPEIXS1asltl8fPQtO3Sb1qMpuL61unQajUmM8zIxeMF1AlqzWXM3QedcYgTTFiJCew5uJjyhpmqhc0+g==", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/exporter-logs-otlp-http/node_modules/@opentelemetry/core": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.24.0.tgz", + "integrity": "sha512-FP2oN7mVPqcdxJDTTnKExj4mi91EH+DNuArKfHTjPuJWe2K1JfMIVXNfahw1h3onJxQnxS8K0stKkogX05s+Aw==", + "dependencies": { + "@opentelemetry/semantic-conventions": "1.24.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.9.0" + } + }, + "node_modules/@opentelemetry/exporter-logs-otlp-http/node_modules/@opentelemetry/resources": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.24.0.tgz", + "integrity": "sha512-mxC7E7ocUS1tLzepnA7O9/G8G6ZTdjCH2pXme1DDDuCuk6n2/53GADX+GWBuyX0dfIxeMInIbJAdjlfN9GNr6A==", + "dependencies": { + "@opentelemetry/core": "1.24.0", + "@opentelemetry/semantic-conventions": "1.24.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.9.0" + } + }, + "node_modules/@opentelemetry/exporter-logs-otlp-http/node_modules/@opentelemetry/sdk-logs": { + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.51.0.tgz", + "integrity": "sha512-K4fMBRFD8hQ6khk0rvYFuo6L9ymeGgByir6BcuFIgQuQ00OhYwBi9AruZz5V733Ejq7P8ObR3YyubkOUIbeVAw==", + "dependencies": { + "@opentelemetry/core": "1.24.0", + "@opentelemetry/resources": "1.24.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.4.0 <1.9.0", + "@opentelemetry/api-logs": ">=0.39.1" + } + }, + "node_modules/@opentelemetry/exporter-logs-otlp-http/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.24.0.tgz", + "integrity": "sha512-yL0jI6Ltuz8R+Opj7jClGrul6pOoYrdfVmzQS4SITXRPH7I5IRZbrwe/6/v8v4WYMa6MYZG480S1+uc/IGfqsA==", + "engines": { + "node": ">=14" + } + }, "node_modules/@opentelemetry/exporter-trace-otlp-http": { - "version": "0.38.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.38.0.tgz", - "integrity": "sha512-AWpTCyijC7kt2DbLj8FmdlRquA6/rTXZ+3U4MVl4P2YNI7KLUnx/FEhn2BMTB0+rOy7UxSAocqz2tJ/5Ss/6Ng==", + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.51.0.tgz", + "integrity": "sha512-zODqnLZmPOxj9CarFv0TrVlx9mgj0TfCMCiUiTdNi9iA2rgdKVo+bjJjpYF6LCTJOQCR5TScAUCKyzwkgDI+iA==", "dependencies": { - "@opentelemetry/core": "1.12.0", - "@opentelemetry/otlp-exporter-base": "0.38.0", - "@opentelemetry/otlp-transformer": "0.38.0", - "@opentelemetry/resources": "1.12.0", - "@opentelemetry/sdk-trace-base": "1.12.0" + "@opentelemetry/core": "1.24.0", + "@opentelemetry/otlp-exporter-base": "0.51.0", + "@opentelemetry/otlp-transformer": "0.51.0", + "@opentelemetry/resources": "1.24.0", + "@opentelemetry/sdk-trace-base": "1.24.0" }, "engines": { "node": ">=14" @@ -3182,65 +3282,68 @@ } }, "node_modules/@opentelemetry/exporter-trace-otlp-http/node_modules/@opentelemetry/core": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.12.0.tgz", - "integrity": "sha512-4DWYNb3dLs2mSCGl65jY3aEgbvPWSHVQV/dmDWiYeWUrMakZQFcymqZOSUNZO0uDrEJoxMu8O5tZktX6UKFwag==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.24.0.tgz", + "integrity": "sha512-FP2oN7mVPqcdxJDTTnKExj4mi91EH+DNuArKfHTjPuJWe2K1JfMIVXNfahw1h3onJxQnxS8K0stKkogX05s+Aw==", "dependencies": { - "@opentelemetry/semantic-conventions": "1.12.0" + "@opentelemetry/semantic-conventions": "1.24.0" }, "engines": { "node": ">=14" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.5.0" + "@opentelemetry/api": ">=1.0.0 <1.9.0" } }, "node_modules/@opentelemetry/exporter-trace-otlp-http/node_modules/@opentelemetry/resources": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.12.0.tgz", - "integrity": "sha512-gunMKXG0hJrR0LXrqh7BVbziA/+iJBL3ZbXCXO64uY+SrExkwoyJkpiq9l5ismkGF/A20mDEV7tGwh+KyPw00Q==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.24.0.tgz", + "integrity": "sha512-mxC7E7ocUS1tLzepnA7O9/G8G6ZTdjCH2pXme1DDDuCuk6n2/53GADX+GWBuyX0dfIxeMInIbJAdjlfN9GNr6A==", "dependencies": { - "@opentelemetry/core": "1.12.0", - "@opentelemetry/semantic-conventions": "1.12.0" + "@opentelemetry/core": "1.24.0", + "@opentelemetry/semantic-conventions": "1.24.0" }, "engines": { "node": ">=14" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.5.0" + "@opentelemetry/api": ">=1.0.0 <1.9.0" } }, "node_modules/@opentelemetry/exporter-trace-otlp-http/node_modules/@opentelemetry/sdk-trace-base": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.12.0.tgz", - "integrity": "sha512-pfCOB3tNDlYVoWuz4D7Ji+Jmy9MHnATWHVpkERdCEiwUGEZ+4IvNPXUcPc37wJVmMpjGLeaWgPPrie0KIpWf1A==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.24.0.tgz", + "integrity": "sha512-H9sLETZ4jw9UJ3totV8oM5R0m4CW0ZIOLfp4NV3g0CM8HD5zGZcaW88xqzWDgiYRpctFxd+WmHtGX/Upoa2vRg==", "dependencies": { - "@opentelemetry/core": "1.12.0", - "@opentelemetry/resources": "1.12.0", - "@opentelemetry/semantic-conventions": "1.12.0" + "@opentelemetry/core": "1.24.0", + "@opentelemetry/resources": "1.24.0", + "@opentelemetry/semantic-conventions": "1.24.0" }, "engines": { "node": ">=14" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.5.0" + "@opentelemetry/api": ">=1.0.0 <1.9.0" } }, "node_modules/@opentelemetry/exporter-trace-otlp-http/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.12.0.tgz", - "integrity": "sha512-hO+bdeGOlJwqowUBoZF5LyP3ORUFOP1G0GRv8N45W/cztXbT2ZEXaAzfokRS9Xc9FWmYrDj32mF6SzH6wuoIyA==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.24.0.tgz", + "integrity": "sha512-yL0jI6Ltuz8R+Opj7jClGrul6pOoYrdfVmzQS4SITXRPH7I5IRZbrwe/6/v8v4WYMa6MYZG480S1+uc/IGfqsA==", "engines": { "node": ">=14" } }, "node_modules/@opentelemetry/instrumentation": { - "version": "0.38.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.38.0.tgz", - "integrity": "sha512-wr1WkIbzHGV+oz6SCme88D2c+zNG23COkCjcida8b3jIzX2lJafOpEHPDcbBF38F8ChkRSj/tVnx1wnYAXZvbA==", + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.51.0.tgz", + "integrity": "sha512-Eg/+Od5bEvzpvZQGhvMyKIkrzB9S7jW+6z9LHEI2VXhl/GrqQ3oBqlzJt4tA6pGtxRmqQWKWGM1wAbwDdW/gUA==", "dependencies": { - "require-in-the-middle": "^6.0.0", - "semver": "^7.3.2", + "@opentelemetry/api-logs": "0.51.0", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "1.7.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", "shimmer": "^1.2.1" }, "engines": { @@ -3284,19 +3387,6 @@ "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@opentelemetry/instrumentation-amqplib/node_modules/require-in-the-middle": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz", - "integrity": "sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw==", - "dependencies": { - "debug": "^4.1.1", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.1" - }, - "engines": { - "node": ">=8.6.0" - } - }, "node_modules/@opentelemetry/instrumentation-aws-sdk": { "version": "0.38.1", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-aws-sdk/-/instrumentation-aws-sdk-0.38.1.tgz", @@ -3343,17 +3433,50 @@ "module-details-from-path": "^1.0.3" } }, - "node_modules/@opentelemetry/instrumentation-aws-sdk/node_modules/require-in-the-middle": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz", - "integrity": "sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw==", + "node_modules/@opentelemetry/instrumentation-bunyan": { + "version": "0.37.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-bunyan/-/instrumentation-bunyan-0.37.0.tgz", + "integrity": "sha512-NKHuTIn1JrxfKZ8sVZjwT/bD3wyijkipiWzBvvxGj8pJJJNP5shVHWcEJhk5tQsfKQc4LproTAPdklex1o5/ag==", "dependencies": { - "debug": "^4.1.1", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.1" + "@opentelemetry/api-logs": "^0.50.0", + "@opentelemetry/instrumentation": "^0.50.0", + "@types/bunyan": "1.8.9" }, "engines": { - "node": ">=8.6.0" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-bunyan/node_modules/@opentelemetry/instrumentation": { + "version": "0.50.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.50.0.tgz", + "integrity": "sha512-bhGhbJiZKpuu7wTaSak4hyZcFPlnDeuSF/2vglze8B4w2LubcSbbOnkVTzTs5SXtzh4Xz8eRjaNnAm+u2GYufQ==", + "dependencies": { + "@opentelemetry/api-logs": "0.50.0", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "1.7.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-bunyan/node_modules/import-in-the-middle": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.7.1.tgz", + "integrity": "sha512-1LrZPDtW+atAxH42S6288qyDFNQ2YCty+2mxEPRtfazH6Z5QwkaBSTS2ods7hnVJioF6rkRfNoA6A/MstpFXLg==", + "dependencies": { + "acorn": "^8.8.2", + "acorn-import-assertions": "^1.9.0", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" } }, "node_modules/@opentelemetry/instrumentation-fastify": { @@ -3390,19 +3513,6 @@ "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@opentelemetry/instrumentation-fastify/node_modules/require-in-the-middle": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz", - "integrity": "sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw==", - "dependencies": { - "debug": "^4.1.1", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.1" - }, - "engines": { - "node": ">=8.6.0" - } - }, "node_modules/@opentelemetry/instrumentation-grpc": { "version": "0.41.2", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-grpc/-/instrumentation-grpc-0.41.2.tgz", @@ -3444,19 +3554,6 @@ "node": ">=14" } }, - "node_modules/@opentelemetry/instrumentation-grpc/node_modules/require-in-the-middle": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz", - "integrity": "sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw==", - "dependencies": { - "debug": "^4.1.1", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.1" - }, - "engines": { - "node": ">=8.6.0" - } - }, "node_modules/@opentelemetry/instrumentation-http": { "version": "0.38.0", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.38.0.tgz", @@ -3488,6 +3585,22 @@ "@opentelemetry/api": ">=1.0.0 <1.5.0" } }, + "node_modules/@opentelemetry/instrumentation-http/node_modules/@opentelemetry/instrumentation": { + "version": "0.38.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.38.0.tgz", + "integrity": "sha512-wr1WkIbzHGV+oz6SCme88D2c+zNG23COkCjcida8b3jIzX2lJafOpEHPDcbBF38F8ChkRSj/tVnx1wnYAXZvbA==", + "dependencies": { + "require-in-the-middle": "^6.0.0", + "semver": "^7.3.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, "node_modules/@opentelemetry/instrumentation-http/node_modules/@opentelemetry/semantic-conventions": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.12.0.tgz", @@ -3496,6 +3609,19 @@ "node": ">=14" } }, + "node_modules/@opentelemetry/instrumentation-http/node_modules/require-in-the-middle": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-6.0.0.tgz", + "integrity": "sha512-+dtWQ7l2lqQDxheaG3jjyN1QI37gEwvzACSgjYi4/C2y+ZTUMeRW8BIOm+9NBKvwaMBUSZfPXVOt1skB0vBkRw==", + "dependencies": { + "debug": "^4.1.1", + "module-details-from-path": "^1.0.3", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=8.6.0" + } + }, "node_modules/@opentelemetry/instrumentation-ioredis": { "version": "0.35.2", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.35.2.tgz", @@ -3531,19 +3657,6 @@ "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@opentelemetry/instrumentation-ioredis/node_modules/require-in-the-middle": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz", - "integrity": "sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw==", - "dependencies": { - "debug": "^4.1.1", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.1" - }, - "engines": { - "node": ">=8.6.0" - } - }, "node_modules/@opentelemetry/instrumentation-mongodb": { "version": "0.39.0", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.39.0.tgz", @@ -3589,19 +3702,6 @@ "module-details-from-path": "^1.0.3" } }, - "node_modules/@opentelemetry/instrumentation-mongodb/node_modules/require-in-the-middle": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz", - "integrity": "sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw==", - "dependencies": { - "debug": "^4.1.1", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.1" - }, - "engines": { - "node": ">=8.6.0" - } - }, "node_modules/@opentelemetry/instrumentation-nestjs-core": { "version": "0.34.0", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-nestjs-core/-/instrumentation-nestjs-core-0.34.0.tgz", @@ -3646,19 +3746,6 @@ "module-details-from-path": "^1.0.3" } }, - "node_modules/@opentelemetry/instrumentation-nestjs-core/node_modules/require-in-the-middle": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz", - "integrity": "sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw==", - "dependencies": { - "debug": "^4.1.1", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.1" - }, - "engines": { - "node": ">=8.6.0" - } - }, "node_modules/@opentelemetry/instrumentation-pg": { "version": "0.38.0", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.38.0.tgz", @@ -3706,19 +3793,6 @@ "module-details-from-path": "^1.0.3" } }, - "node_modules/@opentelemetry/instrumentation-pg/node_modules/require-in-the-middle": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz", - "integrity": "sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw==", - "dependencies": { - "debug": "^4.1.1", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.1" - }, - "engines": { - "node": ">=8.6.0" - } - }, "node_modules/@opentelemetry/instrumentation-redis-4": { "version": "0.35.3", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis-4/-/instrumentation-redis-4-0.35.3.tgz", @@ -3753,25 +3827,78 @@ "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@opentelemetry/instrumentation-redis-4/node_modules/require-in-the-middle": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz", - "integrity": "sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw==", + "node_modules/@opentelemetry/instrumentation-winston": { + "version": "0.36.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-winston/-/instrumentation-winston-0.36.0.tgz", + "integrity": "sha512-NTuGpUA9AGC7EmKQyMn3ABiqJ3XvHihRcxdvqhs8E72nHmIU3n6om+DCYYE3fpEQwbC9N14ir8fqA5Oxn0Ynag==", "dependencies": { - "debug": "^4.1.1", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.1" + "@opentelemetry/instrumentation": "^0.50.0" }, "engines": { - "node": ">=8.6.0" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-winston/node_modules/@opentelemetry/instrumentation": { + "version": "0.50.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.50.0.tgz", + "integrity": "sha512-bhGhbJiZKpuu7wTaSak4hyZcFPlnDeuSF/2vglze8B4w2LubcSbbOnkVTzTs5SXtzh4Xz8eRjaNnAm+u2GYufQ==", + "dependencies": { + "@opentelemetry/api-logs": "0.50.0", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "1.7.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-winston/node_modules/import-in-the-middle": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.7.1.tgz", + "integrity": "sha512-1LrZPDtW+atAxH42S6288qyDFNQ2YCty+2mxEPRtfazH6Z5QwkaBSTS2ods7hnVJioF6rkRfNoA6A/MstpFXLg==", + "dependencies": { + "acorn": "^8.8.2", + "acorn-import-assertions": "^1.9.0", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation/node_modules/@opentelemetry/api-logs": { + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.51.0.tgz", + "integrity": "sha512-m/jtfBPEIXS1asltl8fPQtO3Sb1qMpuL61unQajUmM8zIxeMF1AlqzWXM3QedcYgTTFiJCew5uJjyhpmqhc0+g==", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation/node_modules/import-in-the-middle": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.7.1.tgz", + "integrity": "sha512-1LrZPDtW+atAxH42S6288qyDFNQ2YCty+2mxEPRtfazH6Z5QwkaBSTS2ods7hnVJioF6rkRfNoA6A/MstpFXLg==", + "dependencies": { + "acorn": "^8.8.2", + "acorn-import-assertions": "^1.9.0", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" } }, "node_modules/@opentelemetry/otlp-exporter-base": { - "version": "0.38.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.38.0.tgz", - "integrity": "sha512-VWQo7vUDyW/7/FT8RErAtM/29i/fllCc9xMtnK7kDuheAjJU68zrZ88bQOsLamHvOCU3KVpozjfTZVxZKQRYXw==", + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.51.0.tgz", + "integrity": "sha512-hR4c9vWVz1QgzCBSyy9zSDkvfTgaK96E6/tfVP6O4dzdZW9HqWimA3lXV/KXadEGqShvM4GToz9EHp2A5RU5bQ==", "dependencies": { - "@opentelemetry/core": "1.12.0" + "@opentelemetry/core": "1.24.0" }, "engines": { "node": ">=14" @@ -3781,109 +3908,122 @@ } }, "node_modules/@opentelemetry/otlp-exporter-base/node_modules/@opentelemetry/core": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.12.0.tgz", - "integrity": "sha512-4DWYNb3dLs2mSCGl65jY3aEgbvPWSHVQV/dmDWiYeWUrMakZQFcymqZOSUNZO0uDrEJoxMu8O5tZktX6UKFwag==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.24.0.tgz", + "integrity": "sha512-FP2oN7mVPqcdxJDTTnKExj4mi91EH+DNuArKfHTjPuJWe2K1JfMIVXNfahw1h3onJxQnxS8K0stKkogX05s+Aw==", "dependencies": { - "@opentelemetry/semantic-conventions": "1.12.0" + "@opentelemetry/semantic-conventions": "1.24.0" }, "engines": { "node": ">=14" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.5.0" + "@opentelemetry/api": ">=1.0.0 <1.9.0" } }, "node_modules/@opentelemetry/otlp-exporter-base/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.12.0.tgz", - "integrity": "sha512-hO+bdeGOlJwqowUBoZF5LyP3ORUFOP1G0GRv8N45W/cztXbT2ZEXaAzfokRS9Xc9FWmYrDj32mF6SzH6wuoIyA==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.24.0.tgz", + "integrity": "sha512-yL0jI6Ltuz8R+Opj7jClGrul6pOoYrdfVmzQS4SITXRPH7I5IRZbrwe/6/v8v4WYMa6MYZG480S1+uc/IGfqsA==", "engines": { "node": ">=14" } }, "node_modules/@opentelemetry/otlp-transformer": { - "version": "0.38.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.38.0.tgz", - "integrity": "sha512-ykQEipby0NVSi2ih5E8J2GNJ6y9zYDPSef0nD8j33XPKxfyVG5184rUrCsh6TIk1d/GlYl8gB9Wy4TdRvwl6kA==", + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.51.0.tgz", + "integrity": "sha512-ylLgx2xumVoSefDHP9GMAU/LG+TU3+8eacVDXV5o1RqWxsdVOaQmCTY0XyDgeRTn6hIOVAq/HHQbRq3iWOrt2A==", "dependencies": { - "@opentelemetry/core": "1.12.0", - "@opentelemetry/resources": "1.12.0", - "@opentelemetry/sdk-metrics": "1.12.0", - "@opentelemetry/sdk-trace-base": "1.12.0" + "@opentelemetry/api-logs": "0.51.0", + "@opentelemetry/core": "1.24.0", + "@opentelemetry/resources": "1.24.0", + "@opentelemetry/sdk-logs": "0.51.0", + "@opentelemetry/sdk-metrics": "1.24.0", + "@opentelemetry/sdk-trace-base": "1.24.0" }, "engines": { "node": ">=14" }, "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.5.0" + "@opentelemetry/api": ">=1.3.0 <1.9.0" + } + }, + "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/api-logs": { + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.51.0.tgz", + "integrity": "sha512-m/jtfBPEIXS1asltl8fPQtO3Sb1qMpuL61unQajUmM8zIxeMF1AlqzWXM3QedcYgTTFiJCew5uJjyhpmqhc0+g==", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" } }, "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/core": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.12.0.tgz", - "integrity": "sha512-4DWYNb3dLs2mSCGl65jY3aEgbvPWSHVQV/dmDWiYeWUrMakZQFcymqZOSUNZO0uDrEJoxMu8O5tZktX6UKFwag==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.24.0.tgz", + "integrity": "sha512-FP2oN7mVPqcdxJDTTnKExj4mi91EH+DNuArKfHTjPuJWe2K1JfMIVXNfahw1h3onJxQnxS8K0stKkogX05s+Aw==", "dependencies": { - "@opentelemetry/semantic-conventions": "1.12.0" + "@opentelemetry/semantic-conventions": "1.24.0" }, "engines": { "node": ">=14" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.5.0" + "@opentelemetry/api": ">=1.0.0 <1.9.0" } }, "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/resources": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.12.0.tgz", - "integrity": "sha512-gunMKXG0hJrR0LXrqh7BVbziA/+iJBL3ZbXCXO64uY+SrExkwoyJkpiq9l5ismkGF/A20mDEV7tGwh+KyPw00Q==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.24.0.tgz", + "integrity": "sha512-mxC7E7ocUS1tLzepnA7O9/G8G6ZTdjCH2pXme1DDDuCuk6n2/53GADX+GWBuyX0dfIxeMInIbJAdjlfN9GNr6A==", "dependencies": { - "@opentelemetry/core": "1.12.0", - "@opentelemetry/semantic-conventions": "1.12.0" + "@opentelemetry/core": "1.24.0", + "@opentelemetry/semantic-conventions": "1.24.0" }, "engines": { "node": ">=14" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.5.0" + "@opentelemetry/api": ">=1.0.0 <1.9.0" } }, - "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/sdk-metrics": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.12.0.tgz", - "integrity": "sha512-zOy88Jfk88eTxqu+9ypHLs184dGydJocSWtvWMY10QKVVaxhC3SLKa0uxI/zBtD9S+x0LP65wxrTSfSoUNtCOA==", + "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/sdk-logs": { + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.51.0.tgz", + "integrity": "sha512-K4fMBRFD8hQ6khk0rvYFuo6L9ymeGgByir6BcuFIgQuQ00OhYwBi9AruZz5V733Ejq7P8ObR3YyubkOUIbeVAw==", "dependencies": { - "@opentelemetry/core": "1.12.0", - "@opentelemetry/resources": "1.12.0", - "lodash.merge": "4.6.2" + "@opentelemetry/core": "1.24.0", + "@opentelemetry/resources": "1.24.0" }, "engines": { "node": ">=14" }, "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.5.0" + "@opentelemetry/api": ">=1.4.0 <1.9.0", + "@opentelemetry/api-logs": ">=0.39.1" } }, "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/sdk-trace-base": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.12.0.tgz", - "integrity": "sha512-pfCOB3tNDlYVoWuz4D7Ji+Jmy9MHnATWHVpkERdCEiwUGEZ+4IvNPXUcPc37wJVmMpjGLeaWgPPrie0KIpWf1A==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.24.0.tgz", + "integrity": "sha512-H9sLETZ4jw9UJ3totV8oM5R0m4CW0ZIOLfp4NV3g0CM8HD5zGZcaW88xqzWDgiYRpctFxd+WmHtGX/Upoa2vRg==", "dependencies": { - "@opentelemetry/core": "1.12.0", - "@opentelemetry/resources": "1.12.0", - "@opentelemetry/semantic-conventions": "1.12.0" + "@opentelemetry/core": "1.24.0", + "@opentelemetry/resources": "1.24.0", + "@opentelemetry/semantic-conventions": "1.24.0" }, "engines": { "node": ">=14" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.5.0" + "@opentelemetry/api": ">=1.0.0 <1.9.0" } }, "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.12.0.tgz", - "integrity": "sha512-hO+bdeGOlJwqowUBoZF5LyP3ORUFOP1G0GRv8N45W/cztXbT2ZEXaAzfokRS9Xc9FWmYrDj32mF6SzH6wuoIyA==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.24.0.tgz", + "integrity": "sha512-yL0jI6Ltuz8R+Opj7jClGrul6pOoYrdfVmzQS4SITXRPH7I5IRZbrwe/6/v8v4WYMa6MYZG480S1+uc/IGfqsA==", "engines": { "node": ">=14" } @@ -4010,20 +4150,110 @@ "@opentelemetry/api": ">=1.0.0 <1.7.0" } }, + "node_modules/@opentelemetry/sdk-logs": { + "version": "0.50.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.50.0.tgz", + "integrity": "sha512-PeUEupBB29p9nlPNqXoa1PUWNLsZnxG0DCDj3sHqzae+8y76B/A5hvZjg03ulWdnvBLYpnJslqzylG9E0IL87g==", + "dependencies": { + "@opentelemetry/core": "1.23.0", + "@opentelemetry/resources": "1.23.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.4.0 <1.9.0", + "@opentelemetry/api-logs": ">=0.39.1" + } + }, + "node_modules/@opentelemetry/sdk-logs/node_modules/@opentelemetry/core": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.23.0.tgz", + "integrity": "sha512-hdQ/a9TMzMQF/BO8Cz1juA43/L5YGtCSiKoOHmrTEf7VMDAZgy8ucpWx3eQTnQ3gBloRcWtzvcrMZABC3PTSKQ==", + "dependencies": { + "@opentelemetry/semantic-conventions": "1.23.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.9.0" + } + }, + "node_modules/@opentelemetry/sdk-logs/node_modules/@opentelemetry/resources": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.23.0.tgz", + "integrity": "sha512-iPRLfVfcEQynYGo7e4Di+ti+YQTAY0h5mQEUJcHlU9JOqpb4x965O6PZ+wMcwYVY63G96KtdS86YCM1BF1vQZg==", + "dependencies": { + "@opentelemetry/core": "1.23.0", + "@opentelemetry/semantic-conventions": "1.23.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.9.0" + } + }, + "node_modules/@opentelemetry/sdk-logs/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.23.0.tgz", + "integrity": "sha512-MiqFvfOzfR31t8cc74CTP1OZfz7MbqpAnLCra8NqQoaHJX6ncIRTdYOQYBDQ2uFISDq0WY8Y9dDTWvsgzzBYRg==", + "engines": { + "node": ">=14" + } + }, "node_modules/@opentelemetry/sdk-metrics": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.17.1.tgz", - "integrity": "sha512-eHdpsMCKhKhwznxvEfls8Wv3y4ZBWkkXlD3m7vtHIiWBqsMHspWSfie1s07mM45i/bBCf6YBMgz17FUxIXwmZA==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.24.0.tgz", + "integrity": "sha512-4tJ+E6N019OZVB/nUW/LoK9xHxfeh88TCoaTqHeLBE9wLYfi6irWW6J9cphMav7J8Qk0D5b7/RM4VEY4dArWOA==", "dependencies": { - "@opentelemetry/core": "1.17.1", - "@opentelemetry/resources": "1.17.1", + "@opentelemetry/core": "1.24.0", + "@opentelemetry/resources": "1.24.0", "lodash.merge": "^4.6.2" }, "engines": { "node": ">=14" }, "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.7.0" + "@opentelemetry/api": ">=1.3.0 <1.9.0" + } + }, + "node_modules/@opentelemetry/sdk-metrics/node_modules/@opentelemetry/core": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.24.0.tgz", + "integrity": "sha512-FP2oN7mVPqcdxJDTTnKExj4mi91EH+DNuArKfHTjPuJWe2K1JfMIVXNfahw1h3onJxQnxS8K0stKkogX05s+Aw==", + "dependencies": { + "@opentelemetry/semantic-conventions": "1.24.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.9.0" + } + }, + "node_modules/@opentelemetry/sdk-metrics/node_modules/@opentelemetry/resources": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.24.0.tgz", + "integrity": "sha512-mxC7E7ocUS1tLzepnA7O9/G8G6ZTdjCH2pXme1DDDuCuk6n2/53GADX+GWBuyX0dfIxeMInIbJAdjlfN9GNr6A==", + "dependencies": { + "@opentelemetry/core": "1.24.0", + "@opentelemetry/semantic-conventions": "1.24.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.9.0" + } + }, + "node_modules/@opentelemetry/sdk-metrics/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.24.0.tgz", + "integrity": "sha512-yL0jI6Ltuz8R+Opj7jClGrul6pOoYrdfVmzQS4SITXRPH7I5IRZbrwe/6/v8v4WYMa6MYZG480S1+uc/IGfqsA==", + "engines": { + "node": ">=14" } }, "node_modules/@opentelemetry/sdk-trace-base": { @@ -4142,6 +4372,18 @@ "@opentelemetry/api": "^1.1.0" } }, + "node_modules/@opentelemetry/winston-transport": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/winston-transport/-/winston-transport-0.2.0.tgz", + "integrity": "sha512-6+2a9xV/mQkYyRIHpn4e5sf/1v58Wd765ke0gp6n+N9YfCZ8rE8xqqvccIDE1AbSR2uUhXxZI6HsTTxqtMaXgw==", + "dependencies": { + "@opentelemetry/api-logs": "^0.50.0", + "winston-transport": "4.*" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/@pnpm/config.env-replace": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", @@ -4262,19 +4504,6 @@ "node": ">=14" } }, - "node_modules/@prisma/instrumentation/node_modules/require-in-the-middle": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz", - "integrity": "sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw==", - "dependencies": { - "debug": "^4.1.1", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.1" - }, - "engines": { - "node": ">=8.6.0" - } - }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", @@ -7162,6 +7391,14 @@ "@types/node": "*" } }, + "node_modules/@types/bunyan": { + "version": "1.8.9", + "resolved": "https://registry.npmjs.org/@types/bunyan/-/bunyan-1.8.9.tgz", + "integrity": "sha512-ZqS9JGpBxVOvsawzmVt30sP++gSQMTejCkIAQ3VdadOcRE8izTyW66hufvwLeH+YEGP6Js2AW7Gz+RMyvrEbmw==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/connect": { "version": "3.4.37", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.37.tgz", @@ -7386,6 +7623,12 @@ "@types/node": "*" } }, + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "dev": true + }, "node_modules/@types/semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.4.tgz", @@ -7451,6 +7694,11 @@ "integrity": "sha512-g7CK9nHdwjK2n0ymT2CW698FuWJRIx+RP6embAzZ2Qi8/ilIrA1Imt2LVSeHUzKvpoi7BhmmQcXz95eS0f2JXw==", "dev": true }, + "node_modules/@types/triple-beam": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", + "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==" + }, "node_modules/@types/yargs": { "version": "17.0.29", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.29.tgz", @@ -7854,6 +8102,19 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/acorn": { "version": "8.10.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", @@ -8089,6 +8350,12 @@ "integrity": "sha512-F2+Hkm9xFaRg+GkaNnbwXNDV5O6pnCFEmqyhvfC/Ic5LbgOWjJh3L+mN/s91rxVL3znE7DYVpW0GJFT+4YBgWw==", "dev": true }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true + }, "node_modules/array-ify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", @@ -9156,6 +9423,18 @@ "node": ">=8" } }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/content-type": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", @@ -9258,6 +9537,21 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true + }, "node_modules/core-js-compat": { "version": "3.33.1", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.33.1.tgz", @@ -10381,6 +10675,15 @@ "node": ">=0.10.0" } }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/events": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", @@ -10438,6 +10741,81 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dev": true, + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.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/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/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/express/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/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -10505,6 +10883,11 @@ "bser": "2.1.1" } }, + "node_modules/fecha": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" + }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -10684,6 +11067,24 @@ "is-callable": "^1.1.3" } }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/from2": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", @@ -11367,8 +11768,7 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/ini": { "version": "1.3.8", @@ -11401,6 +11801,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/is-arguments": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", @@ -13902,6 +14311,30 @@ "node": "*" } }, + "node_modules/logform": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.6.0.tgz", + "integrity": "sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==", + "dependencies": { + "@colors/colors": "1.6.0", + "@types/triple-beam": "^1.3.2", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/logform/node_modules/@colors/colors": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "engines": { + "node": ">=0.1.90" + } + }, "node_modules/long": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", @@ -14103,6 +14536,12 @@ "node": ">=10" } }, + "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/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -14118,6 +14557,15 @@ "node": ">= 8" } }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", @@ -14342,6 +14790,15 @@ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", "dev": true }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -17069,7 +17526,6 @@ }, "node_modules/npm/node_modules/lodash._baseindexof": { "version": "3.1.0", - "dev": true, "inBundle": true, "license": "MIT" }, @@ -17085,19 +17541,16 @@ }, "node_modules/npm/node_modules/lodash._bindcallback": { "version": "3.0.1", - "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/lodash._cacheindexof": { "version": "3.0.2", - "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/lodash._createcache": { "version": "3.1.2", - "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -17112,7 +17565,6 @@ }, "node_modules/npm/node_modules/lodash._getnative": { "version": "3.9.1", - "dev": true, "inBundle": true, "license": "MIT" }, @@ -17130,7 +17582,6 @@ }, "node_modules/npm/node_modules/lodash.restparam": { "version": "3.6.1", - "dev": true, "inBundle": true, "license": "MIT" }, @@ -19425,19 +19876,6 @@ "@opentelemetry/api": "^1.3.0" } }, - "node_modules/opentelemetry-instrumentation-express/node_modules/require-in-the-middle": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz", - "integrity": "sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw==", - "dependencies": { - "debug": "^4.1.1", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.1" - }, - "engines": { - "node": ">=8.6.0" - } - }, "node_modules/opentelemetry-instrumentation-kafkajs": { "version": "0.39.1", "resolved": "https://registry.npmjs.org/opentelemetry-instrumentation-kafkajs/-/opentelemetry-instrumentation-kafkajs-0.39.1.tgz", @@ -19468,19 +19906,6 @@ "@opentelemetry/api": "^1.3.0" } }, - "node_modules/opentelemetry-instrumentation-kafkajs/node_modules/require-in-the-middle": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz", - "integrity": "sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw==", - "dependencies": { - "debug": "^4.1.1", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.1" - }, - "engines": { - "node": ">=8.6.0" - } - }, "node_modules/optionator": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", @@ -19576,6 +20001,19 @@ "node": ">=8" } }, + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "dev": true, + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -19996,6 +20434,19 @@ "node": ">=12.0.0" } }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -20110,6 +20561,15 @@ "safe-buffer": "^5.1.0" } }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/raw-body": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", @@ -20236,7 +20696,6 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -20416,9 +20875,9 @@ } }, "node_modules/require-in-the-middle": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-6.0.0.tgz", - "integrity": "sha512-+dtWQ7l2lqQDxheaG3jjyN1QI37gEwvzACSgjYi4/C2y+ZTUMeRW8BIOm+9NBKvwaMBUSZfPXVOt1skB0vBkRw==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.3.0.tgz", + "integrity": "sha512-nQFEv9gRw6SJAwWD2LrL0NmQvAcO7FBwJbwmr2ttPAacfy0xuiOjE5zt+zM4xDyuyvUaxBi/9gb2SoCyNEVJcw==", "dependencies": { "debug": "^4.1.1", "module-details-from-path": "^1.0.3", @@ -20474,6 +20933,15 @@ "node": ">=10" } }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -20541,7 +21009,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, "funding": [ { "type": "github", @@ -20557,6 +21024,14 @@ } ] }, + "node_modules/safe-stable-stringify": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", + "engines": { + "node": ">=10" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -20714,6 +21189,63 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "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/send/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/send/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/send/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/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, "node_modules/serialize-javascript": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", @@ -20723,6 +21255,21 @@ "randombytes": "^2.1.0" } }, + "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/set-function-length": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", @@ -21051,7 +21598,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, "dependencies": { "safe-buffer": "~5.2.0" } @@ -21513,6 +22059,14 @@ "node": ">=8" } }, + "node_modules/triple-beam": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", + "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", + "engines": { + "node": ">= 14.0.0" + } + }, "node_modules/ts-node": { "version": "9.1.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", @@ -21845,8 +22399,7 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "node_modules/utils-merge": { "version": "1.0.1", @@ -21890,6 +22443,15 @@ "spdx-expression-parse": "^3.0.0" } }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/wait-on": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-6.0.1.tgz", @@ -22131,6 +22693,19 @@ "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", "dev": true }, + "node_modules/winston-transport": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.7.0.tgz", + "integrity": "sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg==", + "dependencies": { + "logform": "^2.3.2", + "readable-stream": "^3.6.0", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, "node_modules/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -24536,6 +25111,14 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.4.1.tgz", "integrity": "sha512-O2yRJce1GOc6PAy3QxFM4NzFiWzvScDC1/5ihYBL6BUEVdq0XMWN01sppE+H6bBXbaFYipjwFLEWLg5PaSOThA==" }, + "@opentelemetry/api-logs": { + "version": "0.50.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.50.0.tgz", + "integrity": "sha512-JdZuKrhOYggqOpUljAq4WWNi5nB10PmgoF0y2CvedLGXd0kSawb/UBnWT8gg1ND3bHCNHStAIVT0ELlxJJRqrA==", + "requires": { + "@opentelemetry/api": "^1.0.0" + } + }, "@opentelemetry/context-async-hooks": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-1.9.1.tgz", @@ -24550,60 +25133,137 @@ "@opentelemetry/semantic-conventions": "1.17.1" } }, + "@opentelemetry/exporter-logs-otlp-http": { + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.51.0.tgz", + "integrity": "sha512-7G+RUQ+HzLaQw5sl2hKLYmZ/pWuaZ3IR7+gLIZNS9RpLeEnG/mbNENM2YTWQYPwX/7YpSJUC1NAaiMYxQco0ow==", + "requires": { + "@opentelemetry/api-logs": "0.51.0", + "@opentelemetry/core": "1.24.0", + "@opentelemetry/otlp-exporter-base": "0.51.0", + "@opentelemetry/otlp-transformer": "0.51.0", + "@opentelemetry/sdk-logs": "0.51.0" + }, + "dependencies": { + "@opentelemetry/api-logs": { + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.51.0.tgz", + "integrity": "sha512-m/jtfBPEIXS1asltl8fPQtO3Sb1qMpuL61unQajUmM8zIxeMF1AlqzWXM3QedcYgTTFiJCew5uJjyhpmqhc0+g==", + "requires": { + "@opentelemetry/api": "^1.0.0" + } + }, + "@opentelemetry/core": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.24.0.tgz", + "integrity": "sha512-FP2oN7mVPqcdxJDTTnKExj4mi91EH+DNuArKfHTjPuJWe2K1JfMIVXNfahw1h3onJxQnxS8K0stKkogX05s+Aw==", + "requires": { + "@opentelemetry/semantic-conventions": "1.24.0" + } + }, + "@opentelemetry/resources": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.24.0.tgz", + "integrity": "sha512-mxC7E7ocUS1tLzepnA7O9/G8G6ZTdjCH2pXme1DDDuCuk6n2/53GADX+GWBuyX0dfIxeMInIbJAdjlfN9GNr6A==", + "requires": { + "@opentelemetry/core": "1.24.0", + "@opentelemetry/semantic-conventions": "1.24.0" + } + }, + "@opentelemetry/sdk-logs": { + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.51.0.tgz", + "integrity": "sha512-K4fMBRFD8hQ6khk0rvYFuo6L9ymeGgByir6BcuFIgQuQ00OhYwBi9AruZz5V733Ejq7P8ObR3YyubkOUIbeVAw==", + "requires": { + "@opentelemetry/core": "1.24.0", + "@opentelemetry/resources": "1.24.0" + } + }, + "@opentelemetry/semantic-conventions": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.24.0.tgz", + "integrity": "sha512-yL0jI6Ltuz8R+Opj7jClGrul6pOoYrdfVmzQS4SITXRPH7I5IRZbrwe/6/v8v4WYMa6MYZG480S1+uc/IGfqsA==" + } + } + }, "@opentelemetry/exporter-trace-otlp-http": { - "version": "0.38.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.38.0.tgz", - "integrity": "sha512-AWpTCyijC7kt2DbLj8FmdlRquA6/rTXZ+3U4MVl4P2YNI7KLUnx/FEhn2BMTB0+rOy7UxSAocqz2tJ/5Ss/6Ng==", + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.51.0.tgz", + "integrity": "sha512-zODqnLZmPOxj9CarFv0TrVlx9mgj0TfCMCiUiTdNi9iA2rgdKVo+bjJjpYF6LCTJOQCR5TScAUCKyzwkgDI+iA==", "requires": { - "@opentelemetry/core": "1.12.0", - "@opentelemetry/otlp-exporter-base": "0.38.0", - "@opentelemetry/otlp-transformer": "0.38.0", - "@opentelemetry/resources": "1.12.0", - "@opentelemetry/sdk-trace-base": "1.12.0" + "@opentelemetry/core": "1.24.0", + "@opentelemetry/otlp-exporter-base": "0.51.0", + "@opentelemetry/otlp-transformer": "0.51.0", + "@opentelemetry/resources": "1.24.0", + "@opentelemetry/sdk-trace-base": "1.24.0" }, "dependencies": { "@opentelemetry/core": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.12.0.tgz", - "integrity": "sha512-4DWYNb3dLs2mSCGl65jY3aEgbvPWSHVQV/dmDWiYeWUrMakZQFcymqZOSUNZO0uDrEJoxMu8O5tZktX6UKFwag==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.24.0.tgz", + "integrity": "sha512-FP2oN7mVPqcdxJDTTnKExj4mi91EH+DNuArKfHTjPuJWe2K1JfMIVXNfahw1h3onJxQnxS8K0stKkogX05s+Aw==", "requires": { - "@opentelemetry/semantic-conventions": "1.12.0" + "@opentelemetry/semantic-conventions": "1.24.0" } }, "@opentelemetry/resources": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.12.0.tgz", - "integrity": "sha512-gunMKXG0hJrR0LXrqh7BVbziA/+iJBL3ZbXCXO64uY+SrExkwoyJkpiq9l5ismkGF/A20mDEV7tGwh+KyPw00Q==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.24.0.tgz", + "integrity": "sha512-mxC7E7ocUS1tLzepnA7O9/G8G6ZTdjCH2pXme1DDDuCuk6n2/53GADX+GWBuyX0dfIxeMInIbJAdjlfN9GNr6A==", "requires": { - "@opentelemetry/core": "1.12.0", - "@opentelemetry/semantic-conventions": "1.12.0" + "@opentelemetry/core": "1.24.0", + "@opentelemetry/semantic-conventions": "1.24.0" } }, "@opentelemetry/sdk-trace-base": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.12.0.tgz", - "integrity": "sha512-pfCOB3tNDlYVoWuz4D7Ji+Jmy9MHnATWHVpkERdCEiwUGEZ+4IvNPXUcPc37wJVmMpjGLeaWgPPrie0KIpWf1A==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.24.0.tgz", + "integrity": "sha512-H9sLETZ4jw9UJ3totV8oM5R0m4CW0ZIOLfp4NV3g0CM8HD5zGZcaW88xqzWDgiYRpctFxd+WmHtGX/Upoa2vRg==", "requires": { - "@opentelemetry/core": "1.12.0", - "@opentelemetry/resources": "1.12.0", - "@opentelemetry/semantic-conventions": "1.12.0" + "@opentelemetry/core": "1.24.0", + "@opentelemetry/resources": "1.24.0", + "@opentelemetry/semantic-conventions": "1.24.0" } }, "@opentelemetry/semantic-conventions": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.12.0.tgz", - "integrity": "sha512-hO+bdeGOlJwqowUBoZF5LyP3ORUFOP1G0GRv8N45W/cztXbT2ZEXaAzfokRS9Xc9FWmYrDj32mF6SzH6wuoIyA==" + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.24.0.tgz", + "integrity": "sha512-yL0jI6Ltuz8R+Opj7jClGrul6pOoYrdfVmzQS4SITXRPH7I5IRZbrwe/6/v8v4WYMa6MYZG480S1+uc/IGfqsA==" } } }, "@opentelemetry/instrumentation": { - "version": "0.38.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.38.0.tgz", - "integrity": "sha512-wr1WkIbzHGV+oz6SCme88D2c+zNG23COkCjcida8b3jIzX2lJafOpEHPDcbBF38F8ChkRSj/tVnx1wnYAXZvbA==", + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.51.0.tgz", + "integrity": "sha512-Eg/+Od5bEvzpvZQGhvMyKIkrzB9S7jW+6z9LHEI2VXhl/GrqQ3oBqlzJt4tA6pGtxRmqQWKWGM1wAbwDdW/gUA==", "requires": { - "require-in-the-middle": "^6.0.0", - "semver": "^7.3.2", + "@opentelemetry/api-logs": "0.51.0", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "1.7.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", "shimmer": "^1.2.1" + }, + "dependencies": { + "@opentelemetry/api-logs": { + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.51.0.tgz", + "integrity": "sha512-m/jtfBPEIXS1asltl8fPQtO3Sb1qMpuL61unQajUmM8zIxeMF1AlqzWXM3QedcYgTTFiJCew5uJjyhpmqhc0+g==", + "requires": { + "@opentelemetry/api": "^1.0.0" + } + }, + "import-in-the-middle": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.7.1.tgz", + "integrity": "sha512-1LrZPDtW+atAxH42S6288qyDFNQ2YCty+2mxEPRtfazH6Z5QwkaBSTS2ods7hnVJioF6rkRfNoA6A/MstpFXLg==", + "requires": { + "acorn": "^8.8.2", + "acorn-import-assertions": "^1.9.0", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + } } }, "@opentelemetry/instrumentation-amqplib": { @@ -24627,16 +25287,6 @@ "semver": "^7.5.2", "shimmer": "^1.2.1" } - }, - "require-in-the-middle": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz", - "integrity": "sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw==", - "requires": { - "debug": "^4.1.1", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.1" - } } } }, @@ -24673,15 +25323,41 @@ "cjs-module-lexer": "^1.2.2", "module-details-from-path": "^1.0.3" } + } + } + }, + "@opentelemetry/instrumentation-bunyan": { + "version": "0.37.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-bunyan/-/instrumentation-bunyan-0.37.0.tgz", + "integrity": "sha512-NKHuTIn1JrxfKZ8sVZjwT/bD3wyijkipiWzBvvxGj8pJJJNP5shVHWcEJhk5tQsfKQc4LproTAPdklex1o5/ag==", + "requires": { + "@opentelemetry/api-logs": "^0.50.0", + "@opentelemetry/instrumentation": "^0.50.0", + "@types/bunyan": "1.8.9" + }, + "dependencies": { + "@opentelemetry/instrumentation": { + "version": "0.50.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.50.0.tgz", + "integrity": "sha512-bhGhbJiZKpuu7wTaSak4hyZcFPlnDeuSF/2vglze8B4w2LubcSbbOnkVTzTs5SXtzh4Xz8eRjaNnAm+u2GYufQ==", + "requires": { + "@opentelemetry/api-logs": "0.50.0", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "1.7.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + } }, - "require-in-the-middle": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz", - "integrity": "sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw==", + "import-in-the-middle": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.7.1.tgz", + "integrity": "sha512-1LrZPDtW+atAxH42S6288qyDFNQ2YCty+2mxEPRtfazH6Z5QwkaBSTS2ods7hnVJioF6rkRfNoA6A/MstpFXLg==", "requires": { - "debug": "^4.1.1", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.1" + "acorn": "^8.8.2", + "acorn-import-assertions": "^1.9.0", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" } } } @@ -24707,16 +25383,6 @@ "semver": "^7.5.2", "shimmer": "^1.2.1" } - }, - "require-in-the-middle": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz", - "integrity": "sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw==", - "requires": { - "debug": "^4.1.1", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.1" - } } } }, @@ -24745,16 +25411,6 @@ "version": "1.15.2", "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.15.2.tgz", "integrity": "sha512-CjbOKwk2s+3xPIMcd5UNYQzsf+v94RczbdNix9/kQh38WiQkM90sUOi3if8eyHFgiBjBjhwXrA7W3ydiSQP9mw==" - }, - "require-in-the-middle": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz", - "integrity": "sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw==", - "requires": { - "debug": "^4.1.1", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.1" - } } } }, @@ -24777,10 +25433,30 @@ "@opentelemetry/semantic-conventions": "1.12.0" } }, + "@opentelemetry/instrumentation": { + "version": "0.38.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.38.0.tgz", + "integrity": "sha512-wr1WkIbzHGV+oz6SCme88D2c+zNG23COkCjcida8b3jIzX2lJafOpEHPDcbBF38F8ChkRSj/tVnx1wnYAXZvbA==", + "requires": { + "require-in-the-middle": "^6.0.0", + "semver": "^7.3.2", + "shimmer": "^1.2.1" + } + }, "@opentelemetry/semantic-conventions": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.12.0.tgz", "integrity": "sha512-hO+bdeGOlJwqowUBoZF5LyP3ORUFOP1G0GRv8N45W/cztXbT2ZEXaAzfokRS9Xc9FWmYrDj32mF6SzH6wuoIyA==" + }, + "require-in-the-middle": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-6.0.0.tgz", + "integrity": "sha512-+dtWQ7l2lqQDxheaG3jjyN1QI37gEwvzACSgjYi4/C2y+ZTUMeRW8BIOm+9NBKvwaMBUSZfPXVOt1skB0vBkRw==", + "requires": { + "debug": "^4.1.1", + "module-details-from-path": "^1.0.3", + "resolve": "^1.22.1" + } } } }, @@ -24806,16 +25482,6 @@ "semver": "^7.5.2", "shimmer": "^1.2.1" } - }, - "require-in-the-middle": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz", - "integrity": "sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw==", - "requires": { - "debug": "^4.1.1", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.1" - } } } }, @@ -24851,16 +25517,6 @@ "cjs-module-lexer": "^1.2.2", "module-details-from-path": "^1.0.3" } - }, - "require-in-the-middle": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz", - "integrity": "sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw==", - "requires": { - "debug": "^4.1.1", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.1" - } } } }, @@ -24895,16 +25551,6 @@ "cjs-module-lexer": "^1.2.2", "module-details-from-path": "^1.0.3" } - }, - "require-in-the-middle": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz", - "integrity": "sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw==", - "requires": { - "debug": "^4.1.1", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.1" - } } } }, @@ -24942,16 +25588,6 @@ "cjs-module-lexer": "^1.2.2", "module-details-from-path": "^1.0.3" } - }, - "require-in-the-middle": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz", - "integrity": "sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw==", - "requires": { - "debug": "^4.1.1", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.1" - } } } }, @@ -24976,94 +25612,127 @@ "semver": "^7.5.2", "shimmer": "^1.2.1" } + } + } + }, + "@opentelemetry/instrumentation-winston": { + "version": "0.36.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-winston/-/instrumentation-winston-0.36.0.tgz", + "integrity": "sha512-NTuGpUA9AGC7EmKQyMn3ABiqJ3XvHihRcxdvqhs8E72nHmIU3n6om+DCYYE3fpEQwbC9N14ir8fqA5Oxn0Ynag==", + "requires": { + "@opentelemetry/instrumentation": "^0.50.0" + }, + "dependencies": { + "@opentelemetry/instrumentation": { + "version": "0.50.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.50.0.tgz", + "integrity": "sha512-bhGhbJiZKpuu7wTaSak4hyZcFPlnDeuSF/2vglze8B4w2LubcSbbOnkVTzTs5SXtzh4Xz8eRjaNnAm+u2GYufQ==", + "requires": { + "@opentelemetry/api-logs": "0.50.0", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "1.7.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + } }, - "require-in-the-middle": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz", - "integrity": "sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw==", + "import-in-the-middle": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.7.1.tgz", + "integrity": "sha512-1LrZPDtW+atAxH42S6288qyDFNQ2YCty+2mxEPRtfazH6Z5QwkaBSTS2ods7hnVJioF6rkRfNoA6A/MstpFXLg==", "requires": { - "debug": "^4.1.1", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.1" + "acorn": "^8.8.2", + "acorn-import-assertions": "^1.9.0", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" } } } }, "@opentelemetry/otlp-exporter-base": { - "version": "0.38.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.38.0.tgz", - "integrity": "sha512-VWQo7vUDyW/7/FT8RErAtM/29i/fllCc9xMtnK7kDuheAjJU68zrZ88bQOsLamHvOCU3KVpozjfTZVxZKQRYXw==", + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.51.0.tgz", + "integrity": "sha512-hR4c9vWVz1QgzCBSyy9zSDkvfTgaK96E6/tfVP6O4dzdZW9HqWimA3lXV/KXadEGqShvM4GToz9EHp2A5RU5bQ==", "requires": { - "@opentelemetry/core": "1.12.0" + "@opentelemetry/core": "1.24.0" }, "dependencies": { "@opentelemetry/core": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.12.0.tgz", - "integrity": "sha512-4DWYNb3dLs2mSCGl65jY3aEgbvPWSHVQV/dmDWiYeWUrMakZQFcymqZOSUNZO0uDrEJoxMu8O5tZktX6UKFwag==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.24.0.tgz", + "integrity": "sha512-FP2oN7mVPqcdxJDTTnKExj4mi91EH+DNuArKfHTjPuJWe2K1JfMIVXNfahw1h3onJxQnxS8K0stKkogX05s+Aw==", "requires": { - "@opentelemetry/semantic-conventions": "1.12.0" + "@opentelemetry/semantic-conventions": "1.24.0" } }, "@opentelemetry/semantic-conventions": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.12.0.tgz", - "integrity": "sha512-hO+bdeGOlJwqowUBoZF5LyP3ORUFOP1G0GRv8N45W/cztXbT2ZEXaAzfokRS9Xc9FWmYrDj32mF6SzH6wuoIyA==" + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.24.0.tgz", + "integrity": "sha512-yL0jI6Ltuz8R+Opj7jClGrul6pOoYrdfVmzQS4SITXRPH7I5IRZbrwe/6/v8v4WYMa6MYZG480S1+uc/IGfqsA==" } } }, "@opentelemetry/otlp-transformer": { - "version": "0.38.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.38.0.tgz", - "integrity": "sha512-ykQEipby0NVSi2ih5E8J2GNJ6y9zYDPSef0nD8j33XPKxfyVG5184rUrCsh6TIk1d/GlYl8gB9Wy4TdRvwl6kA==", + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.51.0.tgz", + "integrity": "sha512-ylLgx2xumVoSefDHP9GMAU/LG+TU3+8eacVDXV5o1RqWxsdVOaQmCTY0XyDgeRTn6hIOVAq/HHQbRq3iWOrt2A==", "requires": { - "@opentelemetry/core": "1.12.0", - "@opentelemetry/resources": "1.12.0", - "@opentelemetry/sdk-metrics": "1.12.0", - "@opentelemetry/sdk-trace-base": "1.12.0" + "@opentelemetry/api-logs": "0.51.0", + "@opentelemetry/core": "1.24.0", + "@opentelemetry/resources": "1.24.0", + "@opentelemetry/sdk-logs": "0.51.0", + "@opentelemetry/sdk-metrics": "1.24.0", + "@opentelemetry/sdk-trace-base": "1.24.0" }, "dependencies": { + "@opentelemetry/api-logs": { + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.51.0.tgz", + "integrity": "sha512-m/jtfBPEIXS1asltl8fPQtO3Sb1qMpuL61unQajUmM8zIxeMF1AlqzWXM3QedcYgTTFiJCew5uJjyhpmqhc0+g==", + "requires": { + "@opentelemetry/api": "^1.0.0" + } + }, "@opentelemetry/core": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.12.0.tgz", - "integrity": "sha512-4DWYNb3dLs2mSCGl65jY3aEgbvPWSHVQV/dmDWiYeWUrMakZQFcymqZOSUNZO0uDrEJoxMu8O5tZktX6UKFwag==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.24.0.tgz", + "integrity": "sha512-FP2oN7mVPqcdxJDTTnKExj4mi91EH+DNuArKfHTjPuJWe2K1JfMIVXNfahw1h3onJxQnxS8K0stKkogX05s+Aw==", "requires": { - "@opentelemetry/semantic-conventions": "1.12.0" + "@opentelemetry/semantic-conventions": "1.24.0" } }, "@opentelemetry/resources": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.12.0.tgz", - "integrity": "sha512-gunMKXG0hJrR0LXrqh7BVbziA/+iJBL3ZbXCXO64uY+SrExkwoyJkpiq9l5ismkGF/A20mDEV7tGwh+KyPw00Q==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.24.0.tgz", + "integrity": "sha512-mxC7E7ocUS1tLzepnA7O9/G8G6ZTdjCH2pXme1DDDuCuk6n2/53GADX+GWBuyX0dfIxeMInIbJAdjlfN9GNr6A==", "requires": { - "@opentelemetry/core": "1.12.0", - "@opentelemetry/semantic-conventions": "1.12.0" + "@opentelemetry/core": "1.24.0", + "@opentelemetry/semantic-conventions": "1.24.0" } }, - "@opentelemetry/sdk-metrics": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.12.0.tgz", - "integrity": "sha512-zOy88Jfk88eTxqu+9ypHLs184dGydJocSWtvWMY10QKVVaxhC3SLKa0uxI/zBtD9S+x0LP65wxrTSfSoUNtCOA==", + "@opentelemetry/sdk-logs": { + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.51.0.tgz", + "integrity": "sha512-K4fMBRFD8hQ6khk0rvYFuo6L9ymeGgByir6BcuFIgQuQ00OhYwBi9AruZz5V733Ejq7P8ObR3YyubkOUIbeVAw==", "requires": { - "@opentelemetry/core": "1.12.0", - "@opentelemetry/resources": "1.12.0", - "lodash.merge": "4.6.2" + "@opentelemetry/core": "1.24.0", + "@opentelemetry/resources": "1.24.0" } }, "@opentelemetry/sdk-trace-base": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.12.0.tgz", - "integrity": "sha512-pfCOB3tNDlYVoWuz4D7Ji+Jmy9MHnATWHVpkERdCEiwUGEZ+4IvNPXUcPc37wJVmMpjGLeaWgPPrie0KIpWf1A==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.24.0.tgz", + "integrity": "sha512-H9sLETZ4jw9UJ3totV8oM5R0m4CW0ZIOLfp4NV3g0CM8HD5zGZcaW88xqzWDgiYRpctFxd+WmHtGX/Upoa2vRg==", "requires": { - "@opentelemetry/core": "1.12.0", - "@opentelemetry/resources": "1.12.0", - "@opentelemetry/semantic-conventions": "1.12.0" + "@opentelemetry/core": "1.24.0", + "@opentelemetry/resources": "1.24.0", + "@opentelemetry/semantic-conventions": "1.24.0" } }, "@opentelemetry/semantic-conventions": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.12.0.tgz", - "integrity": "sha512-hO+bdeGOlJwqowUBoZF5LyP3ORUFOP1G0GRv8N45W/cztXbT2ZEXaAzfokRS9Xc9FWmYrDj32mF6SzH6wuoIyA==" + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.24.0.tgz", + "integrity": "sha512-yL0jI6Ltuz8R+Opj7jClGrul6pOoYrdfVmzQS4SITXRPH7I5IRZbrwe/6/v8v4WYMa6MYZG480S1+uc/IGfqsA==" } } }, @@ -25143,14 +25812,71 @@ "@opentelemetry/semantic-conventions": "1.17.1" } }, + "@opentelemetry/sdk-logs": { + "version": "0.50.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.50.0.tgz", + "integrity": "sha512-PeUEupBB29p9nlPNqXoa1PUWNLsZnxG0DCDj3sHqzae+8y76B/A5hvZjg03ulWdnvBLYpnJslqzylG9E0IL87g==", + "requires": { + "@opentelemetry/core": "1.23.0", + "@opentelemetry/resources": "1.23.0" + }, + "dependencies": { + "@opentelemetry/core": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.23.0.tgz", + "integrity": "sha512-hdQ/a9TMzMQF/BO8Cz1juA43/L5YGtCSiKoOHmrTEf7VMDAZgy8ucpWx3eQTnQ3gBloRcWtzvcrMZABC3PTSKQ==", + "requires": { + "@opentelemetry/semantic-conventions": "1.23.0" + } + }, + "@opentelemetry/resources": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.23.0.tgz", + "integrity": "sha512-iPRLfVfcEQynYGo7e4Di+ti+YQTAY0h5mQEUJcHlU9JOqpb4x965O6PZ+wMcwYVY63G96KtdS86YCM1BF1vQZg==", + "requires": { + "@opentelemetry/core": "1.23.0", + "@opentelemetry/semantic-conventions": "1.23.0" + } + }, + "@opentelemetry/semantic-conventions": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.23.0.tgz", + "integrity": "sha512-MiqFvfOzfR31t8cc74CTP1OZfz7MbqpAnLCra8NqQoaHJX6ncIRTdYOQYBDQ2uFISDq0WY8Y9dDTWvsgzzBYRg==" + } + } + }, "@opentelemetry/sdk-metrics": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.17.1.tgz", - "integrity": "sha512-eHdpsMCKhKhwznxvEfls8Wv3y4ZBWkkXlD3m7vtHIiWBqsMHspWSfie1s07mM45i/bBCf6YBMgz17FUxIXwmZA==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.24.0.tgz", + "integrity": "sha512-4tJ+E6N019OZVB/nUW/LoK9xHxfeh88TCoaTqHeLBE9wLYfi6irWW6J9cphMav7J8Qk0D5b7/RM4VEY4dArWOA==", "requires": { - "@opentelemetry/core": "1.17.1", - "@opentelemetry/resources": "1.17.1", + "@opentelemetry/core": "1.24.0", + "@opentelemetry/resources": "1.24.0", "lodash.merge": "^4.6.2" + }, + "dependencies": { + "@opentelemetry/core": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.24.0.tgz", + "integrity": "sha512-FP2oN7mVPqcdxJDTTnKExj4mi91EH+DNuArKfHTjPuJWe2K1JfMIVXNfahw1h3onJxQnxS8K0stKkogX05s+Aw==", + "requires": { + "@opentelemetry/semantic-conventions": "1.24.0" + } + }, + "@opentelemetry/resources": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.24.0.tgz", + "integrity": "sha512-mxC7E7ocUS1tLzepnA7O9/G8G6ZTdjCH2pXme1DDDuCuk6n2/53GADX+GWBuyX0dfIxeMInIbJAdjlfN9GNr6A==", + "requires": { + "@opentelemetry/core": "1.24.0", + "@opentelemetry/semantic-conventions": "1.24.0" + } + }, + "@opentelemetry/semantic-conventions": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.24.0.tgz", + "integrity": "sha512-yL0jI6Ltuz8R+Opj7jClGrul6pOoYrdfVmzQS4SITXRPH7I5IRZbrwe/6/v8v4WYMa6MYZG480S1+uc/IGfqsA==" + } } }, "@opentelemetry/sdk-trace-base": { @@ -25228,6 +25954,15 @@ "@opentelemetry/core": "^1.1.0" } }, + "@opentelemetry/winston-transport": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/winston-transport/-/winston-transport-0.2.0.tgz", + "integrity": "sha512-6+2a9xV/mQkYyRIHpn4e5sf/1v58Wd765ke0gp6n+N9YfCZ8rE8xqqvccIDE1AbSR2uUhXxZI6HsTTxqtMaXgw==", + "requires": { + "@opentelemetry/api-logs": "^0.50.0", + "winston-transport": "4.*" + } + }, "@pnpm/config.env-replace": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", @@ -25313,16 +26048,6 @@ "version": "1.13.0", "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.13.0.tgz", "integrity": "sha512-LMGqfSZkaMQXqewO0o1wvWr/2fQdCh4a3Sqlxka/UsJCe0cfLulh6x2aqnKLnsrSGiCq5rSCwvINd152i0nCqw==" - }, - "require-in-the-middle": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz", - "integrity": "sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw==", - "requires": { - "debug": "^4.1.1", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.1" - } } } }, @@ -27399,6 +28124,14 @@ "@types/node": "*" } }, + "@types/bunyan": { + "version": "1.8.9", + "resolved": "https://registry.npmjs.org/@types/bunyan/-/bunyan-1.8.9.tgz", + "integrity": "sha512-ZqS9JGpBxVOvsawzmVt30sP++gSQMTejCkIAQ3VdadOcRE8izTyW66hufvwLeH+YEGP6Js2AW7Gz+RMyvrEbmw==", + "requires": { + "@types/node": "*" + } + }, "@types/connect": { "version": "3.4.37", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.37.tgz", @@ -27621,6 +28354,12 @@ "@types/node": "*" } }, + "@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "dev": true + }, "@types/semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.4.tgz", @@ -27688,6 +28427,11 @@ "integrity": "sha512-g7CK9nHdwjK2n0ymT2CW698FuWJRIx+RP6embAzZ2Qi8/ilIrA1Imt2LVSeHUzKvpoi7BhmmQcXz95eS0f2JXw==", "dev": true }, + "@types/triple-beam": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", + "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==" + }, "@types/yargs": { "version": "17.0.29", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.29.tgz", @@ -27989,6 +28733,16 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, + "accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, "acorn": { "version": "8.10.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", @@ -28179,6 +28933,12 @@ "integrity": "sha512-F2+Hkm9xFaRg+GkaNnbwXNDV5O6pnCFEmqyhvfC/Ic5LbgOWjJh3L+mN/s91rxVL3znE7DYVpW0GJFT+4YBgWw==", "dev": true }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true + }, "array-ify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", @@ -28986,6 +29746,15 @@ } } }, + "content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "requires": { + "safe-buffer": "5.2.1" + } + }, "content-type": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", @@ -29063,6 +29832,18 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, + "cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "dev": true + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true + }, "core-js-compat": { "version": "3.33.1", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.33.1.tgz", @@ -29885,6 +30666,12 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true + }, "events": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", @@ -29927,6 +30714,77 @@ "jest-util": "^29.7.0" } }, + "express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dev": true, + "requires": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.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": { + "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" + } + }, + "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" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + } + } + }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -29988,6 +30846,11 @@ "bser": "2.1.1" } }, + "fecha": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" + }, "figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -30119,6 +30982,18 @@ "is-callable": "^1.1.3" } }, + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true + }, "from2": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", @@ -30636,8 +31511,7 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "ini": { "version": "1.3.8", @@ -30661,6 +31535,12 @@ "p-is-promise": "^3.0.0" } }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true + }, "is-arguments": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", @@ -32533,6 +33413,26 @@ "log-prefix": "0.1.1" } }, + "logform": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.6.0.tgz", + "integrity": "sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==", + "requires": { + "@colors/colors": "1.6.0", + "@types/triple-beam": "^1.3.2", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" + }, + "dependencies": { + "@colors/colors": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==" + } + } + }, "long": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", @@ -32677,6 +33577,12 @@ } } }, + "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 + }, "merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -32689,6 +33595,12 @@ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true + }, "micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", @@ -32861,6 +33773,12 @@ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", "dev": true }, + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true + }, "neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -34877,8 +35795,7 @@ }, "lodash._baseindexof": { "version": "3.1.0", - "bundled": true, - "dev": true + "bundled": true }, "lodash._baseuniq": { "version": "4.6.0", @@ -34891,18 +35808,15 @@ }, "lodash._bindcallback": { "version": "3.0.1", - "bundled": true, - "dev": true + "bundled": true }, "lodash._cacheindexof": { "version": "3.0.2", - "bundled": true, - "dev": true + "bundled": true }, "lodash._createcache": { "version": "3.1.2", "bundled": true, - "dev": true, "requires": { "lodash._getnative": "^3.0.0" } @@ -34914,8 +35828,7 @@ }, "lodash._getnative": { "version": "3.9.1", - "bundled": true, - "dev": true + "bundled": true }, "lodash._root": { "version": "3.0.1", @@ -34929,8 +35842,7 @@ }, "lodash.restparam": { "version": "3.6.1", - "bundled": true, - "dev": true + "bundled": true }, "lodash.union": { "version": "4.6.0", @@ -36758,16 +37670,6 @@ "semver": "^7.5.1", "shimmer": "^1.2.1" } - }, - "require-in-the-middle": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz", - "integrity": "sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw==", - "requires": { - "debug": "^4.1.1", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.1" - } } } }, @@ -36791,16 +37693,6 @@ "semver": "^7.5.1", "shimmer": "^1.2.1" } - }, - "require-in-the-middle": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz", - "integrity": "sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw==", - "requires": { - "debug": "^4.1.1", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.1" - } } } }, @@ -36869,6 +37761,16 @@ "integrity": "sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw==", "dev": true }, + "p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "dev": true, + "requires": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + } + }, "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -37171,6 +38073,16 @@ "long": "^5.0.0" } }, + "proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "requires": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + } + }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -37241,6 +38153,12 @@ "safe-buffer": "^5.1.0" } }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true + }, "raw-body": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", @@ -37346,7 +38264,6 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, "requires": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -37497,9 +38414,9 @@ "dev": true }, "require-in-the-middle": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-6.0.0.tgz", - "integrity": "sha512-+dtWQ7l2lqQDxheaG3jjyN1QI37gEwvzACSgjYi4/C2y+ZTUMeRW8BIOm+9NBKvwaMBUSZfPXVOt1skB0vBkRw==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.3.0.tgz", + "integrity": "sha512-nQFEv9gRw6SJAwWD2LrL0NmQvAcO7FBwJbwmr2ttPAacfy0xuiOjE5zt+zM4xDyuyvUaxBi/9gb2SoCyNEVJcw==", "requires": { "debug": "^4.1.1", "module-details-from-path": "^1.0.3", @@ -37537,6 +38454,12 @@ "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", "dev": true }, + "retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true + }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -37581,8 +38504,12 @@ "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "safe-stable-stringify": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==" }, "safer-buffer": { "version": "2.1.2", @@ -37708,6 +38635,58 @@ "integrity": "sha512-6IiqeZNgq01qGf0TId0t3NvKzSvUsjcpdEO3AQNeIjR6A2+ckTnQlDpl4qu1bjRv0RzN3FP9hzFmws3lKqRWkA==", "dev": true }, + "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" + }, + "dependencies": { + "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 + } + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, "serialize-javascript": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", @@ -37717,6 +38696,18 @@ "randombytes": "^2.1.0" } }, + "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" + } + }, "set-function-length": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", @@ -38008,7 +38999,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, "requires": { "safe-buffer": "~5.2.0" } @@ -38352,6 +39342,11 @@ "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", "dev": true }, + "triple-beam": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", + "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==" + }, "ts-node": { "version": "9.1.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", @@ -38591,8 +39586,7 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "utils-merge": { "version": "1.0.1", @@ -38627,6 +39621,12 @@ "spdx-expression-parse": "^3.0.0" } }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true + }, "wait-on": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-6.0.1.tgz", @@ -38799,6 +39799,16 @@ "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", "dev": true }, + "winston-transport": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.7.0.tgz", + "integrity": "sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg==", + "requires": { + "logform": "^2.3.2", + "readable-stream": "^3.6.0", + "triple-beam": "^1.3.0" + } + }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", diff --git a/package.json b/package.json index d87c5dff..b391d5ab 100644 --- a/package.json +++ b/package.json @@ -25,10 +25,12 @@ "@lumigo/node-core": "1.14.0", "@opentelemetry/api": "1.4.1", "@opentelemetry/core": "1.17.1", - "@opentelemetry/exporter-trace-otlp-http": "0.38.0", - "@opentelemetry/instrumentation": "0.38.0", + "@opentelemetry/exporter-logs-otlp-http": "0.51.0", + "@opentelemetry/exporter-trace-otlp-http": "0.51.0", + "@opentelemetry/instrumentation": "0.51.0", "@opentelemetry/instrumentation-amqplib": "0.33.2", "@opentelemetry/instrumentation-aws-sdk": "^0.38.1", + "@opentelemetry/instrumentation-bunyan": "0.37.0", "@opentelemetry/instrumentation-fastify": "^0.32.3", "@opentelemetry/instrumentation-grpc": "^0.41.0", "@opentelemetry/instrumentation-http": "0.38.0", @@ -37,11 +39,14 @@ "@opentelemetry/instrumentation-nestjs-core": "^0.34.0", "@opentelemetry/instrumentation-pg": "^0.38.0", "@opentelemetry/instrumentation-redis-4": "^0.35.3", + "@opentelemetry/instrumentation-winston": "0.36.0", "@opentelemetry/resource-detector-aws": "1.3.2", "@opentelemetry/resources": "1.17.1", + "@opentelemetry/sdk-logs": "^0.50.0", "@opentelemetry/sdk-trace-base": "1.9.1", "@opentelemetry/sdk-trace-node": "1.9.1", "@opentelemetry/semantic-conventions": "1.17.1", + "@opentelemetry/winston-transport": "0.2.0", "@prisma/instrumentation": "^4.14.0", "opentelemetry-instrumentation-express": "0.39.1", "opentelemetry-instrumentation-kafkajs": "^0.39.1", @@ -78,6 +83,7 @@ "eslint": "^8.40.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-prettier": "^3.4.0", + "express": "^4.19.2", "jest": "^29.4.0", "jest-chain": "^1.1.6", "jest-expect-message": "^1.1.3", @@ -90,6 +96,7 @@ "mock-http-server": "^1.4.5", "node-notifier": "^10.0.0", "npm-install-peers": "^1.2.2", + "p-retry": "^4.6.1", "prettier": "^2.2.1", "rimraf": "^3.0.2", "semantic-release": "^19.0.2", @@ -120,4 +127,4 @@ "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" } } -} +} \ No newline at end of file diff --git a/src/bootstrap.ts b/src/bootstrap.ts index d8beace7..0bd50e80 100644 --- a/src/bootstrap.ts +++ b/src/bootstrap.ts @@ -1,13 +1,26 @@ import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'; +import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http'; import { registerInstrumentations } from '@opentelemetry/instrumentation'; import { Resource, detectResources, envDetector, processDetector } from '@opentelemetry/resources'; import { BasicTracerProvider, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base'; +import { + BatchLogRecordProcessor, + LoggerProvider, + SimpleLogRecordProcessor, +} from '@opentelemetry/sdk-logs'; +import type { LoggerProvider as ApiLoggerProvider } from '@opentelemetry/api-logs'; +import * as logsAPI from '@opentelemetry/api-logs'; import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node'; import * as awsResourceDetectors from '@opentelemetry/resource-detector-aws'; -import { DEFAULT_DEPENDENCIES_ENDPOINT, DEFAULT_LUMIGO_ENDPOINT } from './constants'; +import { + DEFAULT_DEPENDENCIES_ENDPOINT, + DEFAULT_LUMIGO_TRACES_ENDPOINT, + DEFAULT_LUMIGO_LOGS_ENDPOINT, +} from './constants'; import { report } from './dependencies'; -import { FileSpanExporter } from './exporters'; +import { FileLogExporter, FileSpanExporter } from './exporters'; + import LumigoGrpcInstrumentation from './instrumentations/@grpc/grpc-js/GrpcInstrumentation'; import LumigoNestInstrumentation from './instrumentations/@nestjs/core/NestInstrumentation'; import LumigoAmqplibInstrumentation from './instrumentations/amqplib/AmqplibInstrumentation'; @@ -24,6 +37,9 @@ import { LumigoAwsSdkV2LibInstrumentation, LumigoAwsSdkV3LibInstrumentation, } from './instrumentations/aws-sdk'; +import LumigoWinstonInstrumentation from './instrumentations/winston/WinstonInstrumentation'; +import LumigoBunyanInstrumentation from './instrumentations/bunyan/BunyanInstrumentation'; + import { LumigoW3CTraceContextPropagator } from './propagator/w3cTraceContextPropagator'; import { LumigoContainerNameDetector, @@ -31,7 +47,7 @@ import { LumigoKubernetesDetector, LumigoTagDetector, } from './resources/detectors'; -import { getSpanAttributeMaxLength, safeRequire } from './utils'; +import { getLogAttributeMaxLength, getSpanAttributeMaxLength, safeRequire } from './utils'; declare global { // eslint-disable-next-line @typescript-eslint/no-namespace @@ -39,7 +55,10 @@ declare global { interface ProcessEnv { LUMIGO_DEBUG?: string; LUMIGO_DEBUG_SPANDUMP?: string; + LUMIGO_DEBUG_LOGDUMP?: string; LUMIGO_ENDPOINT?: string; + LUMIGO_ENABLE_LOGS?: string; + LUMIGO_LOGS_ENDPOINT?: string; LUMIGO_REPORT_DEPENDENCIES?: string; LUMIGO_SWITCH_OFF?: string; LUMIGO_TRACER_TOKEN?: string; @@ -49,6 +68,7 @@ declare global { export interface LumigoSdkInitialization { readonly tracerProvider: BasicTracerProvider; + readonly loggerProvider: ApiLoggerProvider; readonly instrumentedModules: string[]; readonly reportDependencies: Promise; } @@ -58,8 +78,10 @@ import { logger } from './logging'; import { ProcessEnvironmentDetector } from './resources/detectors/ProcessEnvironmentDetector'; import { LumigoSpanProcessor } from './resources/spanProcessor'; import { getLumigoSampler } from './samplers/lumigoSampler'; +import { LumigoLogRecordProcessor } from './processors/LumigoLogRecordProcessor'; -const lumigoEndpoint = process.env.LUMIGO_ENDPOINT || DEFAULT_LUMIGO_ENDPOINT; +const lumigoTraceEndpoint = process.env.LUMIGO_ENDPOINT || DEFAULT_LUMIGO_TRACES_ENDPOINT; +const lumigoLogEndpoint = process.env.LUMIGO_LOGS_ENDPOINT || DEFAULT_LUMIGO_LOGS_ENDPOINT; let isTraceInitialized = false; @@ -94,8 +116,8 @@ export const init = async (): Promise => { safeRequire(join(__dirname, 'package.json')) || {}; - const ignoredHostnames = [new URL(lumigoEndpoint).hostname]; - if (lumigoEndpoint != DEFAULT_LUMIGO_ENDPOINT) { + const ignoredHostnames = [new URL(lumigoTraceEndpoint).hostname]; + if (lumigoTraceEndpoint != DEFAULT_LUMIGO_TRACES_ENDPOINT) { ignoredHostnames.push(new URL(DEFAULT_DEPENDENCIES_ENDPOINT).hostname); } @@ -114,6 +136,10 @@ export const init = async (): Promise => { new LumigoRedisInstrumentation(), new LumigoAwsSdkV2LibInstrumentation(), new LumigoAwsSdkV3LibInstrumentation(), + + // Loggers + new LumigoWinstonInstrumentation(), + new LumigoBunyanInstrumentation(), ].filter((i) => i.isApplicable()); /* @@ -191,17 +217,32 @@ export const init = async (): Promise => { ); } + const loggerProvider = new LoggerProvider({ + resource, + logRecordLimits: { + attributeValueLengthLimit: getLogAttributeMaxLength(), + }, + }); + loggerProvider.addLogRecordProcessor(new LumigoLogRecordProcessor()); + + if (process.env.LUMIGO_DEBUG_LOGDUMP) { + loggerProvider.addLogRecordProcessor( + new SimpleLogRecordProcessor(new FileLogExporter(process.env.LUMIGO_DEBUG_LOGDUMP)) + ); + } + let reportDependencies: Promise; + if (lumigoToken) { - const otlpExporter = new OTLPTraceExporter({ - url: lumigoEndpoint, + const otlpTraceExporter = new OTLPTraceExporter({ + url: lumigoTraceEndpoint, headers: { Authorization: `LumigoToken ${lumigoToken.trim()}`, }, }); tracerProvider.addSpanProcessor( - new LumigoSpanProcessor(otlpExporter, { + new LumigoSpanProcessor(otlpTraceExporter, { // The maximum queue size. After the size is reached spans are dropped. maxQueueSize: 1000, // The maximum batch size of every export. It must be smaller or equal to maxQueueSize. @@ -209,6 +250,22 @@ export const init = async (): Promise => { }) ); + const otlpLogExporter = new OTLPLogExporter({ + url: lumigoLogEndpoint, + headers: { + Authorization: `LumigoToken ${lumigoToken.trim()}`, + }, + }); + + loggerProvider.addLogRecordProcessor( + new BatchLogRecordProcessor(otlpLogExporter, { + // The maximum queue size. After the size is reached logs are dropped. + maxQueueSize: 1000, + // The maximum batch size of every export. It must be smaller or equal to maxQueueSize. + maxExportBatchSize: 100, + }) + ); + /* * We do not wait for this promise, we do not want to delay the application. * Dependency reporting is done "best effort". @@ -235,6 +292,8 @@ export const init = async (): Promise => { propagator: new LumigoW3CTraceContextPropagator(), }); + logsAPI.logs.setGlobalLoggerProvider(loggerProvider); + logger.info( `Lumigo OpenTelemetry Distro ${ distroVersion ? `v${distroVersion}` : 'with an unknown version' @@ -243,6 +302,7 @@ export const init = async (): Promise => { return { tracerProvider, + loggerProvider, reportDependencies, instrumentedModules, }; diff --git a/src/constants.ts b/src/constants.ts index 1e91bec2..8a6a2edd 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,4 +1,7 @@ export const LUMIGO_LOGGING_NAMESPACE = '@lumigo/opentelemetry'; -export const DEFAULT_LUMIGO_ENDPOINT = 'https://ga-otlp.lumigo-tracer-edge.golumigo.com/v1/traces'; +export const DEFAULT_LUMIGO_TRACES_ENDPOINT = + 'https://ga-otlp.lumigo-tracer-edge.golumigo.com/v1/traces'; +export const DEFAULT_LUMIGO_LOGS_ENDPOINT = + 'https://ga-otlp.lumigo-tracer-edge.golumigo.com/v1/logs'; export const DEFAULT_DEPENDENCIES_ENDPOINT = 'https://ga-otlp.lumigo-tracer-edge.golumigo.com/v1/dependencies'; diff --git a/src/exporters/FileExporter.ts b/src/exporters/FileExporter.ts new file mode 100644 index 00000000..8b4b759e --- /dev/null +++ b/src/exporters/FileExporter.ts @@ -0,0 +1,146 @@ +/* + * Copyright Lumigo + * + * 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 { appendFileSync, closeSync, fsyncSync, openSync } from 'fs'; +import { realpath, lstat } from 'fs/promises'; +import { BindOnceFuture, ExportResult, ExportResultCode } from '@opentelemetry/core'; +import { logger } from '../logging'; + +/** + * This is implementation of {@link Exporter} that prints records to a file. + * This class can be used for debug purposes. It is not advised to use this + * exporter in production. + */ + +const PRINT_TO_CONSOLE_LOG = 'console:log'; +const PRINT_TO_CONSOLE_ERROR = 'console:error'; + +export interface Exporter { + export(record: T[], resultCallback: (result: ExportResult) => void): void; + shutdown(): Promise; +} + +/* eslint-disable no-console */ +export abstract class FileExporter implements Exporter { + private readonly file: string; + private _fd: number; + private readonly _shutdownOnce: BindOnceFuture; + + constructor(file: string) { + this.file = file; + + if (![PRINT_TO_CONSOLE_LOG, PRINT_TO_CONSOLE_ERROR].includes(file)) { + this._fd = openSync(file, 'w'); + this._shutdownOnce = new BindOnceFuture(this._shutdown.bind(this), this); + } + } + + /** + * Export records. + * @param records + * @param resultCallback + */ + export(records: T[], resultCallback: (result: ExportResult) => void): void { + if (!records?.length) { + return resultCallback({ + code: ExportResultCode.SUCCESS, + }); + } + + const recordsJson = + records.map((record) => JSON.stringify(this.exportInfo(record), undefined, 0)).join('\n') + + '\n'; + + try { + if (this._fd) { + appendFileSync(this._fd, recordsJson); + } else if (this.file === PRINT_TO_CONSOLE_LOG) { + console.log(recordsJson); + } else if (this.file === PRINT_TO_CONSOLE_ERROR) { + console.error(recordsJson); + } + } catch (err) { + return resultCallback({ + code: ExportResultCode.FAILED, + error: err, + }); + } + + return resultCallback({ + code: ExportResultCode.SUCCESS, + }); + } + + /** + * converts records info into a more readable format + * @param record + */ + protected abstract exportInfo(record: T): Object; + + forceFlush(): Promise { + if (this._shutdownOnce.isCalled) { + return this._shutdownOnce.promise; + } + return this._flushAll(); + } + + /** + * Shutdown the exporter. + */ + shutdown(): Promise { + return this._shutdownOnce?.call(); + } + + /** + * Called by _shutdownOnce with BindOnceFuture + */ + private async _shutdown(): Promise { + return await this._flushAll().finally(async () => { + if (this._fd) { + /* + * Do not close block and character devices like `/dev/stdout` or `/dev/stderr`. + * We need to resolve symbolic links until we get to the actual file, e.g., + * `/dev/stdout` -> `/proc/self/fd/1` -> `/dev/pts/0`. + */ + try { + const realPath = await realpath(this.file); + const stats = await lstat(realPath); + + if (stats.isFile()) { + closeSync(this._fd); + } + } catch (err) { + logger.error(`An error occurred while shutting down, exporter file: '${this.file}'`, err); + } + } + }); + } + + private _flushAll = async (): Promise => + new Promise((resolve, reject) => { + if (this._fd) { + try { + fsyncSync(this._fd); + } catch (err) { + logger.error(`An error occurred while flushing the records to file '${this.file}'`, err); + reject(err); + return; + } + } + + resolve(); + }); +} diff --git a/src/exporters/FileLogExporter.test.ts b/src/exporters/FileLogExporter.test.ts new file mode 100644 index 00000000..1dc166b1 --- /dev/null +++ b/src/exporters/FileLogExporter.test.ts @@ -0,0 +1,121 @@ +import mockConsole from 'jest-mock-console'; +import mock from 'mock-fs'; + +import { FileLogExporter } from './index'; +import { LoggerProvider, LogRecord, SimpleLogRecordProcessor } from '@opentelemetry/sdk-logs'; + +describe('FileLogExporter tests', () => { + afterEach(() => { + jest.restoreAllMocks(); + jest.clearAllMocks(); + mock.restore(); + }); + + test('should not write anything to file when there is no logs', () => { + const tmpFile = './test-logs-no-logs.json'; + + const exporterUnderTest = new FileLogExporter(tmpFile); + const spyExport = jest.spyOn(exporterUnderTest, 'export'); + + const provider = new LoggerProvider(); + provider.addLogRecordProcessor(new SimpleLogRecordProcessor(exporterUnderTest)); + + expect(spyExport).not.toHaveBeenCalled(); + }); + + test('should write one span to file', async () => { + const tmpFile = './test-logs-one-log.json'; + + const exporterUnderTest = new FileLogExporter(tmpFile); + const spyExport = jest.spyOn(exporterUnderTest, 'export'); + + const provider = new LoggerProvider(); + provider.addLogRecordProcessor(new SimpleLogRecordProcessor(exporterUnderTest)); + + provider.getLogger('default').emit({ attributes: { foo: 'bar' } }); + + await provider.shutdown(); + + expect(spyExport).toHaveBeenCalledTimes(1); + const actualLogRecord = spyExport.mock.calls[0][0][0]; + + expect(actualLogRecord).toEqual(expect.objectContaining({ attributes: { foo: 'bar' } })); + }); + + test('should write one log record to console.log', async () => { + const restoreConsole = mockConsole(); + try { + const exporterUnderTest = new FileLogExporter('console:log'); + + const provider = new LoggerProvider(); + provider.addLogRecordProcessor(new SimpleLogRecordProcessor(exporterUnderTest)); + + provider.getLogger('default').emit({ attributes: { foo: 'bar' } }); + + await provider.shutdown(); + + expect(console.log).toHaveBeenCalledTimes(1); + const actualLogRecord = console.log.mock.calls[0][0]; + + expect(JSON.parse(actualLogRecord)).toEqual( + expect.objectContaining({ attributes: { foo: 'bar' } }) + ); + } finally { + restoreConsole(); + } + }); + + test('should write one span to console error', async () => { + const restoreConsole = mockConsole(); + try { + const exporterUnderTest = new FileLogExporter('console:error'); + + const provider = new LoggerProvider(); + provider.addLogRecordProcessor(new SimpleLogRecordProcessor(exporterUnderTest)); + + provider.getLogger('default').emit({ attributes: { foo: 'bar' } }); + + await provider.shutdown(); + + expect(console.error).toHaveBeenCalledTimes(1); + const actualSpan = console.error.mock.calls[0][0]; + + expect(JSON.parse(actualSpan)).toEqual( + expect.objectContaining({ attributes: { foo: 'bar' } }) + ); + } finally { + restoreConsole(); + } + }); + + test('should write two spans to file', async () => { + const tmpFile = './test-spans-two-spans.json'; + + const exporterUnderTest = new FileLogExporter(tmpFile); + const spyExport = jest.spyOn(exporterUnderTest, 'export'); + + const provider = new LoggerProvider(); + provider.addLogRecordProcessor(new SimpleLogRecordProcessor(exporterUnderTest)); + + provider.getLogger('default').emit({ attributes: { foo: 'bar' } }); + provider.getLogger('default').emit({ attributes: { foo: 'baz' } }); + + await provider.shutdown(); + + expect(spyExport).toHaveBeenCalledTimes(2); + + const firstLog = spyExport.mock.calls[0][0][0]; + expect(firstLog).toEqual(expect.objectContaining({ attributes: { foo: 'bar' } })); + + const secondLog = spyExport.mock.calls[1][0][0]; + expect(secondLog).toEqual(expect.objectContaining({ attributes: { foo: 'baz' } })); + }); + + test('should log an error when provided an invalid file path', async () => { + expect(() => { + new FileLogExporter('\0'); + }).toThrowError( + "The argument 'path' must be a string or Uint8Array without null bytes. Received '\\x00'" + ); + }); +}); diff --git a/src/exporters/FileLogExporter.ts b/src/exporters/FileLogExporter.ts new file mode 100644 index 00000000..5514d8c1 --- /dev/null +++ b/src/exporters/FileLogExporter.ts @@ -0,0 +1,38 @@ +/* + * Copyright Lumigo + * + * 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 { hrTimeToMicroseconds } from '@opentelemetry/core'; +import { ReadableLogRecord } from '@opentelemetry/sdk-logs'; +import { FileExporter } from './FileExporter'; + +/** + * This is implementation of {@link FileExporter} that prints log records to a file. + * This class can be used for debug purposes. It is not advised to use this + * exporter in production. + */ +export class FileLogExporter extends FileExporter { + protected exportInfo(logRecord: ReadableLogRecord): Object { + return { + timestamp: hrTimeToMicroseconds(logRecord.hrTime), + traceId: logRecord.spanContext?.traceId, + spanId: logRecord.spanContext?.spanId, + traceFlags: logRecord.spanContext?.traceFlags, + severityText: logRecord.severityText, + severityNumber: logRecord.severityNumber, + body: logRecord.body, + attributes: logRecord.attributes, + }; + } +} diff --git a/src/exporters/FileSpanExporter.ts b/src/exporters/FileSpanExporter.ts index 467be032..65c847de 100644 --- a/src/exporters/FileSpanExporter.ts +++ b/src/exporters/FileSpanExporter.ts @@ -13,82 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -import { appendFileSync, closeSync, fsyncSync, openSync } from 'fs'; -import { realpath, lstat } from 'fs/promises'; -import { - BindOnceFuture, - ExportResult, - ExportResultCode, - hrTimeToMicroseconds, -} from '@opentelemetry/core'; +import { hrTimeToMicroseconds } from '@opentelemetry/core'; import { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-base'; -import { logger } from '../logging'; +import { FileExporter } from './FileExporter'; /** - * This is implementation of {@link SpanExporter} that prints spans to a file. + * This is implementation of {@link FileExporter} that prints spans to a file. * This class can be used for debug purposes. It is not advised to use this * exporter in production. */ - -const PRINT_SPANS_TO_CONSOLE_LOG = 'console:log'; -const PRINT_SPANS_TO_CONSOLE_ERROR = 'console:error'; - -/* eslint-disable no-console */ -export class FileSpanExporter implements SpanExporter { - private readonly file: string; - private _fd: number; - private readonly _shutdownOnce: BindOnceFuture; - - constructor(file: string) { - this.file = file; - - if (![PRINT_SPANS_TO_CONSOLE_LOG, PRINT_SPANS_TO_CONSOLE_ERROR].includes(file)) { - this._fd = openSync(file, 'w'); - this._shutdownOnce = new BindOnceFuture(this._shutdown.bind(this), this); - } - } - - /** - * Export spans. - * @param spans - * @param resultCallback - */ - export(spans: ReadableSpan[], resultCallback: (result: ExportResult) => void): void { - if (!spans || !spans.length) { - return resultCallback({ - code: ExportResultCode.SUCCESS, - }); - } - - const spansJson = - spans.map((span) => JSON.stringify(this._exportInfo(span), undefined, 0)).join('\n') + '\n'; - - try { - if (this._fd) { - appendFileSync(this._fd, spansJson); - } else if (this.file === PRINT_SPANS_TO_CONSOLE_LOG) { - console.log(spansJson); - } else if (this.file === PRINT_SPANS_TO_CONSOLE_ERROR) { - console.error(spansJson); - } - } catch (err) { - return resultCallback({ - code: ExportResultCode.FAILED, - error: err, - }); - } - - return resultCallback({ - code: ExportResultCode.SUCCESS, - }); - } - - /** - * converts span info into more readable format - * @param span - */ - private _exportInfo(span: ReadableSpan): Object { +export class FileSpanExporter extends FileExporter { + protected exportInfo(span: ReadableSpan): Object { return { traceId: span.spanContext().traceId, parentId: span.parentSpanId, @@ -103,61 +38,4 @@ export class FileSpanExporter implements SpanExporter { resource: span.resource, }; } - - forceFlush(): Promise { - if (this._shutdownOnce.isCalled) { - return this._shutdownOnce.promise; - } - return this._flushAll(); - } - - /** - * Shutdown the exporter. - */ - shutdown(): Promise { - return this._shutdownOnce?.call(); - } - - /** - * Called by _shutdownOnce with BindOnceFuture - */ - private async _shutdown(): Promise { - return await this._flushAll().finally(async () => { - if (this._fd) { - /* - * Do not close block and character devices like `/dev/stdout` or `/dev/stderr`. - * We need to resolve symbolic links until we get to the actual file, e.g., - * `/dev/stdout` -> `/proc/self/fd/1` -> `/dev/pts/0`. - */ - try { - const realPath = await realpath(this.file); - const stats = await lstat(realPath); - - if (stats.isFile()) { - closeSync(this._fd); - } - } catch (err) { - logger.error( - `An error occured while shutting down the spandump exporter to file '${this.file}'`, - err - ); - } - } - }); - } - - private _flushAll = async (): Promise => - new Promise((resolve, reject) => { - if (this._fd) { - try { - fsyncSync(this._fd); - } catch (err) { - logger.error(`An error occured while flushing the spandump to file '${this.file}'`, err); - reject(err); - return; - } - } - - resolve(); - }); } diff --git a/src/exporters/index.ts b/src/exporters/index.ts index 93d8439b..73c078f7 100644 --- a/src/exporters/index.ts +++ b/src/exporters/index.ts @@ -14,4 +14,5 @@ * limitations under the License. */ -export * from './FileSpanExporter'; +export { FileSpanExporter } from './FileSpanExporter'; +export { FileLogExporter } from './FileLogExporter'; diff --git a/src/instrumentations/bunyan/BunyanInstrumentation.ts b/src/instrumentations/bunyan/BunyanInstrumentation.ts new file mode 100644 index 00000000..feb0e579 --- /dev/null +++ b/src/instrumentations/bunyan/BunyanInstrumentation.ts @@ -0,0 +1,16 @@ +import { BunyanInstrumentation } from '@opentelemetry/instrumentation-bunyan'; +import { Instrumentor } from '../instrumentor'; + +export default class LumigoBunyanInstrumentation extends Instrumentor { + getInstrumentedModule(): string { + return 'bunyan'; + } + + getInstrumentation(): BunyanInstrumentation { + return new BunyanInstrumentation(); + } + + override isApplicable(): boolean { + return super.isApplicable() && process.env.LUMIGO_ENABLE_LOGS?.toLowerCase() === 'true'; + } +} diff --git a/src/instrumentations/bunyan/tested_versions/14/bunyan b/src/instrumentations/bunyan/tested_versions/14/bunyan new file mode 100644 index 00000000..a7ed92b3 --- /dev/null +++ b/src/instrumentations/bunyan/tested_versions/14/bunyan @@ -0,0 +1 @@ +1.8.15 \ No newline at end of file diff --git a/src/instrumentations/bunyan/tested_versions/16/bunyan b/src/instrumentations/bunyan/tested_versions/16/bunyan new file mode 100644 index 00000000..a7ed92b3 --- /dev/null +++ b/src/instrumentations/bunyan/tested_versions/16/bunyan @@ -0,0 +1 @@ +1.8.15 \ No newline at end of file diff --git a/src/instrumentations/bunyan/tested_versions/18/bunyan b/src/instrumentations/bunyan/tested_versions/18/bunyan new file mode 100644 index 00000000..a7ed92b3 --- /dev/null +++ b/src/instrumentations/bunyan/tested_versions/18/bunyan @@ -0,0 +1 @@ +1.8.15 \ No newline at end of file diff --git a/src/instrumentations/bunyan/tested_versions/20/bunyan b/src/instrumentations/bunyan/tested_versions/20/bunyan new file mode 100644 index 00000000..a7ed92b3 --- /dev/null +++ b/src/instrumentations/bunyan/tested_versions/20/bunyan @@ -0,0 +1 @@ +1.8.15 \ No newline at end of file diff --git a/src/instrumentations/logsInstrumentation.ts b/src/instrumentations/logsInstrumentation.ts index 3fb5d476..0a89261a 100644 --- a/src/instrumentations/logsInstrumentation.ts +++ b/src/instrumentations/logsInstrumentation.ts @@ -7,7 +7,7 @@ import { SpanKind } from '@opentelemetry/api'; import { logger } from '../logging'; -export default class LogsInstrumentation extends InstrumentationBase { +export default class LogsInstrumentation extends InstrumentationBase { instrumentationDescription: string; supportedVersions: string[]; @@ -15,14 +15,11 @@ export default class LogsInstrumentation extends InstrumentationBase { super('logs-instrumentation', '0.0.1'); } - protected init(): - | InstrumentationModuleDefinition - | InstrumentationModuleDefinition[] - | void { + protected init(): InstrumentationModuleDefinition | InstrumentationModuleDefinition[] | void { logger.debug('in console instrumentation'); return [ - new InstrumentationNodeModuleDefinition( + new InstrumentationNodeModuleDefinition( 'console', ['*'], (moduleExports, moduleVersion) => { @@ -36,6 +33,7 @@ export default class LogsInstrumentation extends InstrumentationBase { ), ]; } + private logsWrapper = (instrumentation, level) => { return (original) => { return ( diff --git a/src/instrumentations/winston/WinstonInstrumentation.ts b/src/instrumentations/winston/WinstonInstrumentation.ts new file mode 100644 index 00000000..d5668f33 --- /dev/null +++ b/src/instrumentations/winston/WinstonInstrumentation.ts @@ -0,0 +1,17 @@ +import { WinstonInstrumentation } from '@opentelemetry/instrumentation-winston'; +import { Instrumentor } from '../instrumentor'; +import { canRequireModule } from '../../utils'; + +export default class LumigoWinstonInstrumentation extends Instrumentor { + getInstrumentedModule(): string { + return 'winston'; + } + + getInstrumentation(): WinstonInstrumentation { + return new WinstonInstrumentation(); + } + + override isApplicable(): boolean { + return super.isApplicable() && process.env.LUMIGO_ENABLE_LOGS?.toLowerCase() === 'true'; + } +} diff --git a/src/instrumentations/winston/tested_versions/14/winston b/src/instrumentations/winston/tested_versions/14/winston new file mode 100644 index 00000000..77fdc6bb --- /dev/null +++ b/src/instrumentations/winston/tested_versions/14/winston @@ -0,0 +1 @@ +3.13.0 \ No newline at end of file diff --git a/src/instrumentations/winston/tested_versions/16/winston b/src/instrumentations/winston/tested_versions/16/winston new file mode 100644 index 00000000..77fdc6bb --- /dev/null +++ b/src/instrumentations/winston/tested_versions/16/winston @@ -0,0 +1 @@ +3.13.0 \ No newline at end of file diff --git a/src/instrumentations/winston/tested_versions/18/winston b/src/instrumentations/winston/tested_versions/18/winston new file mode 100644 index 00000000..77fdc6bb --- /dev/null +++ b/src/instrumentations/winston/tested_versions/18/winston @@ -0,0 +1 @@ +3.13.0 \ No newline at end of file diff --git a/src/instrumentations/winston/tested_versions/20/winston b/src/instrumentations/winston/tested_versions/20/winston new file mode 100644 index 00000000..77fdc6bb --- /dev/null +++ b/src/instrumentations/winston/tested_versions/20/winston @@ -0,0 +1 @@ +3.13.0 \ No newline at end of file diff --git a/src/processors/LumigoLogRecordProcessor.test.ts b/src/processors/LumigoLogRecordProcessor.test.ts new file mode 100644 index 00000000..3844606e --- /dev/null +++ b/src/processors/LumigoLogRecordProcessor.test.ts @@ -0,0 +1,42 @@ +import { LogRecord } from '@opentelemetry/sdk-logs'; +import { LumigoLogRecordProcessor } from './LumigoLogRecordProcessor'; +import { LogAttributes, LogBody } from '@opentelemetry/api-logs'; + +import 'jest-json'; + +describe('LumigoLogRecordProcessor', () => { + it('does not fail on missing attributes', () => { + const logRecord: LogRecord = logRecordWith('some body', undefined); + + // @ts-ignore + delete logRecord.attributes; + + const processor = new LumigoLogRecordProcessor(); + processor.onEmit(logRecord); + + expect(logRecord.body).toEqual('some body'); + expect(logRecord.attributes).toBeUndefined(); + }); + + it('scrubs the log body and attributes when those are objects', () => { + jest.isolateModules(() => { + process.env.LUMIGO_SECRET_MASKING_REGEX = '[".*sekret.*"]'; + const { LumigoLogRecordProcessor } = jest.requireActual('./LumigoLogRecordProcessor'); + + const logRecord: LogRecord = logRecordWith( + { 'sekret-body': '123' }, + { 'sekret-attr': '456' } + ); + + const processor = new LumigoLogRecordProcessor(); + processor.onEmit(logRecord); + + expect(logRecord.body).toMatchObject({ 'sekret-body': '****' }); + expect(logRecord.attributes).toMatchObject({ 'sekret-attr': '****' }); + }); + }); + + const logRecordWith = (body: LogBody, attributes: LogAttributes = {}) => + // @ts-ignore + new LogRecord({ logRecordLimits: {} }, { name: 'test', version: 'v1' }, { body, attributes }); +}); diff --git a/src/processors/LumigoLogRecordProcessor.ts b/src/processors/LumigoLogRecordProcessor.ts new file mode 100644 index 00000000..6109f740 --- /dev/null +++ b/src/processors/LumigoLogRecordProcessor.ts @@ -0,0 +1,20 @@ +import { scrub } from '@lumigo/node-core'; +import { Context } from '@opentelemetry/api'; +import { LogRecord, LogRecordProcessor } from '@opentelemetry/sdk-logs'; + +export class LumigoLogRecordProcessor implements LogRecordProcessor { + forceFlush(): Promise { + return Promise.resolve(); + } + + onEmit(logRecord: LogRecord, context?: Context): void { + logRecord.body = scrub(logRecord.body); + + // @ts-ignore + logRecord.attributes = scrub(logRecord.attributes); + } + + shutdown(): Promise { + return Promise.resolve(); + } +} diff --git a/src/utils.ts b/src/utils.ts index 66d23ced..1141fb92 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -216,6 +216,9 @@ export const getSpanAttributeMaxLength = () => { ); }; +// For now, we use the same set of limits for logs and spans, therefore this is just an alias +export const getLogAttributeMaxLength = getSpanAttributeMaxLength; + export const getResourceAttributeMaxLength = () => { return ( parseInt(process.env.OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT) || DEFAULT_ATTRIBUTE_VALUE_LENGTH_LIMIT diff --git a/test/instrumentations/@aws-sdk/client-sqs/aws-sdk-v3.test.ts b/test/instrumentations/@aws-sdk/client-sqs/aws-sdk-v3.test.ts index d205e10a..e1e85b66 100644 --- a/test/instrumentations/@aws-sdk/client-sqs/aws-sdk-v3.test.ts +++ b/test/instrumentations/@aws-sdk/client-sqs/aws-sdk-v3.test.ts @@ -89,7 +89,7 @@ describe.each(versionsToTest(PACKAGE_NAME, PACKAGE_NAME))(`Instrumentation tests }, async () => { const exporterFile = `${SPANS_DIR}/${INSTRUMENTATION_NAME}-receive-message-spans@${versionToTest}.json`; - testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, exporterFile, { LUMIGO_USE_AWS_SDK_INSTRUMENTATION: true }); + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { spanDumpPath: exporterFile, env: { LUMIGO_USE_AWS_SDK_INSTRUMENTATION: 'true' }}); const { queueUrl, queueName } = await createTempQueue({ sqsClient, sqsPort }); const { MessageId: expectedMessageId } = await sqsClient.sendMessage({ MessageBody: SAMPLE_INNER_SNS_MESSAGE_BODY, QueueUrl: queueUrl }).promise() @@ -158,7 +158,7 @@ describe.each(versionsToTest(PACKAGE_NAME, PACKAGE_NAME))(`Instrumentation tests }, async () => { const exporterFile = `${SPANS_DIR}/${INSTRUMENTATION_NAME}-send-message-spans@${versionToTest}.json`; - testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, exporterFile, { LUMIGO_USE_AWS_SDK_INSTRUMENTATION: true }); + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { spanDumpPath: exporterFile, env: { LUMIGO_USE_AWS_SDK_INSTRUMENTATION: 'true' }}); const { queueUrl, queueName } = await createTempQueue({ sqsClient, sqsPort }); await testApp.invokeGetPath(`/sqs/send-message?${testAppQueryParams({ queueUrl, region, sqsPort})}`); @@ -204,7 +204,7 @@ describe.each(versionsToTest(PACKAGE_NAME, PACKAGE_NAME))(`Instrumentation tests }, async () => { const exporterFile = `${SPANS_DIR}/${INSTRUMENTATION_NAME}-send-message-batch-spans@${versionToTest}.json`; - testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, exporterFile, { LUMIGO_USE_AWS_SDK_INSTRUMENTATION: true }); + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { spanDumpPath: exporterFile, env: { LUMIGO_USE_AWS_SDK_INSTRUMENTATION: 'true' } }); const { queueUrl, queueName } = await createTempQueue({ sqsClient, sqsPort }); await testApp.invokeGetPath(`/sqs/send-message-batch?${testAppQueryParams({ queueUrl, region, sqsPort })}`); @@ -259,7 +259,7 @@ describe.each(versionsToTest(PACKAGE_NAME, PACKAGE_NAME))(`Instrumentation tests }, async () => { const exporterFile = `${SPANS_DIR}/${INSTRUMENTATION_NAME}-send-message-batch-spans@${versionToTest}.json`; - testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, exporterFile, { LUMIGO_USE_AWS_SDK_INSTRUMENTATION: false }); + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { spanDumpPath: exporterFile, env: { LUMIGO_USE_AWS_SDK_INSTRUMENTATION: 'false' } }); const { queueUrl } = await createTempQueue({ sqsClient, sqsPort }); await testApp.invokeGetPath(`/sqs/send-message-batch?${testAppQueryParams({ queueUrl, region, sqsPort })}`); diff --git a/test/instrumentations/amqplib/amqplib.test.ts b/test/instrumentations/amqplib/amqplib.test.ts index 298f40af..70328a5a 100644 --- a/test/instrumentations/amqplib/amqplib.test.ts +++ b/test/instrumentations/amqplib/amqplib.test.ts @@ -116,9 +116,9 @@ describe.each(versionsToTest(INSTRUMENTATION_NAME, INSTRUMENTATION_NAME))( async function () { const exporterFile = `${SPANS_DIR}/amqp-roundtrip.${INSTRUMENTATION_NAME}@${versionToTest}.json`; - testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, exporterFile, { + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { spanDumpPath: exporterFile, env: { OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT: '4096', - }); + }}); const topic = 'test-topic-roundtrip'; const message = 'test-message-roundtrip'; diff --git a/test/instrumentations/amqplib/amqplibTestUtils.js b/test/instrumentations/amqplib/amqplibTestUtils.js index bdda49f8..13d57bb0 100644 --- a/test/instrumentations/amqplib/amqplibTestUtils.js +++ b/test/instrumentations/amqplib/amqplibTestUtils.js @@ -6,7 +6,7 @@ export function getExpectedResourceAttributes() { 'telemetry.sdk.language': 'nodejs', 'telemetry.sdk.name': 'opentelemetry', 'telemetry.sdk.version': expect.any(String), - framework: 'node', + 'framework': expect.toBeOneOf(['node', 'express']), 'process.environ': expect.any(String), 'lumigo.distro.version': expect.stringMatching(/1\.\d+\.\d+/), 'process.pid': expect.any(Number), diff --git a/test/instrumentations/aws-sdk/aws-sdk-v2.test.ts b/test/instrumentations/aws-sdk/aws-sdk-v2.test.ts index 145f415e..fa6820ae 100644 --- a/test/instrumentations/aws-sdk/aws-sdk-v2.test.ts +++ b/test/instrumentations/aws-sdk/aws-sdk-v2.test.ts @@ -89,7 +89,7 @@ describe.each(versionsToTest(INSTRUMENTATION_NAME, PACKAGE_NAME))(`Instrumentati }, async () => { const exporterFile = `${SPANS_DIR}/${INSTRUMENTATION_NAME}-receive-message-spans@${versionToTest}.json`; - testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, exporterFile, { LUMIGO_USE_AWS_SDK_INSTRUMENTATION: true }); + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { spanDumpPath: exporterFile, env: { LUMIGO_USE_AWS_SDK_INSTRUMENTATION: 'true' } }); const { queueUrl, queueName } = await createTempQueue({ sqsClient, sqsPort }); const { MessageId: expectedMessageId } = await sqsClient.sendMessage({ MessageBody: SAMPLE_INNER_SNS_MESSAGE_BODY, QueueUrl: queueUrl }).promise() @@ -162,7 +162,7 @@ describe.each(versionsToTest(INSTRUMENTATION_NAME, PACKAGE_NAME))(`Instrumentati }, async () => { const exporterFile = `${SPANS_DIR}/${INSTRUMENTATION_NAME}-send-message-spans@${versionToTest}.json`; - testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, exporterFile, { LUMIGO_USE_AWS_SDK_INSTRUMENTATION: true }); + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { spanDumpPath: exporterFile, env: { LUMIGO_USE_AWS_SDK_INSTRUMENTATION: 'true' } }); const { queueUrl, queueName } = await createTempQueue({ sqsClient, sqsPort }); await testApp.invokeGetPath(`/sqs/send-message?${testAppQueryParams({ queueUrl, region, sqsPort })}`); @@ -208,7 +208,7 @@ describe.each(versionsToTest(INSTRUMENTATION_NAME, PACKAGE_NAME))(`Instrumentati }, async () => { const exporterFile = `${SPANS_DIR}/${INSTRUMENTATION_NAME}-send-message-batch-spans@${versionToTest}.json`; - testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, exporterFile, { LUMIGO_USE_AWS_SDK_INSTRUMENTATION: true }); + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { spanDumpPath: exporterFile, env: { LUMIGO_USE_AWS_SDK_INSTRUMENTATION: 'true' } }); const { queueUrl, queueName } = await createTempQueue({ sqsClient, sqsPort }); await testApp.invokeGetPath(`/sqs/send-message-batch?${testAppQueryParams({ queueUrl, region, sqsPort })}`); @@ -263,7 +263,7 @@ describe.each(versionsToTest(INSTRUMENTATION_NAME, PACKAGE_NAME))(`Instrumentati }, async () => { const exporterFile = `${SPANS_DIR}/${INSTRUMENTATION_NAME}-send-message-batch-spans@${versionToTest}.json`; - testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, exporterFile, { LUMIGO_USE_AWS_SDK_INSTRUMENTATION: false }); + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { spanDumpPath: exporterFile, env: { LUMIGO_USE_AWS_SDK_INSTRUMENTATION: 'false' } }); const { queueUrl } = await createTempQueue({ sqsClient, sqsPort }); await testApp.invokeGetPath(`/sqs/send-message-batch?${testAppQueryParams({ queueUrl, region, sqsPort })}`); diff --git a/test/instrumentations/bunyan/.gitignore b/test/instrumentations/bunyan/.gitignore new file mode 100644 index 00000000..cd3d2253 --- /dev/null +++ b/test/instrumentations/bunyan/.gitignore @@ -0,0 +1 @@ +logs \ No newline at end of file diff --git a/test/instrumentations/bunyan/app/.gitignore b/test/instrumentations/bunyan/app/.gitignore new file mode 100644 index 00000000..483a9c42 --- /dev/null +++ b/test/instrumentations/bunyan/app/.gitignore @@ -0,0 +1 @@ +package-lock.json \ No newline at end of file diff --git a/test/instrumentations/bunyan/app/bunyan_app.js b/test/instrumentations/bunyan/app/bunyan_app.js new file mode 100644 index 00000000..f9506a87 --- /dev/null +++ b/test/instrumentations/bunyan/app/bunyan_app.js @@ -0,0 +1,58 @@ +const http = require('http'); +const url = require('url'); +const { init } = require("@lumigo/opentelemetry") + +require('log-timestamp'); + +const host = 'localhost'; +let httpServer; + +function respond(res, status, body) { + console.log(`responding with ${status} ${JSON.stringify(body)}`); + res.setHeader('Content-Type', 'application/json'); + res.setHeader('access-control-allow-origin', '*'); + res.writeHead(status); + res.end(JSON.stringify(body)); +} + +const requestListener = async function (req, res) { + await init; + + const bunyan = require('bunyan'); + const bunyanLogger = bunyan.createLogger({ name: __filename }) + + console.error(`Received request: ${req.method} ${req.url}`); + + const requestUrl = url.parse(req.url, true); + + switch (requestUrl.pathname) { + case '/write-log-line': + try { + const logLine = JSON.parse(requestUrl?.query?.logLine) + bunyanLogger.info(logLine); + respond(res, 200, {}) + } catch (err) { + console.error(`Error writing log line`, err); + respond(res, 500, { error: err }); + } + break; + + case '/quit': + console.error('Received quit command'); + respond(res, 200, {}); + httpServer.close(); + break; + + default: + respond(res, 404, { error: 'Resource not found' }); + } +}; + +httpServer = http.createServer(requestListener); +httpServer.listen(0, host, () => { + const port = httpServer.address().port; + console.error(`HTTP server listening on port ${port}`); + if (process.send) { + process.send(port); + } +}); diff --git a/test/instrumentations/bunyan/app/package.json b/test/instrumentations/bunyan/app/package.json new file mode 100644 index 00000000..594ee488 --- /dev/null +++ b/test/instrumentations/bunyan/app/package.json @@ -0,0 +1,14 @@ +{ + "name": "lumigo-bunyan-test", + "version": "1.0.0", + "description": "", + "scripts": { + "start": "node -r @lumigo/opentelemetry bunyan_app.js" + }, + "author": "", + "license": "ISC", + "dependencies": { + "@lumigo/opentelemetry": "file:../../../../distro.tgz", + "bunyan": "^1.8.15" + } +} diff --git a/test/instrumentations/bunyan/bunyan.test.ts b/test/instrumentations/bunyan/bunyan.test.ts new file mode 100644 index 00000000..1a3652a3 --- /dev/null +++ b/test/instrumentations/bunyan/bunyan.test.ts @@ -0,0 +1,133 @@ +import fs from 'fs'; +import { join } from 'path'; +import { itTest } from '../../integration/setup'; +import { TestApp } from '../../utils/test-apps'; +import { installPackage, reinstallPackages, uninstallPackage } from '../../utils/test-setup'; +import { versionsToTest } from '../../utils/versions'; +import { FakeEdge } from '../../utils/fake-edge'; + +const INSTRUMENTATION_NAME = 'bunyan'; +const LOGS_DIR = join(__dirname, 'logs'); +const TEST_APP_DIR = join(__dirname, 'app'); + +describe.each(versionsToTest(INSTRUMENTATION_NAME, INSTRUMENTATION_NAME))( + `Instrumentation tests for the ${INSTRUMENTATION_NAME} package`, + function (versionToTest) { + let testApp: TestApp; + const fakeEdge = new FakeEdge(); + + beforeAll(async () => { + await fakeEdge.start(); + + reinstallPackages({ appDir: TEST_APP_DIR }); + fs.mkdirSync(LOGS_DIR, { recursive: true }); + installPackage({ + appDir: TEST_APP_DIR, + packageName: INSTRUMENTATION_NAME, + packageVersion: versionToTest, + }); + }); + + afterEach(async () => { + fakeEdge.reset(); + + if (testApp) { + await testApp.kill(); + } + }); + + afterAll(async () => { + await fakeEdge.stop(); + + uninstallPackage({ + appDir: TEST_APP_DIR, + packageName: INSTRUMENTATION_NAME, + packageVersion: versionToTest, + }); + }); + + itTest( + { + testName: `${INSTRUMENTATION_NAME} logger: ${versionToTest}`, + packageName: INSTRUMENTATION_NAME, + version: versionToTest, + timeout: 20_000, + }, + async function () { + const logDumpPath = `${LOGS_DIR}/${INSTRUMENTATION_NAME}.${INSTRUMENTATION_NAME}-logs@${versionToTest}.json`; + + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { + logDumpPath, + env: { + LUMIGO_ENABLE_LOGS: 'true', + LUMIGO_SECRET_MASKING_REGEX: '[".*sekret.*"]', + LUMIGO_LOGS_ENDPOINT: fakeEdge.logsUrl, + LUMIGO_ENDPOINT: fakeEdge.tracesUrl, + LUMIGO_TRACER_TOKEN: 't_123456789', + }, + }); + + await writeLogLine('Hello Bunyan!'); + await writeLogLine({ a: 1, sekret: 'this is secret!' }); + + await fakeEdge.waitFor( + () => fakeEdge.resources.length == 1, + 'waiting for resources to be processed' + ); + await fakeEdge.waitFor(() => fakeEdge.logs.length == 2, 'waiting for logs to be processed'); + + expect(fakeEdge.resources[0].attributes).toIncludeAllMembers([ + { + key: 'service.name', + value: { + stringValue: 'bunyan', + }, + }, + ]); + + expect(fakeEdge.logs[0].body).toEqual({ stringValue: 'Hello Bunyan!' }); + // Span context is available since the test app is an instrumented HTTP server + expect(fakeEdge.logs[0]['traceId']).toHaveLength(32); + expect(fakeEdge.logs[0]['spanId']).toHaveLength(16); + + // Logging an object in Bunyan produces attributes, as opposed to making the body an object + expect(fakeEdge.logs[1].attributes).toIncludeAllMembers([ + { key: 'a', value: { intValue: 1 } }, + { key: 'sekret', value: { stringValue: '****' } }, + ]); + expect(fakeEdge.logs[1]['traceId']).toHaveLength(32); + expect(fakeEdge.logs[1]['spanId']).toHaveLength(16); + + // Test the log-dump functionality + await testApp.getFinalLogs(2); + } + ); + + itTest( + { + testName: `${INSTRUMENTATION_NAME} logger: ${versionToTest} - logging off`, + packageName: INSTRUMENTATION_NAME, + version: versionToTest, + timeout: 20_000, + }, + async function () { + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { + logDumpPath: `${LOGS_DIR}/${INSTRUMENTATION_NAME}.${INSTRUMENTATION_NAME}-logs@${versionToTest}.json`, + env: { + LUMIGO_ENABLE_LOGS: 'false', + }, + }); + + await writeLogLine('Hello Bunyan!'); + + // We expect no logs to be sent, therefore waiting for 1 log should fail + await expect(testApp.getFinalLogs(1)).rejects.toThrow(); + } + ); + + const writeLogLine = async (logLine: any) => + testApp.invokeGetPath( + `/write-log-line?logLine=${encodeURIComponent(JSON.stringify(logLine))}` + ); + } +); diff --git a/test/instrumentations/express/express.test.ts b/test/instrumentations/express/express.test.ts index f681d989..a87e722b 100644 --- a/test/instrumentations/express/express.test.ts +++ b/test/instrumentations/express/express.test.ts @@ -18,7 +18,7 @@ const TEST_TIMEOUT = 20_000; const expectedResourceAttributes = { attributes: { - framework: 'express', + 'framework': expect.toBeOneOf(['node', 'express']), 'lumigo.distro.version': expect.stringMatching(/1\.\d+\.\d+/), 'process.environ': expect.any(String), 'process.executable.name': 'node', @@ -73,9 +73,9 @@ describe.each(versionsToTest(INSTRUMENTATION_NAME, INSTRUMENTATION_NAME))( async function () { const exporterFile = `${SPANS_DIR}/basics.express@${versionToTest}.json`; - testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, exporterFile, { + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { spanDumpPath: exporterFile, env: { OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT: '4096', - }); + }}); await testApp.invokeGetPath('/basic'); @@ -126,9 +126,9 @@ describe.each(versionsToTest(INSTRUMENTATION_NAME, INSTRUMENTATION_NAME))( async function () { const exporterFile = `${SPANS_DIR}/secret-masking-requests.express@${versionToTest}.json`; - testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, exporterFile, { + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { spanDumpPath: exporterFile, env: { OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT: '4096', - }); + }}); await testApp.invokeGetPath('/test-scrubbing'); @@ -178,10 +178,10 @@ describe.each(versionsToTest(INSTRUMENTATION_NAME, INSTRUMENTATION_NAME))( async function () { const exporterFile = `${SPANS_DIR}/secret-masking-requests-complete-redaction.express@${versionToTest}.json`; - testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, exporterFile, { + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { spanDumpPath: exporterFile, env: { OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT: '4096', LUMIGO_SECRET_MASKING_REGEX_HTTP_RESPONSE_BODIES: 'all', - }); + }}); await testApp.invokeGetPath('/test-scrubbing'); @@ -263,11 +263,11 @@ describe.each(versionsToTest(INSTRUMENTATION_NAME, INSTRUMENTATION_NAME))( async function () { const exporterFile = `${SPANS_DIR}/skip-http-endpoint-${index}.express@${versionToTest}.json`; - testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, exporterFile, { + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { spanDumpPath: exporterFile, env: { LUMIGO_FILTER_HTTP_ENDPOINTS_REGEX: filterEnvVar, LUMIGO_FILTER_HTTP_ENDPOINTS_REGEX_SERVER: serverFilterEnvVar, LUMIGO_FILTER_HTTP_ENDPOINTS_REGEX_CLIENT: clientFilterEnvVar, - }); + }}); await testApp.invokeGetPath('/send-external-request'); diff --git a/test/instrumentations/fastify/fastify.test.ts b/test/instrumentations/fastify/fastify.test.ts index 9a528afa..563052d3 100644 --- a/test/instrumentations/fastify/fastify.test.ts +++ b/test/instrumentations/fastify/fastify.test.ts @@ -18,7 +18,7 @@ const TEST_TIMEOUT = 20_000; const expectedResourceAttributes = { attributes: { - framework: 'node', + 'framework': expect.toBeOneOf(['node', 'express']), 'lumigo.distro.version': expect.stringMatching(/1\.\d+\.\d+/), 'process.environ': expect.any(String), 'process.executable.name': 'node', @@ -73,9 +73,9 @@ describe.each(versionsToTest(INSTRUMENTATION_NAME, INSTRUMENTATION_NAME))( async function () { const exporterFile = `${SPANS_DIR}/basics.${INSTRUMENTATION_NAME}@${versionToTest}.json`; - testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, exporterFile, { + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { spanDumpPath: exporterFile, env: { OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT: '4096', - }); + }}); await testApp.invokeGetPath('/basic'); diff --git a/test/instrumentations/grpc-js/grpc-js.test.ts b/test/instrumentations/grpc-js/grpc-js.test.ts index 328db041..b2255230 100644 --- a/test/instrumentations/grpc-js/grpc-js.test.ts +++ b/test/instrumentations/grpc-js/grpc-js.test.ts @@ -100,9 +100,9 @@ describe.each(versionsToTest('@grpc/grpc-js', '@grpc/grpc-js'))( async function () { const exporterFile = `${SPANS_DIR}/server-roundtrip-unary-unary-grpc-js@${versionToTest}.json`; - testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, exporterFile, { + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { spanDumpPath: exporterFile, env: { OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT: '4096', - }); + }}); const grpcPort = DEFAULT_GRPC_PORT; @@ -135,9 +135,9 @@ describe.each(versionsToTest('@grpc/grpc-js', '@grpc/grpc-js'))( async function () { const exporterFile = `${SPANS_DIR}/server-roundtrip-unary-stream-grpc-js@${versionToTest}.json`; - testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, exporterFile, { + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { spanDumpPath: exporterFile, env: { OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT: '4096', - }); + }}); const grpcPort = DEFAULT_GRPC_PORT; @@ -173,9 +173,9 @@ describe.each(versionsToTest('@grpc/grpc-js', '@grpc/grpc-js'))( async function () { const exporterFile = `${SPANS_DIR}/server-roundtrip-stream-unary-grpc-js@${versionToTest}.json`; - testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, exporterFile, { + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { spanDumpPath: exporterFile, env: { OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT: '4096', - }); + }}); const grpcPort = DEFAULT_GRPC_PORT; @@ -213,9 +213,9 @@ describe.each(versionsToTest('@grpc/grpc-js', '@grpc/grpc-js'))( async function () { const exporterFile = `${SPANS_DIR}/server-roundtrip-stream-stream-grpc-js@${versionToTest}.json`; - testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, exporterFile, { + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { spanDumpPath: exporterFile, env: { OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT: '4096', - }); + }}); const grpcPort = DEFAULT_GRPC_PORT; diff --git a/test/instrumentations/http/http.test.ts b/test/instrumentations/http/http.test.ts index 584c9ea5..2ee0775b 100644 --- a/test/instrumentations/http/http.test.ts +++ b/test/instrumentations/http/http.test.ts @@ -15,7 +15,7 @@ const INSTRUMENTATION_NAME = 'http'; const expectedResourceAttributes = { attributes: { - 'framework': 'node', + 'framework': expect.toBeOneOf(['node', 'express']), 'lumigo.distro.version': expect.stringMatching(/1\.\d+\.\d+/), 'process.environ': expect.any(String), 'process.executable.name': 'node', @@ -76,10 +76,13 @@ describe('Instrumentation tests for the http package', function () { }); server = targetServer; - testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, spanDumpPath, { - LUMIGO_ENDPOINT: 'https://walle-edge-app-us-west-2.walle.golumigo.com', - LUMIGO_TRACER_TOKEN: 't_123321', - TARGET_URL: `http://localhost:${targetPort}`, + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { + spanDumpPath, + env: { + LUMIGO_ENDPOINT: 'https://some-endpoint-to-divert-reporting-from-production.com', + LUMIGO_TRACER_TOKEN: 't_123321', + TARGET_URL: `http://localhost:${targetPort}`, + } }); await testApp.invokeGetPath('/test1'); @@ -155,9 +158,12 @@ describe('Instrumentation tests for the http package', function () { }); server = targetServer; - testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, spanDumpPath, { - OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT: '1', - TARGET_URL: `http://localhost:${targetPort}`, + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { + spanDumpPath, + env: { + OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT: '1', + TARGET_URL: `http://localhost:${targetPort}`, + } }); await testApp.invokeGetPath('/test2'); @@ -217,9 +223,12 @@ describe('Instrumentation tests for the http package', function () { }); server = targetServer; - testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, spanDumpPath, { - OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT: '3', - TARGET_URL: `http://localhost:${targetPort}`, + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { + spanDumpPath, + env: { + OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT: '3', + TARGET_URL: `http://localhost:${targetPort}`, + } }); await testApp.invokeGetPath('/large-response'); @@ -278,8 +287,11 @@ describe('Instrumentation tests for the http package', function () { }); server = targetServer; - testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, spanDumpPath, { - TARGET_URL: `http://localhost:${targetPort}`, + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { + spanDumpPath, + env: { + TARGET_URL: `http://localhost:${targetPort}`, + } }); const port = await testApp.port(); @@ -338,12 +350,15 @@ describe('Instrumentation tests for the http package', function () { }); server = targetServer; - testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, spanDumpPath, { - TARGET_URL: `http://localhost:${targetPort}`, - LUMIGO_SECRET_MASKING_REGEX_HTTP_REQUEST_BODIES: 'all', - LUMIGO_SECRET_MASKING_REGEX_HTTP_REQUEST_HEADERS: 'all', - LUMIGO_SECRET_MASKING_REGEX_HTTP_RESPONSE_BODIES: 'all', - LUMIGO_SECRET_MASKING_REGEX_HTTP_RESPONSE_HEADERS: 'all', + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { + spanDumpPath, + env:{ + TARGET_URL: `http://localhost:${targetPort}`, + LUMIGO_SECRET_MASKING_REGEX_HTTP_REQUEST_BODIES: 'all', + LUMIGO_SECRET_MASKING_REGEX_HTTP_REQUEST_HEADERS: 'all', + LUMIGO_SECRET_MASKING_REGEX_HTTP_RESPONSE_BODIES: 'all', + LUMIGO_SECRET_MASKING_REGEX_HTTP_RESPONSE_HEADERS: 'all', + } }); const port = await testApp.port(); @@ -403,9 +418,12 @@ describe('Instrumentation tests for the http package', function () { }); server = targetServer; - testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, spanDumpPath, { - TARGET_URL: `http://localhost:${targetPort}`, - LUMIGO_DEBUG: 'true', + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { + spanDumpPath, + env: { + TARGET_URL: `http://localhost:${targetPort}`, + LUMIGO_DEBUG: 'true', + } }); const port = await testApp.port(); diff --git a/test/instrumentations/ioredis/ioredis.test.ts b/test/instrumentations/ioredis/ioredis.test.ts index a8fd15a0..a81cd62b 100644 --- a/test/instrumentations/ioredis/ioredis.test.ts +++ b/test/instrumentations/ioredis/ioredis.test.ts @@ -115,8 +115,9 @@ describe.each(versionsToTest(INSTRUMENTATION_NAME, INSTRUMENTATION_NAME))( async function () { const exporterFile = `${SPANS_DIR}/${INSTRUMENTATION_NAME}.set-and-get@${versionToTest}.json`; - testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, exporterFile, { - OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT: '4096', + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { + spanDumpPath: exporterFile, + env: { OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT: '4096' } }); const key = 'test:set-and-get'; @@ -185,9 +186,9 @@ describe.each(versionsToTest(INSTRUMENTATION_NAME, INSTRUMENTATION_NAME))( async function () { const exporterFile = `${SPANS_DIR}/${INSTRUMENTATION_NAME}.hash@${versionToTest}.json`; - testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, exporterFile, { + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { spanDumpPath: exporterFile, env: { OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT: '4096', - }); + }}); const key = 'test:hash'; const fieldA = 'test-field-a'; @@ -290,9 +291,9 @@ describe.each(versionsToTest(INSTRUMENTATION_NAME, INSTRUMENTATION_NAME))( async function () { const exporterFile = `${SPANS_DIR}/${INSTRUMENTATION_NAME}.transaction@${versionToTest}.json`; - testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, exporterFile, { + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { spanDumpPath: exporterFile, env: { OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT: '4096', - }); + }}); const key = 'test:transaction:set-and-get'; const value = 'test-value'; diff --git a/test/instrumentations/ioredis/ioredisTestUtils.ts b/test/instrumentations/ioredis/ioredisTestUtils.ts index 68c80020..26781cae 100644 --- a/test/instrumentations/ioredis/ioredisTestUtils.ts +++ b/test/instrumentations/ioredis/ioredisTestUtils.ts @@ -6,7 +6,7 @@ export function getExpectedResourceAttributes() { 'telemetry.sdk.language': 'nodejs', 'telemetry.sdk.name': 'opentelemetry', 'telemetry.sdk.version': expect.any(String), - framework: 'node', + 'framework': expect.toBeOneOf(['node', 'express']), 'process.environ': expect.any(String), 'lumigo.distro.version': expect.stringMatching(/1\.\d+\.\d+/), 'process.pid': expect.any(Number), diff --git a/test/instrumentations/kafkajs/app/package.json b/test/instrumentations/kafkajs/app/package.json index 66f54aa6..faba3b50 100644 --- a/test/instrumentations/kafkajs/app/package.json +++ b/test/instrumentations/kafkajs/app/package.json @@ -9,6 +9,6 @@ "license": "ISC", "dependencies": { "@lumigo/opentelemetry": "file:../../../../distro.tgz", - "kafkajs": "^2.0.0" + "kafkajs": "^2.2.4" } } diff --git a/test/instrumentations/kafkajs/kafkaJsTestUtils.js b/test/instrumentations/kafkajs/kafkaJsTestUtils.js index 968a2b08..5aa12728 100644 --- a/test/instrumentations/kafkajs/kafkaJsTestUtils.js +++ b/test/instrumentations/kafkajs/kafkaJsTestUtils.js @@ -6,7 +6,7 @@ export function getExpectedResourceAttributes() { 'telemetry.sdk.language': 'nodejs', 'telemetry.sdk.name': 'opentelemetry', 'telemetry.sdk.version': expect.any(String), - framework: 'node', + 'framework': expect.toBeOneOf(['node', 'express']), 'process.environ': expect.any(String), 'lumigo.distro.version': expect.stringMatching(/1\.\d+\.\d+/), 'process.pid': expect.any(Number), diff --git a/test/instrumentations/kafkajs/kafkajs.test.ts b/test/instrumentations/kafkajs/kafkajs.test.ts index 3554a900..010063ef 100644 --- a/test/instrumentations/kafkajs/kafkajs.test.ts +++ b/test/instrumentations/kafkajs/kafkajs.test.ts @@ -115,9 +115,9 @@ describe.each(versionsToTest(INSTRUMENTATION_NAME, INSTRUMENTATION_NAME))( async function () { const exporterFile = `${SPANS_DIR}/kafka-roundtrip.${INSTRUMENTATION_NAME}@${versionToTest}.json`; - testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, exporterFile, { + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { spanDumpPath: exporterFile, env: { OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT: '4096', - }); + }}); const topic = 'test-topic-roundtrip'; const key = 'test-key-roundtrip'; diff --git a/test/instrumentations/mongodb/mongodb.test.ts b/test/instrumentations/mongodb/mongodb.test.ts index c7513804..1d759eba 100644 --- a/test/instrumentations/mongodb/mongodb.test.ts +++ b/test/instrumentations/mongodb/mongodb.test.ts @@ -102,12 +102,13 @@ describe.each(versionsToTest(INSTRUMENTATION_NAME, INSTRUMENTATION_NAME))( testApp = new TestApp( TEST_APP_DIR, INSTRUMENTATION_NAME, - `${SPANS_DIR}/basic-@${versionToTest}.json`, { - MONGODB_URL: mongoConnectionUrl.toString(), - OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT: '4096', - } - ); + spanDumpPath: `${SPANS_DIR}/basic-@${versionToTest}.json`, + env: { + MONGODB_URL: mongoConnectionUrl.toString(), + OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT: '4096', + } + }); }, DOCKER_WARMUP_TIMEOUT); afterEach(async function () { diff --git a/test/instrumentations/mongodb/mongodbTestUtils.js b/test/instrumentations/mongodb/mongodbTestUtils.js index ba91464e..f2a249e3 100644 --- a/test/instrumentations/mongodb/mongodbTestUtils.js +++ b/test/instrumentations/mongodb/mongodbTestUtils.js @@ -6,7 +6,7 @@ export function getExpectedResourceAttributes() { 'telemetry.sdk.language': 'nodejs', 'telemetry.sdk.name': 'opentelemetry', 'telemetry.sdk.version': expect.any(String), - framework: 'node', + 'framework': expect.toBeOneOf(['node', 'express']), 'process.environ': expect.any(String), 'lumigo.distro.version': expect.stringMatching(/1\.\d+\.\d+/), 'process.pid': expect.any(Number), diff --git a/test/instrumentations/nestjs/nestjs.test.ts b/test/instrumentations/nestjs/nestjs.test.ts index 0ba529d6..6c1a4f4c 100644 --- a/test/instrumentations/nestjs/nestjs.test.ts +++ b/test/instrumentations/nestjs/nestjs.test.ts @@ -54,10 +54,12 @@ describe.each(versionsToTest('@nestjs/core', '@nestjs/core'))( testApp = new TestApp( TEST_APP_DIR, INSTRUMENTATION_NAME, - `${SPANS_DIR}/basic-@${versionToTest}.json`, { - NEST_JS_PORT: port, - OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT: '4096', + spanDumpPath: `${SPANS_DIR}/basic-@${versionToTest}.json`, + env: { + NEST_JS_PORT: String(port), + OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT: '4096', + } } ); }, DOCKER_WARMUP_TIMEOUT); diff --git a/test/instrumentations/pg/postgres.test.ts b/test/instrumentations/pg/postgres.test.ts index fbaada80..de05e48d 100644 --- a/test/instrumentations/pg/postgres.test.ts +++ b/test/instrumentations/pg/postgres.test.ts @@ -78,14 +78,16 @@ describe.each(versionsToTest(INSTRUMENTATION_NAME, INSTRUMENTATION_NAME))( testApp = new TestApp( TEST_APP_DIR, INSTRUMENTATION_NAME, - `${SPANS_DIR}/basic-@${versionToTest}.json`, { - POSTGRES_HOST: postgresContainer.getHost().toString(), - POSTGRES_PORT: postgresContainer.getPort().toString(), - POSTGRES_DATABASE: postgresContainer.getDatabase().toString(), - POSTGRES_USER: postgresContainer.getUsername().toString(), - POSTGRES_PASSWORD: postgresContainer.getPassword().toString(), - OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT: '4096', + spanDumpPath: `${SPANS_DIR}/basic-@${versionToTest}.json`, + env: { + POSTGRES_HOST: postgresContainer.getHost().toString(), + POSTGRES_PORT: postgresContainer.getPort().toString(), + POSTGRES_DATABASE: postgresContainer.getDatabase().toString(), + POSTGRES_USER: postgresContainer.getUsername().toString(), + POSTGRES_PASSWORD: postgresContainer.getPassword().toString(), + OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT: '4096', + } } ); }, DOCKER_WARMUP_TIMEOUT); diff --git a/test/instrumentations/prisma/prisma.mysql.test.ts b/test/instrumentations/prisma/prisma.mysql.test.ts index 62ab91d6..6975fe3f 100644 --- a/test/instrumentations/prisma/prisma.mysql.test.ts +++ b/test/instrumentations/prisma/prisma.mysql.test.ts @@ -207,10 +207,10 @@ describe.each(versionsToTest(INSTRUMENTATION_NAME, INSTRUMENTATION_NAME))( async function () { const exporterFile = `${SPANS_DIR}/${engine.name}-basics.${INSTRUMENTATION_NAME}@${versionToTest}.json`; - testApp = new TestApp(engine.appDir, INSTRUMENTATION_NAME, exporterFile, { + testApp = new TestApp(engine.appDir, INSTRUMENTATION_NAME, { spanDumpPath: exporterFile, env: { DATABASE_URL: buildConnectionUrl(engine, containerHost, containerPort), OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT: '4096', - }); + }}); await testApp.invokeGetPath(`/add-user?name=Alice&email=alice@prisma.io`); diff --git a/test/instrumentations/prisma/prisma.postgres.test.ts b/test/instrumentations/prisma/prisma.postgres.test.ts index 35d727d9..4be7d8d3 100644 --- a/test/instrumentations/prisma/prisma.postgres.test.ts +++ b/test/instrumentations/prisma/prisma.postgres.test.ts @@ -208,10 +208,10 @@ describe.each(versionsToTest(INSTRUMENTATION_NAME, INSTRUMENTATION_NAME))( async function () { const exporterFile = `${SPANS_DIR}/${engine.name}-basics.${INSTRUMENTATION_NAME}@${versionToTest}.json`; - testApp = new TestApp(engine.appDir, INSTRUMENTATION_NAME, exporterFile, { + testApp = new TestApp(engine.appDir, INSTRUMENTATION_NAME, { spanDumpPath: exporterFile, env: { DATABASE_URL: buildConnectionUrl(engine, containerHost, containerPort), OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT: '4096', - }); + }}); await testApp.invokeGetPath(`/add-user?name=Alice&email=alice@prisma.io`); diff --git a/test/instrumentations/prisma/prismaTestUtils.js b/test/instrumentations/prisma/prismaTestUtils.js index 532a4b9f..ab10bc42 100644 --- a/test/instrumentations/prisma/prismaTestUtils.js +++ b/test/instrumentations/prisma/prismaTestUtils.js @@ -7,7 +7,7 @@ export function getExpectedResourceAttributes() { 'telemetry.sdk.language': 'nodejs', 'telemetry.sdk.name': 'opentelemetry', 'telemetry.sdk.version': expect.any(String), - framework: 'node', + 'framework': expect.toBeOneOf(['node', 'express']), 'process.environ': expect.any(String), 'lumigo.distro.version': expect.stringMatching(/1\.\d+\.\d+/), 'process.pid': expect.any(Number), diff --git a/test/instrumentations/redis/redis.test.ts b/test/instrumentations/redis/redis.test.ts index 60cd04b1..1e857be9 100644 --- a/test/instrumentations/redis/redis.test.ts +++ b/test/instrumentations/redis/redis.test.ts @@ -111,9 +111,9 @@ describe.each(versionsToTest(INSTRUMENTATION_NAME, INSTRUMENTATION_NAME))( async function () { const exporterFile = `${SPANS_DIR}/${INSTRUMENTATION_NAME}.set-and-get@${versionToTest}.json`; - testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, exporterFile, { + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { spanDumpPath: exporterFile, env: { OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT: '4096', - }); + }}); const key = 'test:set-and-get'; const value = 'test-set-and-get-value'; @@ -181,9 +181,9 @@ describe.each(versionsToTest(INSTRUMENTATION_NAME, INSTRUMENTATION_NAME))( async function () { const exporterFile = `${SPANS_DIR}/${INSTRUMENTATION_NAME}.hash@${versionToTest}.json`; - testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, exporterFile, { + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { spanDumpPath: exporterFile, env: { OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT: '4096', - }); + }}); const key = 'test:hash'; const fieldA = 'test-field-a'; @@ -271,9 +271,9 @@ describe.each(versionsToTest(INSTRUMENTATION_NAME, INSTRUMENTATION_NAME))( async function () { const exporterFile = `${SPANS_DIR}/${INSTRUMENTATION_NAME}.transaction@${versionToTest}.json`; - testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, exporterFile, { + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { spanDumpPath: exporterFile, env: { OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT: '4096', - }); + }}); const key = 'test:transaction:set-and-get'; const value = 'test-value'; diff --git a/test/instrumentations/redis/redisTestUtils.ts b/test/instrumentations/redis/redisTestUtils.ts index 0c505013..981e2c59 100644 --- a/test/instrumentations/redis/redisTestUtils.ts +++ b/test/instrumentations/redis/redisTestUtils.ts @@ -6,7 +6,7 @@ export function getExpectedResourceAttributes() { 'telemetry.sdk.language': 'nodejs', 'telemetry.sdk.name': 'opentelemetry', 'telemetry.sdk.version': expect.any(String), - framework: 'node', + 'framework': expect.toBeOneOf(['node', 'express']), 'process.environ': expect.any(String), 'lumigo.distro.version': expect.stringMatching(/1\.\d+\.\d+/), 'process.pid': expect.any(Number), diff --git a/test/instrumentations/winston/.gitignore b/test/instrumentations/winston/.gitignore new file mode 100644 index 00000000..cd3d2253 --- /dev/null +++ b/test/instrumentations/winston/.gitignore @@ -0,0 +1 @@ +logs \ No newline at end of file diff --git a/test/instrumentations/winston/app/.gitignore b/test/instrumentations/winston/app/.gitignore new file mode 100644 index 00000000..483a9c42 --- /dev/null +++ b/test/instrumentations/winston/app/.gitignore @@ -0,0 +1 @@ +package-lock.json \ No newline at end of file diff --git a/test/instrumentations/winston/app/package.json b/test/instrumentations/winston/app/package.json new file mode 100644 index 00000000..e44dfd14 --- /dev/null +++ b/test/instrumentations/winston/app/package.json @@ -0,0 +1,15 @@ +{ + "name": "lumigo-winston-test", + "version": "1.0.0", + "description": "", + "scripts": { + "start": "node -r @lumigo/opentelemetry winston_app.js" + }, + "author": "", + "license": "ISC", + "dependencies": { + "@lumigo/opentelemetry": "file:../../../../distro.tgz", + "@opentelemetry/winston-transport": "^0.2.0", + "winston": "^3.13.0" + } +} diff --git a/test/instrumentations/winston/app/winston_app.js b/test/instrumentations/winston/app/winston_app.js new file mode 100644 index 00000000..4dad838f --- /dev/null +++ b/test/instrumentations/winston/app/winston_app.js @@ -0,0 +1,60 @@ +const http = require('http'); +const url = require('url'); +const { init } = require("@lumigo/opentelemetry") + +require('log-timestamp'); + +const host = 'localhost'; +let httpServer; + +function respond(res, status, body) { + console.log(`responding with ${status} ${JSON.stringify(body)}`); + res.setHeader('Content-Type', 'application/json'); + res.setHeader('access-control-allow-origin', '*'); + res.writeHead(status); + res.end(JSON.stringify(body)); +} + +const requestListener = async function (req, res) { + await init; + + const winston = require('winston'); + const winstonLogger = winston.createLogger({ + transports: [new winston.transports.Console()], + }) + + console.error(`Received request: ${req.method} ${req.url}`); + + const requestUrl = url.parse(req.url, true); + + switch (requestUrl.pathname) { + case '/write-log-line': + try { + const logLine = JSON.parse(requestUrl?.query?.logLine) + winstonLogger.info(logLine); + respond(res, 200, {}) + } catch (err) { + console.error(`Error writing log line`, err); + respond(res, 500, { error: err }); + } + break; + + case '/quit': + console.error('Received quit command'); + respond(res, 200, {}); + httpServer.close(); + break; + + default: + respond(res, 404, { error: 'Resource not found' }); + } +}; + +httpServer = http.createServer(requestListener); +httpServer.listen(0, host, () => { + const port = httpServer.address().port; + console.error(`HTTP server listening on port ${port} `); + if (process.send) { + process.send(port); + } +}); diff --git a/test/instrumentations/winston/winston.test.ts b/test/instrumentations/winston/winston.test.ts new file mode 100644 index 00000000..16d727e2 --- /dev/null +++ b/test/instrumentations/winston/winston.test.ts @@ -0,0 +1,134 @@ +import fs from 'fs'; +import { join } from 'path'; +import { itTest } from '../../integration/setup'; +import { TestApp } from '../../utils/test-apps'; +import { installPackage, reinstallPackages, uninstallPackage } from '../../utils/test-setup'; +import { versionsToTest } from '../../utils/versions'; +import { FakeEdge } from '../../utils/fake-edge'; +import { setTimeout } from 'timers/promises'; + +const INSTRUMENTATION_NAME = 'winston'; +const LOGS_DIR = join(__dirname, 'logs'); +const TEST_APP_DIR = join(__dirname, 'app'); + +describe.each(versionsToTest(INSTRUMENTATION_NAME, INSTRUMENTATION_NAME))( + `Instrumentation tests for the ${INSTRUMENTATION_NAME} package`, + function (versionToTest) { + let testApp: TestApp; + const fakeEdge = new FakeEdge(); + + beforeAll(async () => { + await fakeEdge.start(); + + reinstallPackages({ appDir: TEST_APP_DIR }); + fs.mkdirSync(LOGS_DIR, { recursive: true }); + installPackage({ + appDir: TEST_APP_DIR, + packageName: INSTRUMENTATION_NAME, + packageVersion: versionToTest, + }); + }); + + afterEach(async () => { + fakeEdge.reset(); + + if (testApp) { + await testApp.kill(); + } + }); + + afterAll(async () => { + await fakeEdge.stop(); + uninstallPackage({ + appDir: TEST_APP_DIR, + packageName: INSTRUMENTATION_NAME, + packageVersion: versionToTest, + }); + }); + + itTest( + { + testName: `${INSTRUMENTATION_NAME} logger: ${versionToTest}`, + packageName: INSTRUMENTATION_NAME, + version: versionToTest, + timeout: 20_000, + }, + async function () { + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { + logDumpPath: `${LOGS_DIR}/${INSTRUMENTATION_NAME}.${INSTRUMENTATION_NAME}-logs@${versionToTest}.json`, + env: { + LUMIGO_ENABLE_LOGS: 'true', + LUMIGO_SECRET_MASKING_REGEX: '[".*sekret.*"]', + LUMIGO_LOGS_ENDPOINT: fakeEdge.logsUrl, + LUMIGO_ENDPOINT: fakeEdge.tracesUrl, + LUMIGO_TRACER_TOKEN: 't_123456789', + }, + }); + + await writeLogLine('Hello Winston!'); + await writeLogLine({ a: 1, sekret: 'this is secret!' }); + + await fakeEdge.waitFor( + () => fakeEdge.resources.length == 1, + 'waiting for resources to be processed' + ); + await fakeEdge.waitFor(() => fakeEdge.logs.length == 2, 'waiting for logs to be processed'); + + expect(fakeEdge.resources[0].attributes).toIncludeAllMembers([ + { + key: 'service.name', + value: { + stringValue: 'winston', + }, + }, + ]); + + expect(fakeEdge.logs[0].body).toEqual({ stringValue: 'Hello Winston!' }); + // Span context is available since the test app is an instrumented HTTP server + expect(fakeEdge.logs[0]['traceId']).toHaveLength(32); + expect(fakeEdge.logs[0]['spanId']).toHaveLength(16); + + expect(fakeEdge.logs[1].body).toMatchObject({ + kvlistValue: { + values: [ + { key: 'a', value: { intValue: 1 } }, + { key: 'sekret', value: { stringValue: '****' } }, + ], + }, + }); + expect(fakeEdge.logs[1]['traceId']).toHaveLength(32); + expect(fakeEdge.logs[1]['spanId']).toHaveLength(16); + + // Test the log-dump functionality + await testApp.getFinalLogs(2); + } + ); + + itTest( + { + testName: `${INSTRUMENTATION_NAME} logger: ${versionToTest} - logging off`, + packageName: INSTRUMENTATION_NAME, + version: versionToTest, + timeout: 20_000, + }, + async function () { + testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { + logDumpPath: `${LOGS_DIR}/${INSTRUMENTATION_NAME}.${INSTRUMENTATION_NAME}-logs-off@${versionToTest}.json`, + env: { + LUMIGO_ENABLE_LOGS: 'false', + }, + }); + + await writeLogLine('Hello Winston!'); + + // We expect no logs to be sent, therefore waiting for 1 log should fail + await expect(testApp.getFinalLogs(1)).rejects.toThrow(); + } + ); + + const writeLogLine = async (logLine: any) => + testApp.invokeGetPath( + `/write-log-line?logLine=${encodeURIComponent(JSON.stringify(logLine))}` + ); + } +); diff --git a/test/utils/common.ts b/test/utils/common.ts new file mode 100644 index 00000000..db92ea6c --- /dev/null +++ b/test/utils/common.ts @@ -0,0 +1,10 @@ +import { readFileSync } from "fs"; + +export function readDumpFile(dumpFilePath: string): T[] { + try { + return readFileSync(dumpFilePath, 'utf-8').split(/\r?\n/).filter(Boolean).map(line => JSON.parse(line)); + } catch (err) { + // Might be that we try to read as a new record is being written, and the JSON is still malformed + return []; + } +} \ No newline at end of file diff --git a/test/utils/fake-edge.ts b/test/utils/fake-edge.ts new file mode 100644 index 00000000..d79450b8 --- /dev/null +++ b/test/utils/fake-edge.ts @@ -0,0 +1,96 @@ +import {IResource} from "@opentelemetry/resources"; +import { LogRecord } from "@opentelemetry/sdk-logs"; +import express, { Express, Request, Response } from 'express'; +import { Server } from "http"; +import { AddressInfo } from "net"; +import pRetry, { FailedAttemptError } from 'p-retry'; + +export class FakeEdge { + private app: Express; + private _logs: LogRecord[] = []; + private _resources: IResource[] = []; + private server: Server; + private baseUrl: string; + + constructor() { + this.app = express(); + this.app.use(express.json()); + this.app.use('/v1/traces', (req: Request, res: Response) => { + // Currently not used in any tests, just respond with 200 so spans posted during logging tests will not produce errors + res.sendStatus(200); + }); + this.app.use('/v1/logs', (req: Request, res: Response) => { + try { + const logRecords = req.body.resourceLogs.flatMap(rl => rl.scopeLogs.flatMap(sl => sl.logRecords)) + console.log(`Received ${logRecords.length} logs in edge`); + this._logs.push(...logRecords) + + const resources = req.body.resourceLogs.map(rl => rl.resource) + console.log(`Received ${resources.length} resources in edge`); + this._resources.push(...resources) + + } catch (e) { + console.error('Error parsing logs in edge: ', e); + return res.sendStatus(500); + } + res.sendStatus(200); + }); + } + + start() { + return new Promise((resolve, reject) => { + this.server = this.app.listen(0, () => { + this.server.on('error', (err: any) => reject(err)); + + const addressInfo = this.server.address() as AddressInfo + this.baseUrl = `localhost:${addressInfo.port}`; + + console.log(`Edge is running on address ${this.baseUrl}`); + resolve(this.baseUrl); + }); + }); + } + + get logsUrl() { + return `http://${this.baseUrl}/v1/logs`; + } + + get tracesUrl() { + return `http://${this.baseUrl}/v1/traces`; + } + + async waitFor(condition: () => boolean, message: string, timeout = 5000) { + await pRetry(() => { + if (condition()) { + return Promise.resolve(); + } else { + return Promise.reject(new Error('Condition not met')); + } + }, { maxTimeout: timeout, onFailedAttempt: () => console.log(message)}) + } + + stop() { + return new Promise((resolve, reject) => { + this.server.close((err: unknown) => { + if (err) { + reject(err); + } else { + resolve(undefined); + } + }); + }); + } + + get logs() { + return this._logs; + } + + get resources() { + return this._resources; + } + + reset() { + this._logs = []; + this._resources = []; + } +} \ No newline at end of file diff --git a/test/utils/spans.ts b/test/utils/spans.ts index 7a71e9ad..6b4eae23 100644 --- a/test/utils/spans.ts +++ b/test/utils/spans.ts @@ -1,7 +1,9 @@ -import { readFileSync } from 'fs'; import { SpanKind } from '@opentelemetry/api'; import { BasicTracerProvider, Span } from '@opentelemetry/sdk-trace-base'; +export { Span } from '@opentelemetry/sdk-trace-base'; +export { LogRecord } from '@opentelemetry/sdk-logs'; + export function getSpanByName(spans: Span[] = [], spanName: string) { return spans.find((span) => span.name === spanName); } @@ -18,19 +20,10 @@ export const getSpansByAttribute = (spans: Span[], attributeKey: string, attribu return spans.filter((span) => span.attributes[attributeKey] === attributeValue); } -export function readSpanDump(spanDumpPath: string): Span[] { - try { - return readFileSync(spanDumpPath, 'utf-8').split(/\r?\n/).filter(Boolean).map(line => JSON.parse(line)); - } catch (err) { - // Might be we try to read as a new span is being written, and the JSON is still malformed - return []; - } -} - export const rootSpanWithAttributes = (attributes: Record, kind?: SpanKind): Span => { const provider = new BasicTracerProvider(); const root = provider.getTracer('default').startSpan('root', { kind, attributes }); root.setAttributes(attributes); return root as Span; - }; + }; \ No newline at end of file diff --git a/test/utils/test-apps.ts b/test/utils/test-apps.ts index 878c4829..6d40a40b 100644 --- a/test/utils/test-apps.ts +++ b/test/utils/test-apps.ts @@ -1,45 +1,49 @@ import { ChildProcessWithoutNullStreams, execSync, spawn } from 'child_process'; import { existsSync, unlinkSync } from 'fs'; import waitOn from 'wait-on'; -import { Span, readSpanDump } from './spans'; +import { Span } from './spans'; import { sleep } from './time'; +import { LogRecord } from '@opentelemetry/sdk-logs'; +import {readDumpFile} from './common'; const WAIT_ON_INITIAL_DELAY = 1_000; const WAIT_ON_TIMEOUT = 10_000; const PORT_REGEX = new RegExp('.*([Ll]istening on port )([0-9]*)', 'g'); -export class TestApp { +type TestAppOptions = { + spanDumpPath?: string, + logDumpPath?: string, + env?: Record, + showStdout?: boolean +} +export class TestApp { private app: ChildProcessWithoutNullStreams; private closePromise: Promise; - private cwd: string; - private envVars: any; private exitCode: number | null = null; private hasAppExited = false; private pid: number | undefined = undefined; private portPromise: Promise; - private serviceName: string; - private spanDumpPath: string; - private readonly showStdout: boolean; constructor( - cwd: string, - serviceName: string, - spanDumpPath: string, - envVars = {}, - showStdout = false + private readonly cwd: string, + private readonly serviceName: string, + private readonly options: TestAppOptions = { + env: {}, + showStdout: false, + } ) { - this.cwd = cwd; - this.envVars = envVars; - this.serviceName = serviceName; - this.spanDumpPath = spanDumpPath; - this.showStdout = showStdout; - - if (existsSync(spanDumpPath)) { + const { logDumpPath, spanDumpPath } = options; + if (spanDumpPath && existsSync(spanDumpPath)) { console.info(`removing previous span dump file ${spanDumpPath}...`) unlinkSync(spanDumpPath); } + if (logDumpPath && existsSync(logDumpPath)) { + console.info(`removing previous log dump file ${logDumpPath}...`) + unlinkSync(logDumpPath); + } + this.runAppScript(); } @@ -55,17 +59,20 @@ export class TestApp { }; public runAppScript(): void { - console.info(`starting test app with span dump file ${this.spanDumpPath}...`); + const { spanDumpPath, logDumpPath, showStdout, env: envVars } = this.options; + + console.info(`starting test app with span dump file ${spanDumpPath}, log dump file ${logDumpPath}...`); this.app = spawn('npm', ['run', 'start'], { cwd: this.cwd, env: { ...process.env, ...{ OTEL_SERVICE_NAME: this.serviceName, - LUMIGO_DEBUG_SPANDUMP: this.spanDumpPath, + LUMIGO_DEBUG_SPANDUMP: spanDumpPath, + LUMIGO_DEBUG_LOGDUMP: logDumpPath, LUMIGO_DEBUG: String(true), }, - ...this.envVars, + ...envVars, }, shell: true, }); @@ -105,7 +112,7 @@ export class TestApp { console.info('spawn data stderr: ', dataStr); }); - if (this.showStdout) { + if (showStdout) { this.app.stdout.on('data', (data) => { console.info(`[${this.serviceName}] `, data.toString()); }); @@ -217,7 +224,7 @@ export class TestApp { if (err) { return reject(err) } else { - resolve(readSpanDump(spanDumpPath)); + resolve(readDumpFile(spanDumpPath)); } } ); @@ -258,32 +265,55 @@ export class TestApp { }); } - public async getFinalSpans(expectedNumberOfSpans: number | null = null, timeout = 10_000): Promise { - const spanDumpPath = this.spanDumpPath; + public async getFinalSpans(expectedNumberOfSpans?: number, timeout = 10_000): Promise { + const { spanDumpPath } = this.options; - let spans = readSpanDump(spanDumpPath) + if (!spanDumpPath) { + throw new Error('spanDumpPath was not provided in the TestApp options'); + } - if (expectedNumberOfSpans) { + return await this.getFinalRecords(spanDumpPath, expectedNumberOfSpans, timeout); + } + + public async getFinalLogs(expectedNumberOfLogs?: number, timeout = 10_000): Promise { + const { logDumpPath } = this.options; + + if (!logDumpPath) { + throw new Error('logDumpPath was not provided in the TestApp options'); + } + + return await this.getFinalRecords(logDumpPath, expectedNumberOfLogs, timeout); + } + + public async getFinalRecords(dumpFilePath: string, expectedNumberOfRecords?: number, timeout = 10_000): Promise { + let records: T[] = readDumpFile(dumpFilePath) + + if (expectedNumberOfRecords) { const sleepTime = 500; let timeoutRemaining = timeout; - while (spans.length < expectedNumberOfSpans && timeoutRemaining > 0) { + while (records.length < expectedNumberOfRecords && timeoutRemaining > 0) { await sleep(sleepTime); timeoutRemaining -= sleepTime; - spans = readSpanDump(spanDumpPath); + records = readDumpFile(dumpFilePath); } - if (spans.length < expectedNumberOfSpans) { - throw new Error(`expected ${expectedNumberOfSpans} spans, but only found ${spans.length} spans`); + if (records.length < expectedNumberOfRecords) { + throw new Error(`expected ${expectedNumberOfRecords} records, but only found ${records.length}`); } } await this.invokeShutdown(); - return spans; + + return records; } public async kill(): Promise { console.info(`killing app with pid '${this.pid}'...`); try { + // Avoids PIPEWRAP open handle error when killing the test app + this.app.stdout.destroy() + this.app.stderr.destroy() + this.app.kill('SIGKILL'); await this.closePromise; } catch (err) {