Skip to content

A universal TypeScript logging library that works consistently across all JavaScript runtimes: Node.js, Deno, Bun, browsers, and WebAssembly environments.

License

Notifications You must be signed in to change notification settings

llbbl/logan-logger-ts

Repository files navigation

Logan Logger

CI npm JSR

A universal TypeScript logging library that works consistently across all JavaScript runtimes: Node.js, Deno, Bun, browsers, and WebAssembly environments.

Features

  • 🌐 Universal Runtime Support - Works in Node.js, Deno, Bun, browsers, and WebAssembly
  • βš›οΈ Next.js Ready - Full compatibility with App Router, Server Components, and API Routes
  • πŸͺΆ Zero Dependencies - Core functionality with no required dependencies
  • ⚑ Performance First - Lazy evaluation, zero-allocation logging, minimal memory footprint
  • 🎯 TypeScript Native - Full type safety with comprehensive type definitions
  • πŸ”§ Flexible Configuration - Environment-based auto-configuration or manual setup
  • πŸ”’ Safe Serialization - Handles circular references, Error objects, and sensitive data filtering
  • 🎨 Rich Browser Support - Console styling, performance marks, grouping
  • πŸ“Š Structured Logging - Rich metadata support with child loggers

Quick Start

# NPM
npm install logan-logger
# or
pnpm add logan-logger
# or
yarn add logan-logger

# JSR (Deno/Node.js)
deno add @logan/logger
# or
npx jsr add @logan/logger

Basic Usage

import { createLogger, LogLevel } from 'logan-logger';

// Create logger with automatic environment configuration
const logger = createLogger({
  level: LogLevel.DEBUG,
  colorize: true
});

// Basic logging
logger.info('Application started');
logger.warn('Configuration missing', { file: 'config.json' });
logger.error('Database connection failed', { error: new Error('Connection failed') });

// Child loggers with additional context
const requestLogger = logger.child({ 
  requestId: 'req-123', 
  userId: 'user-456' 
});

requestLogger.info('Processing request', { endpoint: '/api/users' });

Next.js Integration

Logan Logger is fully compatible with Next.js 13+ App Router, including Server Components, Client Components, and API Routes.

Server Components

import { createLogger, LogLevel } from 'logan-logger';

const logger = createLogger({
  level: process.env.NODE_ENV === 'development' ? LogLevel.DEBUG : LogLevel.INFO,
  format: 'json'
});

export default async function ServerComponent() {
  logger.info('Server component rendered');
  
  // Server-side data fetching
  const data = await fetchData();
  logger.debug('Data fetched', { recordCount: data.length });
  
  return <div>Server content</div>;
}

Client Components

'use client';

import { createLogger, LogLevel } from 'logan-logger';

const logger = createLogger({
  level: LogLevel.INFO,
  colorize: true
});

export default function ClientComponent() {
  const handleClick = () => {
    logger.info('User interaction', { action: 'button_click' });
  };

  return <button onClick={handleClick}>Click me</button>;
}

API Routes

// app/api/users/route.ts
import { NextResponse } from 'next/server';
import { createLogger } from 'logan-logger';

const logger = createLogger({
  format: 'json',
  metadata: { service: 'api' }
});

export async function GET() {
  const start = Date.now();
  logger.info('API request started', { endpoint: '/api/users' });
  
  try {
    const users = await getUsers();
    const duration = Date.now() - start;
    
    logger.info('API request completed', { 
      statusCode: 200, 
      duration,
      userCount: users.length 
    });
    
    return NextResponse.json(users);
  } catch (error) {
    const duration = Date.now() - start;
    logger.error('API request failed', { 
      statusCode: 500, 
      duration,
      error: error instanceof Error ? error.message : 'Unknown error'
    });
    
    return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 });
  }
}

πŸ“‹ See Next.js Compatibility Guide for complete setup instructions, advanced patterns, and troubleshooting.

Advanced Features

Lazy Evaluation for Performance

// Function is only called if debug level is enabled
logger.debug(() => `Expensive computation: ${computeHeavyValue()}`);

Environment-Based Configuration

import { createLoggerForEnvironment } from 'logan-logger';

// Automatically configures based on NODE_ENV
const logger = createLoggerForEnvironment();
// Production: ERROR level, JSON format
// Development: DEBUG level, colored console
// Test: WARN level

Runtime-Specific Imports

Logan Logger provides runtime-specific entry points for optimal bundling and type safety:

🟒 Node.js with Winston Support:

import { createLogger, NodeLogger, createMorganStream } from 'logan-logger/node';

const logger = new NodeLogger({
  transports: [
    { type: 'file', options: { filename: 'app.log' } }
  ]
});

// Express/Morgan integration
app.use(morgan('combined', { stream: createMorganStream(logger) }));

🌐 Browser-Optimized (Webpack/Vite-Safe):

import { createLogger, BrowserLogger, PerformanceLogger } from 'logan-logger/browser';

const logger = new PerformanceLogger();

logger.mark('api-start');
// ... API call
logger.measure('api-duration', 'api-start');

πŸ¦• Deno-Optimized:

import { createLogger, BrowserLogger } from 'logan-logger/deno';

const logger = createLogger({ colorize: true });
logger.info('Deno application started');

πŸ₯Ÿ Bun-Optimized:

import { createLogger, NodeLogger } from 'logan-logger/bun';

const logger = createLogger({ level: LogLevel.DEBUG });
logger.info('Bun application started');

πŸ”§ Auto-Detection (Generic):

import { createLogger } from 'logan-logger';

// Automatically selects appropriate logger based on runtime
const logger = createLogger();

Safe Data Handling

import { filterSensitiveData } from 'logan-logger';

const userData = {
  name: 'John Doe',
  email: 'john@example.com',
  password: 'secret123',  // Will be filtered
  apiKey: 'sk_live_...'   // Will be filtered
};

const safeData = filterSensitiveData(userData);
logger.info('User processed', safeData);
// Logs: { name: 'John Doe', email: 'john@example.com', password: '[REDACTED]', apiKey: '[REDACTED]' }

Runtime Support & Import Paths

Runtime Import Path Status Implementation Features
Next.js 13+ logan-logger βœ… Full Auto-detection Server/Client Components, API Routes, Edge Runtime
Node.js 20+ logan-logger/node βœ… Full Winston + Console File logging, transports, Morgan integration
Bun logan-logger/bun βœ… Full NodeLogger adapter Same as Node.js
Browser logan-logger/browser βœ… Full Console API CSS styling, performance marks, grouping
Deno @logan/logger/deno (JSR) βœ… Basic BrowserLogger adapter Console logging (native implementation planned)
WebWorker logan-logger/browser βœ… Basic Console adapter Basic console logging
Auto-detect logan-logger βœ… Basic Runtime detection Automatic adapter selection

Configuration

Log Levels

enum LogLevel {
  DEBUG = 0,    // Most verbose
  INFO = 1,     // General information  
  WARN = 2,     // Warning messages
  ERROR = 3,    // Error messages
  SILENT = 4    // No output
}

Environment Variables

LOG_LEVEL=debug      # debug, info, warn, error, silent
LOG_FORMAT=json      # json, text
LOG_TIMESTAMP=true   # true, false
LOG_COLOR=false      # true, false

πŸ“‹ See Environment Variables Documentation for complete details, examples, and runtime-specific considerations.

Configuration Options

interface LoggerConfig {
  level: LogLevel;
  format: 'json' | 'text' | 'custom';
  timestamp: boolean;
  colorize: boolean;
  metadata: Record<string, any>;
  transports?: TransportConfig[];
}

API Reference

Core Methods

interface ILogger {
  debug(message: string | (() => string), metadata?: any): void;
  info(message: string | (() => string), metadata?: any): void;
  warn(message: string | (() => string), metadata?: any): void;
  error(message: string | (() => string), metadata?: any): void;
  
  setLevel(level: LogLevel): void;
  getLevel(): LogLevel;
  child(metadata: Record<string, any>): ILogger;
}

Factory Functions

// Create logger with explicit configuration
createLogger(config?: Partial<LoggerConfig>): ILogger;

// Create logger based on environment
createLoggerForEnvironment(): ILogger;

Development

Setup

git clone <repository>
cd logan-logger-ts
pnpm install

Commands

# Development
pnpm dev                    # Run with bun
pnpm test                   # Test watch mode
pnpm test:run              # Single test run
pnpm test:ui               # Test UI

# Building
pnpm build                 # Full build
pnpm typecheck            # Type checking
pnpm lint                  # Code linting

# Specific tests
vitest run tests/logger.test.ts

Architecture

Logan Logger uses a Factory + Adapter pattern:

  1. Runtime Detection - Automatically detects the current JavaScript environment
  2. Factory Creation - Creates the appropriate logger implementation
  3. Runtime Adapters - Optimized implementations for each environment
  4. Unified Interface - Consistent API across all runtimes

File Structure

src/
β”œβ”€β”€ core/           # Core interfaces and factory
β”œβ”€β”€ runtime/        # Runtime-specific implementations  
β”œβ”€β”€ utils/          # Utilities (serialization, config, runtime detection)
└── index.ts        # Main exports

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Ensure all tests pass: pnpm test:run
  5. Submit a pull request

License

MIT License - see LICENSE file for details.

Credits

Created by Logan Lindquist Land

About

A universal TypeScript logging library that works consistently across all JavaScript runtimes: Node.js, Deno, Bun, browsers, and WebAssembly environments.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •