Logger Utilities
Structured logging with Pino. This module provides a robust logging system with features like hierarchical loggers, request-scoped logging, error handling, and sensitive data redaction.
API Summary​
getLogger(newInstance?: boolean): Logger
- Retrieves the current logger instance from the request context or falls back to the global logger.createChildLogger(bindings: Record<string, any>, parentLogger?: Logger): Logger
- Creates a child logger with additional context that will be included in all log entries.createRequestLogger(requestId: string, additionalContext?: Record<string, any>): Logger
- Creates a request-scoped logger with request ID and stores it in the async context.logError(error: Error | unknown, message?: string, context?: Record<string, any>): void
- Utility to safely log errors with proper stack trace extractionresetLogger(): void
- Resets the global logger to its default configuration.getRedactCensor(): (key: string) => boolean
- Gets the current global redaction censor function used for log redaction.setRedactCensor(censor: (key: string) => boolean): void
- Sets the global redaction censor function used throughout the application for log redaction.addRedactFields(fields: string | string[]): void
- Extends the current redaction function with additional fields to redact.setSensitiveFields(fields: string[]): void
- Replaces the default list of sensitive fields with a new list.addSensitiveFields(fields: string | string[]): void
- Adds additional field names to the default sensitive fields list.
Environment Variables​
Environment Variable | Default Value | Description |
---|---|---|
LOGGER_LEVEL | info | Log level for the application |
LOGGER_NAME | process.env.npm_package_name | Name of the logger |
LOGGER_PRETTY | true | Enable pretty logging |
LOGGER_PRETTY_COLORIZE | true | Enable colorized output for pretty-print |
LOGGER_PRETTY_SINGLE_LINE | false | Enable single-line logging |
Interfaces & Types​
// Main logger type (Pino logger)
export type Logger = pino.Logger;
// Logger levels from Pino
export type LoggerLevels = pino.Level; // 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace'
Example Usage​
import { getLogger } from "@catbee/utils";
const logger = getLogger();
// Different log levels
logger.trace("Very detailed info for debugging");
logger.debug("Debugging information");
logger.info("Normal application information");
logger.warn("Warning conditions");
logger.error("Error conditions");
logger.fatal("Critical errors");
// Structured logging with context
logger.info({ userId: "123", action: "login" }, "User logged in");
Function Documentation & Usage Examples​
getLogger()
​
Retrieves the current logger instance from the request context or falls back to the global logger.
Method Signature:
function getLogger(newInstance?: boolean): Logger
Parameters:
newInstance
(optional): Iftrue
, returns a fresh logger instance without any request context or global configuration. Default isfalse
.
Returns:
- The current
Logger
instance, or a new instance ifnewInstance
istrue
.
Example:
import { getLogger } from "@catbee/utils";
// Get current logger (request-scoped if in request context, or global)
const logger = getLogger();
logger.info("App started");
logger.debug({ user: "john" }, "User logged in");
// Create a completely fresh logger instance without request context
const freshLogger = getLogger(true);
freshLogger.info("Logging outside of request context");
createChildLogger()
​
Creates a child logger with additional context that will be included in all log entries.
Method Signature:
function createChildLogger(bindings: Record<string, any>, parentLogger?: Logger): Logger
Parameters:
bindings
: Key-value pairs to include in all log entries from this logger.parentLogger
(optional): The parent logger to derive from. If not provided, uses the global logger.
Returns:
- A new
Logger
instance with the specified bindings.
Example:
import { getLogger, createChildLogger } from "@catbee/utils";
// Create a module-specific logger
const moduleLogger = createChildLogger({ module: "payments" });
moduleLogger.info("Processing payment");
// Child loggers can be nested
const transactionLogger = createChildLogger({
transactionId: "tx_12345"
}, moduleLogger);
transactionLogger.info("Transaction completed");
createRequestLogger()
​
Creates a request-scoped logger with request ID and stores it in the async context.
Method Signature:
function createRequestLogger(requestId: string, additionalContext?: Record<string, any>): Logger
Parameters:
requestId
: Unique identifier for the request (e.g., UUID).additionalContext
(optional): Additional key-value pairs to include in all log entries for this request.
Returns:
- A new
Logger
instance scoped to the request.
Example:
import { createRequestLogger, uuid } from "@catbee/utils";
// In an API request handler:
function handleRequest(req, res) {
const requestId = req.headers['x-request-id'] || uuid();
const logger = createRequestLogger(requestId, {
userId: req.user?.id,
path: req.path
});
logger.info("Request received");
// All subsequent calls to getLogger() in this request will return this logger
}
logError()
​
Utility to safely log errors with proper stack trace extraction.
- If
error
is an instance ofError
, logs its message and stack trace. - If
error
is not anError
, logs it as a stringified value.
Method Signature:
function logError(error: Error | unknown, message?: string, context?: Record<string, any>): void
Parameters:
error
: The error object or any value to log as an error.message
(optional): Additional message to log alongside the error.context
(optional): Additional context to include in the log entry.
Example:
import { logError } from "@catbee/utils";
try {
throw new Error("Something went wrong");
} catch (error) {
logError(error, "Failed during processing", { operation: "dataSync" });
}
// Works with any error type
logError("Invalid input", "Validation error");
resetLogger()
​
Resets the global logger instance to its initial state, removing any custom configurations or child loggers.
Method Signature:
function resetLogger(): void
Example:
import { resetLogger } from "@catbee/utils";
// After modifying logger configuration for tests
afterEach(() => {
resetLogger();
});
Redaction and Security​
getRedactCensor()
​
Gets the current global redaction censor function used for log redaction.
Method Signature:
function getRedactCensor(): (value: unknown, path: string[], sensitiveFields?: string[]) => string
Returns:
- The current redaction censor function.
Example:
import { getRedactCensor } from "@catbee/utils";
const currentCensor = getRedactCensor();
// Use current censor in custom logic
setRedactCensor()
​
Sets the global redaction censor function used throughout the application for log redaction.
Method Signature:
function setRedactCensor(fn: (value: unknown, path: string[], sensitiveFields?: string[]) => string): void
Parameters:
fn
: A function that takes a value, its path in the object, and an optional list of sensitive fields, returning a redacted string.value
: The value to potentially redact.path
: An array representing the path to the value in the object.sensitiveFields
: An optional array of field names considered sensitive.
Example:
import { setRedactCensor } from "@catbee/utils";
// Custom censor that redacts only specific values
setRedactCensor((value, path, sensitiveFields) => {
if (path.includes('password')) return '***';
if (typeof value === 'string' && value.includes('secret')) return '***';
return value as string;
});
addRedactFields()
​
Extends the current redaction function with additional fields to redact.
Method Signature:
function addRedactFields(fields: string[]): void
Parameters:
fields
: An array of field names to add to the redaction list.
Example:
import { addRedactFields } from "@catbee/utils";
// Add custom fields to be redacted in all logs
addRedactFields(['customerId', 'accountNumber', 'ssn']);
setSensitiveFields()
​
Replaces the default list of sensitive fields with a new list.
Method Signature:
function setSensitiveFields(fields: string[]): void
Parameters:
fields
: An array of field names to set as the new sensitive fields list.
Example:
import { setSensitiveFields } from "@catbee/utils";
// Replace default sensitive fields with a custom list
setSensitiveFields(['password', 'ssn', 'creditCard']);
addSensitiveFields()
​
Adds additional field names to the default sensitive fields list.
Method Signature:
function addSensitiveFields(fields: string[]): void
Parameters:
fields
: An array of field names to add to the existing sensitive fields list.
Example:
import { addSensitiveFields } from "@catbee/utils";
// Add domain-specific sensitive fields to the default list
addSensitiveFields(['socialSecurityNumber', 'medicalRecordNumber']);