Files
breedr/server/utils/startupLog.js

177 lines
9.5 KiB
JavaScript
Raw Permalink Normal View History

const os = require('os');
const path = require('path');
const fs = require('fs');
/**
* Startup Log Utility
* Displays comprehensive system information and branding on server start
*/
function getSystemInfo() {
return {
hostname: os.hostname(),
platform: os.platform(),
arch: os.arch(),
nodeVersion: process.version,
cpuCores: os.cpus().length,
totalMemory: (os.totalmem() / 1024 / 1024 / 1024).toFixed(2) + ' GB',
freeMemory: (os.freemem() / 1024 / 1024 / 1024).toFixed(2) + ' GB',
uptime: process.uptime().toFixed(2) + 's'
};
}
function getProcessInfo() {
const memUsage = process.memoryUsage();
return {
pid: process.pid,
heapUsed: (memUsage.heapUsed / 1024 / 1024).toFixed(2) + ' MB',
heapTotal: (memUsage.heapTotal / 1024 / 1024).toFixed(2) + ' MB',
external: (memUsage.external / 1024 / 1024).toFixed(2) + ' MB'
};
}
function checkDirectories(dirs) {
const status = {};
dirs.forEach(({ name, path: dirPath }) => {
status[name] = {
exists: fs.existsSync(dirPath),
path: dirPath,
writable: false
};
// Check write permissions if directory exists
if (status[name].exists) {
try {
fs.accessSync(dirPath, fs.constants.W_OK);
status[name].writable = true;
} catch (err) {
status[name].writable = false;
}
}
});
return status;
}
function getAppVersion() {
try {
const packagePath = path.join(__dirname, '../../package.json');
if (fs.existsSync(packagePath)) {
const pkg = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
return pkg.version || 'unknown';
}
} catch (err) {
// Silently fail
}
return 'unknown';
}
function logStartupBanner(config = {}) {
const {
appName = 'BREEDR',
port = 3000,
environment = 'development',
dataDir = './data',
uploadPath = './uploads',
staticPath = './static',
dbStatus = 'unknown'
} = config;
const version = getAppVersion();
const sysInfo = getSystemInfo();
const procInfo = getProcessInfo();
const timestamp = new Date().toISOString();
const directories = [
{ name: 'Data', path: dataDir },
{ name: 'Uploads', path: uploadPath },
{ name: 'Static', path: staticPath }
];
const dirStatus = checkDirectories(directories);
// ASCII Banner
console.log('\n');
console.log('╔══════════════════════════════════════════════════════════╗');
console.log('║ ║');
console.log('║ ██████╗ ██████╗ ███████╗███████╗██████╗ ██████╗ ║');
console.log('║ ██╔══██╗██╔══██╗██╔════╝██╔════╝██╔══██╗██╔══██╗ ║');
console.log('║ ██████╔╝██████╔╝█████╗ █████╗ ██║ ██║██████╔╝ ║');
console.log('║ ██╔══██╗██╔══██╗██╔══╝ ██╔══╝ ██║ ██║██╔══██╗ ║');
console.log('║ ██████╔╝██║ ██║███████╗███████╗██████╔╝██║ ██║ ║');
console.log('║ ╚═════╝ ╚═╝ ╚═╝╚══════╝╚══════╝╚═════╝ ╚═╝ ╚═╝ ║');
console.log('║ ║');
console.log('║ Dog Breeding Genealogy Management System ║');
console.log('║ ║');
console.log('╚══════════════════════════════════════════════════════════╝');
console.log('');
// Application Info
console.log('┌─────────────────────────────────────────────────────────┐');
console.log('│ 📦 APPLICATION INFO │');
console.log('├─────────────────────────────────────────────────────────┤');
console.log(`│ Version : ${version.padEnd(40)}`);
console.log(`│ Environment : ${environment.padEnd(40)}`);
console.log(`│ Started : ${timestamp.padEnd(40)}`);
console.log(`│ Node.js : ${sysInfo.nodeVersion.padEnd(40)}`);
console.log('└─────────────────────────────────────────────────────────┘');
console.log('');
// Server Configuration
console.log('┌─────────────────────────────────────────────────────────┐');
console.log('│ 🌐 SERVER CONFIGURATION │');
console.log('├─────────────────────────────────────────────────────────┤');
console.log(`│ Port : ${String(port).padEnd(40)}`);
console.log(`│ Access URL : http://localhost:${port}${' '.repeat(27)}`);
console.log(`│ Database : ${dbStatus.padEnd(40)}`);
console.log('└─────────────────────────────────────────────────────────┘');
console.log('');
// Directory Status
console.log('┌─────────────────────────────────────────────────────────┐');
console.log('│ 📁 DIRECTORY STATUS │');
console.log('├─────────────────────────────────────────────────────────┤');
Object.entries(dirStatus).forEach(([name, status]) => {
const statusIcon = status.exists ? (status.writable ? '✓' : '⚠') : '✗';
const statusText = status.exists ? (status.writable ? 'OK' : 'READ-ONLY') : 'MISSING';
console.log(`${statusIcon} ${name.padEnd(10)} : ${statusText.padEnd(10)} ${status.path.substring(0, 25).padEnd(25)}`);
});
console.log('└─────────────────────────────────────────────────────────┘');
console.log('');
// System Resources
console.log('┌─────────────────────────────────────────────────────────┐');
console.log('│ 💻 SYSTEM RESOURCES │');
console.log('├─────────────────────────────────────────────────────────┤');
console.log(`│ Hostname : ${sysInfo.hostname.padEnd(40)}`);
console.log(`│ Platform : ${sysInfo.platform.padEnd(40)}`);
console.log(`│ Architecture : ${sysInfo.arch.padEnd(40)}`);
console.log(`│ CPU Cores : ${String(sysInfo.cpuCores).padEnd(40)}`);
console.log(`│ Total Memory : ${sysInfo.totalMemory.padEnd(40)}`);
console.log(`│ Free Memory : ${sysInfo.freeMemory.padEnd(40)}`);
console.log('└─────────────────────────────────────────────────────────┘');
console.log('');
// Process Info
console.log('┌─────────────────────────────────────────────────────────┐');
console.log('│ ⚙️ PROCESS INFO │');
console.log('├─────────────────────────────────────────────────────────┤');
console.log(`│ PID : ${String(procInfo.pid).padEnd(40)}`);
console.log(`│ Heap Used : ${procInfo.heapUsed.padEnd(40)}`);
console.log(`│ Heap Total : ${procInfo.heapTotal.padEnd(40)}`);
console.log(`│ External : ${procInfo.external.padEnd(40)}`);
console.log(`│ Uptime : ${sysInfo.uptime.padEnd(40)}`);
console.log('└─────────────────────────────────────────────────────────┘');
console.log('');
// Ready message
console.log('🚀 Server is ready and listening for connections');
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log('');
}
module.exports = {
logStartupBanner,
getSystemInfo,
getProcessInfo,
checkDirectories,
getAppVersion
};