@bernierllc/logging
Version:
A comprehensive logging package with Winston integration for audit and system logging
382 lines (381 loc) • 13.7 kB
JavaScript
"use strict";
/*
Copyright (c) 2025 Bernier LLC
This file is licensed to the client under a limited-use license.
The client may use and modify this code *only within the scope of the project it was delivered for*.
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.ServiceLoggingManager = void 0;
exports.createServiceLoggingManager = createServiceLoggingManager;
exports.getServiceLoggingManager = getServiceLoggingManager;
exports.resetServiceLoggingManager = resetServiceLoggingManager;
exports.createConfiguredLogger = createConfiguredLogger;
const coreLogger_1 = require("./mocks/coreLogger");
const loadConfiguration_1 = require("./config/loadConfiguration");
const systemLogger_1 = require("./systemLogger");
const auditLogger_1 = require("./auditLogger");
const coreLoggerBridge_1 = require("./coreLoggerBridge");
/**
* Service Logging Manager
*
* This class orchestrates the entire logging service, managing both:
* 1. Core @bernierllc/logger integration with runtime configuration
* 2. Service-level Winston-based system and audit logging
*
* It provides a unified interface that bridges the gap between the
* atomic core logger and the comprehensive service-level logging needs.
*/
class ServiceLoggingManager {
config;
configSources = [];
coreLogger;
systemLogger;
auditLogger;
coreLoggerBridge;
isInitialized = false;
constructor(runtimeConfig) {
// Load configuration with inheritance from core logger
this.initializeConfiguration(runtimeConfig);
}
/**
* Initialize configuration synchronously
*/
initializeConfiguration(runtimeConfig) {
try {
// Load service configuration without core logger first
const { config, sources } = (0, loadConfiguration_1.loadServiceLoggingConfigurationWithSources)();
// Apply runtime configuration overrides
if (runtimeConfig) {
this.mergeConfiguration(config, runtimeConfig);
sources.push({
key: 'runtime-override',
value: runtimeConfig,
source: 'override',
description: 'Runtime configuration override'
});
}
this.config = config;
this.configSources = sources;
}
catch (error) {
console.error('❌ Failed to load logging service configuration:', error);
throw new Error(`Logging service configuration failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
/**
* Load and merge configuration from all sources (async version for core logger integration)
*/
async loadConfigurationWithCoreLogger(runtimeConfig) {
try {
// First, try to get core logger configuration to inherit from
let coreLoggerConfig;
try {
const coreLogger = await (0, coreLogger_1.createLoggerFromConfig)();
coreLoggerConfig = coreLogger.getConfig();
}
catch (error) {
console.warn('⚠️ Could not load core logger configuration, using service defaults');
}
// Load service configuration with core logger inheritance
const { config, sources } = (0, loadConfiguration_1.loadServiceLoggingConfigurationWithSources)(coreLoggerConfig);
// Apply runtime configuration overrides
if (runtimeConfig) {
this.mergeConfiguration(config, runtimeConfig);
sources.push({
key: 'runtime-override',
value: runtimeConfig,
source: 'override',
description: 'Runtime configuration override'
});
}
this.config = config;
this.configSources = sources;
// Log configuration loading transparency
console.log('⚙️ Service Logging: Configuration loaded successfully');
const nonDefaultSources = sources.filter(s => s.source !== 'default');
if (nonDefaultSources.length > 0) {
console.log(' Configuration sources:');
nonDefaultSources.forEach(source => {
console.log(` └── ${source.source}: ${source.description}`);
});
}
}
catch (error) {
console.error('❌ Failed to load logging service configuration:', error);
throw new Error(`Logging service configuration failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
/**
* Initialize the logging service with all configured loggers
*/
async initialize() {
if (this.isInitialized)
return;
try {
// Initialize core logger with service configuration
await this.initializeCoreLogger();
// Initialize service-level loggers
await this.initializeServiceLoggers();
this.isInitialized = true;
console.log('✅ Service Logging: All loggers initialized successfully');
}
catch (error) {
console.error('❌ Failed to initialize logging service:', error);
throw new Error(`Logging service initialization failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
/**
* Initialize core logger with service configuration
*/
async initializeCoreLogger() {
try {
// Create core logger configuration from service configuration
const coreConfig = this.mapServiceConfigToCoreConfig();
// Create core logger bridge
this.coreLoggerBridge = await (0, coreLoggerBridge_1.createCoreSystemLogger)();
this.coreLogger = this.coreLoggerBridge.getCoreLogger();
console.log('✅ Core logger bridge initialized');
}
catch (error) {
console.warn('⚠️ Core logger initialization failed, service will use Winston fallback:', error);
}
}
/**
* Initialize service-level Winston loggers
*/
async initializeServiceLoggers() {
// Initialize system logger
if (this.config.system.enabled) {
this.systemLogger = this.createWinstonSystemLogger();
console.log('✅ Winston system logger initialized');
}
// Initialize audit logger
if (this.config.audit.enabled) {
this.auditLogger = this.createWinstonAuditLogger();
console.log('✅ Winston audit logger initialized');
}
}
/**
* Map service configuration to core logger configuration
*/
mapServiceConfigToCoreConfig() {
return {
level: this.config.level,
enableCorrelation: this.config.enableCorrelation,
sanitize: this.config.sanitize,
sanitizeFields: this.config.sanitizeFields,
context: this.config.context,
transports: {
console: this.config.system.console,
file: this.config.system.file,
http: this.config.system.http
}
};
}
/**
* Create Winston system logger from service configuration
*/
createWinstonSystemLogger() {
const systemConfig = this.config.system;
return (0, systemLogger_1.createSystemLogger)({
level: systemConfig.level,
enableConsole: systemConfig.console?.enabled,
enableFile: systemConfig.file?.enabled,
filePath: systemConfig.file?.filename || './logs/system.log',
maxSize: systemConfig.file?.maxSize?.toString() || '10m',
maxFiles: systemConfig.file?.maxFiles?.toString() || '5',
defaultMeta: {
service: this.config.context.service,
version: this.config.context.version,
environment: this.config.context.environment,
hostname: this.config.context.hostname,
pid: this.config.context.pid
}
});
}
/**
* Create Winston audit logger from service configuration
*/
createWinstonAuditLogger() {
const auditConfig = this.config.audit;
return (0, auditLogger_1.createAuditLogger)({
level: auditConfig.level,
enableConsole: auditConfig.console?.enabled || false,
enableFile: auditConfig.file?.enabled ?? true,
filePath: auditConfig.file?.filename || './logs/audit.log',
defaultMeta: {
service: this.config.context.service,
version: this.config.context.version,
environment: this.config.context.environment,
hostname: this.config.context.hostname,
pid: this.config.context.pid
}
});
}
/**
* Merge configuration objects recursively
*/
mergeConfiguration(target, source) {
Object.keys(source).forEach(key => {
if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
if (!target[key])
target[key] = {};
this.mergeConfiguration(target[key], source[key]);
}
else {
target[key] = source[key];
}
});
}
/**
* Get the core logger instance (preferred for new code)
*/
getCoreLogger() {
return this.coreLogger;
}
/**
* Get the core logger bridge (Winston-compatible interface)
*/
getCoreLoggerBridge() {
return this.coreLoggerBridge;
}
/**
* Get the Winston system logger (legacy compatibility)
*/
getSystemLogger() {
return this.systemLogger;
}
/**
* Get the Winston audit logger
*/
getAuditLogger() {
return this.auditLogger;
}
/**
* Get resolved configuration
*/
getConfiguration() {
return this.config;
}
/**
* Get configuration sources for transparency
*/
getConfigurationSources() {
return [...this.configSources];
}
/**
* Log using the best available logger (core logger preferred, Winston fallback)
*/
log(level, message, metadata) {
if (this.coreLogger) {
this.coreLogger.log(level, message, metadata || {});
}
else if (this.systemLogger) {
this.systemLogger.log(level, message, metadata);
}
else {
console.log(`[${level.toUpperCase()}] ${message}`, metadata);
}
}
/**
* Convenience logging methods
*/
error(message, error, metadata) {
if (error && metadata) {
metadata.error = error.message;
metadata.stack = error.stack;
}
this.log('error', message, metadata);
}
warn(message, metadata) {
this.log('warn', message, metadata);
}
info(message, metadata) {
this.log('info', message, metadata);
}
debug(message, metadata) {
this.log('debug', message, metadata);
}
/**
* Audit logging method
*/
audit(entry) {
const auditEntry = {
...entry,
timestamp: new Date().toISOString(),
service: this.config.context.service,
environment: this.config.context.environment
};
if (this.auditLogger) {
this.auditLogger.info('Audit Event', auditEntry);
}
else if (this.coreLogger) {
this.coreLogger.info('Audit Event', auditEntry);
}
else {
console.log('[AUDIT]', auditEntry);
}
}
/**
* Check if service is initialized
*/
isReady() {
return this.isInitialized;
}
/**
* Shutdown all loggers gracefully
*/
async shutdown() {
console.log('🔄 Service Logging: Shutting down...');
// Close Winston loggers
if (this.systemLogger) {
this.systemLogger.end();
}
if (this.auditLogger) {
this.auditLogger.end();
}
// Core logger cleanup would happen here if needed
console.log('✅ Service Logging: Shutdown complete');
}
}
exports.ServiceLoggingManager = ServiceLoggingManager;
/**
* Global service logging manager instance
*/
let globalServiceLoggingManager = null;
/**
* Create or get the global service logging manager
*/
async function createServiceLoggingManager(runtimeConfig) {
if (!globalServiceLoggingManager) {
globalServiceLoggingManager = new ServiceLoggingManager(runtimeConfig);
await globalServiceLoggingManager.initialize();
}
return globalServiceLoggingManager;
}
/**
* Get the global service logging manager (must be created first)
*/
function getServiceLoggingManager() {
return globalServiceLoggingManager;
}
/**
* Reset global service logging manager (for testing)
*/
function resetServiceLoggingManager() {
globalServiceLoggingManager = null;
}
/**
* Convenience function to create a logger with runtime configuration
*/
async function createConfiguredLogger(runtimeConfig) {
const manager = await createServiceLoggingManager(runtimeConfig);
return {
coreLogger: manager.getCoreLogger(),
systemLogger: manager.getSystemLogger(),
auditLogger: manager.getAuditLogger(),
manager
};
}
//# sourceMappingURL=serviceLoggingManager.js.map