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

@warlock.js/logger

v4.7.0

Published

A powerful logging system for messages and errors in nodejs.

Readme

@warlock.js/logger

Structured, multi-channel logging for Node.js — six severity levels (debug / info / warn / error / success / fatal), a clean three-argument API, and full TypeScript support. Non-blocking by default; synchronous or async flush on demand.

Install

npm install @warlock.js/logger
# or
yarn add @warlock.js/logger

30-second tour

import { log, ConsoleLog, FileLog } from "@warlock.js/logger";

log.setChannels([
  new ConsoleLog(),
  new FileLog({ chunk: "daily" }),
]);

await log.info("users", "register", "New user created");
await log.error("payments", "charge", new Error("Card declined"));

The logger starts with no channels — nothing is printed or written until you register at least one.

The module · action · message pattern

Every call carries three pieces of context. Modules and actions become searchable keys in file and JSON channels:

await log.info("auth", "login", "User signed in");
await log.warn("api", "rateLimitApproaching", "80% of quota used");
await log.success("payments", "captured", "Payment of $49.99 captured");

Pass an object instead of positional args when you need context metadata:

await log.error({
  module: "orders",
  action: "checkout",
  message: "Card declined",
  context: { orderId: "ord_9f2a", amount: 4999 },
});

Levels

debug · info · warn · error · success · fatal — each has a shorthand method on the log singleton (and on every Logger instance). fatal is strictly above error for unrecoverable failures where the app is going down (failed bootstrap, uncaughtException); it does not auto-flush or exit on its own.

Built-in channels

| Channel | Name | Purpose | |---|---|---| | ConsoleLog | "console" | Colorized terminal output | | FileLog | "file" | Plain-text files, optional chunking + rotation + grouping | | JSONFileLog | "fileJson" | Structured JSON files — ideal for aggregators | | SentryLog | "sentry" | Forwards to Sentry (events + breadcrumbs); needs the optional @sentry/node peer |

All channels share the BasicLogConfigurations options (levels, filter, dateFormat); FileLog / JSONFileLog add storage, chunking, rotation, and grouping options, and SentryLog adds client / options / eventLevels.

log and Logger

The package exports one default singleton and one class:

  • log — a pre-instantiated Logger. Day-to-day logging and configuration both go through it: log.info(...), log.configure(...), log.flush() / log.flushSync(), log.addChannel(...).
  • Logger — the class. Use it when you need an isolated logger (libraries, sandboxes, parallel test suites).

log is a Logger instance, not a function — every level shortcut and configuration method is reachable on it. The bare-callable log(data) form was removed; use log.log(data) for the data-object form, or log.info(...) / log.error(...) / etc. for the positional form.

Graceful shutdown

FileLog and JSONFileLog buffer entries. Tell the logger to drain them on exit:

log.configure({
  channels: [new ConsoleLog(), new FileLog({ chunk: "daily" })],
  autoFlushOn: ["SIGINT", "SIGTERM", "beforeExit"],
});

Signal events flush then re-raise (so Node exits with its normal signal semantics); beforeExit flushes in place. For full control, call log.flushSync() (sync) — or await log.flush() (async, for network/async channels) — inside your own handler instead.

Capturing unhandled errors

import { captureAnyUnhandledRejection } from "@warlock.js/logger";

captureAnyUnhandledRejection();

Registers process-level handlers for unhandledRejection (→ log.error("app", ...), process kept alive) and uncaughtException (→ log.fatal("app", ...), then process.exit(1) so a fatal crash is never silently swallowed into exit 0). Pass { exitOnUncaughtException: false } to log without exiting. Call once at startup, after channels are registered.

Custom channels

Extend LogChannel and implement log(data):

import { LogChannel, type LoggingData } from "@warlock.js/logger";

export class SlackLog extends LogChannel<{ webhookUrl: string }> {
  public name = "slack";

  public async log(data: LoggingData) {
    if (!this.shouldBeLogged(data)) return;
    await fetch(this.config("webhookUrl"), {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        text: `[${data.type}] [${data.module}][${data.action}]: ${data.message}`,
      }),
    });
  }
}

Set terminal = true on the class if your channel writes to a TTY — otherwise ANSI codes are auto-stripped from string messages.

Full documentation

The complete guide lives in the project docs:

  • Getting Started
  • Configuration
  • Channels (ConsoleLog, FileLog, JSONFileLog, SentryLog)
  • Lifecycle & Flushing
  • Capturing Unhandled Errors
  • Custom Channels
  • Recipes
  • API Reference
  • Types

Tests

This package uses Vitest. From the repo root:

npx vitest run --root @warlock.js/logger

License

MIT