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 thesource
identifier 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 | string Optional 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
context
object 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 | ELoggerLogLevel The log level to use. | ELoggerLogLevel.INFO |
source | string The 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 level
Output 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.