@stool/logging
v3.2.5
Published
Logger
Readme
@stool/logging
A simple, logging library inspired by Python's logging module. Features include multiple log levels, custom formatters, filters, and handlers.
Features
- 🏗️ Hierarchical logger structure with parent-child relationships
- 📊 Multiple log levels (DEBUG, INFO, WARN, ERROR, FATAL/CRITICAL)
- 🎨 Customizable formatters for log output
- 🔍 Filtering capabilities for fine-grained log control
- 📤 Multiple handlers (Console, and extensible for custom handlers)
- 🌐 Global logger factory for consistent logging across your application
Install
npm install @stool/loggingQuick Start
import { getLogger, ConsoleHandler, SimpleFormater } from '@stool/logging';
// Get a logger instance
const logger = getLogger('app');
logger.setLevel('DEBUG');
// Add a console handler with custom formatting
const consoleHandler = new ConsoleHandler();
consoleHandler.setFormater(new SimpleFormater('{name} {levelName} {msg}'));
logger.addHandler(consoleHandler);
// Start logging
logger.info('Application started');
logger.error('Something went wrong');Basic Usage
Creating Loggers
import { getLogger } from '@stool/logging';
// Root logger
const rootLogger = getLogger();
// Named logger
const appLogger = getLogger('app');
// Child logger (inherits from parent)
const dbLogger = getLogger('app.database');
const userLogger = getLogger('app.user');Log Levels
const logger = getLogger('myapp');
// Set minimum log level
logger.setLevel('INFO'); // or use Levels.INFO
// Logging methods (in order of severity)
logger.debug('Debug information'); // Lowest priority
logger.info('General information');
logger.warn('Warning message'); // or logger.warning()
logger.error('Error occurred');
logger.fatal('Critical error'); // or logger.critical()
// Exception logging
try {
throw new Error('Something failed');
} catch (error) {
logger.exception(error); // Logs error with stack trace
}Advanced Logging with Extra Data
const logger = getLogger('app');
// Log with extra context data
logger.info('User login', { userId: 123, ip: '192.168.1.1' });
logger.error('Database error', new Error('Connection failed'), {
query: 'SELECT * FROM users',
duration: 1500
});Handlers
Handlers determine where log messages are sent. You can add multiple handlers to a logger.
Console Handler
import { ConsoleHandler, SimpleFormater } from '@stool/logging';
const logger = getLogger('app');
// Basic console handler
const handler = new ConsoleHandler();
logger.addHandler(handler);
// Console handler with custom formatting
const customHandler = new ConsoleHandler();
customHandler.setFormater(new SimpleFormater('{levelName}: {msg}'));
customHandler.setLevel('WARN'); // Only log warnings and above
logger.addHandler(customHandler);Creating Custom Handlers
import { BaseHandler, IRecord } from '@stool/logging';
class FileHandler extends BaseHandler {
constructor(private filename: string) {
super();
}
emit(record: IRecord): void {
const message = this.formater.format(record);
// Write to file (implement your file writing logic)
console.log(`Writing to ${this.filename}: ${message}`);
}
}
// Usage
const fileHandler = new FileHandler('app.log');
logger.addHandler(fileHandler);Formatters
Formatters control the structure and appearance of log messages.
Built-in Formatters
import { SimpleFormater } from '@stool/logging';
const logger = getLogger('app');
const handler = new ConsoleHandler();
// Predefined formats
handler.setFormater(new SimpleFormater(SimpleFormater.FULL)); // Full details
handler.setFormater(new SimpleFormater(SimpleFormater.BASIC)); // Basic info
handler.setFormater(new SimpleFormater(SimpleFormater.MINIMAL)); // Just message
// Custom format template
handler.setFormater(new SimpleFormater('{created} [{levelName}] {name}: {msg}'));Available Format Variables
{created}- ISO timestamp{timestamp}- Unix timestamp{name}- Logger name{level}- Numeric level{levelName}- Level name (DEBUG, INFO, etc.){msg}- Log message{exception}- Exception information{extra}- Extra context data
Custom Formatters
import { IFormater, IRecord } from '@stool/logging';
class JsonFormater implements IFormater {
format(record: IRecord): string {
return JSON.stringify({
timestamp: record.timestamp,
level: record.levelName,
logger: record.name,
message: record.msg,
extra: record.extra
});
}
}
// Usage
const handler = new ConsoleHandler();
handler.setFormater(new JsonFormater());Filters
Filters provide fine-grained control over which log records are processed.
Built-in Filter
import { Filter } from '@stool/logging';
const logger = getLogger('app');
const handler = new ConsoleHandler();
// Only log records from 'app.database' and its children
const filter = new Filter('app.database');
handler.addFilter(filter);
logger.addHandler(handler);Custom Filters
// Function-based filter
const errorOnlyFilter = (record) => record.level >= Levels.ERROR;
handler.addFilter(errorOnlyFilter);
// Class-based filter
class TimeFilter {
constructor(private startHour: number, private endHour: number) {}
filter(record: IRecord): boolean {
const hour = record.created.getHours();
return hour >= this.startHour && hour <= this.endHour;
}
}
// Only log during business hours
handler.addFilter(new TimeFilter(9, 17));Hierarchical Logging
Loggers form a hierarchy based on their names (separated by dots). Child loggers inherit settings from parents and can propagate messages up the hierarchy.
const appLogger = getLogger('app');
const dbLogger = getLogger('app.database');
const userDbLogger = getLogger('app.database.users');
// Add handler to parent
const handler = new ConsoleHandler();
appLogger.addHandler(handler);
// Child loggers will use parent's handler
dbLogger.info('Database connected'); // Will use app's handler
userDbLogger.info('User table ready'); // Will also use app's handler
// Add specific handler to child
const dbHandler = new ConsoleHandler();
dbHandler.setFormater(new SimpleFormater('DB: {msg}'));
dbLogger.addHandler(dbHandler);
// Now dbLogger will use both handlers
dbLogger.info('Query executed'); // Appears in both formatsComplete Example
import {
getLogger,
ConsoleHandler,
SimpleFormater,
Filter,
Levels
} from '@stool/logging';
// Create main application logger
const appLogger = getLogger('myapp');
appLogger.setLevel(Levels.DEBUG);
// Set up console handler with custom formatting
const consoleHandler = new ConsoleHandler();
consoleHandler.setFormater(new SimpleFormater(
'{created} [{levelName}] {name}: {msg} {extra}'
));
appLogger.addHandler(consoleHandler);
// Create specialized loggers
const httpLogger = getLogger('myapp.http');
const dbLogger = getLogger('myapp.database');
// Add filter to only show errors for database
const dbHandler = new ConsoleHandler();
dbHandler.setLevel(Levels.ERROR);
dbHandler.setFormater(new SimpleFormater('DB ERROR: {msg}'));
dbLogger.addHandler(dbHandler);
// Usage
appLogger.info('Application starting');
httpLogger.info('Server listening on port 3000');
dbLogger.info('Database connected'); // Won't show (below ERROR level)
dbLogger.error('Query failed', { query: 'SELECT * FROM users' });
// Exception handling
try {
throw new Error('Something went wrong');
} catch (error) {
appLogger.exception(error);
}API Reference
Logger Methods
setLevel(level: LevelType)- Set minimum log leveladdHandler(handler: IHandler)- Add output handlerremoveHandler(handler: IHandler)- Remove handlerdebug(msg: string)- Log debug messageinfo(msg: string, extra?: any)- Log info messagewarn(msg: string, exception?: any, extra?: any)- Log warningerror(msg: string, exception?: any, extra?: any)- Log errorfatal(msg: string, exception?: any, extra?: any)- Log fatal errorexception(error: Error)- Log exception with stack trace
Log Levels
import { Levels } from '@stool/logging';
Levels.DEBUG // 1
Levels.INFO // 2
Levels.WARN // 4
Levels.ERROR // 8
Levels.FATAL // 16
Levels.NOTSET // 0License
MIT
