@decaf-ts/logging
v0.10.13
Published
simple winston inspired wrapper for cross lib logging
Readme
Logging Library (decaf-ts/logging)
Decaf’s logging toolkit keeps one fast MiniLogger at the core while exposing adapters, filters, and utilities that fit both browser and Node.js runtimes:
- Configure once through
Logging.setConfigor theEnvironmentaccumulator and let impersonated child loggers inherit overrides without allocations. - Apply filter chains, transports, and adapter-specific features (Pino, Winston, custom factories) through the shared
LoggingConfigcontract. - Instrument classes using decorators,
LoggedClass, andLogging.becausewhile StopWatch, text/time utilities, and environment helpers round out the diagnostics surface.
Core Concepts
Logging: A static class for managing global logging configuration and creating logger instances.MiniLogger: A lightweight, default logger implementation.LoggedClass: An abstract base class that provides a pre-configured logger instance to its subclasses.LoggedEnvironment: A class for managing environment-specific logging configurations.- Decorators: A set of decorators (
@log,@benchmark, etc.) for easily adding logging and benchmarking to your methods. - Filters and Transports: A system for filtering sensitive information and transporting logs to different destinations.
- Pino and Winston Integration: Built-in support for two popular logging libraries, Pino and Winston.
Documentation available here
Minimal size: 6.2 KB kb gzipped
Logging Library — Detailed Description
The logging package is a lightweight, extensible logging solution for TypeScript projects. It centers on two main constructs:
- MiniLogger — a minimal, context-aware logger used by default.
- Logging — a static facade that manages global configuration, creates loggers for classes/functions/strings, and applies optional theming.
It also offers:
- A concise set of decorators (log, debug, info, verbose, silly) to instrument methods with consistent logging and optional benchmarking.
- Pluggable factories so that alternate implementations (e.g., WinstonLogger) can be used without changing call sites.
- Strong typing for configuration and theming primitives.
Core files and their roles
src/types.ts: Type definitions and contracts
- Logger: the runtime contract with methods silly, verbose, info, debug, error, for, setConfig.
- LoggingConfig: runtime configuration for filtering, formatting, and styling.
- LoggerFactory: factory signature returning a Logger for a given context and optional config.
- Theme/ThemeOption/ThemeOptionByLogLevel: shape of color and style configuration, optionally varying by LogLevel.
- Additional helpers: StringLike, AnyFunction, Class, LoggingContext.
src/constants.ts: Defaults and enums
- LogLevel: error | info | verbose | debug | silly (string values), plus NumericLogLevels for filtering.
- LoggingMode: RAW | JSON (current implementation focuses on RAW; JSON is available for adapters like Winston).
- DefaultTheme: sensible default colors/styles per component and per log level.
- DefaultLoggingConfig: default global configuration (info level, no styling, timestamp on, etc.).
src/logging.ts: Implementations and static facade
- MiniLogger: A small, dependency-light logger that:
- Generates formatted log strings (timestamp, log level, context, correlation id, message, stack) according to config.
- Supports child loggers via .for(method|config) with a Proxy to overlay per-child config and extend the context (class.method).
- Emits to console.log/console.debug/console.error based on level. Verbosity controls .silly output (gated by config.verbose).
- Logging: The static entry point that:
- Holds global configuration (Logging.getConfig(), Logging.setConfig()).
- Creates loggers for arbitrary contexts (Logging.for(object|class|function|string, config?)).
- Provides convenience static logging methods (info, debug, error, verbose, silly) delegating to a global logger instance.
- Supports theming (Logging.theme) by applying Theme options through styled-string-builder when style=true.
- Allows replacing the logger factory (Logging.setFactory) to integrate with other backends (e.g., Winston).
- MiniLogger: A small, dependency-light logger that:
src/decorators.ts: Method decorators
- log(level=info, benchmark=false, verbosity=0): wraps a method to emit a call log and optionally a completion time; supports Promise-returning methods.
- debug/info/silly/verbose: concise wrappers around log() for common patterns.
src/LoggedClass.ts: Base convenience class
- LoggedClass exposes a protected this.log getter returning a context-aware Logger built via Logging.for(this), simplifying logging inside class methods.
src/winston/winston.ts: Optional Winston adapter
- WinstonLogger: extends MiniLogger but delegates emission to a configured Winston instance.
- WinstonFactory: a LoggerFactory you can install with Logging.setFactory(WinstonFactory) to globally route logs through Winston.
Design principles
- Minimal by default: Console output with small surface area and no heavy dependencies (except styled-string-builder when style is enabled).
- Config-driven: Behavior (level thresholds, verbosity, timestamps, separators, theming) is controlled via LoggingConfig.
- Context-first: Log context is explicit ("MyClass" or "MyClass.method"), aiding filtering and debugging.
- Extensible: Swap logger implementations via a factory; MiniLogger serves as a reference implementation.
- Safe theming: Logging.theme guards against invalid theme keys and values and logs errors instead of throwing.
Key behaviors
- Level filtering: NumericLogLevels are used to compare configured level with the message level and decide emission.
- Verbosity: .silly obeys LoggingConfig.verbose; only messages with <= configured verbosity are emitted.
- Theming and styling: When style=true, Logging.theme applies Theme rules per component (class, message, logLevel, id, stack, timestamp). Theme can vary per LogLevel via ThemeOptionByLogLevel.
- Correlation IDs: If correlationId is configured in a logger or child logger, it is included in output for easier traceability.
Public API surface
- Classes: MiniLogger, Logging, LoggedClass; WinstonLogger (optional).
- Decorators: log, debug, info, verbose, silly.
- Enums/Consts: LogLevel, LoggingMode, NumericLogLevels, DefaultTheme, DefaultLoggingConfig.
- Types: Logger, LoggingConfig, LoggerFactory, Theme, ThemeOption, ThemeOptionByLogLevel, LoggingContext.
Intended usage
- Use Logging.setConfig() at application startup to set level/style/timestamps.
- Create class- or method-scoped loggers via Logging.for(MyClass) or logger.for('method').
- Adopt LoggedClass to remove boilerplate in classes.
- Add decorators to methods for automatic call/benchmark logs.
- For advanced deployments, swap to WinstonFactory.
How to Use
This guide provides examples of how to use the main features of the @decaf-ts/logging library.
Initial Configuration
You can set the initial logging configuration using Logging.setConfig().
import { Logging, LogLevel } from '@decaf-ts/logging';
Logging.setConfig({
level: LogLevel.debug,
style: true,
timestamp: true,
});Impersonation Mechanism
The logging framework uses a proxy-based impersonation mechanism to create child loggers. This provides a significant performance gain by avoiding the need to create new logger instances for each context.
import { Logging } from '@decaf-ts/logging';
const rootLogger = Logging.get();
const childLogger = rootLogger.for('MyClass');
// childLogger is a proxy that inherits the configuration of rootLogger
childLogger.info('This is a message from the child logger');Filters
Filters allow you to process log messages before they are written. You can use them to filter out sensitive information.
import { Logging, PatternFilter } from '@decaf-ts/logging';
// Filter out passwords
const passwordFilter = new PatternFilter(/password/i, '********');
Logging.setConfig({
filters: [passwordFilter],
});
const logger = Logging.get();
logger.info('User logged in with password: mysecretpassword');
// Output will be: User logged in with password: ********Transports
Transports are responsible for writing log messages to a destination. The library includes a default console transport, and you can create your own.
Note: The library currently focuses on filters and logger implementation, with transport-like functionality being a feature of the underlying adapters (Pino, Winston).
Pino and Winston Integration
The library includes built-in support for Pino and Winston.
Pino
import { Logging } from '@decaf-ts/logging';
import { pino } from 'pino';
import { PinoLogFactory } from '@decaf-ts/logging/pino';
const pinoInstance = pino();
Logging.setFactory(new PinoLogFactory(pinoInstance));
const logger = Logging.get();
logger.info('This message will be logged by Pino');Winston
import { Logging } from '@decaf-ts/logging';
import * as winston from 'winston';
import { WinstonLogFactory } from '@decaf-ts/logging/winston';
const winstonInstance = winston.createLogger({
transports: [new winston.transports.Console()],
});
Logging.setFactory(new WinstonLogFactory(winstonInstance));
const logger = Logging.get();
logger.info('This message will be logged by Winston');LoggedEnvironment
The LoggedEnvironment class allows you to manage environment-specific logging configurations.
import { LoggedEnvironment } from '@decaf-ts/logging';
// Set the application name
LoggedEnvironment.app = 'MyAwesomeApp';
// Accumulate additional environment configuration
LoggedEnvironment.accumulate({
database: {
host: 'localhost',
port: 5432,
},
});LoggedClass
The LoggedClass is an abstract base class that provides a pre-configured logger instance to its subclasses.
import { LoggedClass } from '@decaf-ts/logging';
class MyService extends LoggedClass {
doSomething() {
this.log.info('Doing something...');
}
}
const service = new MyService();
service.doSomething();Decorators
The library provides a set of decorators for easily adding logging and benchmarking to your methods.
@log
import { log, LogLevel } from '@decaf-ts/logging';
class MyDecoratedService {
@log(LogLevel.info)
myMethod(arg1: string) {
// ...
}
}@benchmark
import { benchmark } from '@decaf-ts/logging';
class MyBenchmarkedService {
@benchmark()
myLongRunningMethod() {
// ...
}
}Related
Social
Languages
Getting help
If you have bug reports, questions or suggestions please create a new issue.
Contributing
I am grateful for any contributions made to this project. Please read this to get started.
Supporting
The first and easiest way you can support it is by Contributing. Even just finding a typo in the documentation is important.
Financial support is always welcome and helps keep both me and the project alive and healthy.
So if you can, if this project in any way. either by learning something or simply by helping you save precious time, please consider donating.
License
This project is released under the MIT License.
By developers, for developers...
