-
Notifications
You must be signed in to change notification settings - Fork 2
Slogger Migration
Migrating to Slogger from other logging libraries.
console.log('Application started');
console.log('User logged in:', userId);
console.error('Database connection failed:', error);
console.warn('Deprecated API used');import { Slogger, SyslogSeverities } from '@tundralibs/slogger';
declare const userId: string;
declare const error: Error;
const logger = new Slogger({
appName: 'MyApp',
level: SyslogSeverities.INFO,
handlers: [{
name: 'console',
type: 'ConsoleHandler',
level: SyslogSeverities.INFO,
formatter: 'standard',
}],
});
logger.info('Application started');
logger.info('User logged in', { userId });
logger.error('Database connection failed', { error: error.message });
logger.warning('Deprecated API used');- Structured context instead of string concatenation
- Log levels for filtering
- Multiple output destinations
- Consistent formatting
- Better performance with lazy evaluation
Winston is a popular Node.js logging library.
const winston = require('winston');
const logger = winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json(),
),
transports: [
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' }),
new winston.transports.Console({
format: winston.format.simple(),
}),
],
});
logger.info('User logged in', { userId: '123' });
logger.error('Operation failed', { error: err.message });import { Slogger, SyslogSeverities } from '@tundralibs/slogger';
declare const err: Error;
const logger = new Slogger({
appName: 'MyApp',
level: SyslogSeverities.INFO,
handlers: [
{
name: 'error-file',
type: 'FileHandler',
level: SyslogSeverities.ERROR,
directory: './',
filenameTemplate: 'error.log',
formatter: 'json',
},
{
name: 'combined-file',
type: 'FileHandler',
level: SyslogSeverities.INFO,
directory: './',
filenameTemplate: 'combined.log',
formatter: 'json',
},
{
name: 'console',
type: 'ConsoleHandler',
level: SyslogSeverities.INFO,
formatter: 'standard',
},
],
});
logger.info('User logged in', { userId: '123' });
logger.error('Operation failed', { error: err.message });| Winston | Slogger |
|---|---|
| error | error |
| warn | warning |
| info | info |
| http | notice |
| verbose | info |
| debug | debug |
| silly | debug |
| Winston Format | Slogger Formatter |
|---|---|
format.json() |
'json' |
format.simple() |
'standard' |
format.prettyPrint() |
'detailed' |
| Custom | Custom formatter function |
Pino is a fast Node.js logger with low overhead.
const pino = require('pino');
const logger = pino({
level: 'info',
transport: {
target: 'pino-pretty',
options: {
useColor: true,
},
},
});
logger.info({ userId: '123' }, 'User logged in');
logger.error({ err }, 'Operation failed');import { Slogger, SyslogSeverities } from '@tundralibs/slogger';
declare const err: Error;
const logger = new Slogger({
appName: 'MyApp',
level: SyslogSeverities.INFO,
handlers: [{
name: 'console',
type: 'ConsoleHandler',
level: SyslogSeverities.INFO,
useColor: true,
formatter: 'detailed',
}],
});
logger.info('User logged in', { userId: '123' });
logger.error('Operation failed', { err: err.message });Don't pass the raw
Errorobject as a context value.Error'smessage/stackare non-enumerable, soJSON.stringify— whatjsonFormatter,logfmtFormatterandotelLogFormatterall use under the hood — serialises a bareErrorto{}. Extract the fields you want (error.message,error.stack) into the context explicitly. See Formatters → JSON Formatter.
Message/Context Order:
- Pino:
logger.info(context, message) - Slogger:
logger.info(message, context)
Child Loggers:
// Pino
const child = logger.child({ component: 'auth' });
// Slogger equivalent: use context
logger.info('Login attempt', { component: 'auth', userId });Bunyan is a JSON logging library for Node.js.
const bunyan = require('bunyan');
const logger = bunyan.createLogger({
name: 'myapp',
streams: [
{
level: 'info',
stream: process.stdout,
},
{
level: 'error',
path: './logs/error.log',
},
],
});
logger.info('Server started on port %d', port);
logger.error({ err: error }, 'Request failed');import { Slogger, SyslogSeverities } from '@tundralibs/slogger';
declare const port: number;
declare const error: Error;
const logger = new Slogger({
appName: 'myapp',
level: SyslogSeverities.INFO,
handlers: [
{
name: 'stdout',
type: 'ConsoleHandler',
level: SyslogSeverities.INFO,
formatter: 'json',
},
{
name: 'error-file',
type: 'FileHandler',
level: SyslogSeverities.ERROR,
directory: './logs',
filenameTemplate: 'error.log',
formatter: 'json',
},
],
});
logger.info('Server started on port', { port });
logger.error('Request failed', { err: error.message });| Bunyan | Slogger |
|---|---|
| fatal (60) | emergency |
| error (50) | error |
| warn (40) | warning |
| info (30) | info |
| debug (20) | debug |
| trace (10) | debug |
Log4js is a logging framework inspired by Log4j.
const log4js = require('log4js');
log4js.configure({
appenders: {
file: { type: 'file', filename: 'app.log' },
console: { type: 'console' },
},
categories: {
default: { appenders: ['file', 'console'], level: 'info' },
},
});
const logger = log4js.getLogger();
logger.info('Application started');
logger.error('Error occurred', error);import { Slogger, SyslogSeverities } from '@tundralibs/slogger';
declare const error: Error;
const logger = new Slogger({
appName: 'MyApp',
level: SyslogSeverities.INFO,
handlers: [
{
name: 'file',
type: 'FileHandler',
level: SyslogSeverities.INFO,
directory: './',
filenameTemplate: 'app.log',
formatter: 'json',
},
{
name: 'console',
type: 'ConsoleHandler',
level: SyslogSeverities.INFO,
formatter: 'standard',
},
],
});
logger.info('Application started');
logger.error('Error occurred', { error: error.message });| Log4js | Slogger |
|---|---|
| fatal | emergency |
| error | error |
| warn | warning |
| info | info |
| debug | debug |
| trace | debug |
Deno's standard library logging module.
import * as log from 'https://deno.land/std/log/mod.ts';
await log.setup({
handlers: {
console: new log.handlers.ConsoleHandler('DEBUG'),
file: new log.handlers.FileHandler('INFO', {
filename: './logs/app.log',
formatter: '{datetime} {levelName} {msg}',
}),
},
loggers: {
default: {
level: 'DEBUG',
handlers: ['console', 'file'],
},
},
});
const logger = log.getLogger();
logger.info('Application started');
logger.error('Error occurred', error);import { Slogger, SyslogSeverities } from '@tundralibs/slogger';
declare const error: Error;
const logger = new Slogger({
appName: 'MyApp',
level: SyslogSeverities.DEBUG,
handlers: [
{
name: 'console',
type: 'ConsoleHandler',
level: SyslogSeverities.DEBUG,
formatter: 'standard',
},
{
name: 'file',
type: 'FileHandler',
level: SyslogSeverities.INFO,
directory: './logs',
filenameTemplate: 'app.log',
formatter: 'json',
},
],
});
logger.info('Application started');
logger.error('Error occurred', { error: error.message });- Better TypeScript support
- Cross-runtime compatibility (Deno, Bun, Node.js)
- Built-in sensitive data masking
- HTTP handler for remote logging
- Sampling support for high-volume logs
- Lazy context evaluation
- Better performance
# Deno
deno add @tundralibs/slogger
# Bun
bunx jsr add @tundralibs/slogger
# Node.js
npx jsr add @tundralibs/sloggerReplace your existing logger setup with Slogger configuration.
- Change log method names if needed (e.g.,
warn→warning) - Ensure message is first parameter, context is second
- Use objects for context instead of string concatenation
Refer to level mapping tables above for your previous library.
Map your previous transports/handlers to Slogger handlers:
- Console → ConsoleHandler
- File → FileHandler
- HTTP → HTTPHandler
Choose appropriate Slogger formatters or create custom ones:
- JSON →
'json' - Simple text →
'standard' - Detailed →
'detailed'
Verify logs are being written correctly:
- Check all log levels work
- Verify file rotation
- Test error scenarios
- Confirm context serialization
Take advantage of Slogger-specific features:
- Data masking for sensitive fields
- Sampling for high-volume logs
- Lazy context evaluation
- Multiple concurrent handlers
import type { Slogger } from '@tundralibs/slogger';
declare const logger: Slogger;
declare const userId: string;
declare const ip: string;
// Before
logger.info(`User ${userId} logged in from ${ip}`);
// After
logger.info('User logged in', { userId, ip });// Before
logger.error('Failed:', error);
// After
logger.error('Failed', {
error: error.message,
stack: error.stack,
code: error.code,
});// Before (Winston/Pino child loggers)
const childLogger = logger.child({ component: 'auth' });
childLogger.info('Login attempt');
// After (context-based)
logger.info('Login attempt', { component: 'auth' });
// Or create separate logger instance
const authLogger = new Slogger({
appName: 'MyApp-Auth',
// ... same handlers
});// Before (Winston)
const customFormat = winston.format.printf(({ level, message, timestamp }) => {
return `${timestamp} ${level}: ${message}`;
});
// After (Slogger)
import type { SlogObject } from '@tundralibs/slogger';
function customFormatter(log: SlogObject): string {
return `${log.isoDate} ${log.levelName}: ${log.message}`;
}
const logger = new Slogger({
appName: 'MyApp',
level: SyslogSeverities.INFO,
handlers: [{
name: 'console',
type: 'ConsoleHandler',
level: SyslogSeverities.INFO,
formatter: customFormatter,
}],
});Solution: Check log level configuration. Slogger uses syslog levels (0-7), lower is more severe.
// Set to DEBUG to see all logs
level: SyslogSeverities.DEBUG;Solution: Ensure context is an object, not concatenated to message.
import type { Slogger } from '@tundralibs/slogger';
declare const logger: Slogger;
declare const userId: string;
// ❌ Wrong
logger.info('User: ' + userId);
// ✅ Correct
logger.info('User action', { userId });Solution: Check file permissions and ensure directory exists.
// Slogger creates directories automatically, but check permissions
{
directory: './logs', // Must have write permission
filenameTemplate: 'app.log'
}Solution: Use lazy context evaluation and appropriate log levels.
// Use lazy context for expensive operations
logger.debug('Expensive data', () => ({
data: expensiveCalculation(),
}));
// Raise log level in production
level: isProduction ? SyslogSeverities.INFO : SyslogSeverities.DEBUG;- Configuration - Complete configuration guide
- Examples - Usage examples
- Handlers - Handler details
- Formatters - Formatter details