telemetry-wrap
v1.0.4
Published
Generic telemetry wrapper — API lifecycle capture, session context, pluggable dispatcher
Maintainers
Readme
What it does
Wraps @project-sunbird/telemetry-sdk v2 and exposes a unified, initialise-once API to capture the full lifecycle of every outbound API call — automatically or manually.
- Outbound HTTP request details — URL, method, payload
- Response details — status, body, latency
- Empty response detection — status 200 but empty body
- Session and question context —
sessionId,questionId - Custom context — Beckn (
transaction_id,action,domain) or any key-value map - Sensitive field redaction —
aadhaar,pan,otp,passwordand more auto-redacted
Table of Contents
- Installation
- Quick Start
- NestJS — Auto Lifecycle Capture
- Manual Logging
- Custom Dispatcher
- API Reference
- Event Fields
- Works With
- Project Structure
- Contributing
- License
Installation
npm install telemetry-wrapPeer dependencies (install only what your project uses):
# NestJS projects
npm install @nestjs/common rxjs
# All projects
npm install @project-sunbird/telemetry-sdkQuick Start
Call TelemetryWrap.init() once at app bootstrap — before any HTTP calls are made. Subsequent calls from any module are silently ignored.
import { TelemetryWrap } from 'telemetry-wrap';
TelemetryWrap.init({
pdata : { id: 'my-backend', ver: '1.0.0', pid: 'my-service' },
channel : process.env.TELEMETRY_CHANNEL,
endpoint : process.env.TELEMETRY_ENDPOINT,
batchSize: 20,
});NestJS — Auto Lifecycle Capture
Register HttpLifecycleInterceptor globally in AppModule. Every outbound HTTP call made via HttpService (Axios) is captured automatically — no per-service changes needed.
import { Module } from '@nestjs/common';
import { APP_INTERCEPTOR } from '@nestjs/core';
import { HttpLifecycleInterceptor } from 'telemetry-wrap';
@Module({
providers: [
{
provide : APP_INTERCEPTOR,
useFactory: () => new HttpLifecycleInterceptor(() => ({
sessionId : 'sess-xyz',
questionId: 'q-001',
context : {
// Beckn projects
beckn_transaction_id: 'txn-abc',
beckn_action : 'init',
beckn_domain : 'agri-schemes',
},
})),
},
],
})
export class AppModule {}Tip: Use
AsyncLocalStorageto inject the context dynamically per request rather than hardcoding values.
Manual Logging
For cases where HTTP calls bypass the interceptor — third-party SDKs, raw fetch, or non-NestJS projects:
import { TelemetryWrap } from 'telemetry-wrap';
TelemetryWrap.logApiCall({
requestTime : new Date().toISOString(),
url : 'https://api.example.com/data',
method : 'POST',
requestPayload : { id: '123' },
responseStatus : 200,
responseBody : {},
isEmptyResponse: true,
latencyMs : 342,
sessionId : 'sess-xyz',
questionId : 'q-001',
context : {
// Beckn projects
beckn_transaction_id: 'txn-abc',
beckn_action : 'init',
beckn_domain : 'agri-schemes',
// or any non-Beckn project
correlationId: 'req-123',
module : 'payments',
},
});Log a lifecycle event:
TelemetryWrap.logLifecycle({
action : 'order.confirmed',
domain : 'payments',
durationMs: 520,
context : { correlationId: 'req-123' },
});Custom Dispatcher
By default events are dispatched to the Sunbird v1 endpoint. Pass a custom dispatcher to init() to override:
import { TelemetryWrap } from 'telemetry-wrap';
const dispatcher = {
dispatch(events: object[]): void {
fetch(process.env.TELEMETRY_ENDPOINT, {
method : 'POST',
headers: { 'Content-Type': 'application/json' },
body : JSON.stringify({
id : 'api.telemetry',
ver : '1.0',
ts : new Date().toISOString(),
events: events,
}),
}).catch(err => console.error('[telemetry] dispatch failed:', err.message));
},
};
TelemetryWrap.init({
pdata : { id: 'my-backend', ver: '1.0.0', pid: 'my-service' },
channel : process.env.TELEMETRY_CHANNEL,
endpoint : process.env.TELEMETRY_ENDPOINT,
batchSize : 20,
dispatcher,
});API Reference
| Method | Description |
|---|---|
| TelemetryWrap.init(config) | Initialise once at app bootstrap — subsequent calls are no-ops |
| TelemetryWrap.logApiCall(event) | Log full API lifecycle event — auto-triggers error / empty response events |
| TelemetryWrap.logError(event) | Log API error event explicitly |
| TelemetryWrap.logEmptyResponse(event) | Log empty 200 response explicitly |
| TelemetryWrap.logLifecycle(event) | Log any custom lifecycle event |
Config options
| Field | Type | Required | Description |
|---|---|---|---|
| pdata | PData | Yes | Producer data — id, version, pid |
| channel | string | Yes | Telemetry channel identifier |
| endpoint | string | Yes | Sunbird v1 observability endpoint URL |
| batchSize | number | No | Events per batch — default 20 |
| dispatcher | TelemetryDispatcher | No | Custom dispatcher override |
Event Fields
interface ApiLifecycleEvent {
// -- Request details --
requestTime : string; // ISO timestamp at point of outbound dispatch
url : string; // full external URL
method : string; // GET | POST | PUT | PATCH | DELETE
requestPayload : object; // sanitised outbound body / query params
// -- Session & question context --
sessionId : string; // session identifier
questionId : string; // request / trace ID
// -- Response details --
responseStatus : number; // HTTP status code returned by external API
responseBody : object; // sanitised response body (capped at 2 KB)
isEmptyResponse : boolean; // true if status 200 but body is empty / {} / []
latencyMs : number; // Date.now() delta — full round-trip
error ?: string; // error message if call threw or status >= 400
// -- Custom context — any project, any key-value map --
context : Record<string, string>;
}Sensitive fields auto-redacted
The following keys are automatically replaced with ***REDACTED*** before any event is dispatched:
aadhaar aadhar pan password token otp secret mobile phone account ssn dob credit_card cvv pin
Works With
| Runtime | Support |
|---|---|
| NestJS | Auto-capture via HttpLifecycleInterceptor |
| Express / Fastify / Koa | Manual logging via TelemetryWrap.logApiCall() |
| Any Node.js TypeScript project | Full support |
| Beckn protocol backends | Native context support via context field |
| Browser / React / Vue | Not supported — Node.js only |
Project Structure
telemetry-wrap/
├── src/
│ ├── index.ts # public API surface
│ ├── TelemetryWrap.ts # singleton — wraps Sunbird SDK
│ ├── interceptors/
│ │ └── HttpLifecycle.interceptor.ts # NestJS outbound HTTP hook
│ ├── types.ts # config & event type definitions
│ └── utils.ts # payload sanitiser, ID helpers
└── package.jsonContributing
Pull requests are welcome. For major changes please open an issue first to discuss what you would like to change.
git clone https://github.com/akshat-rbg/telemetry-wrap
cd telemetry-wrap
npm install
npm run devBuild:
npm run buildPublish:
npm run prepublishOnly
npm publish --access publicLicense
MIT — Kenpath Technology © 2026
