Logging Service
Effective logging is crucial for understanding application behavior and debugging issues. @elsikora/cladi provides a flexible logging system through the ILogger interface and a ready-to-use ConsoleLoggerService.
ILogger Interface
This defines the standard contract for any logger implementation. It includes methods for different severity levels:
// Located in: src/domain/interface/logger/interface.ts
export interface ILogger {
debug(message: string, options?: ILoggerMethodOptions): void;
error(message: string, options?: ILoggerMethodOptions): void;
info(message: string, options?: ILoggerMethodOptions): void;
trace(message: string, options?: ILoggerMethodOptions): void;
warn(message: string, options?: ILoggerMethodOptions): void;
}
// Located in: src/domain/interface/logger/method-options.interface.ts
export interface ILoggerMethodOptions {
/** Additional structured data to include with the log entry */
context?: Record<string, unknown>;
/** Overrides the default logger source for this specific message */
source?: string;
}- Levels:
trace(most verbose),debug,info,warn,error(least verbose). - Options: Allow passing extra
context(like user ID, request details) and overriding thesourceidentifier for specific messages.
ILoggerMethodOptions
These options can be passed to individual logger methods (.debug(), .info(), etc.) to provide additional context or override the default source for that specific log entry.
| Name | Type | Default |
|---|---|---|
context | Record<string, unknown>Optional context to include with the log. | |
source | stringOptional source identifier (e.g. “React”, “NestJS Scheduler”). |
ConsoleLoggerService
This is the default implementation provided, suitable for most Node.js and browser environments. It logs messages to the standard console (console.debug, console.info, etc.).
Key Features:
- Configurable Level: Set the minimum log level via
IConsoleLoggerOptions. Messages below this level are ignored. - Timestamping: Automatically adds an ISO timestamp.
- Level Display: Clearly shows the log level (e.g.,
[INFO]). - Source Identification: Includes a source tag (e.g.,
[AuthService],[App -> DataProcessor]) for easier filtering and context. - Structured Context: Appends the
contextobject as a formatted JSON string.
Constructor Options (IConsoleLoggerOptions)
These options are passed to the createLogger utility or the ConsoleLoggerService constructor to configure the logger instance.
| Name | Type | Default |
|---|---|---|
level | ELoggerLogLevelThe log level to use. | ELoggerLogLevel.INFO |
source | stringThe source to use for the logger. |
Example Usage:
import { createLogger, ELoggerLogLevel, type ILogger } from '@elsikora/cladi';
// Create a logger instance
const logger: ILogger = createLogger({
level: ELoggerLogLevel.DEBUG, // Show debug, info, warn, error
source: "MainApp", // Default source for this logger
});
logger.info("Application setup initiated.");
function processUser(userId: number) {
logger.debug("Starting user processing", {
source: "UserProcessor", // Override default source
context: { userId },
});
try {
// Simulate some work
if (userId === 0) {
throw new Error("Invalid user ID");
}
logger.info("User processed successfully", {
source: "UserProcessor",
context: { userId, status: "completed" },
});
} catch (error) {
logger.error("Error processing user", {
source: "UserProcessor",
context: { userId, errorMsg: (error as Error).message },
// If using BaseError, you might log error.CODE or error.context here too
});
}
}
processUser(123);
processUser(0); // This will trigger the error log
logger.trace("Detailed trace message - only shown if level is TRACE"); // Won't show with DEBUG levelOutput Example (Conceptual):
[2023-10-27T10:00:00.000Z] INFO: [MainApp] Application setup initiated.
[2023-10-27T10:00:00.001Z] DEBUG: [MainApp -> UserProcessor] Starting user processing {"userId":123}
[2023-10-27T10:00:00.002Z] INFO: [MainApp -> UserProcessor] User processed successfully {"userId":123,"status":"completed"}
[2023-10-27T10:00:00.003Z] DEBUG: [MainApp -> UserProcessor] Starting user processing {"userId":0}
[2023-10-27T10:00:00.004Z] ERROR: [MainApp -> UserProcessor] Error processing user {"userId":0,"errorMsg":"Invalid user ID"}Creating Loggers (createLogger Utility)
The easiest way to get a ConsoleLoggerService instance is via the createLogger helper:
import { createLogger, ELoggerLogLevel } from '@elsikora/cladi';
// Logger with default level (INFO) and no source
const infoLogger = createLogger();
// Logger showing all messages, with a default source
const debugLogger = createLogger({
level: ELoggerLogLevel.TRACE,
source: "MyDebugModule",
});Integrating with Dependency Injection
Typically, you create a logger instance early in your application setup and register it with the Container using EServiceToken.LOGGER. Other services can then receive the logger via constructor injection.