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

@loomantix/logging

v0.3.2

Published

Structured logging primitives for NestJS backends: pino + OpenTelemetry trace context, PHI-safe redaction + detector, and a pluggable event sink.

Readme

@loomantix/logging

Structured logging primitives for NestJS backends. Wraps pino with:

  • NestJS LoggerService implementation — drop into NestFactory.create({ logger }) or inject via createLogger(context).
  • OpenTelemetry trace context — every log line gets traceId / spanId / traceFlags from the active OTel context, so logs correlate with traces in Grafana / Tempo.
  • PHI-safe redaction + detector — pino redact.paths covers ~30 common auth/PII/PHI fields; detectPHI / assertPHISafe / logMetadata catch leaks in test or pre-emit.
  • Pluggable event sink — register a callback via setEventSink to forward entries carrying an event field to a queue / audit store. PHI stripped before forwarding.
  • Pretty logs in dev, JSON in prod — controlled by NODE_ENV + optional LOG_FORMAT=json|pretty override.

Install

pnpm add @loomantix/logging

Published with npm provenance under Apache 2.0.

Peer deps (consumer app owns the install): @nestjs/common, @opentelemetry/api, pino, pino-pretty, reflect-metadata, rxjs.

Usage

NestJS bootstrap

import { NestFactory } from '@nestjs/core';
import { PinoLoggerService } from '@loomantix/logging';

const app = await NestFactory.create(AppModule, {
  logger: new PinoLoggerService('Bootstrap'),
});

Per-class logger

import { createLogger } from '@loomantix/logging';

export class MyService {
  private readonly logger = createLogger(MyService.name);

  someMethod() {
    this.logger.log('Processing request', { requestId: '123' });
    // → {"level":30,"time":"...","msg":"Processing request",
    //     "context":"MyService","requestId":"123",
    //     "traceId":"...","spanId":"..."}
  }
}

Service name

Resolution order (first non-empty wins):

  1. serviceName argument to createLogger(context, serviceName) / new PinoLoggerService(context, serviceName)
  2. SERVICE_NAME environment variable
  3. 'unknown' (loud default — set one of the above in deployment)

Event sink (for audit forwarding / external sinks)

import { setEventSink } from '@loomantix/logging';

setEventSink((entry) => {
  if (entry['event'] === 'encounter_created') {
    auditQueue.publish(entry);
  }
});

Only entries with an event field are forwarded. Before the callback fires, values at any of the known PHI/PII field names (see phi-detector.ts PHI_FIELD_NAMES) are stripped or reduced to metadata (lengths, counts, sentinels), and the accompanying msg string is dropped if it matches one of the PHI regex patterns. This is a best-effort defense — custom field names outside the list are passed through unmodified, so application code should still avoid logging sensitive values under novel keys.

Sink errors are caught — they never affect the logging pipeline.

PHI safety in tests

import { assertPHISafe } from '@loomantix/logging';

it('does not leak transcript text', () => {
  const captured = captureLogs(() => service.process(payload));
  expect(() => assertPHISafe(captured, 'process')).not.toThrow();
});

assertPHISafe throws if the message object contains any known PHI field (e.g. text, transcript, soapNote, patientId, S3 URLs, …) or matches one of the PHI regex patterns.

Environment variables

  • LOG_LEVEL — pino log level (default: debug in dev, info in prod)
  • LOG_FORMATjson or pretty; overrides auto-detection
  • NODE_ENVdevelopment / staging / production / test
  • SERVICE_NAME — service name for structured logs
  • APP_VERSION / GIT_COMMIT — included in every log's base fields