{"_id":"@dudousxd/nestjs-telescope-observe","name":"@dudousxd/nestjs-telescope-observe","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@dudousxd/nestjs-telescope-observe","version":"0.1.0","description":"Forward @dudousxd/nestjs-telescope entries to NestJS Observe (observe.nestjs.com).","license":"MIT","repository":{"type":"git","url":"git+https://github.com/DavideCarvalho/nestjs-telescope.git","directory":"packages/observe"},"author":{"name":"Davi Carvalho","email":"davi@goflip.ai"},"type":"module","sideEffects":false,"main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"}},"peerDependencies":{"@dudousxd/nestjs-telescope":"^1.28.0"},"devDependencies":{"@types/node":"^20.0.0","typescript":"^5.4.0","vitest":"^3.0.0","@dudousxd/nestjs-telescope":"1.28.0"},"engines":{"node":">=20"},"keywords":["nestjs","telescope","observe","observability","exporter","apm"],"scripts":{"build":"tsc -p tsconfig.json","test":"vitest run --passWithNoTests","test:watch":"vitest","typecheck":"tsc -p tsconfig.json --noEmit && tsc -p tsconfig.spec.json --noEmit"},"_id":"@dudousxd/nestjs-telescope-observe@0.1.0","bugs":{"url":"https://github.com/DavideCarvalho/nestjs-telescope/issues"},"homepage":"https://github.com/DavideCarvalho/nestjs-telescope#readme","_integrity":"sha512-xBIhr/1VUA0ghqj4laLNtQL785zsBXqsZKNYD09bv/6RXQiY8VNAA1PoaRIwsuPOIgOTAIIm1Mns4kdtPOH8Bg==","_resolved":"/tmp/a1f2fa08589f6e726fd8277a1761bda3/dudousxd-nestjs-telescope-observe-0.1.0.tgz","_from":"file:dudousxd-nestjs-telescope-observe-0.1.0.tgz","_nodeVersion":"20.20.2","_npmVersion":"10.8.2","dist":{"integrity":"sha512-xBIhr/1VUA0ghqj4laLNtQL785zsBXqsZKNYD09bv/6RXQiY8VNAA1PoaRIwsuPOIgOTAIIm1Mns4kdtPOH8Bg==","shasum":"59be385d7985f381add015af3ce249c02b0a0ca6","tarball":"https://registry.npmjs.org/@dudousxd/nestjs-telescope-observe/-/nestjs-telescope-observe-0.1.0.tgz","fileCount":80,"unpackedSize":200913,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIA1N/lkoXeOCnbMBYYpynF9EBk1DtR0N6LyssVaaesK1AiEAtywBIr0yIj8ROHzFCu3KFppaTE7ltd6hNC56vXR2EQE="}]},"_npmUser":{"name":"dudousxd","email":"davi_carvalho96@hotmail.com"},"directories":{},"maintainers":[{"name":"dudousxd","email":"davi_carvalho96@hotmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/nestjs-telescope-observe_0.1.0_1787611701154_0.8153064524015587"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-24T22:48:21.004Z","0.1.0":"2026-08-24T22:48:21.312Z","modified":"2026-08-24T22:48:21.498Z"},"maintainers":[{"name":"dudousxd","email":"davi_carvalho96@hotmail.com"}],"description":"Forward @dudousxd/nestjs-telescope entries to NestJS Observe (observe.nestjs.com).","homepage":"https://github.com/DavideCarvalho/nestjs-telescope#readme","keywords":["nestjs","telescope","observe","observability","exporter","apm"],"repository":{"type":"git","url":"git+https://github.com/DavideCarvalho/nestjs-telescope.git","directory":"packages/observe"},"author":{"name":"Davi Carvalho","email":"davi@goflip.ai"},"bugs":{"url":"https://github.com/DavideCarvalho/nestjs-telescope/issues"},"license":"MIT","readme":"# @dudousxd/nestjs-telescope-observe\n\n> Forwards [@dudousxd/nestjs-telescope](https://github.com/DavideCarvalho/nestjs-telescope)\n> entries to [NestJS Observe](https://observe.nestjs.com), so the same capture\n> that feeds your in-app dashboard also feeds their hosted one.\n\n**Status:** early development (`0.0.0`). Requires an Observe project API key.\n\n## Why this exists\n\nObserve's own SDK instruments by proxying every provider in the Nest container.\nThat gives it a span for every method call, but it only sees what is a Nest\nprovider: a Prisma query arrives as `PrismaService.user` with no SQL, and `pg`,\n`ioredis`, `fetch` and `nodemailer` are invisible to it entirely.\n\nTelescope instruments each library through its public API instead, so it already\nholds the SQL with its bindings, the cache tier and hit/miss, the Redis command,\nthe outbound HTTP host and status. This package ships that detail into Observe's\nUI as spans on the request that caused them.\n\nIt is also a way to feed Observe without adopting the `instrument` bootstrap\nhook, which pins you to recent Nest 11 internals.\n\n## Install\n\n```sh\npnpm add @dudousxd/nestjs-telescope-observe\n```\n\nNo runtime dependencies — gzip comes from `node:zlib` and the POST from global\n`fetch`.\n\n## Usage\n\n```ts\nimport { TelescopeModule } from '@dudousxd/nestjs-telescope';\nimport { ObserveExporter } from '@dudousxd/nestjs-telescope-observe';\n\nconst observe = new ObserveExporter({\n  appKey: process.env.OBSERVE_APP_KEY!,\n  appSecret: process.env.OBSERVE_APP_SECRET!,\n  serviceId: 'orders-api',\n  serviceVersion: process.env.GIT_SHA,\n});\n\nTelescopeModule.forRoot({\n  storage,\n  watchers: [...],\n  extensions: [observe],\n});\n```\n\nCall `await observe.close()` on shutdown to flush what is still buffered.\n\n## What maps to what\n\n| Telescope | Observe |\n| --- | --- |\n| a batch rooted at a `request` entry | one snapshot, `op` = `GET /orders/:id` |\n| the batch's other entries | child spans, positioned by their offset into the request |\n| `job` and `schedule` entries | job snapshots, with queue wait and attempts |\n| `log` entries | forwarded logs, correlated to their trace |\n| `exception` / `client_exception` | the error on the snapshot or on the span |\n| process CPU, memory, GC, event loop | the `runtime` snapshot behind Observe's Profiler |\n| every record, counted before sampling | `telescope.entries` and `telescope.duration_ms` custom metrics |\n\n## Controlling the bill\n\nObserve meters per ingested record — a request, job, error or log each count as\none event, a span as a quarter — so the defaults here are deliberately explicit\nrather than \"send everything and hope\".\n\n```ts\nnew ObserveExporter({\n  // ...credentials,\n  include: { requests: true, spans: true, jobs: true, logs: false, runtime: true, metrics: true },\n  sampleRate: 0.2,\n  filter: (entry) => entry.type !== 'cache',\n});\n```\n\n- **`include`** turns whole sections off. `logs` needs a paid Observe plan. `runtime` and\n  `metrics` describe the process rather than the traffic, so sampling does not apply to them.\n- **`sampleRate`** is per batch, not per entry, so a sampled request keeps all of\n  its spans instead of a random half. A batch containing a failure is always\n  forwarded regardless of the rate.\n- **`filter`** gets the last word on any single entry.\n\nThis is separate from Telescope's own `sampling` on purpose: what is worth\nkeeping locally for an hour is not the same question as what is worth paying to\nretain for ninety days.\n\n## Notes\n\n- **The ingest API is private.** `POST /applications/telemetry` is undocumented,\n  unversioned, and validated against a strict allowlist on their side, so a\n  renamed field there becomes a `400` here. That failure is logged with its\n  status; it is not retried, because retrying cannot fix it.\n- **Wrong credentials trip a breaker.** Consecutive `401`/`403` responses disable\n  the exporter and re-log on a decaying schedule, so a bad key is visible in the\n  log instead of becoming a silent daily 401 storm.\n- **Retries exist.** Network errors, `408`, `429` and `5xx` are retried with\n  backoff — Observe's own SDK drops every batch it fails to deliver.\n- **Nothing blocks the host.** The Telescope flush hook only buffers; encoding\n  and the POST run on this exporter's own unref'd timer, and no error escapes\n  into capture.\n- **`runtime` is all-or-nothing.** Observe's collector answers `500` — not a validation `400` —\n  to a `runtime` object missing any of CPU, memory, GC or event loop, an empty one included. A\n  snapshot that could not measure all four is withheld and retried on the next flush rather than\n  sent partially.\n- **Counters are taken before sampling.** They come from Telescope's `observeRecord` hook, so\n  `telescope.entries` reports what the process actually did, not what survived `sampleRate`.\n- **User data stays out of span tags.** SQL bindings, cache values, request\n  payloads and mail bodies are never put on the wire — this ships to a\n  third-party SaaS.\n- **It cannot be pointed somewhere private.** `endpoint` is configurable, but no\n  open-source collector for this protocol exists, so there is no self-hosted\n  destination to aim it at. For an environment where data may not leave the\n  network, Telescope's own storage is the answer, not this package.\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-2d880d5bd3a79fead97b4b573bcea0e1"}