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

@tony4ork/nestjs-logger

v0.0.2

Published

Company-standard logger for NestJS: pino, single-line JSON, OpenTelemetry field names

Readme

@tony4ork/nestjs-logger

The standard logger for all of the company's NestJS products. Built on pino, writes single-line JSON to stdout, with field names following the OpenTelemetry convention so SigNoz can automatically correlate logs with traces.

Developers don't need to learn anything new: you still write new Logger(OrderService.name) exactly like standard NestJS.

Log format

{
  "level": "info",
  "time": "2026-09-28T08:15:30.123Z",
  "service.name": "product-x",
  "service.version": "1.4.2",
  "deployment.environment": "production",
  "request_id": "a1b2c3d4-...",
  "user.id": "u_123",
  "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
  "span_id": "00f067aa0ba902b7",
  "trace_flags": "01",
  "context": "OrderService",
  "msg": "Order created",
  "orderId": "ord_789"
}

| Field | Source | |---|---| | service.name, service.version, deployment.environment | Fixed at startup, from options or the OTEL_* env vars | | request_id, user.id, job.id | Automatic, from @tony4ork/nestjs-context | | client.app_version, client.platform, client.bundle_id | Automatic, from the x-app-version, x-os, x-app-bundle-id headers (read by @tony4ork/nest-core) | | trace_id, span_id, trace_flags | Automatic, from OpenTelemetry once tracing is enabled; absent otherwise | | context | The class name passed to new Logger(...) | | err | Present only when logging an error: type, message, stack |

The HTTP log (one line per request) uses OpenTelemetry attribute names: http.request.method, url.path, http.route, http.response.status_code, duration_ms, client.address, user_agent.original.

Installation

pnpm add @tony4ork/nestjs-logger @tony4ork/nestjs-context
pnpm add -D pino-pretty     # for easy reading locally

1. Declare the configuration in src/integrations/logger.integration.ts:

import { ConfigService } from '@nestjs/config';
import { LoggerModule } from '@tony4ork/nestjs-logger';

export const LoggerIntegration = LoggerModule.forRootAsync({
  inject: [ConfigService],
  useFactory: (cfg: ConfigService) => ({
    serviceName: cfg.get('OTEL_SERVICE_NAME', 'product-x'),
    version: cfg.get('APP_VERSION'),
    env: cfg.get('NODE_ENV'),
    level: cfg.get('LOG_LEVEL', 'info'),
    pretty: cfg.get('NODE_ENV') === 'local',
  }),
});

2. Import it in AppModule, after ContextModule:

imports: [ContextModule.forRoot(), LoggerIntegration, ...]

3. Replace Nest's logger in main.ts:

const app = await NestFactory.create(AppModule, { bufferLogs: true });
app.useLogger(app.get(AppLogger));
await app.listen(3000);

bufferLogs: true holds onto startup logs until the logger is ready. app.listen() automatically flushes them. If you use NestFactory.createApplicationContext() (a worker with no HTTP), call app.flushLogs() after useLogger.

Usage

@Injectable()
export class OrderService {
  private readonly logger = new Logger(OrderService.name);

  async create(dto: CreateOrderDto) {
    const order = await this.repo.save(dto);
    this.logger.log('Order created', { orderId: order.id });     // style 1
    this.logger.log({ msg: 'Order created', orderId: order.id }); // style 2, equivalent
    return order;
  }

  async charge(orderId: string) {
    try {
      await this.payment.charge(orderId);
    } catch (err) {
      this.logger.error('Charge failed', err, { orderId });       // pass the Error to keep the stack
      throw err;
    }
  }
}

Log levels: error, warn, log (info), debug, verbose (trace), fatal.

Outside Nest DI (scripts, seeds, migrations):

import { createLogger } from '@tony4ork/nestjs-logger';
import { runWithContext } from '@tony4ork/nestjs-context';

const logger = createLogger({ serviceName: 'product-x-seed' }).forContext('Seed');
await runWithContext({}, async () => logger.log('Seeding...'));

Configuration

| Option | Default | Note | |---|---|---| | serviceName | OTEL_SERVICE_NAME | Required in at least one of the two places | | version | service.version in OTEL_RESOURCE_ATTRIBUTES, then APP_VERSION | | | env | deployment.environment in OTEL_RESOURCE_ATTRIBUTES, then NODE_ENV | | | level | LOG_LEVEL, then info | An invalid value falls back to info | | pretty | false | Requires pino-pretty; falls back to JSON with a warning if missing. Customized via messageFormat/customPrettifiers to print in NestJS's default ConsoleLogger format + colors ([Nest] pid - time LEVEL [Context] message +Xms); fields outside the core set (request_id, duration_ms, orderId...) and err are still printed below by pino-pretty as usual | | redactKeys | | Additional field names to redact | | redactPaths | | pino redact paths, for redacting deeply nested fields, e.g. payload.card.number | | base | | Fixed fields added to every log line | | http.enabled | true | Disables the per-request log | | http.ignorePaths | /health, /ready, /metrics, /favicon.ico | Strings (exact or prefix match) or a RegExp | | http.slowThresholdMs | 0 (disabled) | Requests slower than the threshold are raised to warn |

It's best for the logger and OpenTelemetry to read the same set of env vars, so the service name always matches on SigNoz:

OTEL_SERVICE_NAME=product-x
OTEL_RESOURCE_ATTRIBUTES=service.version=1.4.2,deployment.environment=production

Redacting sensitive data

The following fields are always replaced with [REDACTED] at the root level and one level of nesting: password, newPassword, oldPassword, token, accessToken, refreshToken, idToken (and their snake_case forms), secret, clientSecret, apiKey, authorization, cookie, otp, pin, cardNumber, cvv, cvc.

Limitation to be aware of: exact name match (case-sensitive) and only one level deep. { user: { password } } is redacted, but { a: { b: { password } } } is not — use redactPaths for that case. The safest approach is still to avoid logging a whole request/entity object.

The HTTP log does not record the query string, headers, or body.

HTTP request log levels

5xx logs at error, 4xx logs at warn, a client disconnecting mid-request logs at warn with http.aborted: true, everything else logs at info.

Compatibility

NestJS 10 and 11, Node 18.18 or later. The test suite runs against both Nest versions.

Important note: if a project ends up with two copies of @nestjs/common in node_modules (usually from a version mismatch between the app and an SDK), app.useLogger() only applies to one copy — logs from the other copy print in Nest's default format instead of JSON. Every @tony4ork/* SDK must declare @nestjs/* as a peerDependency. Check with pnpm why @nestjs/common.

Dependencies and imports

@tony4ork/nestjs-context is a peerDependency: a project declares both packages. Import context functions directly from it instead of through this logger:

import { RequestContext, contextForJob, runWithContext } from '@tony4ork/nestjs-context';

HTTP client error logging

Pino's default error serializer copies every property of the error. For axios errors, that pulls config (with the Authorization header and outgoing body) into the log. This logger strips config, request, response from axios errors, keeping only message, code, stack, and status.