@catbee/utils
Version:
A modular, production-grade utility toolkit for Node.js and TypeScript, designed for robust, scalable applications (including Express-based services). All utilities are tree-shakable and can be imported independently.
113 lines • 4.17 kB
JavaScript
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
import pino, { stdTimeFunctions } from "pino";
import { Config } from "../config";
import { ContextStore, StoreKeys } from "./context-store.utils";
/**
* Symbol used to store the root logger in the Node.js global object.
*/
var GLOBAL_LOGGER_KEY = Symbol.for("logger");
/**
* Use an object compatible with either modern or legacy global scopes.
*/
export var _globalThis = typeof globalThis === "object" ? globalThis : global;
var _global = _globalThis;
/**
* Initializes the global root logger according to app configuration.
*
* - Sets log name, level, timestamp, and redaction for sensitive fields.
* - Uses singleton in global symbol registry.
*/
function setupLogger() {
var logParams = {
name: Config.Logger.name,
level: Config.Logger.level,
redact: {
paths: ["req.authorization", "url"],
censor: function (value, path) {
if (path[0] === "url") {
return value.replace(/access_token=[a-zA-Z0-9_-]*/, "access_token=***");
}
else if (path[1] === "authorization") {
return value.replace(/\s+(\S+)$/, " ***");
}
return "***";
},
},
};
if (Config.Logger.isoTimestamp) {
logParams.timestamp = stdTimeFunctions.isoTime;
}
_global[GLOBAL_LOGGER_KEY] = pino(logParams);
_global[GLOBAL_LOGGER_KEY].debug("Logger initialized");
}
/**
* Retrieves the current logger instance:
* - Returns a request-scoped logger from AsyncLocalStorage if available
* - Falls back to the global (singleton) logger
* - Initializes the global logger if not created yet
*
* @returns {Logger} The logger instance (request-bound or global root logger)
*/
export function getLogger() {
var logger = ContextStore.get(StoreKeys.LOGGER);
if (logger)
return logger;
if (!_global[GLOBAL_LOGGER_KEY]) {
setupLogger();
}
return _global[GLOBAL_LOGGER_KEY];
}
/**
* Creates a child logger with additional context.
*
* @param {Record<string, any>} bindings - Properties to attach to all log records
* @param {Logger} [parentLogger] - Parent logger (defaults to current context logger or global)
* @returns {Logger} Child logger with merged context
*/
export function createChildLogger(bindings, parentLogger) {
var logger = parentLogger || getLogger();
return logger.child(bindings);
}
/**
* Creates a request-scoped logger with request ID and stores it in context
*
* @param {string} requestId - Unique request identifier
* @param {object} [additionalContext] - Additional context to include in logs
* @returns {Logger} Request-scoped logger instance
*/
export function createRequestLogger(requestId, additionalContext) {
if (additionalContext === void 0) { additionalContext = {}; }
var logger = createChildLogger(__assign({ requestId: requestId }, additionalContext));
try {
ContextStore.set(StoreKeys.LOGGER, logger);
}
catch (_a) {
// Context not initialized, can't store logger
logger.debug("Failed to store logger in context - AsyncLocalStorage not initialized");
}
return logger;
}
/**
* Utility to safely log errors with proper stack trace extraction
*
* @param {Error|unknown} error - Error object to log
* @param {string} [message] - Optional message to include
* @param {Record<string, any>} [context] - Additional context properties
*/
export function logError(error, message, context) {
var logger = getLogger();
var errObj = error instanceof Error ? error : new Error(String(error));
var logContext = __assign(__assign({}, context), { err: errObj });
logger.error(logContext, message || errObj.message);
}
//# sourceMappingURL=logger.utils.js.map