snes-disassembler
Version:
A Super Nintendo (SNES) ROM disassembler for 65816 assembly
244 lines • 8.44 kB
JavaScript
;
/**
* Central Logger Configuration for SNES Disassembler
*
* Provides a robust logging system using Pino with:
* - Environment-specific configuration
* - Structured logging with context
* - Performance tracking
* - File and console output
* - Log rotation support
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Logger = void 0;
exports.createLogger = createLogger;
exports.logApplicationStartup = logApplicationStartup;
exports.logApplicationShutdown = logApplicationShutdown;
exports.measurePerformance = measurePerformance;
const pino_1 = __importDefault(require("pino"));
const perf_hooks_1 = require("perf_hooks");
// Log levels enum for type safety
var LogLevel;
(function (LogLevel) {
LogLevel["FATAL"] = "fatal";
LogLevel["ERROR"] = "error";
LogLevel["WARN"] = "warn";
LogLevel["INFO"] = "info";
LogLevel["DEBUG"] = "debug";
LogLevel["TRACE"] = "trace";
})(LogLevel || (LogLevel = {}));
// Default configuration based on environment
const getDefaultConfig = () => {
const isDevelopment = process.env.NODE_ENV !== 'production';
const logLevel = process.env.LOG_LEVEL || (isDevelopment ? LogLevel.DEBUG : LogLevel.INFO);
return {
level: logLevel,
prettyPrint: isDevelopment,
timestamp: true,
fileOutput: {
enabled: !isDevelopment,
filepath: './logs/snes-disassembler.log',
maxSize: '10M',
maxFiles: 5
}
};
};
// Create the main logger instance
const config = getDefaultConfig();
const pinoConfig = {
level: config.level,
timestamp: config.timestamp ? pino_1.default.stdTimeFunctions.isoTime : false,
formatters: {
level: (label) => {
return { level: label };
}
},
serializers: {
error: pino_1.default.stdSerializers.err,
req: pino_1.default.stdSerializers.req,
res: pino_1.default.stdSerializers.res
}
};
// Add pretty printing for development
if (config.prettyPrint) {
pinoConfig.transport = {
target: 'pino-pretty',
options: {
colorize: true,
translateTime: 'yyyy-mm-dd HH:MM:ss',
ignore: 'pid,hostname',
messageFormat: '[{component}] {msg}',
errorLikeObjectKeys: ['err', 'error']
}
};
}
// Create base logger
const baseLogger = (0, pino_1.default)(pinoConfig);
// Enhanced logger class with additional functionality
class Logger {
constructor(component, parentLogger) {
this.performanceTrackers = new Map();
this.component = component;
this.logger = (parentLogger ?? baseLogger).child({ component });
}
// Basic logging methods
fatal(message, data) {
this.logger.fatal(data, message);
}
error(message, error) {
if (error instanceof Error) {
this.logger.error({ err: error }, message);
}
else {
this.logger.error(error, message);
}
}
warn(message, data) {
this.logger.warn(data, message);
}
info(message, data) {
this.logger.info(data, message);
}
debug(message, data) {
this.logger.debug(data, message);
}
trace(message, data) {
this.logger.trace(data, message);
}
// Performance tracking methods
startPerformanceTracking(operation, metadata) {
const trackingId = `${operation}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
const context = {
operation,
startTime: perf_hooks_1.performance.now(),
metadata
};
this.performanceTrackers.set(trackingId, context);
this.debug(`Started performance tracking for ${operation}`, { trackingId, metadata });
return trackingId;
}
endPerformanceTracking(trackingId, additionalData) {
const context = this.performanceTrackers.get(trackingId);
if (!context) {
this.warn('Performance tracking context not found', { trackingId });
return null;
}
const endTime = perf_hooks_1.performance.now();
const duration = endTime - context.startTime;
this.info(`Completed ${context.operation}`, {
duration: `${duration.toFixed(2)}ms`,
trackingId,
metadata: context.metadata,
...additionalData
});
this.performanceTrackers.delete(trackingId);
return duration;
}
// ROM processing specific methods
logROMInfo(romPath, size, checksum) {
this.info('ROM loaded successfully', {
path: romPath,
sizeBytes: size,
sizeKB: Math.round(size / 1024),
checksum
});
}
logDisassemblyProgress(address, instruction, progress) {
this.debug('Disassembling instruction', {
address: `0x${address.toString(16).toUpperCase()}`,
instruction,
progress: progress ? `${progress.toFixed(1)}%` : undefined
});
}
logAnalysisResult(analysisType, result) {
this.info(`Analysis completed: ${analysisType}`, result);
}
// Audio processing specific methods
logAudioProcessing(operation, sampleRate, channels, duration) {
this.info(`Audio processing: ${operation}`, {
sampleRate,
channels,
durationMs: duration
});
}
logBRRDecoding(blockCount, sampleCount, compressionRatio) {
this.info('BRR decoding completed', {
blocks: blockCount,
samples: sampleCount,
compressionRatio: compressionRatio ? `${compressionRatio.toFixed(2)}:1` : undefined
});
}
// Error handling with context
logErrorWithContext(error, context, additionalData) {
this.error(`Error in ${context}`, {
err: error,
context,
stack: error.stack,
...additionalData
});
}
// Memory usage logging
logMemoryUsage(operation) {
const memUsage = process.memoryUsage();
this.debug('Memory usage', {
operation,
heapUsed: `${Math.round(memUsage.heapUsed / 1024 / 1024)}MB`,
heapTotal: `${Math.round(memUsage.heapTotal / 1024 / 1024)}MB`,
external: `${Math.round(memUsage.external / 1024 / 1024)}MB`,
rss: `${Math.round(memUsage.rss / 1024 / 1024)}MB`
});
}
// Create child logger for sub-components
child(childComponent) {
return new Logger(`${this.component}:${childComponent}`, this.logger);
}
// Get the underlying Pino logger for advanced usage
getPinoLogger() {
return this.logger;
}
}
exports.Logger = Logger;
// Create and export the main application logger
const mainLogger = new Logger('SNES-Disassembler');
// Factory function to create component-specific loggers
function createLogger(component) {
return new Logger(component);
}
// Utility functions for application lifecycle logging
function logApplicationStartup(version, config) {
mainLogger.info('🚀 SNES Disassembler starting up', {
version,
nodeVersion: process.version,
platform: process.platform,
arch: process.arch,
config
});
}
function logApplicationShutdown(exitCode = 0) {
mainLogger.info('🛑 SNES Disassembler shutting down', { exitCode });
}
// Performance measurement decorator
function measurePerformance(logger, operation) {
return function (target, propertyName, descriptor) {
const method = descriptor.value;
descriptor.value = async function (...args) {
const trackingId = logger.startPerformanceTracking(`${target.constructor.name}.${propertyName}`, {
operation,
arguments: args.length
});
try {
const result = await method.apply(this, args);
logger.endPerformanceTracking(trackingId, { success: true });
return result;
}
catch (error) {
logger.endPerformanceTracking(trackingId, { success: false, error: error instanceof Error ? error.message : String(error) });
throw error;
}
};
};
}
//# sourceMappingURL=logger.js.map