A universal TypeScript logging library that works consistently across all JavaScript runtimes: Node.js, Deno, Bun, browsers, and WebAssembly environments.
- π 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
# 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
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' });
Logan Logger is fully compatible with Next.js 13+ App Router, including Server Components, Client Components, and API Routes.
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>;
}
'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>;
}
// 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.
// Function is only called if debug level is enabled
logger.debug(() => `Expensive computation: ${computeHeavyValue()}`);
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
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();
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 | 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 |
enum LogLevel {
DEBUG = 0, // Most verbose
INFO = 1, // General information
WARN = 2, // Warning messages
ERROR = 3, // Error messages
SILENT = 4 // No output
}
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.
interface LoggerConfig {
level: LogLevel;
format: 'json' | 'text' | 'custom';
timestamp: boolean;
colorize: boolean;
metadata: Record<string, any>;
transports?: TransportConfig[];
}
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;
}
// Create logger with explicit configuration
createLogger(config?: Partial<LoggerConfig>): ILogger;
// Create logger based on environment
createLoggerForEnvironment(): ILogger;
git clone <repository>
cd logan-logger-ts
pnpm install
# 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
Logan Logger uses a Factory + Adapter pattern:
- Runtime Detection - Automatically detects the current JavaScript environment
- Factory Creation - Creates the appropriate logger implementation
- Runtime Adapters - Optimized implementations for each environment
- Unified Interface - Consistent API across all runtimes
src/
βββ core/ # Core interfaces and factory
βββ runtime/ # Runtime-specific implementations
βββ utils/ # Utilities (serialization, config, runtime detection)
βββ index.ts # Main exports
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass:
pnpm test:run
- Submit a pull request
MIT License - see LICENSE file for details.
Created by Logan Lindquist Land