npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

resilient-otel

v0.4.0

Published

Framework-agnostic OpenTelemetry library: SDK init, extensible PII scrubber, taxonomy, metrics, log bridge, and NestJS adapter.

Readme

Resilient OTEL

A config-first OpenTelemetry library for Node.js services: SDK init, an extensible PII/secrets scrubber, taxonomy, metrics, log bridge, plus a NestJS adapter and a Next.js helper.

Works with Node.js 22+. Install one package, pass config, stop copying an observability folder into every project.

Features

  • One-call setup: init(config) wires traces + logs + metrics, returns a graceful-shutdown handle
  • Extensible scrubber: redact your own fields and secret patterns at runtime — before anything is exported
  • Backend-agnostic: emits OTLP only; the sink (Grafana, SigNoz, Elastic, …) is your Collector's concern
  • Config-first: the library reads no env vars of its own; every option is a typed field with a default
  • NestJS adapter and Next.js helper for the App Router proxy/BFF layer
  • Tree-shakeable, TypeScript first

Installation

# npm
npm install resilient-otel

# yarn
yarn add resilient-otel

# pnpm
pnpm add resilient-otel

That single install is everything for traces + logs + metrics over OTLP/HTTP and the scrubber — the OTel SDK and @opentelemetry/api come bundled. Extras (auto-instrumentation, gRPC, Winston, NestJS) are opt-in — each is one install + one wiring step, all in docs/EXTRAS.md. The most common one (auto-instrumentation) is also shown below.

Quick Start

import { init } from 'resilient-otel';
import { createScrubber } from 'resilient-otel/scrub';

const handle = await init({
  serviceName: 'my-service',
  endpoint: 'http://localhost:4318', // your OTel Collector (or set OTEL_EXPORTER_OTLP_ENDPOINT)
  scrubber: createScrubber({ extraDenylist: ['internal_account_id'] }),
});

// custom spans / logs / metrics work now:
import { emitLog } from 'resilient-otel';
emitLog('info', { msg: 'started' });

// flush + shut down telemetry on termination
process.on('SIGTERM', () => handle.shutdown());

That's the whole core: manual spans, logs, and metrics export to your Collector, with PII/secrets redacted. No other packages needed.

Auto-instrumentation (optional)

To get spans automatically for HTTP, databases, etc., (1) install the OTel instrumentation(s) you use, (2) pass them to init, and (3) launch with the preload (patching must happen before your modules load):

npm install @opentelemetry/instrumentation-http @opentelemetry/instrumentation-pg
// instrumentation.ts
import { init } from 'resilient-otel';
import { createScrubber } from 'resilient-otel/scrub';
import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
import { PgInstrumentation } from '@opentelemetry/instrumentation-pg';

await init({
  serviceName: 'my-service',
  scrubber: createScrubber(),
  instrumentations: [new HttpInstrumentation(), new PgInstrumentation()],
});
node --import ./dist/instrumentation.js ./dist/main.js

Installing an instrumentation package does not activate it — you must register it like above. Full list + queues + manual instrumentation: docs/INSTRUMENTATION.md.

Elastic-safe log attributes (default-on)

Elastic Cloud and Elasticsearch do not index nested objects in log attributes — they must be flat scalars or JSON strings. The library serializes complex attribute values to JSON strings by default, making every emitLog() call Elastic-safe without any changes in your application code.

What is serialized: the named set { body, headers, metadata, error, exception } plus any other non-array object attribute (catch-all). Scalars, arrays, already-stringified strings, signal: 'log', and the native trace_id/span_id are untouched.

Security ordering: serialization runs strictly after the scrubber, so structural PII redaction (e.g. body.password → '[REDACTED]') is always applied before the object is turned into a string. This ordering is enforced in the pipeline — it cannot be reversed.

Native trace correlation is preserved: the library does NOT add trace_id/span_id as custom attributes. Correlation uses the OTel-standard native LogRecord trace fields (trace.id in Elastic), which the SDK populates automatically from the active span context.

To opt out (non-Elastic backends that can consume nested objects natively):

// Option A — config field (permanent, per-instance)
const handle = await init({
  serviceName: 'my-service',
  scrubberConfig: { mode: 'moderate' },
  serializeComplexAttributes: false, // disable Elastic serialization
});
# Option B — env var (override per deployment)
OTEL_RESILIENT_SERIALIZE_ATTRS=false node dist/main.js

The opt-out does not affect PII redaction — the scrubber always runs regardless of this flag.

Contraindication — mode: 'disabled' + serialization: Using scrubberConfig: { mode: 'disabled' } together with serialization enabled means nested PII (e.g. body.password) is exported as a fully-indexed JSON string without redaction. The library emits a diag.warn at startup when this combination is detected. If you are using mode: 'disabled' intentionally (e.g. dev testing), either also set serializeComplexAttributes: false or accept that attribute contents are exported verbatim.

Environment variables

The library is config-first and reads no env vars of its own — every option is a field on init(). The only env vars involved are the standard OpenTelemetry OTEL_* ones, read natively by the underlying SDK. They act as fallbacks when the matching config field is omitted (config always wins):

| Variable | Maps to | Example | |----------|---------|---------| | OTEL_EXPORTER_OTLP_ENDPOINT | endpoint | http://otel-collector:4317 | | OTEL_EXPORTER_OTLP_PROTOCOL | protocol | grpc or http/protobuf | | OTEL_SERVICE_NAME | serviceName | my-service | | OTEL_RESOURCE_ATTRIBUTES | resource attributes | deployment.environment=production | | OTEL_TRACES_SAMPLER_ARG | samplingRatio | 1.0 | | OTEL_SDK_DISABLED | kill-switch (true → no-op) | true | | OTEL_RESILIENT_CONSOLE | consoleExport | true | | OTEL_RESILIENT_SERIALIZE_ATTRS | serializeComplexAttributes opt-out | false |

Full option contract: docs/CONFIG.md.

Documentation

  • Configuration — every init() / createScrubber() option, defaults, and the standard OTEL_* fallbacks
  • Optional dependencies — enabling auto-instrumentation, gRPC, Winston, and NestJS (what to install + how to wire each)
  • Usage guide — full init(), backends (Collector vs direct-to-vendor), preload ordering, taxonomy
  • Instrumentation — use cases, activating auto-instrumentation, manual spans/logs/metrics
  • Scrubber — redaction, the secret-regex bank, modes, and the boot guard
  • Governance — naming, trace↔log correlation, sampling, and redaction contract
  • NestJSObservabilityModule, interceptors, middlewares, lifecycle
  • Next.jsregister() for instrumentation.ts and the proxy/BFF Route Handler
  • API reference — exports per subpath and the TypeScript types
  • Migration — replacing a vendored observability/ folder
  • Vision — what the library is and why it exists
  • Roadmap — path to 1.0 and the planned genai adapter

License

MIT