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

@gratheon/log-lib

v2.2.7

Published

Logging library with console and MySQL database persistence

Readme

log-lib

A TypeScript logging library with console output and MySQL database persistence support.

Features

  • Dual Output: Logs to both console and MySQL database
  • Color-Coded Console: ANSI colored output for different log levels
  • Automatic Stacktrace Capture: Every log includes file:line information
    • CLI Output: Shows the most relevant TypeScript file:line in gray color
    • Database Storage: Stores full stacktrace filtered to TypeScript files only
  • Enhanced Stack Traces: Shows code frames with 5 lines of context around errors (dev mode)
  • Error Cause Chain Tracking: Traverses and displays the full error.cause chain
  • Callsite Capture: Captures where logger.error was called when error lacks stack frames
  • Automatic Database Creation: Creates logs database and table if they don't exist
  • Non-blocking Initialization: App starts even if logging DB fails
  • Connection Pool Optimization: Suppresses known MySQL warnings for cleaner logs
  • Global Exception Handlers: Captures uncaught exceptions and unhandled rejections
  • TypeScript Support: Full type definitions included
  • Fastify Integration: Special logger interface for Fastify framework
  • Flexible Metadata: Support for structured metadata in logs
  • Multiple Log Levels: info, error, warn, debug (debug logs are not persisted to DB)
  • Log Level Filtering: Configure minimum log level via config or LOG_LEVEL env var

Installation

npm install @gratheon/log-lib

Database Setup

The logger automatically creates the database and table on first initialization. No manual setup required!

Automatic Migrations: When updating from older versions, the logger automatically runs migrations on initialization:

  • Checks if the stacktrace column exists
  • Adds it if missing (for v2.2.0+ compatibility)
  • Non-blocking: app starts even if migration fails

For reference, migration scripts are available in the migrations/ directory.

Usage

Basic Usage

import { createLogger, LoggerConfig } from '@gratheon/log-lib';

const config: LoggerConfig = {
  mysql: {
    host: 'localhost',
    port: 3306,
    user: 'your_user',
    password: 'your_password',
    database: 'logs' // optional, defaults to 'logs'
  },
  logLevel: 'info' // optional, defaults to 'debug' in dev, 'info' in prod
};

const { logger, fastifyLogger } = createLogger(config);

// Log messages - each log automatically includes file:line location
logger.info('Application started');
// Output: 12:34:56 [info]: Application started  src/index.ts:42

logger.warn('Low memory warning', { available: '100MB' });
// Output: 12:34:56 [warn]: Low memory warning {"available":"100MB"} src/memory.ts:15

logger.error('Failed to connect to API', { endpoint: '/api/users' });
logger.debug('Processing item', { id: 123 }); // Not stored in DB

// Error with stack trace and code frame (in dev mode)
try {
  throw new Error('Something went wrong');
} catch (err) {
  logger.error(err); // Logs error with stack trace, cause chain, and code frame
}

// Enriched error logging
logger.errorEnriched('Database query failed', err, { query: 'SELECT * FROM users' });

Development Mode Features

Set ENV_ID=dev to enable enhanced error diagnostics:

ENV_ID=dev node app.js

In dev mode, you get:

  • Code frames: Shows 5 lines of source code around the error location
  • Column markers: Caret (^) pointing to the exact error position
  • Callsite capture: When error lacks project stack frames, shows where logger was called
  • Enhanced debugging: More verbose error output

Example dev mode output:

12:34:56 [error]: Something went wrong {"stack":"Error: Something went wrong\n  at /app/src/user.ts:42:15\n..."}

Code frame:
  40 | function processUser(user) {
  41 |   if (!user.id) {
> 42 |     throw new Error('Something went wrong');
     |               ^
  43 |   }
  44 |   return user;

Fastify Integration

import Fastify from 'fastify';
import { createLogger, LoggerConfig } from '@gratheon/log-lib';

const config: LoggerConfig = {
  mysql: {
    host: 'localhost',
    port: 3306,
    user: 'your_user',
    password: 'your_password'
  }
};

const { fastifyLogger } = createLogger(config);

const fastify = Fastify({
  logger: fastifyLogger
});

fastify.listen(3000);

API Reference

createLogger(config: LoggerConfig)

Creates and returns logger instances.

Parameters:

  • config: Configuration object with MySQL connection details

Returns:

{
  logger: Logger,
  fastifyLogger: FastifyLogger
}

Logger Methods

logger.info(message: string, meta?: LogMetadata)

Logs informational messages (console + DB)

logger.error(message: string | Error, meta?: LogMetadata)

Logs errors with automatic Error object detection (console + DB)

logger.errorEnriched(message: string, error: Error, meta?: LogMetadata)

Logs enriched error messages with context (console + DB)

logger.warn(message: string, meta?: LogMetadata)

Logs warning messages (console + DB)

logger.debug(message: string, meta?: LogMetadata)

Logs debug messages (console only, not persisted)

FastifyLogger Methods

Compatible with Fastify's logger interface:

  • info(msg: any)
  • error(message: string | Error, meta?: LogMetadata)
  • warn(msg: any)
  • debug(msg: any)
  • fatal(msg: any) - Logs error and calls process.exit(1) after 100ms delay
  • trace(msg: any) - No-op
  • child(meta: any) - Returns the same logger instance

Advanced Features

Connection Pool Configuration

The logger uses an optimized connection pool:

  • Pool size: 3 connections
  • Max uses per connection: 200
  • Idle timeout: 30 seconds
  • Queue timeout: 60 seconds
  • Automatic error suppression for known MySQL warnings

Message Truncation

To prevent database bloat:

  • Messages are truncated to 2000 characters
  • Metadata is truncated to 2000 characters
  • JSON stringification uses fast-safe-stringify for circular reference handling

Async Initialization

The logger initializes asynchronously in the background:

const { logger } = createLogger(config);
logger.info('App starting'); // Works immediately, DB writes happen when ready

Environment-Specific Behavior

Set ENV_ID to control behavior:

  • ENV_ID=dev: Enhanced diagnostics, code frames, callsite capture
  • ENV_ID=prod: Production mode with minimal overhead

Console Output Colors

  • Time: Blue
  • Error: Red (level) + Magenta (metadata) + Gray (file:line)
  • Info: Green (level) + Magenta (metadata) + Gray (file:line)
  • Debug: Gray (dimmed, including file:line)
  • Warn: Yellow (level) + Magenta (metadata) + Gray (file:line)
  • File Location: Gray (file:line) - automatically captured from call stack

Database Schema

CREATE TABLE `logs` (
    `id`         int auto_increment primary key,
    `level`      varchar(16)   not null,
    `message`    varchar(2048) not null,
    `meta`       varchar(2048) not null,
    `stacktrace` text,
    `timestamp`  datetime      not null
);

The stacktrace column stores the full call stack filtered to TypeScript files only, making it easy to trace the origin of each log entry.

Error Handling

The logger provides comprehensive error handling:

Automatic Database Creation

  • Creates the logs database if it doesn't exist
  • Creates the logs table with proper schema and indexes
  • Non-blocking initialization - app starts even if DB fails

Graceful Degradation

  • Logs are always written to console
  • Database errors are logged but don't crash the application
  • Connection pool errors are suppressed (packets out of order, inactivity warnings)
  • Fire-and-forget database logging (no await in hot path)

Enhanced Error Diagnostics

  • Error Cause Chain: Automatically traverses and displays error.cause chains
  • Stack Trace Enhancement: Formats and colorizes stack traces
  • Code Frames (dev mode): Shows source code context around errors
  • Callsite Capture (dev mode): Shows where logger was called when error lacks stack

Global Exception Handling

The logger automatically registers handlers for:

  • uncaughtException: Logs the error and exits gracefully (100ms delay for log flush)
  • unhandledRejection: Logs the rejection and continues running

Example with error cause chain:

try {
  const dbError = new Error('Connection refused');
  throw new Error('Failed to fetch user', { cause: dbError });
} catch (err) {
  logger.error(err);
  // Output:
  // [error]: Failed to fetch user
  // [stack trace]
  // Cause chain: Error: Connection refused
}

TypeScript Types

interface LoggerConfig {
  mysql?: {
    host: string;
    port: number;
    user: string;
    password: string;
    database?: string; // defaults to 'logs'
  };
  logLevel?: LogLevel; // 'debug' | 'info' | 'warn' | 'error', defaults to 'debug' in dev, 'info' in prod
}

interface LogMetadata {
  [key: string]: any;
}

License

ISC