fix(logger): Replace direct console logging with unified logger interface for consistent formatting

This commit is contained in:
Philipp Kunz 2025-03-26 22:28:38 +00:00
parent 03056d279d
commit f3de3f0618
9 changed files with 157 additions and 106 deletions

View File

@ -1,5 +1,13 @@
# Changelog # Changelog
## 2025-03-26 - 2.6.15 - fix(logger)
Replace direct console logging with unified logger interface for consistent formatting
- Substitute console.log, console.error, and related calls with logger methods in cli, daemon, systemd, nupst, and index modules
- Integrate logBox formatting for structured output and consistent log presentation
- Update test expectations in test.logger.ts to check for standardized error messages
- Refactor logging calls throughout the codebase for improved clarity and maintainability
## 2025-03-26 - 2.6.14 - fix(systemd) ## 2025-03-26 - 2.6.14 - fix(systemd)
Shorten closing log divider in systemd service installation output for consistent formatting. Shorten closing log divider in systemd service installation output for consistent formatting.

View File

@ -53,16 +53,19 @@ tap.test('should handle width persistence between logbox calls', async () => {
tap.test('should throw error when using logBoxLine without width', async () => { tap.test('should throw error when using logBoxLine without width', async () => {
let errorThrown = false; let errorThrown = false;
let errorMessage = '';
try { try {
// Should throw because no width is set // Should throw because no width is set
logger.logBoxLine('This should fail'); logger.logBoxLine('This should fail');
} catch (error) { } catch (error) {
errorThrown = true; errorThrown = true;
expect((error as Error).message).toContain('No box width specified'); errorMessage = (error as Error).message;
} }
expect(errorThrown).toBeTruthy(); expect(errorThrown).toBeTruthy();
expect(errorMessage).toBeTruthy();
expect(errorMessage.includes('No box width')).toBeTruthy();
}); });
tap.test('should create a complete logbox in one call', async () => { tap.test('should create a complete logbox in one call', async () => {

View File

@ -3,6 +3,6 @@
*/ */
export const commitinfo = { export const commitinfo = {
name: '@serve.zone/nupst', name: '@serve.zone/nupst',
version: '2.6.14', version: '2.6.15',
description: 'Node.js UPS Shutdown Tool for SNMP-enabled UPS devices' description: 'Node.js UPS Shutdown Tool for SNMP-enabled UPS devices'
} }

View File

@ -3,6 +3,7 @@ import { promises as fs } from 'fs';
import { dirname, join } from 'path'; import { dirname, join } from 'path';
import { fileURLToPath } from 'url'; import { fileURLToPath } from 'url';
import { Nupst } from './nupst.js'; import { Nupst } from './nupst.js';
import { logger } from './logger.js';
/** /**
* Class for handling CLI commands * Class for handling CLI commands

View File

@ -4,6 +4,7 @@ import { exec, execFile } from 'child_process';
import { promisify } from 'util'; import { promisify } from 'util';
import { NupstSnmp } from './snmp/manager.js'; import { NupstSnmp } from './snmp/manager.js';
import type { ISnmpConfig } from './snmp/types.js'; import type { ISnmpConfig } from './snmp/types.js';
import { logger } from './logger.js';
const execAsync = promisify(exec); const execAsync = promisify(exec);
const execFileAsync = promisify(execFile); const execFileAsync = promisify(execFile);
@ -147,11 +148,11 @@ export class NupstDaemon {
*/ */
public async start(): Promise<void> { public async start(): Promise<void> {
if (this.isRunning) { if (this.isRunning) {
console.log('Daemon is already running'); logger.log('Daemon is already running');
return; return;
} }
console.log('Starting NUPST daemon...'); logger.log('Starting NUPST daemon...');
try { try {
// Load configuration - this will throw an error if config doesn't exist // Load configuration - this will throw an error if config doesn't exist
@ -165,11 +166,12 @@ export class NupstDaemon {
this.snmp.getNupst().checkForUpdates().then(updateAvailable => { this.snmp.getNupst().checkForUpdates().then(updateAvailable => {
if (updateAvailable) { if (updateAvailable) {
const updateStatus = this.snmp.getNupst().getUpdateStatus(); const updateStatus = this.snmp.getNupst().getUpdateStatus();
console.log('┌─ Update Available ───────────────────────┐'); const boxWidth = 45;
console.log(`│ Current Version: ${updateStatus.currentVersion}`); logger.logBoxTitle('Update Available', boxWidth);
console.log(`│ Latest Version: ${updateStatus.latestVersion}`); logger.logBoxLine(`Current Version: ${updateStatus.currentVersion}`);
console.log('│ Run "sudo nupst update" to update'); logger.logBoxLine(`Latest Version: ${updateStatus.latestVersion}`);
console.log('└──────────────────────────────────────────┘'); logger.logBoxLine('Run "sudo nupst update" to update');
logger.logBoxEnd();
} }
}).catch(() => {}); // Ignore errors checking for updates }).catch(() => {}); // Ignore errors checking for updates
@ -178,7 +180,7 @@ export class NupstDaemon {
await this.monitor(); await this.monitor();
} catch (error) { } catch (error) {
this.isRunning = false; this.isRunning = false;
console.error(`Daemon failed to start: ${error.message}`); logger.error(`Daemon failed to start: ${error.message}`);
process.exit(1); // Exit with error process.exit(1); // Exit with error
} }
} }
@ -187,23 +189,24 @@ export class NupstDaemon {
* Log the loaded configuration settings * Log the loaded configuration settings
*/ */
private logConfigLoaded(): void { private logConfigLoaded(): void {
console.log('┌─ Configuration Loaded ─────────────────────┐'); const boxWidth = 50;
console.log('│ SNMP Settings:'); logger.logBoxTitle('Configuration Loaded', boxWidth);
console.log(`│ Host: ${this.config.snmp.host}`); logger.logBoxLine('SNMP Settings:');
console.log(`│ Port: ${this.config.snmp.port}`); logger.logBoxLine(` Host: ${this.config.snmp.host}`);
console.log(`│ Version: ${this.config.snmp.version}`); logger.logBoxLine(` Port: ${this.config.snmp.port}`);
console.log('│ Thresholds:'); logger.logBoxLine(` Version: ${this.config.snmp.version}`);
console.log(`│ Battery: ${this.config.thresholds.battery}%`); logger.logBoxLine('Thresholds:');
console.log(`│ Runtime: ${this.config.thresholds.runtime} minutes`); logger.logBoxLine(` Battery: ${this.config.thresholds.battery}%`);
console.log(`│ Check Interval: ${this.config.checkInterval / 1000} seconds`); logger.logBoxLine(` Runtime: ${this.config.thresholds.runtime} minutes`);
console.log('└────────────────────────────────────────────┘'); logger.logBoxLine(`Check Interval: ${this.config.checkInterval / 1000} seconds`);
logger.logBoxEnd();
} }
/** /**
* Stop the monitoring daemon * Stop the monitoring daemon
*/ */
public stop(): void { public stop(): void {
console.log('Stopping NUPST daemon...'); logger.log('Stopping NUPST daemon...');
this.isRunning = false; this.isRunning = false;
} }
@ -211,7 +214,7 @@ export class NupstDaemon {
* Monitor the UPS status and trigger shutdown when necessary * Monitor the UPS status and trigger shutdown when necessary
*/ */
private async monitor(): Promise<void> { private async monitor(): Promise<void> {
console.log('Starting UPS monitoring...'); logger.log('Starting UPS monitoring...');
let lastStatus: 'online' | 'onBattery' | 'unknown' = 'unknown'; let lastStatus: 'online' | 'onBattery' | 'unknown' = 'unknown';
let lastLogTime = 0; // Track when we last logged status let lastLogTime = 0; // Track when we last logged status
@ -226,20 +229,22 @@ export class NupstDaemon {
// Log status changes // Log status changes
if (status.powerStatus !== lastStatus) { if (status.powerStatus !== lastStatus) {
console.log('┌─ Power Status Change ─────────────────────┐'); const statusBoxWidth = 45;
console.log(`│ Status changed: ${lastStatus}${status.powerStatus}`); logger.logBoxTitle('Power Status Change', statusBoxWidth);
console.log('└───────────────────────────────────────────┘'); logger.logBoxLine(`Status changed: ${lastStatus}${status.powerStatus}`);
logger.logBoxEnd();
lastStatus = status.powerStatus; lastStatus = status.powerStatus;
lastLogTime = currentTime; // Reset log timer when status changes lastLogTime = currentTime; // Reset log timer when status changes
} }
// Log status periodically (at least every 5 minutes) // Log status periodically (at least every 5 minutes)
else if (shouldLogStatus) { else if (shouldLogStatus) {
const timestamp = new Date().toISOString(); const timestamp = new Date().toISOString();
console.log('┌─ Periodic Status Update ──────────────────┐'); const periodicBoxWidth = 45;
console.log(`│ Timestamp: ${timestamp}`); logger.logBoxTitle('Periodic Status Update', periodicBoxWidth);
console.log(`│ Power Status: ${status.powerStatus}`); logger.logBoxLine(`Timestamp: ${timestamp}`);
console.log(`│ Battery: ${status.batteryCapacity}% | Runtime: ${status.batteryRuntime} min`); logger.logBoxLine(`Power Status: ${status.powerStatus}`);
console.log('└───────────────────────────────────────────┘'); logger.logBoxLine(`Battery: ${status.batteryCapacity}% | Runtime: ${status.batteryRuntime} min`);
logger.logBoxEnd();
lastLogTime = currentTime; lastLogTime = currentTime;
} }
@ -293,7 +298,7 @@ export class NupstDaemon {
* @param reason Reason for shutdown * @param reason Reason for shutdown
*/ */
public async initiateShutdown(reason: string): Promise<void> { public async initiateShutdown(reason: string): Promise<void> {
console.log(`Initiating system shutdown due to: ${reason}`); logger.log(`Initiating system shutdown due to: ${reason}`);
// Set a longer delay for shutdown to allow VMs and services to close // Set a longer delay for shutdown to allow VMs and services to close
const shutdownDelayMinutes = 5; const shutdownDelayMinutes = 5;
@ -312,7 +317,7 @@ export class NupstDaemon {
try { try {
if (fs.existsSync(path)) { if (fs.existsSync(path)) {
shutdownCmd = path; shutdownCmd = path;
console.log(`Found shutdown command at: ${shutdownCmd}`); logger.log(`Found shutdown command at: ${shutdownCmd}`);
break; break;
} }
} catch (e) { } catch (e) {
@ -322,32 +327,32 @@ export class NupstDaemon {
if (shutdownCmd) { if (shutdownCmd) {
// Execute shutdown command with delay to allow for VM graceful shutdown // Execute shutdown command with delay to allow for VM graceful shutdown
console.log(`Executing: ${shutdownCmd} -h +${shutdownDelayMinutes} "UPS battery critical..."`); logger.log(`Executing: ${shutdownCmd} -h +${shutdownDelayMinutes} "UPS battery critical..."`);
const { stdout } = await execFileAsync(shutdownCmd, [ const { stdout } = await execFileAsync(shutdownCmd, [
'-h', '-h',
`+${shutdownDelayMinutes}`, `+${shutdownDelayMinutes}`,
`UPS battery critical, shutting down in ${shutdownDelayMinutes} minutes` `UPS battery critical, shutting down in ${shutdownDelayMinutes} minutes`
]); ]);
console.log('Shutdown initiated:', stdout); logger.log(`Shutdown initiated: ${stdout}`);
console.log(`Allowing ${shutdownDelayMinutes} minutes for VMs to shut down safely`); logger.log(`Allowing ${shutdownDelayMinutes} minutes for VMs to shut down safely`);
} else { } else {
// Try using the PATH to find shutdown // Try using the PATH to find shutdown
try { try {
console.log('Shutdown command not found in common paths, trying via PATH...'); logger.log('Shutdown command not found in common paths, trying via PATH...');
const { stdout } = await execAsync(`shutdown -h +${shutdownDelayMinutes} "UPS battery critical, shutting down in ${shutdownDelayMinutes} minutes"`, { const { stdout } = await execAsync(`shutdown -h +${shutdownDelayMinutes} "UPS battery critical, shutting down in ${shutdownDelayMinutes} minutes"`, {
env: process.env // Pass the current environment env: process.env // Pass the current environment
}); });
console.log('Shutdown initiated:', stdout); logger.log(`Shutdown initiated: ${stdout}`);
} catch (e) { } catch (e) {
throw new Error(`Shutdown command not found: ${e.message}`); throw new Error(`Shutdown command not found: ${e.message}`);
} }
} }
// Monitor UPS during shutdown and force immediate shutdown if battery gets too low // Monitor UPS during shutdown and force immediate shutdown if battery gets too low
console.log('Monitoring UPS during shutdown process...'); logger.log('Monitoring UPS during shutdown process...');
await this.monitorDuringShutdown(); await this.monitorDuringShutdown();
} catch (error) { } catch (error) {
console.error('Failed to initiate shutdown:', error); logger.error(`Failed to initiate shutdown: ${error}`);
// Try alternative shutdown methods // Try alternative shutdown methods
const alternatives = [ const alternatives = [
@ -376,24 +381,24 @@ export class NupstDaemon {
} }
if (cmdPath) { if (cmdPath) {
console.log(`Trying alternative shutdown method: ${cmdPath} ${alt.args.join(' ')}`); logger.log(`Trying alternative shutdown method: ${cmdPath} ${alt.args.join(' ')}`);
await execFileAsync(cmdPath, alt.args); await execFileAsync(cmdPath, alt.args);
return; // Exit if successful return; // Exit if successful
} else { } else {
// Try using PATH environment // Try using PATH environment
console.log(`Trying alternative via PATH: ${alt.cmd} ${alt.args.join(' ')}`); logger.log(`Trying alternative via PATH: ${alt.cmd} ${alt.args.join(' ')}`);
await execAsync(`${alt.cmd} ${alt.args.join(' ')}`, { await execAsync(`${alt.cmd} ${alt.args.join(' ')}`, {
env: process.env // Pass the current environment env: process.env // Pass the current environment
}); });
return; // Exit if successful return; // Exit if successful
} }
} catch (altError) { } catch (altError) {
console.error(`Alternative method ${alt.cmd} failed:`, altError); logger.error(`Alternative method ${alt.cmd} failed: ${altError}`);
// Continue to next method // Continue to next method
} }
} }
console.error('All shutdown methods failed'); logger.error('All shutdown methods failed');
} }
} }

View File

@ -1,6 +1,7 @@
#!/usr/bin/env node #!/usr/bin/env node
import { NupstCli } from './cli.js'; import { NupstCli } from './cli.js';
import { logger } from './logger.js';
/** /**
* Main entry point for NUPST * Main entry point for NUPST
@ -13,6 +14,6 @@ async function main() {
// Run the main function and handle any errors // Run the main function and handle any errors
main().catch(error => { main().catch(error => {
console.error('Error:', error); logger.error(`Error: ${error}`);
process.exit(1); process.exit(1);
}); });

View File

@ -4,6 +4,7 @@
*/ */
export class Logger { export class Logger {
private currentBoxWidth: number | null = null; private currentBoxWidth: number | null = null;
private static instance: Logger;
/** /**
* Creates a new Logger instance * Creates a new Logger instance
@ -12,6 +13,17 @@ export class Logger {
this.currentBoxWidth = null; this.currentBoxWidth = null;
} }
/**
* Get the singleton logger instance
* @returns The singleton logger instance
*/
public static getInstance(): Logger {
if (!Logger.instance) {
Logger.instance = new Logger();
}
return Logger.instance;
}
/** /**
* Log a message * Log a message
* @param message Message to log * @param message Message to log
@ -129,4 +141,7 @@ export class Logger {
public logDivider(width: number, character: string = '─'): void { public logDivider(width: number, character: string = '─'): void {
console.log(character.repeat(width)); console.log(character.repeat(width));
} }
} }
// Export a singleton instance for easy use
export const logger = Logger.getInstance();

View File

@ -4,6 +4,7 @@ import { NupstSystemd } from './systemd.js';
import { commitinfo } from './00_commitinfo_data.js'; import { commitinfo } from './00_commitinfo_data.js';
import { spawn } from 'child_process'; import { spawn } from 'child_process';
import * as https from 'https'; import * as https from 'https';
import { logger } from './logger.js';
/** /**
* Main Nupst class that coordinates all components * Main Nupst class that coordinates all components
@ -70,7 +71,7 @@ export class Nupst {
return this.updateAvailable; return this.updateAvailable;
} catch (error) { } catch (error) {
console.error(`Error checking for updates: ${error.message}`); logger.error(`Error checking for updates: ${error.message}`);
return false; return false;
} }
} }
@ -162,28 +163,33 @@ export class Nupst {
*/ */
public logVersionInfo(checkForUpdates: boolean = true): void { public logVersionInfo(checkForUpdates: boolean = true): void {
const version = this.getVersion(); const version = this.getVersion();
console.log('┌─ NUPST Version ────────────────────────────┐'); const boxWidth = 45;
console.log(`│ Current Version: ${version}`);
logger.logBoxTitle('NUPST Version', boxWidth);
logger.logBoxLine(`Current Version: ${version}`);
if (this.updateAvailable && this.latestVersion) { if (this.updateAvailable && this.latestVersion) {
console.log(`│ Update Available: ${this.latestVersion}`); logger.logBoxLine(`Update Available: ${this.latestVersion}`);
console.log('│ Run "sudo nupst update" to update'); logger.logBoxLine('Run "sudo nupst update" to update');
logger.logBoxEnd();
} else if (checkForUpdates) { } else if (checkForUpdates) {
console.log('│ Checking for updates...'); logger.logBoxLine('Checking for updates...');
// We can't end the box yet since we're in an async operation
this.checkForUpdates().then(updateAvailable => { this.checkForUpdates().then(updateAvailable => {
if (updateAvailable) { if (updateAvailable) {
console.log(`Update Available: ${this.latestVersion}`); logger.logBoxLine(`Update Available: ${this.latestVersion}`);
console.log('│ Run "sudo nupst update" to update'); logger.logBoxLine('Run "sudo nupst update" to update');
} else { } else {
console.log('│ You are running the latest version'); logger.logBoxLine('You are running the latest version');
} }
console.log('└──────────────────────────────────────────┘'); logger.logBoxEnd();
}).catch(() => { }).catch(() => {
console.log('│ Could not check for updates'); logger.logBoxLine('Could not check for updates');
console.log('└──────────────────────────────────────────┘'); logger.logBoxEnd();
}); });
} else { } else {
console.log('└──────────────────────────────────────────┘'); logger.logBoxEnd();
} }
} }
} }

View File

@ -1,6 +1,7 @@
import { promises as fs } from 'fs'; import { promises as fs } from 'fs';
import { execSync } from 'child_process'; import { execSync } from 'child_process';
import { NupstDaemon } from './daemon.js'; import { NupstDaemon } from './daemon.js';
import { logger } from './logger.js';
/** /**
* Class for managing systemd service * Class for managing systemd service
@ -47,10 +48,11 @@ WantedBy=multi-user.target
try { try {
await fs.access(configPath); await fs.access(configPath);
} catch (error) { } catch (error) {
console.error('┌─ Configuration Error ─────────────────────┐'); const boxWidth = 50;
console.error(`│ No configuration file found at ${configPath}`); logger.logBoxTitle('Configuration Error', boxWidth);
console.error('│ Please run \'nupst setup\' first to create a configuration.'); logger.logBoxLine(`No configuration file found at ${configPath}`);
console.error('└──────────────────────────────────────────┘'); logger.logBoxLine("Please run 'nupst setup' first to create a configuration.");
logger.logBoxEnd();
throw new Error('Configuration not found'); throw new Error('Configuration not found');
} }
} }
@ -66,23 +68,24 @@ WantedBy=multi-user.target
// Write the service file // Write the service file
await fs.writeFile(this.serviceFilePath, this.serviceTemplate); await fs.writeFile(this.serviceFilePath, this.serviceTemplate);
console.log('┌─ Service Installation ──────────────────────┐'); const boxWidth = 50;
console.log(`│ Service file created at ${this.serviceFilePath}`); logger.logBoxTitle('Service Installation', boxWidth);
logger.logBoxLine(`Service file created at ${this.serviceFilePath}`);
// Reload systemd daemon // Reload systemd daemon
execSync('systemctl daemon-reload'); execSync('systemctl daemon-reload');
console.log('│ Systemd daemon reloaded'); logger.logBoxLine('Systemd daemon reloaded');
// Enable the service // Enable the service
execSync('systemctl enable nupst.service'); execSync('systemctl enable nupst.service');
console.log('│ Service enabled to start on boot'); logger.logBoxLine('Service enabled to start on boot');
console.log('└─────────────────────────────────────────────┘'); logger.logBoxEnd();
} catch (error) { } catch (error) {
if (error.message === 'Configuration not found') { if (error.message === 'Configuration not found') {
// Just rethrow the error as the message has already been displayed // Just rethrow the error as the message has already been displayed
throw error; throw error;
} }
console.error('Failed to install systemd service:', error); logger.error(`Failed to install systemd service: ${error}`);
throw error; throw error;
} }
} }
@ -97,15 +100,16 @@ WantedBy=multi-user.target
await this.checkConfigExists(); await this.checkConfigExists();
execSync('systemctl start nupst.service'); execSync('systemctl start nupst.service');
console.log('┌─ Service Status ───────────────────────────┐'); const boxWidth = 45;
console.log('│ NUPST service started successfully'); logger.logBoxTitle('Service Status', boxWidth);
console.log('└────────────────────────────────────────────┘'); logger.logBoxLine('NUPST service started successfully');
logger.logBoxEnd();
} catch (error) { } catch (error) {
if (error.message === 'Configuration not found') { if (error.message === 'Configuration not found') {
// Exit with error code since configuration is required // Exit with error code since configuration is required
process.exit(1); process.exit(1);
} }
console.error('Failed to start service:', error); logger.error(`Failed to start service: ${error}`);
throw error; throw error;
} }
} }
@ -117,9 +121,9 @@ WantedBy=multi-user.target
public async stop(): Promise<void> { public async stop(): Promise<void> {
try { try {
execSync('systemctl stop nupst.service'); execSync('systemctl stop nupst.service');
console.log('NUPST service stopped'); logger.success('NUPST service stopped');
} catch (error) { } catch (error) {
console.error('Failed to stop service:', error); logger.error(`Failed to stop service: ${error}`);
throw error; throw error;
} }
} }
@ -132,9 +136,10 @@ WantedBy=multi-user.target
try { try {
// Enable debug mode if requested // Enable debug mode if requested
if (debugMode) { if (debugMode) {
console.log('┌─ Debug Mode ─────────────────────────────┐'); const boxWidth = 45;
console.log('│ SNMP debugging enabled - detailed logs will be shown'); logger.logBoxTitle('Debug Mode', boxWidth);
console.log('└──────────────────────────────────────────┘'); logger.logBoxLine('SNMP debugging enabled - detailed logs will be shown');
logger.logBoxEnd();
this.daemon.getNupstSnmp().enableDebug(); this.daemon.getNupstSnmp().enableDebug();
} }
@ -152,7 +157,7 @@ WantedBy=multi-user.target
await this.displayServiceStatus(); await this.displayServiceStatus();
await this.displayUpsStatus(); await this.displayUpsStatus();
} catch (error) { } catch (error) {
console.error(`Failed to get status: ${error.message}`); logger.error(`Failed to get status: ${error.message}`);
} }
} }
@ -163,13 +168,18 @@ WantedBy=multi-user.target
private async displayServiceStatus(): Promise<void> { private async displayServiceStatus(): Promise<void> {
try { try {
const serviceStatus = execSync('systemctl status nupst.service').toString(); const serviceStatus = execSync('systemctl status nupst.service').toString();
console.log('┌─ Service Status ─────────────────────────┐'); const boxWidth = 45;
console.log(serviceStatus.split('\n').map(line => `${line}`).join('\n')); logger.logBoxTitle('Service Status', boxWidth);
console.log('└──────────────────────────────────────────┘'); // Process each line of the status output
serviceStatus.split('\n').forEach(line => {
logger.logBoxLine(line);
});
logger.logBoxEnd();
} catch (error) { } catch (error) {
console.error('┌─ Service Status ─────────────────────────┐'); const boxWidth = 45;
console.error('│ Service is not running'); logger.logBoxTitle('Service Status', boxWidth);
console.error('└──────────────────────────────────────────┘'); logger.logBoxLine('Service is not running');
logger.logBoxEnd();
} }
} }
@ -190,22 +200,24 @@ WantedBy=multi-user.target
timeout: Math.min(config.snmp.timeout, 10000) // Use at most 10 seconds for status check timeout: Math.min(config.snmp.timeout, 10000) // Use at most 10 seconds for status check
}; };
console.log('┌─ Connecting to UPS... ─────────────────────┐'); const boxWidth = 45;
console.log(`│ Host: ${config.snmp.host}:${config.snmp.port}`); logger.logBoxTitle('Connecting to UPS...', boxWidth);
console.log(`│ UPS Model: ${config.snmp.upsModel || 'cyberpower'}`); logger.logBoxLine(`Host: ${config.snmp.host}:${config.snmp.port}`);
console.log('└────────────────────────────────────────────┘'); logger.logBoxLine(`UPS Model: ${config.snmp.upsModel || 'cyberpower'}`);
logger.logBoxEnd();
const status = await snmp.getUpsStatus(snmpConfig); const status = await snmp.getUpsStatus(snmpConfig);
console.log('┌─ UPS Status ─────────────────────────────┐'); logger.logBoxTitle('UPS Status', boxWidth);
console.log(`Power Status: ${status.powerStatus}`); logger.logBoxLine(`Power Status: ${status.powerStatus}`);
console.log(`Battery Capacity: ${status.batteryCapacity}%`); logger.logBoxLine(`Battery Capacity: ${status.batteryCapacity}%`);
console.log(`Runtime Remaining: ${status.batteryRuntime} minutes`); logger.logBoxLine(`Runtime Remaining: ${status.batteryRuntime} minutes`);
console.log('└──────────────────────────────────────────┘'); logger.logBoxEnd();
} catch (error) { } catch (error) {
console.error('┌─ UPS Status ─────────────────────────────┐'); const boxWidth = 45;
console.error(`│ Failed to retrieve UPS status: ${error.message}`); logger.logBoxTitle('UPS Status', boxWidth);
console.error('└──────────────────────────────────────────┘'); logger.logBoxLine(`Failed to retrieve UPS status: ${error.message}`);
logger.logBoxEnd();
} }
} }
@ -221,10 +233,10 @@ WantedBy=multi-user.target
// Reload systemd daemon // Reload systemd daemon
execSync('systemctl daemon-reload'); execSync('systemctl daemon-reload');
console.log('Systemd daemon reloaded'); logger.log('Systemd daemon reloaded');
console.log('NUPST service has been successfully uninstalled'); logger.success('NUPST service has been successfully uninstalled');
} catch (error) { } catch (error) {
console.error('Failed to disable and uninstall service:', error); logger.error(`Failed to disable and uninstall service: ${error}`);
throw error; throw error;
} }
} }
@ -235,11 +247,11 @@ WantedBy=multi-user.target
*/ */
private async stopService(): Promise<void> { private async stopService(): Promise<void> {
try { try {
console.log('Stopping NUPST service...'); logger.log('Stopping NUPST service...');
execSync('systemctl stop nupst.service'); execSync('systemctl stop nupst.service');
} catch (error) { } catch (error) {
// Service might not be running, that's okay // Service might not be running, that's okay
console.log('Service was not running or could not be stopped'); logger.log('Service was not running or could not be stopped');
} }
} }
@ -249,10 +261,10 @@ WantedBy=multi-user.target
*/ */
private async disableService(): Promise<void> { private async disableService(): Promise<void> {
try { try {
console.log('Disabling NUPST service...'); logger.log('Disabling NUPST service...');
execSync('systemctl disable nupst.service'); execSync('systemctl disable nupst.service');
} catch (error) { } catch (error) {
console.log('Service was not enabled or could not be disabled'); logger.log('Service was not enabled or could not be disabled');
} }
} }
@ -262,11 +274,11 @@ WantedBy=multi-user.target
*/ */
private async removeServiceFile(): Promise<void> { private async removeServiceFile(): Promise<void> {
if (await fs.stat(this.serviceFilePath).catch(() => null)) { if (await fs.stat(this.serviceFilePath).catch(() => null)) {
console.log(`Removing service file ${this.serviceFilePath}...`); logger.log(`Removing service file ${this.serviceFilePath}...`);
await fs.unlink(this.serviceFilePath); await fs.unlink(this.serviceFilePath);
console.log('Service file removed'); logger.log('Service file removed');
} else { } else {
console.log('Service file did not exist'); logger.log('Service file did not exist');
} }
} }
} }