{"_id":"@5stones/nestjs-observability-utilities","_rev":"3-6c858a12272482b0c9d6ae21c0a8467f","name":"@5stones/nestjs-observability-utilities","dist-tags":{"latest":"1.0.0-rc.2"},"versions":{"0.0.1":{"name":"@5stones/nestjs-observability-utilities","version":"0.0.1","keywords":["nest","nestjs","nest.js","observability","otel","telemetry"],"author":{"name":"Ken Michalak","email":"kmichalak@weare5stones.com"},"license":"MIT","_id":"@5stones/nestjs-observability-utilities@0.0.1","maintainers":[{"name":"jspizziri","email":"jake_20@hotmail.com"},{"name":"ken-michalak","email":"Ken.Michalak@gmail.com"},{"name":"abourge","email":"abourge@weare5stones.com"}],"dist":{"shasum":"e0cbb870989e02ae72ec446fc2220e9481691115","tarball":"https://registry.npmjs.org/@5stones/nestjs-observability-utilities/-/nestjs-observability-utilities-0.0.1.tgz","fileCount":49,"integrity":"sha512-oHb/qaqTRzfFU7bhfgJUq6f5ppn2osBGXXLt3T2jj7rZvaVGWlcM7ET76P9c5xZkTyMPrKaVTKTyg1TCy5pEFw==","signatures":[{"sig":"MEUCIC4FSx90X9ec6LuLxLpJpbWO6s/viqqbyk9b2L2fxbpuAiEAv+e/ewt2iyFIIO5WtRyxuVsS7bZOr/akg/kL/6OSp2w=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":48439},"jest":{"roots":["<rootDir>/src/","<rootDir>/libs/"],"rootDir":".","testRegex":".*\\.spec\\.ts$","transform":{"^.+\\.(t|j)s$":"ts-jest"},"testEnvironment":"node","moduleNameMapper":{"^@5stones/nestjs-observability-utilities(|/.*)$":"<rootDir>/libs/nestjs-observability-utilities/src/$1"},"coverageDirectory":"./coverage","collectCoverageFrom":["**/*.(t|j)s"],"moduleFileExtensions":["js","json","ts"]},"gitHead":"8d5ae78b03083ea6ec38c143379a06d8abffb0dd","private":false,"scripts":{"lint":"eslint \"{src,apps,libs,test}/**/*.ts\" --fix","test":"jest","build":"nest build","start":"nest start","format":"prettier --write \"src/**/*.ts\" \"test/**/*.ts\" \"libs/**/*.ts\"","version":"npm run changelog && git add CHANGELOG.md","test:cov":"jest --coverage","test:e2e":"jest --config ./test/jest-e2e.json","changelog":"conventional-changelog -p angular -i CHANGELOG.md -s -r 0","start:dev":"nest start --watch","start:prod":"node dist/main","test:debug":"node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand","test:watch":"jest --watch","postversion":"npm run publish:git && npm run publish:npm","publish:git":"git push && git push --tags","publish:npm":"npm run build && npm publish --access public","start:debug":"nest start --debug --watch"},"_npmUser":{"name":"jspizziri","email":"jake_20@hotmail.com"},"_npmVersion":"10.9.0","description":"A collection of utilities for logging, error handling, and traces, which fills in some gaps missing from the base NestJS project.","directories":{},"_nodeVersion":"23.3.0","dependencies":{"rxjs":"^7.8.1","@nestjs/core":"^10.0.0","@nestjs/common":"^10.0.0","reflect-metadata":"^0.2.0","@nestjs/platform-express":"^10.0.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.5.0","eslint":"^8.0.0","ts-jest":"^29.1.0","ts-node":"^10.9.1","prettier":"^3.0.0","supertest":"^7.0.0","ts-loader":"^9.4.3","typescript":"^5.1.3","@nestjs/cli":"^10.0.0","@types/jest":"^29.5.2","@types/node":"^20.3.1","@types/express":"^5.0.0","tsconfig-paths":"^4.2.0","@nestjs/testing":"^10.0.0","@types/supertest":"^6.0.0","@nestjs/schematics":"^10.0.0","@opentelemetry/api":"^1.9.0","source-map-support":"^0.5.21","@nestjs/microservices":"^10.4.15","eslint-config-prettier":"^9.0.0","eslint-plugin-prettier":"^5.0.0","@opentelemetry/sdk-node":"^0.57.0","@typescript-eslint/parser":"^8.0.0","conventional-changelog-cli":"^5.0.0","@typescript-eslint/eslint-plugin":"^8.0.0","@opentelemetry/auto-instrumentations-node":"^0.55.0"},"_npmOperationalInternal":{"tmp":"tmp/nestjs-observability-utilities_0.0.1_1736773824219_0.09168388015488338","host":"s3://npm-registry-packages-npm-production"}},"1.0.0-rc.0":{"name":"@5stones/nestjs-observability-utilities","version":"1.0.0-rc.0","keywords":["nest","nestjs","nest.js","observability","otel","telemetry"],"author":{"name":"Ken Michalak","email":"kmichalak@weare5stones.com"},"license":"MIT","_id":"@5stones/nestjs-observability-utilities@1.0.0-rc.0","maintainers":[{"name":"jspizziri","email":"jake_20@hotmail.com"},{"name":"ken-michalak","email":"Ken.Michalak@gmail.com"},{"name":"abourge","email":"abourge@weare5stones.com"}],"dist":{"shasum":"6dcf559489a3df98ed076c76ed6c8ec07c658b39","tarball":"https://registry.npmjs.org/@5stones/nestjs-observability-utilities/-/nestjs-observability-utilities-1.0.0-rc.0.tgz","fileCount":50,"integrity":"sha512-Rg9hahRs9eoLVVL/oNp/+HSJ5bEEjA24qcA1rC0B7+JhMq9YK2vJGI0PGueZjeNBkPoBX23l9GeKtNR25xuCtA==","signatures":[{"sig":"MEQCIEaS0cbDFPD6Idn+cARsPL4xe3xn+G6dlkWdI3bcwOdRAiBxhvAz72JYIqOCxq997rOF1+Vs2HdhFxnHr0YnuT7G2g==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":48698},"jest":{"roots":["<rootDir>/src/","<rootDir>/libs/"],"rootDir":".","testRegex":".*\\.spec\\.ts$","transform":{"^.+\\.(t|j)s$":"ts-jest"},"testEnvironment":"node","moduleNameMapper":{"^@5stones/nestjs-observability-utilities(|/.*)$":"<rootDir>/libs/nestjs-observability-utilities/src/$1"},"coverageDirectory":"./coverage","collectCoverageFrom":["**/*.(t|j)s"],"moduleFileExtensions":["js","json","ts"]},"gitHead":"dce4aaff222ca1d951da76784311f2383c72ade5","private":false,"scripts":{"lint":"eslint \"{src,apps,libs,test}/**/*.ts\" --fix","test":"jest","build":"nest build","start":"nest start","format":"prettier --write \"src/**/*.ts\" \"test/**/*.ts\" \"libs/**/*.ts\"","version":"npm run changelog && git add CHANGELOG.md","test:cov":"jest --coverage","test:e2e":"jest --config ./test/jest-e2e.json","changelog":"conventional-changelog -p angular -i CHANGELOG.md -s -r 0","start:dev":"nest start --watch","start:prod":"node dist/main","test:debug":"node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand","test:watch":"jest --watch","postversion":"npm run publish:git && npm run publish:npm","publish:git":"git push && git push --tags","publish:npm":"npm run build && npm publish --access public","start:debug":"nest start --debug --watch"},"_npmUser":{"name":"jspizziri","email":"jake_20@hotmail.com"},"_npmVersion":"10.9.0","description":"A collection of utilities for logging, error handling, and traces, which fills in some gaps missing from the base NestJS project.","directories":{},"_nodeVersion":"23.3.0","dependencies":{"rxjs":"^7.8.1","@nestjs/core":"^10.0.0","@nestjs/common":"^10.0.0","reflect-metadata":"^0.2.0","@nestjs/platform-express":"^10.0.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.5.0","eslint":"^8.0.0","ts-jest":"^29.1.0","ts-node":"^10.9.1","prettier":"^3.0.0","supertest":"^7.0.0","ts-loader":"^9.4.3","typescript":"^5.1.3","@nestjs/cli":"^10.0.0","@types/jest":"^29.5.2","@types/node":"^20.3.1","@types/express":"^5.0.0","tsconfig-paths":"^4.2.0","@nestjs/testing":"^10.0.0","@types/supertest":"^6.0.0","@nestjs/schematics":"^10.0.0","@opentelemetry/api":"^1.9.0","source-map-support":"^0.5.21","@nestjs/microservices":"^10.4.15","eslint-config-prettier":"^9.0.0","eslint-plugin-prettier":"^5.0.0","@opentelemetry/sdk-node":"^0.57.0","@typescript-eslint/parser":"^8.0.0","conventional-changelog-cli":"^5.0.0","@typescript-eslint/eslint-plugin":"^8.0.0","@opentelemetry/auto-instrumentations-node":"^0.55.0"},"_npmOperationalInternal":{"tmp":"tmp/nestjs-observability-utilities_1.0.0-rc.0_1736774071494_0.15611331405806217","host":"s3://npm-registry-packages-npm-production"}},"1.0.0-rc.1":{"name":"@5stones/nestjs-observability-utilities","version":"1.0.0-rc.1","keywords":["nest","nestjs","nest.js","observability","otel","telemetry"],"author":{"name":"Ken Michalak","email":"kmichalak@weare5stones.com"},"license":"MIT","_id":"@5stones/nestjs-observability-utilities@1.0.0-rc.1","maintainers":[{"name":"jspizziri","email":"jake_20@hotmail.com"},{"name":"ken-michalak","email":"Ken.Michalak@gmail.com"},{"name":"abourge","email":"abourge@weare5stones.com"}],"dist":{"shasum":"6fffb2fda51d9a6f62a57eb34075428e542fdf58","tarball":"https://registry.npmjs.org/@5stones/nestjs-observability-utilities/-/nestjs-observability-utilities-1.0.0-rc.1.tgz","fileCount":95,"integrity":"sha512-2SiEh//in6j1/I9a7V8tCkuM1Lv8o8Wk3EY5pomgXFrMXG2idcV/nTCLguUujcwUctoraHWvYpFufEspdVhUww==","signatures":[{"sig":"MEQCIHsOA28jwhemeoUZzQQOmbqsKNEWguRkkpoLMM2SHHllAiB1QVEJu4xgaLNl+CItioZDiCfC5Tu5KlUEe1eKypwdFQ==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":247664},"jest":{"roots":["<rootDir>/src/","<rootDir>/libs/"],"rootDir":".","testRegex":".*\\.spec\\.ts$","transform":{"^.+\\.(t|j)s$":"ts-jest"},"testEnvironment":"node","moduleNameMapper":{"^@5stones/nestjs-observability-utilities(|/.*)$":"<rootDir>/libs/nestjs-observability-utilities/src/$1"},"coverageDirectory":"./coverage","collectCoverageFrom":["**/*.(t|j)s"],"moduleFileExtensions":["js","json","ts"]},"types":"./index.d.ts","gitHead":"2e933e11aba0672058ace85323359991a2170946","private":false,"scripts":{"lint":"eslint \"{src,apps,libs,test}/**/*.ts\" --fix","test":"jest","build":"nest build nestjs-observability-utilities","start":"nest start","format":"prettier --write \"src/**/*.ts\" \"test/**/*.ts\" \"libs/**/*.ts\"","version":"npm run changelog && git add CHANGELOG.md","test:cov":"jest --coverage","test:e2e":"jest --config ./test/jest-e2e.json","changelog":"conventional-changelog -p angular -i CHANGELOG.md -s -r 0","postbuild":"cp package.json dist/libs/nestjs-observability-utilities/","start:dev":"nest start --watch","start:prod":"node dist/main","test:debug":"node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand","test:watch":"jest --watch","postversion":"npm run publish:git && npm run publish:npm","publish:git":"git push && git push --tags","publish:npm":"npm run build && npm publish ./dist/libs/nestjs-observability-utilities --access public","start:debug":"nest start --debug --watch"},"_npmUser":{"name":"ken-michalak","email":"Ken.Michalak@gmail.com"},"_npmVersion":"10.8.2","directories":{},"_nodeVersion":"18.20.5","dependencies":{"rxjs":"^7.8.1","@nestjs/core":"^10.0.0","@nestjs/common":"^10.0.0","reflect-metadata":"^0.2.0","@nestjs/platform-express":"^10.0.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.5.0","eslint":"^8.0.0","ts-jest":"^29.1.0","ts-node":"^10.9.1","prettier":"^3.0.0","supertest":"^7.0.0","ts-loader":"^9.4.3","typescript":"^5.1.3","@nestjs/cli":"^10.0.0","@types/jest":"^29.5.2","@types/node":"^20.3.1","@types/express":"^5.0.0","tsconfig-paths":"^4.2.0","@nestjs/testing":"^10.0.0","@types/supertest":"^6.0.0","@nestjs/schematics":"^10.0.0","@opentelemetry/api":"^1.9.0","source-map-support":"^0.5.21","@nestjs/microservices":"^10.4.15","eslint-config-prettier":"^9.0.0","eslint-plugin-prettier":"^5.0.0","@opentelemetry/sdk-node":"^0.57.0","@typescript-eslint/parser":"^8.0.0","conventional-changelog-cli":"^5.0.0","@typescript-eslint/eslint-plugin":"^8.0.0","@opentelemetry/auto-instrumentations-node":"^0.55.0"},"_npmOperationalInternal":{"tmp":"tmp/nestjs-observability-utilities_1.0.0-rc.1_1736971552299_0.29798597950110217","host":"s3://npm-registry-packages-npm-production"}},"1.0.0-rc.2":{"name":"@5stones/nestjs-observability-utilities","version":"1.0.0-rc.2","description":"A collection of utilities for logging, error handling, and traces, which fills in some gaps missing from the base NestJS project.","author":{"name":"Ken Michalak","email":"kmichalak@weare5stones.com"},"private":false,"license":"MIT","keywords":["nest","nestjs","nest.js","observability","otel","telemetry"],"scripts":{"build":"nest build nestjs-observability-utilities","postbuild":"cp package.json CHANGELOG.md LICENSE README.md dist/libs/nestjs-observability-utilities/","format":"prettier --write \"src/**/*.ts\" \"test/**/*.ts\" \"libs/**/*.ts\"","start":"nest start","start:dev":"nest start --watch","start:debug":"nest start --debug --watch","start:prod":"node dist/main","lint":"eslint \"{src,apps,libs,test}/**/*.ts\" --fix","test":"jest","test:watch":"jest --watch","test:cov":"jest --coverage","test:debug":"node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand","test:e2e":"jest --config ./test/jest-e2e.json","version":"npm run changelog && git add CHANGELOG.md","postversion":"npm run publish:git && npm run publish:npm","changelog":"conventional-changelog -p angular -i CHANGELOG.md -s -r 0","publish:git":"git push && git push --tags","publish:npm":"npm run build && npm publish ./dist/libs/nestjs-observability-utilities --access public"},"dependencies":{"@nestjs/common":"^10.0.0","@nestjs/core":"^10.0.0","@nestjs/platform-express":"^10.0.0","reflect-metadata":"^0.2.0","rxjs":"^7.8.1"},"devDependencies":{"@nestjs/cli":"^10.0.0","@nestjs/microservices":"^10.4.15","@nestjs/schematics":"^10.0.0","@nestjs/testing":"^10.0.0","@opentelemetry/api":"^1.9.0","@opentelemetry/auto-instrumentations-node":"^0.55.0","@opentelemetry/sdk-node":"^0.57.0","@types/express":"^5.0.0","@types/jest":"^29.5.2","@types/node":"^20.3.1","@types/supertest":"^6.0.0","@typescript-eslint/eslint-plugin":"^8.0.0","@typescript-eslint/parser":"^8.0.0","conventional-changelog-cli":"^5.0.0","eslint":"^8.0.0","eslint-config-prettier":"^9.0.0","eslint-plugin-prettier":"^5.0.0","jest":"^29.5.0","prettier":"^3.0.0","source-map-support":"^0.5.21","supertest":"^7.0.0","ts-jest":"^29.1.0","ts-loader":"^9.4.3","ts-node":"^10.9.1","tsconfig-paths":"^4.2.0","typescript":"^5.1.3"},"jest":{"moduleFileExtensions":["js","json","ts"],"rootDir":".","testRegex":".*\\.spec\\.ts$","transform":{"^.+\\.(t|j)s$":"ts-jest"},"collectCoverageFrom":["**/*.(t|j)s"],"coverageDirectory":"./coverage","testEnvironment":"node","roots":["<rootDir>/src/","<rootDir>/libs/"],"moduleNameMapper":{"^@5stones/nestjs-observability-utilities(|/.*)$":"<rootDir>/libs/nestjs-observability-utilities/src/$1"}},"_id":"@5stones/nestjs-observability-utilities@1.0.0-rc.2","gitHead":"847f1e935e0cb682c8569ae46b89c1b311a0247a","types":"./index.d.ts","_nodeVersion":"22.12.0","_npmVersion":"10.9.0","dist":{"integrity":"sha512-BfhpW+wXiFLb3F4t2g/6UMm65NCOo3VRTXcN89V7nM5bwAGHdGl8rzWL1cJogXBSOh1bJN+rRmWkmm9KLQHLtw==","shasum":"5a08d1015837a36bdfc37c6298cffec50e7c8bcd","tarball":"https://registry.npmjs.org/@5stones/nestjs-observability-utilities/-/nestjs-observability-utilities-1.0.0-rc.2.tgz","fileCount":98,"unpackedSize":262483,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGzInvlcet62tIifkSbhiD9rLZO4dHEdFaC1F77cJyVMAiA7+wTKXCcwWqO/CaFjH2lmJNH3jtbsD5oUCto0cXr+2g=="}]},"_npmUser":{"name":"ken-michalak","email":"Ken.Michalak@gmail.com"},"directories":{},"maintainers":[{"name":"jspizziri","email":"jake_20@hotmail.com"},{"name":"ken-michalak","email":"Ken.Michalak@gmail.com"},{"name":"abourge","email":"abourge@weare5stones.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/nestjs-observability-utilities_1.0.0-rc.2_1737139680729_0.9162202020133583"},"_hasShrinkwrap":false}},"time":{"created":"2025-01-13T13:10:23.870Z","modified":"2025-01-17T18:48:01.180Z","0.0.1":"2025-01-13T13:10:24.412Z","1.0.0-rc.0":"2025-01-13T13:14:31.712Z","1.0.0-rc.1":"2025-01-15T20:05:52.563Z","1.0.0-rc.2":"2025-01-17T18:48:00.942Z"},"author":{"name":"Ken Michalak","email":"kmichalak@weare5stones.com"},"license":"MIT","keywords":["nest","nestjs","nest.js","observability","otel","telemetry"],"maintainers":[{"name":"jspizziri","email":"jake_20@hotmail.com"},{"name":"ken-michalak","email":"Ken.Michalak@gmail.com"},{"name":"abourge","email":"abourge@weare5stones.com"}],"readme":"# NestJS Observability Utilities\n\nA collection of utilities for logging, error handling, and traces, which fills in some gaps missing from the base NestJS project.\n\n### Basic Setup\n\n```ts\n// main.ts\n...\nimport { HttpAdapterHost } from '@nestjs/core';\nimport {\n  OneLineLogger,\n  ExceptionFilter,\n} from '@5stones/nestjs-observability-utilities/logging';\n\nasync function bootstrap() {\n  const app = await NestFactory.create(AppModule, {\n    logger: new OneLineLogger(),\n  });\n\n  const { httpAdapter } = app.get(HttpAdapterHost);\n  app.useGlobalFilters(new ExceptionFilter(httpAdapter));\n\n  ...\n}\n```\n\n\n## Logging\n\nFor log collection tools like EFK/ELK, Loki, and Cloudwatch Logs, log entries and stack traces should be kept to oneline.\n\n### log Tag Function\n\nA string template function which uses JSON.stringify on each parameter,\nand has special handling for errors, which includes stack traces as an array.\nThis can be used with the NestJS logger, but is also useful for CLI output or Error messages.\n\n```ts\nimport { log } from '@5stones/nestjs-observability-utilities/logging';\n...\n  this.logger.warn(log`Something failed ${{ ip }}: ${err}`);\n  // \"Something failed {\"ip\":\"::ffff:10.89.5.17\"}: \"Error: some message\" [\"/srv/app/dist/main.js:499:19\"]\n\n  throw new Error(log`Something failed for user: ${user}`);\n```\n\n### OneLineLogger Service\n\nKeeps all logs to one line, while still using NestJS's log format.\nThe stack traces and extra parameters are space separated and stay in one line, similar to the `log` tag function.\nBy default, the `LOG_LEVEL` environment variable will be used to determine log levels.\nThere is also an `otelEvents` option to send logs as OpenTelemetry events along with the console logs.\n\n```ts\n// main.ts\nimport { OneLineLogger } from '@5stones/nestjs-observability-utilities/logging';\n\nasync function bootstrap() {\n  const app = await NestFactory.create(AppModule, {\n    logger: new OneLineLogger(undefined, {\n      // otelEvents: true,\n    }),\n  });\n```\n\n### envLogLevels Function\n\nIf you're not using the OneLineLogger, you can still set log levels with an environment variable.\nThe default is equivalent to setting `LOG_LEVEL=log`.\n\n```ts\n// main.ts\nimport { envLogLevels } from '@5stones/nestjs-observability-utilities/logging';\n\nasync function bootstrap() {\n  const app = await NestFactory.create(AppModule, {\n    logger: envLogLevels(),\n  });\n```\n\n### ExceptionFilter\n\nReplaces the default ExceptionHandler to log warnings and include context.\nAll Errors that bubble up through the controller will be logged.\nNestJS HttpExceptions will be logged at the warning level.\nOther unhandled errors will be at the error level.\n\n```ts\n// main.ts\nimport { HttpAdapterHost } from '@nestjs/core';\nimport { ExceptionFilter } from '@5stones/nestjs-observability-utilities/logging';\n\nasync function bootstrap() {\n  ...\n  const { httpAdapter } = app.get(HttpAdapterHost);\n  app.useGlobalFilters(new ExceptionFilter(httpAdapter));\n```\n\n\n## OpenTelemetry\n\nThe official library for creating spans does not include a try/catch/finally for error handling and ending spans,\nso this fills in those gaps.\n\n### withSpan Function\n\n```ts\nimport { trace } from '@opentelemetry/api';\nimport { withSpan } from '@5stones/nestjs-observability-utilities/otel';\n\nconst tracer = trace.getTracer(`your-project.module.YourService`);\n...\n  async someMethod() {\n    return await withSpan(tracer, 'span name', async (span) => {\n      ...\n      span.addEvent('some event');\n      ...\n      return ...\n    });\n```\n\n### @otelSpan Decorator\n\n```ts\nimport { trace } from '@opentelemetry/api';\nimport { otelSpan } from '@5stones/nestjs-observability-utilities/otel';\n\nconst tracer = trace.getTracer(`your-project.module.YourService`);\n...\n  @otelSpan(tracer, 'span name')\n  async someMethod() {\n    const span = trace.getActiveSpan();\n    ...\n    span?.addEvent('some event');\n    ...\n    return ...\n```\n\n\n## Error Handling in NestJS Microservices\n\nWith the built-in error handling, errors in message handlers are not logged,\nand then are sent back to the client as an \"Internal server error\",\ngiving no indication of what went wrong on either side.\n\n### RpcExceptionsFilter\n\nLogs errors with stack traces, and passes back HttpException info.\n\n```ts\nimport { RpcExceptionsFilter } from '@5stones/nestjs-observability-utilities/rpc';\n\n@Controller(...)\n@UseFilters(RpcExceptionsFilter)\nexport class SomeController {\n```\n\n### transformError Function\n\nThe other side of the RpcExceptionsFilter to get HttpException instances back on the client-side.\n`const typedError = transformError(genericError);`\n\n```ts\nimport { transformError } from '@5stones/nestjs-observability-utilities/rpc';\n...\n  /** Microservice send that's strongly-typed, promisified, in an otel span, with error handling. */\n  async send<\n    P extends keyof RpcMessages,\n    TResult extends RpcMessages[P]['result'],\n    TInput extends RpcMessages[P]['input'],\n  >(pattern: P, data: TInput, timeoutMs = 30000): Promise<TResult> {\n    return await withSpan(tracer, 'rpc ${pattern}', async (span) => {\n      try {\n        const result = await firstValueFrom(\n          this.client.send(pattern, data).pipe(timeout(timeoutMs)),\n          // prevents an error on void results\n          { defaultValue: undefined as TResult },\n        );\n\n        // add a 'log' to the span of the trace\n        span.addEvent('response', {\n          data: JSON.stringify(data),\n          result: JSON.stringify(result),\n        });\n\n        return result;\n      } catch (err) {\n        throw transformError(err, { logger: this.logger });\n      }\n    });\n  }\n```\n\n\n## Other Useful Utilities\n\n```ts\nimport { ... } from '@5stones/nestjs-observability-utilities';\n\n// uri: encodeURIComponent on each parameter\nconst path = uri`/something/${email}`;\n\n// notNull: use truthy value or throw NotFoundException\nconst value = notNull(valueOrNull);\n\n// notNullFrom: get truthy value from Observable or throw NotFoundException\nconst value = await notNullFrom(observable);\n\n// required: get truthy param or throw BadRequestException with the name\nconst email = required('email', data.email);\n\n// requiredService: get optional service or throw ServiceUnavailableException with the name\nconst myService = requiredService('MyService', this.myService);\n\n// inParallel: run an async function on each item in parallel, up to a limit of simultaneous executions\nconst resultArray = await inParallel(items, 10, async (item) => {...});\n\n// promiseAllEntries: like Promise.all for an object\nconst obj = await promiseAllEntries({ v1: promise1, v2: promise2 });\n\n// timeLimitedPromise: return another value if a promise takes too long\nconst valueOrUndefined = await timeLimitedPromise(somePromise, 500, undefined);\n\n// handleNotFound: returns null on a NotFoundException\nconst valueOrNull = await somePromise.catch(handleNotFound);\n\n// filterEntries: like array.filter for an object\nconst newObj = filterEntries(obj, ([key, value], index) => ...);\n\n// filterKeys: create a new object containing only specified properties\nconst newObj = filterKeys(obj, ['key1', 'key2']);\n\n// TimedInterceptor: log execution time with severity thresholds: debug < warn < error\n@UseInterceptors(new TimedInterceptor(2000, 60000))\n\n// TimeoutInterceptor: throw RequestTimeoutException after an interval\n@UseInterceptors(new TimeoutInterceptor(10000, 'Your error message'))\n```\n\n\n## Dev environment\n\n```bash\n$ npm ci\n```\n\n### run the project\n\n```bash\n// with docker\ndocker-compose up\n\n// without docker\n$ npm run start:dev\n```\n\n## Release\n\nThe standard release command for this project is:\n\n```sh\nnpm version [<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease | from-git]\n```\n\nThis command will:\n\n1. Generate/update the Changelog\n1. Bump the package version\n1. Tag & pushing the commit\n\ne.g.\n\n```sh\nnpm version 1.2.17\nnpm version patch // 1.2.17 -> 1.2.18\n```\n\n## License\n\n[MIT licensed](./LICENSE).\n","readmeFilename":"README.md","description":"A collection of utilities for logging, error handling, and traces, which fills in some gaps missing from the base NestJS project."}