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

@batkit/logger

v1.0.1

Published

Logger facade with default console implementation for Node.js and browser

Readme

@batkit/logger

Logger facade with default console implementation for Node.js and browser environments.

Installation

npm install @batkit/logger

Overview

A lightweight logger facade that provides a consistent logging interface for both Node.js and browser environments. Includes a production-ready console logger implementation with structured logging support.

Developing in this monorepo

This package builds two outputs (index / console and the Node-only @batkit/logger/async-local) using tsup (see tsup.config.ts and tsup.async-local.config.ts). The dev script runs concurrently so both tsup --watch processes start together. From the repo root, vp run dev starts the Express reference app and workspace watchers (including this package). From packages/logger, run vp run dev for logger-only watch mode.

Features

  • ✅ Simple, intuitive API
  • ✅ Works in Node.js and browsers (the main entry is isomorphic; @batkit/logger/async-local is Node-only)
  • ✅ Structured logging support
  • Async-local log context (Node): @batkit/logger/async-local
  • ✅ Log level filtering
  • ✅ Pretty and JSON output modes
  • ✅ Zero runtime dependencies on the core facade
  • ✅ TypeScript-first
  • ✅ ESM and CommonJS support

Usage

Basic Logging

import { LoggerFacade } from "@batkit/logger";

const logger = LoggerFacade.getLogger("my-app");

logger.debug("Debug message");
logger.info("Application started");
logger.warn("Low disk space");
logger.error(new Error("Failed to connect to database"));

Structured Logging

import { LoggerFacade } from "@batkit/logger";

const logger = LoggerFacade.getLogger("my-app");

// Add structured data to logs
logger.info("User logged in", {
  userId: "123",
  timestamp: Date.now(),
  ipAddress: "192.168.1.1",
});

// Error logging (error first, then message, then context)
try {
  // ... some code
} catch (error) {
  if (error instanceof Error) {
    logger.error(error, "Operation failed", { operation: "createUser" });
  }
}

Async-local log context (Node only)

Background: Understanding AsyncLocalStorage

For request- or job-scoped fields (requestId, transactionId, etc.), use the @batkit/logger/async-local entry (built on AsyncLocalStorage). Wrap your LoggerProvider with ContextualLoggerProvider once at bootstrap, then everywhere else call mergeContext/runWithContext on the Logger instance you already have from LoggerFacade.getLogger(...)—no further @batkit/logger/async-local import needed.

// bootstrap.ts — one-time setup
import { LoggerFacade } from "@batkit/logger";
import { ContextualLoggerProvider } from "@batkit/logger/async-local";
import { PinoLoggerProvider } from "@batkit/logger-pino";

LoggerFacade.setProvider(new ContextualLoggerProvider(new PinoLoggerProvider({ level: "info" })));
// anywhere else — only ever imports LoggerFacade
import { LoggerFacade } from "@batkit/logger";
import { randomUUID } from "node:crypto";

const log = LoggerFacade.getLogger("payments");

log.runWithContext({ requestId: randomUUID() }, () => {
  log.mergeContext({ transactionId: "txn-123" });
  log.info("Captured"); // structured context includes both ids
});

Need the raw context bag directly (rare—e.g. forwarding correlation ids to a non-logging call)? getLogContext from @batkit/logger/async-local reads it without a Logger instance.

In Express, mount logContextMiddleware early instead of calling runWithContext yourself at the top of every route.

JSON / structured output

For JSON log lines in production, use @batkit/logger-pino (or another LoggerProvider) and attach it with LoggerFacade.setProvider.

API Reference

See exported types in src/types.ts. Highlights:

  • Loggerdebug / info / warn / error use the LogMethod overloads (context-only, message + context, error + context, error + message + context). Also mergeContext(partial) and runWithContext(initial, fn) (real when wrapped with ContextualLoggerProvider; the default console logger's mergeContext throws with setup instructions).
  • LoggerProvidergetLogger(name), isLogLevelEnabled.
  • LoggerFacadegetLogger, setProvider, getProvider, configure.
  • Node-only: @batkit/logger/async-localContextualLoggerProvider (bootstrap) plus getLogContext for reading the raw context bag without a Logger instance.

Using with Other Implementations

This package provides the logger facade. You can use alternative implementations:

import type { Logger } from "@batkit/logger";
import { PinoLoggerProvider } from "@batkit/logger-pino";

// Example: use LoggerFacade.setProvider(new PinoLoggerProvider({ level: 'info' }))
// or wrap with ContextualLoggerProvider when using async-local context.
const provider = new PinoLoggerProvider({ level: "info" });
const logger: Logger = provider.getLogger("app");

logger.info("Using Pino implementation");

Integration with Express

Use logContextMiddleware together with ContextualLoggerProvider so each request runs inside runWithContext and structured logs include correlation fields. See apps/express-api for a full example (POST /api/demo/fulfillment).

Best Practices

  1. Use appropriate log levels:

    • debug: Detailed diagnostic information
    • info: General informational messages
    • warn: Warning messages for potentially harmful situations
    • error: Error messages for failures
  2. Add structured context instead of string interpolation:

    // ✅ Good
    logger.info("User created", { userId, email });
    
    // ❌ Avoid
    logger.info(`User ${userId} created with email ${email}`);
  3. Use @batkit/logger/async-local on Node when many layers need the same correlation ids without threading them through every function

  4. Include errors first (per LogMethod overloads), then optional message, then context:

    logger.error(error, "Failed to save user", { userId });

TypeScript

Full TypeScript support with exported types:

import type { Logger, LoggerProvider } from "@batkit/logger";

function setupLogger(provider: LoggerProvider, name: string): Logger {
  return provider.getLogger(name);
}

Tree-Shaking

For optimal tree-shaking, import from the specific entry point:

// Import only the console entry (re-exports console helpers)
import { ConsoleLoggerProvider } from "@batkit/logger/console";

Node-only: @batkit/logger/async-local

Links

License

MIT © Ken Courville