Custom Metrics
Record custom counters, gauges, and histograms with the monitor object — every call is automatically tagged with the active trace, user, and tenant ID.
Custom Metrics
Alongside the metrics the SDK captures automatically (HTTP latency, DB query time, AI token usage), you can record your own business metrics through the monitor object — the same one returned by createSdk().
const { monitor } = require('./trasys');
monitor.counter('orders.created', 1, { plan: 'pro' });
monitor.gauge('queue.depth', pendingJobs.length, { queue: 'emails' });
monitor.histogram('file.upload.bytes', file.size, { type: file.mimetype });All three share the same shape: (name, value?, tags?, options?).
monitor.counter(name, value?, tags?)
Increments a running total. value defaults to 1, so monitor.counter('payments.processed') is a valid one-argument call for simple "count this happened" events.
monitor.counter('payments.processed', 1, { currency: 'INR' });
monitor.counter('webhook.delivery.failed'); // value defaults to 1monitor.gauge(name, value, tags?)
Records a point-in-time snapshot — the current value of something, not a running total. Use this for things like queue depth or active connection count, where the latest value is what matters, not the sum of every value you've ever recorded.
monitor.gauge('queue.depth', currentDepth);
monitor.gauge('active_connections', pool.totalCount);Internally this uses an OTel ObservableGauge — calling monitor.gauge() just stores the latest value; the SDK reports it on the next metrics export cycle (transport.metricExportIntervalMs, default every 15 seconds — see Transport). If you call it multiple times between export cycles, only the most recent value per unique tag combination is reported.
monitor.histogram(name, value, tags?)
Records a single observation into a distribution — use this for anything you want percentiles on, like request size or processing duration.
monitor.histogram('api.latency.ms', responseTime);
monitor.histogram('file.upload.bytes', file.size, { type: file.mimetype });Histograms use fixed bucket boundaries tuned for millisecond-scale durations: 0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 10000. If your values are on a very different scale (bytes, dollars), the percentiles are still computed correctly — the buckets just won't be as finely tuned.
Automatic trace correlation
Every monitor.* call automatically attaches trace_id, user_id, and tenant_id tags (when available from the active request context) on top of whatever tags you pass — no extra code needed to correlate a custom metric back to the request that produced it.
monitor.counter('orders.created', 1, { plan: 'pro' });
// recorded tags: { plan: 'pro', trace_id: '...', user_id: '...', tenant_id: '...' }Instrument reuse
Calling monitor.counter('orders.created') repeatedly reuses the same underlying OTel instrument rather than creating a new one each time — OTel logs a warning if you create two instruments with the same name, so this is handled for you automatically.
Next steps
Prompt & Response Data Security
Control what AI prompt and response content the SDK captures, mask sensitive fields before it's recorded, and use the SDK's AES-256-GCM encryption utility for your own captured payloads.
Sampling
Control which requests get recorded to manage data volume and cost — set per-route rates, and AI calls and debug users are always kept regardless of rate.

