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

glowlog

v5.0.0

Published

The last Node.js logger you'll ever need. Beautiful, configurable, zero dependencies.

Readme

◆ glowlog

The last Node.js logger you'll ever need. Beautiful. Configurable. Zero dependencies.

npm version npm downloads License: MIT Zero deps

  ┌──────────────────────────────────────────────────────────────┐
  │ ●  INFO                                                      │
  ├──────────────────────────────────────────────────────────────┤
  │ Time     : 09:15:42                                          │
  │ Message  : Server started                                    │
  │ Source   : server.js:12                                      │
  ├──────────────────────────────────────────────────────────────┤
  │ port     : 3000                                              │
  │ env      : development                                       │
  └──────────────────────────────────────────────────────────────┘

  ╔══════════════════════════════════════════════════════════════╗
  ║ ✗  ERROR                                                     ║
  ╠══════════════════════════════════════════════════════════════╣
  ║ Time     : 09:15:45                                          ║
  ║ Message  : DB connection failed                              ║
  ╠══════════════════════════════════════════════════════════════╣
  ║ error    : ECONNREFUSED: 127.0.0.1:5432                      ║
  ║   → Could not connect — is the server/database running?      ║
  ╚══════════════════════════════════════════════════════════════╝

📦 Why glowlog?

| What you used to install | With glowlog | |---|---| | winston + winston-daily-rotate-file + morgan + pino-pretty + cls-hooked + redaction lib | glowlog | | 6 packages, 200KB+ | 1 package, ~17KB |


🚀 Install

npm install glowlog

Setup wizard (optional):

npx glowlog init

Asks 4 questions → generates glowlog.config.json. Done.


⚡ Quick Start

import { GlowLogger } from 'glowlog';

const logger = new GlowLogger();

logger.info('Server started', { port: 3000 });
logger.success('User registered', { userId: 'u_001' });
logger.warn('Rate limit', { used: 95, limit: 100 });
logger.error('DB failed', new Error('ECONNREFUSED'));
logger.debug('Query ran', { ms: 12, rows: 47 });
logger.http('POST', '/api/login', 200, 123);

🎨 4 Display Styles

box — Full bordered boxes (default, great for development)

  ┌──────────────────────────────────────────┐     ╔══════════════════════════════════════════╗
  │ ●  INFO                                  │     ║ ⚠  WARNING                               ║
  ├──────────────────────────────────────────┤     ╠══════════════════════════════════════════╣
  │ Time    : 09:15:42                       │     ║ Time    : 09:15:44                        ║
  │ Message : Server started                 │     ║ Message : Rate limit approaching          ║
  └──────────────────────────────────────────┘     ╚══════════════════════════════════════════╝

INFO/SUCCESS/DEBUG = single border · WARN/ERROR = double border

line — Separator lines (staging / readable)

  ──────────────────────────────────────────────────
  ● INFO  09:15:42  server.js:12
    → Server started  port=3000
  ──────────────────────────────────────────────────

compact — One line per log (production)

  ● 09:15:42  INFO     → Server started  port=3000
  ✓ 09:15:43  SUCCESS  → User registered  userId=u_001
  ⚠ 09:15:44  WARN     → Rate limit  used=95  limit=100
  ✗ 09:15:45  ERROR    → DB failed  error=ECONNREFUSED  → Is your DB running?

minimal — Icon + message only (CI / scripts)

  ●  Server started
  ✓  User registered
  ⚠  Rate limit approaching
  ✗  DB failed  → Is your DB running?

⚙️ Full Config

const logger = new GlowLogger({

  // ── DISPLAY ──────────────────────────────────────────────────
  style:      'box',        // 'box' | 'line' | 'compact' | 'minimal'
  spacing:    1,            //  0 | 1 | 2  blank lines between logs
  timeFormat: 'HH:MM:SS',  // 'HH:MM' | 'DD Mon HH:MM:SS' | 'ISO' | false

  // ── SHOW / HIDE FIELDS ────────────────────────────────────────
  show: {
    timestamp: true,   // time value
    source:    true,   // file:line  (auto-detected!)
    label:     true,   // INFO / ERROR / WARN label
    icon:      true,   // ● ✓ ⚠ ✗ ◆ ⚡
    requestId: true,   // req ID from AsyncLocalStorage
    meta:      true,   // extra key:value data
    hint:      true,   // plain English error hints
    stack:     false,  // stack trace lines
    divider:   true,   // separator lines inside box
  },

  // ── FILE LOGGING ──────────────────────────────────────────────
  file: true,
  fileOptions: {
    dir:       './logs',   // where to store logs
    rotation:  'daily',   // 'daily' | 'hourly' | 'size' | 'none'
    maxSizeMB: 10,         // size-based rotation limit
    maxFiles:  7,          // auto-delete files older than N
    compress:  true,       // gzip old files automatically
    format:    'json',     // 'text' | 'json'
    separate:  true,       // separate error.log file
  },

  // ── FEATURES ─────────────────────────────────────────────────
  redact:         true,    // auto-redact passwords, tokens, API keys
  requestId:      true,    // thread req ID via AsyncLocalStorage
  catchErrors:    true,    // capture uncaughtException + unhandledRejection
  productionSafe: true,    // mute DEBUG+INFO in NODE_ENV=production

  // Log sampling — only log X% in production
  sampling: {
    INFO:    0.1,   // 10% of INFO logs
    DEBUG:   0.05,  // 5% of DEBUG logs
    WARN:    1.0,   // 100% always
    ERROR:   1.0,   // 100% always
  },
});

🕐 Timestamp Formats

timeFormat: 'HH:MM:SS'              // 09:15:42
timeFormat: 'HH:MM'                 // 09:15
timeFormat: 'DD Mon HH:MM:SS'       // 21 Apr 09:15:42
timeFormat: 'DD Month YYYY HH:MM AM'// 21 April 2026  9:15 AM
timeFormat: 'ISO'                   // 2026-04-21T09:15:42.000Z
timeFormat: false                   // hidden completely

👶 Child Loggers

Module-scoped loggers that inherit parent config:

const logger   = new GlowLogger({ style: 'compact' });
const dbLogger = logger.child('database');
const authLog  = logger.child('auth');

dbLogger.info('Query executed', { ms: 45 });
// ● INFO [database]  → Query executed  ms=45

authLog.error('Login failed', { userId: 'u_001' });
// ✗ ERROR [auth]  → Login failed  userId=u_001

🔒 Auto-Redaction

Zero config. Works automatically:

logger.info('Login', {
  username: 'adarsh',
  password: 'secret123',   // → [REDACTED]
  token:    'eyJhbGci...',  // → [REDACTED]
  ip:       '192.168.1.1', // → shown (not sensitive)
});

Add your own sensitive keys:

import { addSensitiveKey } from 'glowlog';
addSensitiveKey('aadhaar');
addSensitiveKey('panNumber');

🧵 Request ID Threading

Every log in a request carries the same ID — automatically:

import { GlowLogger, requestIdMiddleware, withContext } from 'glowlog';

const logger = new GlowLogger();

// Express / NestJS
app.use(requestIdMiddleware());
app.use(logger.middleware());

// Manual (queues, crons, scripts)
await withContext({ requestId: 'job_001' }, async () => {
  logger.info('Processing batch');  // → Req ID: job_001
  logger.debug('Step 1 done');     // → Req ID: job_001
});

📁 File Rotation

logs/
├── app-2026-04-21.log        ← today (active)
├── app-2026-04-20.log.gz     ← yesterday (compressed)
├── app-2026-04-19.log.gz     ← 2 days ago
├── app-2026-04-18.log.gz     ← 3 days ago
│   ...
└── error-2026-04-21.log      ← separate error log (if separate: true)

Files beyond maxFiles are auto-deleted. Old files are auto-compressed to .gz.


🎯 Log Sampling

In high traffic — log only a % of verbose logs:

sampling: {
  DEBUG: 0.05,  // 5% — very sparse
  INFO:  0.1,   // 10% — reduce noise
  WARN:  1.0,   // 100% — always show
  ERROR: 1.0,   // 100% — always show
}

📦 Presets

Zero-config shortcuts for common setups:

import { dev, prod, ci, neat, nest } from 'glowlog/presets';

const logger = dev('app');    // box + all fields + colors
const logger = prod('app');   // compact + json file + gzip + 14 days
const logger = ci('app');     // minimal + no noise
const logger = neat('app');   // line style, middle ground
const nestLog = nest('App');  // NestJS LoggerService compatible

NestJS

// main.ts
import { nest } from 'glowlog/presets';
import { requestIdMiddleware } from 'glowlog';

app.use(requestIdMiddleware());
app.useLogger(nest('MyApp', './logs'));

🌐 Express Middleware

const logger = new GlowLogger();

// Logs every HTTP request automatically
app.use(requestIdMiddleware());  // thread request ID
app.use(logger.middleware());    // log HTTP requests

Output:

● 09:15:42  HTTP  POST  /api/login   200  123ms
✗ 09:15:43  HTTP  GET   /api/secret  401    8ms
⚡ 09:15:44  HTTP  POST  /api/payment 500  2341ms  ← red (slow + error)

💡 Plain English Error Hints

No more cryptic Node.js errors:

| Raw Error | glowlog Shows | |---|---| | ECONNREFUSED | → Could not connect — is the server/database running? | | ENOTFOUND | → Server not found — check the URL or internet | | ENOENT | → File not found — check the path | | EADDRINUSE | → Port already in use — try a different port | | 401 | → Unauthorized — check API key or credentials | | MODULE_NOT_FOUND | → Did you run npm install? |


🌐 Browser Support

Same import, auto-detected environment:

import { GlowLogger } from 'glowlog';

const logger = new GlowLogger();
// In Node: beautiful ANSI terminal output
// In Browser: CSS-styled console groups

🔄 Runtime Changes

logger.setLevel('WARN');   // only WARN + ERROR from now
logger.setStyle('compact');// switch style live
logger.setSpacing(0);      // remove spacing

logger.banner('MyApp v2.0'); // print a big banner
logger.files();              // list all log files
logger.clearFiles();         // delete all log files

📊 Log Files Management

logger.files();
// ● app-2026-04-21.log         12.4 KB
// ● app-2026-04-20.log.gz       3.1 KB
// ● error-2026-04-21.log        1.2 KB

logger.clearFiles(); // delete all

⚡ Serverless (Lambda / Vercel / Netlify)

import { GlowLogger, withLogFlush } from 'glowlog';

const logger = new GlowLogger();

// Wrap handler — auto-flushes before function freezes
export const handler = withLogFlush(async (event) => {
  logger.info('Event received', { id: event.id });
  return { statusCode: 200 };
});

📋 All Log Levels

| Method | Icon | Border | Color | When | |---|---|---|---|---| | logger.info() | ● | single | cyan | General info | | logger.success() | ✓ | single | green | Completed actions | | logger.warn() | ⚠ | double | yellow | Needs attention | | logger.error() | ✗ | double | red | Something broke | | logger.debug() | ◆ | single | magenta | Dev details | | logger.http() | ⚡ | single | blue | HTTP requests |


🏆 vs Winston / Pino

| | Winston | Pino | glowlog | |---|---|---|---| | Packages needed | 6+ | 3+ | 1 | | Beautiful terminal | manual | needs pino-pretty | built-in | | Browser support | ❌ | partial | | | Auto-redaction | ❌ | manual | ✅ zero config | | Request ID | 3 packages | manual | ✅ built-in | | File rotation | separate pkg | separate pkg | ✅ built-in | | File compression | ❌ | ❌ | ✅ gzip auto | | Child loggers | buggy | ✅ | | | Error hints | ❌ | ❌ | | | Log sampling | ❌ | ❌ | | | Zero dependencies | ❌ | ❌ | |


📄 License

MIT © Adarsh


🤝 Contributing

Issues, bugs, ideas — all welcome!

glowlog is open source and free forever.