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

ligelog

v1.1.0

Published

Lightweight, fast, hook-based JSON logger for Node.js

Downloads

102

Readme

ligelog

ligelog (from Spanish ligero — lightweight) is a lightweight, hook-based structured JSON logger for Node.js, written in TypeScript.

  • Zero runtime dependencies
  • Custom NDJSON serializer for predictable output and low overhead
  • Non-blocking async ring-buffer queue (queueMicrotask)
  • Hook pipeline: onBeforeWriteonSerializeonAfterWrite
  • ESM + CJS dual build

Installation

npm install ligelog

Quick Start

import { createLogger, FileTransport } from 'ligelog'

const logger = createLogger({
  level:   'info',
  context: { app: 'api-server', env: process.env.NODE_ENV },
  transports: [
    new FileTransport({ path: './logs/app.log' }),
  ],
})

logger.info('server started', { port: 3000 })
logger.error('unhandled error', { error: new Error('ETIMEOUT') })

process.on('beforeExit', () => logger.close())

Output (one JSON line per entry):

{"time":1700000000000,"iso":"2023-11-14T22:13:20Z","level":20,"lvl":"info","pid":1234,"msg":"server started","app":"api-server","port":3000}

Log Levels

| Name | Value | |---------|-------| | debug | 10 | | info | 20 | | warn | 30 | | error | 40 | | fatal | 50 |

API Reference

createLogger(opts?)

Factory function. Returns a Logger instance.

| Option | Type | Default | Description | |--------|------|---------|-------------| | level | LevelName | 'info' | Minimum level to emit | | context | Record<string, unknown> | {} | Static fields merged into every record | | transports | Transport[] | [StdoutTransport] | Output destinations | | hooks | Hooks | {} | Lifecycle hooks | | queueSize | number | 8192 | Ring buffer capacity (power of 2) | | onHookError | (phase, error) => void | — | Called when a hook throws | | onDrop | (dropped) => void | — | Called when an entry is dropped due to back-pressure |

logger.debug(msg, extra?) / .info() / .warn() / .error() / .fatal()

Emit a log entry at the given level. extra fields are shallow-merged with the logger context.

logger.child(ctx)

Create a scoped logger that inherits transports, hooks, and context, then merges ctx on top. All children share the parent's async queue.

logger.use(hooks)

Append hooks to the pipeline. Returns this for chaining.

logger.flush()

Returns a Promise that resolves when all queued entries have been written.

logger.close()

Flush, then close all transports. Call before process exit.

logger.getDropped()

Returns the number of entries dropped due to queue back-pressure.

logger.getWriteErrors()

Returns the number of transport write failures observed.

Hooks

onBeforeWrite

Called before serialization. Return false to drop the entry.

logger.use({
  onBeforeWrite: [ctx => {
    if (ctx.record.path === '/healthz') return false
    return ctx
  }],
})

onSerialize

Override the default NDJSON format. Set ctx.output to replace the serialized string.

onAfterWrite

Side-effects after the line has been queued (e.g. forwarding to external services).

Transports

StdoutTransport (default)

Writes to process.stdout. Used automatically when no transports are specified.

FileTransport

new FileTransport({ path: './logs/app.log' })

Appends to a file via fs.WriteStream. Parent directories are created automatically.

Custom Transport

Implement the Transport interface:

import type { Transport, LogRecord } from 'ligelog'

class MyTransport implements Transport {
  write(line: string, record: LogRecord): void {
    myService.send(line)
  }
  async flush(): Promise<void> { /* optional */ }
  async close(): Promise<void> { /* optional */ }
}

Serialization Behavior

  • bigint → strings (123n"123")
  • Date → ISO strings
  • Error{ name, message, stack } + enumerable custom properties
  • Circular references → "[Circular]"
  • Deep objects (>12 levels) → "[MaxDepth]"

Ecosystem

Extend ligelog with @ligelog/* packages:

| Package | Description | |---------|-------------| | @ligelog/caller | Auto-attach caller file, line, and function name | | @ligelog/catch | Wrap functions with automatic error logging | | @ligelog/pretty | Colorized human-readable output for development | | @ligelog/rotate | Size and time-based log file rotation | | @ligelog/sentry | Sentry integration via onAfterWrite hook |

License

MIT