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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@2run/logger

v1.0.1

Published

Lightweight, type-safe logger with history, transports, and JSON support for Node.js and React Native

Readme

@2run/logger

npm version License: MIT TypeScript

Lightweight, type-safe logger with history, transports, and JSON support for Node.js and React Native.

Features

  • TypeScript First: Full type safety with strict mode
  • Zero Dependencies: No external runtime dependencies
  • Platform Agnostic: Works in Node.js, React Native, and browsers
  • Pluggable Transports: Console, file, or custom transports
  • Multiple Formatters: Text or JSON output
  • Log History: Configurable in-memory history
  • Subscriptions: Listen to log events in real-time
  • Log Filtering: Environment-based log level filtering
  • File Rotation: Automatic file rotation for Node.js
  • Safe Serialization: Handles circular references and Error objects
  • Async Support: Non-blocking file writes with buffering

Installation

npm install @2run/logger
# or
yarn add @2run/logger
# or
pnpm add @2run/logger

Quick Start

Basic Usage

import { logger } from '@2run/logger';

// Simple logging
logger.info('Application started');
logger.debug('Debug information', { userId: 123 });
logger.warn('Warning message');
logger.error('Error occurred', { error: new Error('Something went wrong') });

Custom Logger with Configuration

import { createLogger, JSONFormatter, FileTransport } from '@2run/logger';

const logger = createLogger({
  prefix: 'MyApp',
  minLogLevel: 'info',
  maxHistory: 500,
  defaultMetadata: { appVersion: '1.0.0' },
});

logger.info('Configured logger ready');

JSON Logging (Structured Logs)

import { createLogger, JSONFormatter, ConsoleTransport } from '@2run/logger';

const logger = createLogger({
  transports: [new ConsoleTransport(new JSONFormatter())],
});

logger.info('User action', { userId: 123, action: 'login' });
// Output: {"timestamp":"2025-12-13T10:30:00.000Z","level":"info","message":"User action","id":"...","metadata":{"userId":123,"action":"login"}}

File Logging (Node.js)

import { createLogger, FileTransport } from '@2run/logger';

const logger = createLogger({
  transports: [
    new FileTransport({
      filePath: './logs/app.log',
      maxFileSize: 10 * 1024 * 1024, // 10MB
      maxFiles: 5,
    }),
  ],
});

logger.info('This will be written to file');

Multiple Transports

import { createLogger, ConsoleTransport, FileTransport, JSONFormatter } from '@2run/logger';

const logger = createLogger({
  transports: [
    new ConsoleTransport(), // Console output
    new FileTransport({ filePath: './logs/app.log' }), // File output
    new FileTransport(
      { filePath: './logs/app.json.log' },
      new JSONFormatter() // JSON file output
    ),
  ],
});

logger.info('Logged to console and two files');

Log Subscriptions

import { logger } from '@2run/logger';

// Subscribe to all log events
const unsubscribe = logger.subscribe((entry) => {
  console.log('Log event:', entry);
  // Send to analytics, remote logging service, etc.
});

logger.info('This will trigger the subscription');

// Unsubscribe when done
unsubscribe();

React Native Integration

import { createLogger } from '@2run/logger';

// Logger automatically detects React Native platform
const logger = createLogger({
  prefix: 'MyApp',
  platformInfo: true, // Includes iOS/Android version info
});

logger.info('Running on React Native');
// Output: [MyApp][INFO] Running on React Native [ios/14.5]

API Reference

createLogger(config?): Logger

Creates a new logger instance with the given configuration.

Parameters:

  • config (optional): LoggerConfig
    • prefix (string): Prefix for log messages (default: '')
    • maxHistory (number): Maximum history size (default: 200)
    • minLogLevel (LogLevel): Minimum log level to emit (default: 'debug' in dev, 'warn' in production)
    • platformInfo (boolean): Include platform info (default: true)
    • transports (Transport[]): Custom transports (default: [ConsoleTransport])
    • formatter (Formatter): Custom formatter (default: TextFormatter)
    • defaultMetadata (Record<string, unknown>): Default metadata for all logs
    • correlationIdGenerator (() => string): Custom ID generator

Returns: Logger instance

Logger Methods

logger.debug(message, metadata?)

Logs a debug message.

logger.info(message, metadata?)

Logs an info message.

logger.warn(message, metadata?)

Logs a warning message.

logger.error(message, metadata?)

Logs an error message.

logger.getHistory(): LogEntry[]

Returns a copy of the log history.

logger.subscribe(listener): () => void

Subscribes to log events. Returns an unsubscribe function.

logger.flushToConsole()

Flushes all history to console with [History] tag.

logger.close(): Promise<void>

Closes all transports and flushes pending logs.

TypeScript Types

type LogLevel = 'debug' | 'info' | 'warn' | 'error';

interface LogEntry {
  id: string;
  level: LogLevel;
  message: string;
  metadata?: Record<string, unknown>;
  timestamp: number;
}

interface Transport {
  log(entry: LogEntry): void | Promise<void>;
  flush?(): void | Promise<void>;
  close?(): void | Promise<void>;
}

interface Formatter {
  format(entry: LogEntry, platformInfo?: PlatformInfo): string;
}

Examples

Example: Custom Transport

import { createLogger } from '@2run/logger';
import type { Transport, LogEntry } from '@2run/logger';

class RemoteTransport implements Transport {
  async log(entry: LogEntry) {
    await fetch('https://api.example.com/logs', {
      method: 'POST',
      body: JSON.stringify(entry),
    });
  }
}

const logger = createLogger({
  transports: [new RemoteTransport()],
});

Example: Conditional Logging

import { createLogger } from '@2run/logger';

const logger = createLogger({
  minLogLevel: process.env.NODE_ENV === 'production' ? 'warn' : 'debug',
});

// This will only log in development
logger.debug('Debug info');

// This will log in all environments
logger.error('Critical error');

Example: Correlation IDs

import { createLogger } from '@2run/logger';
import { v4 as uuidv4 } from 'uuid';

const logger = createLogger({
  correlationIdGenerator: () => uuidv4(),
});

logger.info('Request started'); // ID: abc-123-def
logger.info('Processing'); // ID: xyz-456-ghi

Performance Considerations

  • Async File Writes: File transport uses buffering and async writes to avoid blocking
  • Log History: Limited to configurable size (default: 200 entries)
  • Lazy Serialization: Metadata is only serialized when needed
  • Level Filtering: Logs below minimum level are filtered before transport
  • Zero Dependencies: No runtime overhead from external packages

Best Practices

  1. Use appropriate log levels: debug < info < warn < error
  2. Include contextual metadata: Add relevant data to help debugging
  3. Configure per environment: Use debug in development, warn+ in production
  4. Handle sensitive data: Don't log passwords, tokens, or PII
  5. Use structured logging: JSON format for production logs
  6. Implement log rotation: Prevent disk space issues in long-running apps
  7. Clean up subscriptions: Always unsubscribe when components unmount

Contributing

Contributions are welcome! Please read our Contributing Guide for details.

License

MIT © 2Run

Support


Made with ❤️ by the 2Run team