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

@asaidimu/utils-logger

v1.0.4

Published

A collection of logger utilities.

Readme

@asaidimu/utils-logger

A robust, structured logging library for TypeScript/JavaScript applications. It provides a context-aware logger with support for multiple sinks (console, event bus, custom destinations), hierarchical child loggers, and advanced error formatting—all designed to simplify observability in complex systems.


Features

  • Structured Logging – Logs are consistent objects with level, event, timestamp, data, and context fields.
  • Log Levelstrace, debug, info, warn, error with priority filtering.
  • Context Propagation – Attach contextual metadata to a logger; child loggers inherit and merge context.
  • Pluggable Sinks – Send logs to one or multiple destinations (console, event bus, files, etc.).
  • Built‑in SinksConsoleSink (stdout/stderr) and EventBusSink (integrates with an event bus).
  • Fuzz Logger – Generate random logs for testing and performance benchmarking.
  • Error‑Aware – Automatically extracts structured fields from SystemError and plain Error objects.
  • Type‑Safe – Written in TypeScript with full type definitions included.

Installation

npm install @asaidimu/utils-logger

Peer dependency: ws (^8.21.0) is required if you use the UnsecureWebSocketServerSink with WebSocket‑based buses. Install it separately if needed. Peer dependency: @asaidimu/utils-events (^1.2.0) is required if you use the EventBusSink Install it separately if needed.


Quick Start

import { Logger, ConsoleSink } from "@asaidimu/utils-logger";

// Create a logger that writes to the console
const logger = new Logger([new ConsoleSink()], {
  app: "my-service",
  environment: "development",
});

// Basic logging
logger.info("user_logged_in", { userId: "123", ip: "192.168.1.1" });

// Error logging
try {
  // ...
} catch (err) {
  logger.error("database_query_failed", err);
}

// Child logger with additional context
const childLogger = logger.child({ requestId: "abc-123" });
childLogger.debug("processing_payment", { amount: 99.99 });

Core Concepts

Logger

The main entry point implementing the SystemLogger interface. It holds a set of sinks, a base context, and methods for each log level.

Sinks

A sink is any object implementing the LogSink interface:

interface LogSink {
  write(record: SystemLog): void | Promise<void>;
}

When a log is emitted, it is passed to all registered sinks concurrently. If a sink returns a Promise, it is awaited (with Promise.all) but errors are swallowed to prevent logging failures from crashing the application.

Context

Context is an arbitrary object attached to every log record. It is useful for adding static metadata like service name, environment, or trace IDs. Child loggers merge new context onto the parent’s context.


Built‑in Sinks

ConsoleSink

Writes formatted log lines to stdout or stderr. It automatically detects the runtime:

  • In Node.js, uses process.stdout.write / process.stderr.write.
  • In browsers, falls back to console.log, console.error, etc.

Options

| Option | Type | Description | | --------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------- | | pipeMap | Partial<Record<LogLevel, ConsolePipe>> | Override the output stream for specific levels (default: warn/errorstderr, others → stdout). | | format | (record: SystemLog) => string | Custom string formatter. Default produces [ISO timestamp] LEVEL event ctx=... data=.... |

Example

const consoleSink = new ConsoleSink({
  pipeMap: { error: "stdout" }, // send errors to stdout
  format: (r) => `[${r.level}] ${r.event}`,
});

EventBusSink

Routes logs to an event bus, either statically or dynamically. This is useful for cross‑component communication, WebSocket broadcasts, or centralised log aggregation.

Requirements

  • An event bus that implements the EventBus<TEventMap> interface (from @asaidimu/utils-events). The event map defines the allowed event names and their payload shapes.

Static Routing – All logs go to a fixed event name.

import { EventBusSink } from '@asaidimu/utils-logger';

const eventBus = /* your event bus instance */;

const sink = new EventBusSink(eventBus, {
  event: 'system:log',          // static event name
  map: (record) => ({           // optional mapping
    level: record.level,
    message: record.event,
    timestamp: record.timestamp,
    extra: record.data
  })
});

Dynamic Routing – Choose the event name per log record.

const sink = new EventBusSink(eventBus, {
  resolve: (record) => {
    // Route based on log level or event name
    return record.level === "error" ? "error:log" : "info:log";
  },
  map: (record, eventName) => ({
    // eventName is the resolved name
    severity: record.level,
    details: record.data,
  }),
});

The sink guards against exceptions so that failures in event emission do not break the logging flow.


Fuzz

A helper class that generates random log entries at random intervals. Useful for load testing, demo environments, or stress‑testing your logging pipeline.

import { Fuzz } from "@asaidimu/utils-logger";
import { Logger, ConsoleSink } from "@asaidimu/utils-logger";

const realLogger = new Logger([new ConsoleSink()]);
const fuzz = new Fuzz(realLogger, {
  minIntervalMs: 200,
  maxIntervalMs: 1500,
  allowedLevels: ["info", "warn", "error"],
  eventRegistry: {
    info: ["user_login", "order_placed", "payment_success"],
    error: ["db_timeout", "stripe_failure"],
  },
});

// Start emitting random logs every 200–1500ms
fuzz.start();

// Later, stop
fuzz.stop();

Options

| Option | Type | Default | Description | | --------------- | ------------------------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------- | | minIntervalMs | number | 100 | Minimum delay between logs (ms). | | maxIntervalMs | number | 1000 | Maximum delay between logs (ms). | | allowedLevels | LogLevel[] | ['trace','debug','info','warn','error'] | Which levels may be emitted. | | eventRegistry | Partial<Record<LogLevel, string[]>> | {} | Custom event name pools per level. If empty, random hacker‑style names are generated. |


API Reference

SystemLogger Interface

| Method | Description | | -------------------------------------------- | --------------------------------------------------------------------------- | | trace(event: string, data?: object): void | Log at trace level. | | debug(event: string, data?: object): void | Log at debug level. | | info(event: string, data?: object): void | Log at info level. | | log(event: string, data?: object): void | Alias for info. | | warn(event: string, data?: object): void | Log at warn level. | | error(event: string, data?: unknown): void | Log at error level. data can be an Error object (see Error handling). | | write(record: SystemLog): void | Write a pre‑constructed SystemLog record directly. | | child(context: object): SystemLogger | Create a child logger with additional context (merged over parent). |

Logger Class

The concrete implementation. Constructor:

new Logger(sinks: LogSink[], context?: object)

All methods from SystemLogger are available.

LogSink Interface

interface LogSink {
  write(record: SystemLog): void | Promise<void>;
}

Implement this to create custom sinks (e.g., file, HTTP, Sentry, etc.).

SystemLog Structure

| Field | Type | Description | | ----------- | ---------- | ---------------------------------------------------- | | level | LogLevel | Severity level. | | event | string | Distinct event name (e.g., "user_login"). | | data | object | (Optional) Payload specific to the log. | | context | object | (Optional) Static metadata from the logger instance. | | timestamp | number | Unix timestamp in milliseconds (auto‑generated). |

LogLevel

type LogLevel = "trace" | "debug" | "info" | "warn" | "error";

Priority order (low to high): trace (10), debug (20), info (30), warn (40), error (50). The constant LogLevelPriority provides these numeric values.


Error Handling

When you pass an Error object (or any subclass) to logger.error(), the logger automatically extracts structured information:

  • For plain Error: it captures name, message, and stack.
  • For SystemError (from @asaidimu/utils-error): it additionally extracts code, category, severity, path, operation, issues, httpStatus, action, and cause.

All extracted fields are placed under the error key in the log’s data property, ensuring consistent error reporting across your system.


License

MIT © Saidimu


Contributing & Issues

Found a bug or want to suggest an improvement? Please open an issue on the GitHub repository.

For more details, visit the homepage.