agmission/Development/server/helpers/logger.js

175 lines
4.6 KiB
JavaScript

'use strict';
/**
* Pino Logger for Partner Operations
* High-performance, structured logging with minimal overhead
*/
const pino = require('pino');
// Environment-based module filtering with wildcard support
const activeModules = process.env.LOG_MODULES ?
process.env.LOG_MODULES.split(',').map(m => m.trim()) : ['*'];
/**
* Check if a module should log based on LOG_MODULES environment variable
* Supports wildcards: 'partner*', 'satloc*', etc.
* Examples:
* - LOG_MODULES=* (log all modules)
* - LOG_MODULES=partner_controller,satloc_service
* - LOG_MODULES=partner*,redis*
* - LOG_MODULES=partner_controller,satloc*
*/
function shouldLog(moduleName) {
if (!moduleName) return true;
return activeModules.includes('*') ||
activeModules.includes(moduleName) ||
activeModules.some(pattern => {
if (pattern.endsWith('*')) {
return moduleName.startsWith(pattern.slice(0, -1));
}
return false;
});
}
// Create Pino logger instance
const logger = pino({
name: 'agm-partner-system',
level: process.env.LOG_LEVEL || 'info',
...(process.env.NODE_ENV !== 'production' && {
transport: {
target: 'pino-pretty',
options: {
colorize: process.env.PINO_COLORIZE === 'true' || process.env.PINO_COLORIZE == 1,
ignore: 'pid,hostname',
translateTime: 'SYS:standard'
}
}
}),
...(process.env.NODE_ENV === 'production' && {
formatters: {
time: () => `,"time":"${new Date().toISOString()}"`
}
})
});
class SimpleLogger {
constructor() {
this.logger = logger;
}
/**
* Create a child logger for a specific module
* @param {string} moduleName - Name of the module
* @returns {object} Child logger instance with filtering
*/
child(moduleName) {
const childLogger = this.logger.child({ module: moduleName });
// Add filtering wrapper
return this._createFilteredLogger(childLogger, moduleName);
}
/**
* Create a module-specific logger (alternative syntax)
* @param {string} moduleName - Name of the module
* @returns {object} Child logger instance with filtering
*/
module(moduleName) {
return this.child(moduleName);
}
/**
* Create a filtered logger that respects LOG_MODULES environment variable
* @private
*/
_createFilteredLogger(logger, moduleName) {
const isEnabled = shouldLog(moduleName);
return {
trace: isEnabled ? logger.trace.bind(logger) : () => { },
debug: isEnabled ? logger.debug.bind(logger) : () => { },
info: isEnabled ? logger.info.bind(logger) : () => { },
warn: isEnabled ? logger.warn.bind(logger) : () => { },
error: isEnabled ? logger.error.bind(logger) : () => { },
fatal: isEnabled ? logger.fatal.bind(logger) : () => { },
child: (bindings) => this._createFilteredLogger(logger.child(bindings), moduleName),
// Add convenience methods
enabled: isEnabled,
moduleName: moduleName
};
}
/**
* Log partner operations (success/failure)
* @param {string} operation - Operation name
* @param {string} partner - Partner code
* @param {boolean} success - Whether operation succeeded
* @param {object} metadata - Additional metadata
*/
logPartnerOperation(operation, partner, success, metadata = {}) {
const logData = {
operation,
partner,
success,
...metadata
};
if (success) {
this.logger.info(logData, 'Partner operation completed');
} else {
this.logger.error(logData, 'Partner operation failed');
}
}
/**
* Log critical errors
* @param {Error} error - Error object
* @param {object} context - Error context
*/
logError(error, context = {}) {
this.logger.error({
err: error,
context
}, 'Partner system error');
}
/**
* Log sync activities
* @param {string} customerId - Customer ID
* @param {string} partner - Partner ID
* @param {string} operation - Sync operation
* @param {string} status - Operation status
* @param {object} metadata - Additional metadata
*/
logSync(customerId, partner, operation, status, metadata = {}) {
this.logger.info({
customerId,
partner,
operation,
status,
...metadata
}, 'Partner sync activity');
}
/**
* Log assignment activities
* @param {string} jobId - Job ID
* @param {string} userId - User ID
* @param {string} status - Assignment status
* @param {object} metadata - Additional metadata
*/
logAssignment(jobId, userId, status, metadata = {}) {
this.logger.info({
jobId,
userId,
status,
...metadata
}, 'Job assignment');
}
}
module.exports = new SimpleLogger();