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

@vanilla-bean/log

v7.0.0

Published

A console log wrapper with tags, colors, and verbosity

Readme

Log

License: MIT

Zero-dependency console logging with tags, verbosity control, and unlimited custom log levels.

Why Log

Log follows Unix philosophy: do logging well, let the system handle output routing. Writes to stdout as plain text; containers, process supervisors, and log tails handle the rest.

  • Zero runtime dependencies
  • Custom methods (log.success(), log.database()) alongside native console methods, no configuration needed
  • Tagged loggers, verbosity filtering, color, and global registry in ~1KB, easy to read, easy to fork

Installation

npm install @vanilla-bean/log
# or
bun add @vanilla-bean/log

Quick Start

Create tagged loggers that share instances and support unlimited custom methods:

import Log from '@vanilla-bean/log';

// Create tagged logger instances
const api = new Log({ tag: 'api', verbosity: 2, color: true });
const db = new Log({ tag: 'database', verbosity: 1 });

// Use all console methods
api.info('Server started');
api.warn('High memory usage');
api.error('Connection failed');

// Custom methods work automatically
api.success('Request completed');
db.query('SELECT * FROM users');

// Verbosity-gated calls: log(n)('msg') shows when logger verbosity > n
api(1)('Debug info'); // shows when verbosity > 1 (visible here, verbosity is 2)
api(3)('Trace data'); // shows when verbosity > 3 (hidden here, verbosity is 2)

// log('msg') is shorthand for log(0)('msg') — shows when verbosity > 0
api('Request received');

Core Features

Tagged Logger Registry

Identical tags return the same logger instance, preventing duplicates and enabling cross-module coordination:

// Module A
const log = new Log({ tag: 'app', verbosity: 1 });

// Module B - gets same logger instance
const log = new Log({ tag: 'app' }); // Inherits verbosity: 1

// Access any logger globally
import { loggers } from '@vanilla-bean/log';
loggers.app.options.verbosity = 3; // Updates everywhere

Note: Calling new Log() without a tag uses the shared __default singleton. Two unrelated modules both doing new Log() will share the same logger instance and options. Always pass a tag when you want an independent logger.

Verbosity Control

The primary form is log(n)('msg'): logs when the logger's verbosity is greater than n, silent otherwise. Calling log('msg') directly is shorthand for log(0)('msg'): shows when verbosity is greater than 0.

const log = new Log({ verbosity: 3 });

log(1)('High priority');     // shows when verbosity > 1
log(2)('Debug info');        // shows when verbosity > 2
log(5)('Trace data');        // shows when verbosity > 5 (hidden here)

log('Shorthand');            // shorthand for log(0)('Shorthand') — shows when verbosity > 0

// Works the same on any method
log.warn(1)('Important warning');
log.error(0)('Critical error');

Gotcha: A lone number is always treated as a verbosity level, never as a message. log(42) returns a curried function; it does not log the number 42. To log a bare number, pass a second argument: log(42, '').

Unlimited Log Methods

Create unlimited custom log methods alongside native console methods:

const log = new Log({ tag: 'app' });

// Native console methods
log.info('Information');
log.warn('Warning');
log.error('Error');
log.debug('Debug data');

// Custom methods work automatically
log.success('Operation completed');
log.database('Query executed');
log.network('Request sent');
log.cache('Cache hit');
log.security('Auth failed');

Color Output

Add color support for enhanced terminal readability:

const log = new Log({ color: true });

log.info('Blue text'); // Built-in blue
log.warn('Yellow text'); // Built-in yellow
log.error('Red text'); // Built-in red

// Custom colors per tag or method
const colorLog = new Log({
	color: true,
	colorMap: {
		success: '\x1b[32m', // Green
		critical: '\x1b[91m', // Bright red
	},
});

Configuration Options

const log = new Log({
	tag: 'myapp',       // Logger identifier (omit to share the global __default singleton)
	verbosity: 0,       // Default: 0 (silent). log(n)() shows when n < verbosity; log('msg') shows when verbosity > 0
	color: false,       // Disable color output
	silentTag: false,   // Hide [tag] prefix
	methodTag: false,   // Show [method] label for native methods (info/warn/error); custom methods always show their label
	colorMap: {},       // Custom ANSI color codes
});

Advanced Usage

Dynamic Configuration

const log = new Log({ tag: 'api', verbosity: 1 });

log(2)('This is hidden');

// Increase verbosity at runtime
log.options.verbosity = 3;

log(2)('Now visible');

Tag Management

const log = new Log({ tag: 'init' });
log('Starting up');

// Switch to different tag
log.setTag('runtime');
log('Now running');

Global Configuration

Set process-wide defaults before creating loggers, or map custom methods to console methods:

import Log, { setDefaults, setMethodMap } from '@vanilla-bean/log';

setDefaults({ verbosity: 2, color: true });
setMethodMap({ critical: 'error', trace: 'debug' });

const log = new Log({ tag: 'app' }); // inherits verbosity: 2, color: true
log.critical('Fatal error');          // routes to console.error

Cross-Module Coordination

// logger.js
import Log from '@vanilla-bean/log';
export const appLog = new Log({ tag: 'app', verbosity: 1 });

// module1.js
import { appLog } from './logger.js';
appLog.info('Module 1 loaded');

// module2.js
import { loggers } from '@vanilla-bean/log';
loggers.app.warn('Module 2 warning'); // Same logger instance

Production Deployment

Log Aggregation

Log writes human-readable text to stdout. For log aggregation pipelines that expect JSON (ELK, Fluentd, Datadog), you'll need a JSON logger. Log is the right tool when a human is reading the output — development, debugging, process supervision, or simple production tails.

For plain-text pipelines, disable colors and keep tags for pattern matching:

const log = new Log({
	tag: 'api',
	silentTag: false, // keep [api] prefix for grep/awk
	color: false,     // no ANSI codes in log files
});

log.info('user_login', { userId: 123, ip: '1.2.3.4' });
// Output: [api] user_login { userId: 123, ip: '1.2.3.4' }

Environment Configuration

const log = new Log({
	tag: process.env.SERVICE_NAME || 'app',
	verbosity: process.env.LOG_LEVEL || 1,
	color: process.env.NODE_ENV === 'development',
});

Comparison

| Feature | Log | Winston | Pino | Debug | | ----------------- | --------------------- | ---------------------- | ---------------- | ----------- | | Bundle Size | ~1KB | ~2MB | ~1MB | ~8KB | | Dependencies | 0 | Many | Some | 1 | | Log Levels | Unlimited | 6 + custom | 6 standard | 1 | | Verbosity Control | ✓ Core | ✓ | ✓ | Environment | | Tags/Namespaces | ✓ Singleton | ✓ | ✓ | ✓ | | Transports | stdout only | 20+ built-in | Plugin ecosystem | stdout only | | Container-Native | ✓ | Configuration required | ✓ | ✓ |

API Reference

Constructor

new Log(options?: {
  tag?: string;           // Default: '__default'
  verbosity?: number;     // Default: 0
  color?: boolean;        // Default: false
  silentTag?: boolean;    // Default: false
  methodTag?: boolean;    // Default: false — shows [method] for native methods; custom methods always show it
  colorMap?: object;      // Custom colors
})

Logger Methods

// Primary form: verbosity-gated, curried
log(verbosity: number): (message: any, ...args: any[]) => void;
log.methodName(verbosity: number): (message: any, ...args: any[]) => void;

// Shorthand: equivalent to log(0)('msg') — shows when verbosity > 0
log(message: any, ...args: any[]): void;
log.methodName(message: any, ...args: any[]): void;

Instance Methods

log.setTag(newTag: string): void;
log.options: object;  // Mutable configuration

Global Configuration

setDefaults(options: Partial<LogOptions>): void;
setMethodMap(map: Record<string, string>): void;

Exports

import Log, { loggers, defaults, methodMap, setDefaults, setMethodMap } from '@vanilla-bean/log';

Contributing

Contributions welcome! Submit Pull Requests for improvements. Open issues first for major changes.

Development Setup

# Clone and setup
git clone https://github.com/fatlard1993/log.git
cd log
bun install

# Development workflow
bun test           # Run tests
bun run demo       # Run examples
bun run lint       # Check code style
bun test --watch   # Watch mode

License

MIT License - see the LICENSE file for details.