Logging for TypeScript: Best Solutions
Logging is a critical component of any production application. For the TypeScript ecosystem, there are many libraries, each offering a unique set of features. In this article, we will look at five best solutions: Winston, Pino, Bunyan, Log4js, and TSLog. You will learn their strengths, configuration specifics, and get ready-made code examples.
1. Winston — The Universal Standard
Winston is the most popular logging library for Node.js with full TypeScript support. It provides a powerful system of transports (where to send logs) and formatting.
import winston from 'winston';
const logger = winston.createLogger({ level: 'info', format: winston.format.combine( winston.format.timestamp(), winston.format.json() ), transports: [ new winston.transports.Console(), new winston.transports.File({ filename: 'error.log', level: 'error' }) ]});
logger.info('Application started', { service: 'user-service' });logger.error('Database connection error', { error: err.message });Advantages:
- Flexible transport system (files, console, HTTP, MongoDB, Elasticsearch)
- Built-in log rotation support via winston-daily-rotate-file
- Excellent TypeScript integration — full typing
- Compatibility with profilers and APM systems
2. Pino — Ultra-Fast Logger
Pino is performance-oriented — it is 5-10 times faster than Winston. An ideal choice for high-load systems and microservices.
import pino from 'pino';
const logger = pino({ level: process.env.LOG_LEVEL || 'info', transport: { target: 'pino-pretty', options: { colorize: true } }});
logger.info({ user: { id: 123 } }, 'User authorized');Key Features:
- Minimal CPU and memory consumption
- Native support for Node.js streams
- Efficient object serialization
- Support for child loggers for contextual logging
3. Bunyan — Structured Logging from Joyent
Bunyan was created for working with microservice architecture. All logs are output in JSON format, simplifying their parsing and analysis.
import bunyan from 'bunyan';
const logger = bunyan.createLogger({ name: 'myapp', level: 'info', serializers: { req: bunyan.stdSerializers.req, err: bunyan.stdSerializers.err }});
logger.info({ req: request }, 'Incoming request');Features:
- Built-in serializers for HTTP requests and errors
- Support for ringbuffer to store the last N records
- Bunyan CLI utility for formatted console output
- Easy integration with the ELK stack
4. Log4js — Familiar Approach from Java
Log4js is a port of the popular Java framework Log4j. It offers familiar configuration through levels and appenders.
import log4js from 'log4js';
log4js.configure({ appenders: { out: { type: 'stdout' }, app: { type: 'file', filename: 'application.log' } }, categories: { default: { appenders: ['out', 'app'], level: 'debug' } }});
const logger = log4js.getLogger();logger.debug('Connection debugging');logger.error('Critical error');Strengths:
- Flexible category and filter system
- Support for multiple appenders (files, databases, TCP)
- Ability to override levels for different modules
- Built-in clustering support
5. TSLog — Lightweight Solution for TypeScript
TSLog is a minimalistic library written specifically for TypeScript. It is ideal for non-
Also in library
Machine Learning in Rust: Overview of Libraries for ML and Data Science
Sending SMS in Java: Overview and Examples of Using API Libraries (Twilio, Nexmo)
Working with Images in Swift: resize and crop for iOS/macOS
Email Sending in JavaScript (Node.js) — Libraries and Code Examples