fix(logger): Replace raw console logging calls with structured logger usage across certificate management, connection handling, and route processing for improved observability.

This commit is contained in:
2025-05-19 23:37:11 +00:00
parent e61766959f
commit c9abdea556
6 changed files with 456 additions and 240 deletions

View File

@ -1,4 +1,5 @@
import * as plugins from '../../plugins.js';
import { logger } from '../../core/utils/logger.js';
// Importing required components
import { ConnectionManager } from './connection-manager.js';
@ -239,7 +240,7 @@ export class SmartProxy extends plugins.EventEmitter {
);
if (autoRoutes.length === 0 && !this.hasStaticCertRoutes()) {
console.log('No routes require certificate management');
logger.log('info', 'No routes require certificate management', { component: 'certificate-manager' });
return;
}
@ -256,7 +257,7 @@ export class SmartProxy extends plugins.EventEmitter {
useProduction: this.settings.acme.useProduction || false,
port: this.settings.acme.port || 80
};
console.log(`Using top-level ACME configuration with email: ${acmeOptions.email}`);
logger.log('info', `Using top-level ACME configuration with email: ${acmeOptions.email}`, { component: 'certificate-manager' });
} else if (autoRoutes.length > 0) {
// Check for route-level ACME config
const routeWithAcme = autoRoutes.find(r => r.action.tls?.acme?.email);
@ -267,7 +268,7 @@ export class SmartProxy extends plugins.EventEmitter {
useProduction: routeAcme.useProduction || false,
port: routeAcme.challengePort || 80
};
console.log(`Using route-level ACME configuration from route '${routeWithAcme.name}' with email: ${acmeOptions.email}`);
logger.log('info', `Using route-level ACME configuration from route '${routeWithAcme.name}' with email: ${acmeOptions.email}`, { component: 'certificate-manager' });
}
}
@ -305,7 +306,7 @@ export class SmartProxy extends plugins.EventEmitter {
public async start() {
// Don't start if already shutting down
if (this.isShuttingDown) {
console.log("Cannot start SmartProxy while it's shutting down");
logger.log('warn', "Cannot start SmartProxy while it's in the shutdown process");
return;
}
@ -332,9 +333,9 @@ export class SmartProxy extends plugins.EventEmitter {
const allWarnings = [...configWarnings, ...acmeWarnings];
if (allWarnings.length > 0) {
console.log("Configuration warnings:");
logger.log('warn', `${allWarnings.length} configuration warnings found`, { count: allWarnings.length });
for (const warning of allWarnings) {
console.log(` - ${warning}`);
logger.log('warn', `${warning}`);
}
}
@ -353,7 +354,7 @@ export class SmartProxy extends plugins.EventEmitter {
// Now that ports are listening, provision any required certificates
if (this.certManager) {
console.log('Starting certificate provisioning now that ports are ready');
logger.log('info', 'Starting certificate provisioning now that ports are ready', { component: 'certificate-manager' });
await this.certManager.provisionAllCertificates();
}
@ -411,16 +412,26 @@ export class SmartProxy extends plugins.EventEmitter {
const terminationStats = this.connectionManager.getTerminationStats();
// Log detailed stats
console.log(
`Active connections: ${connectionRecords.size}. ` +
`Types: TLS=${tlsConnections} (Completed=${completedTlsHandshakes}, Pending=${pendingTlsHandshakes}), ` +
`Non-TLS=${nonTlsConnections}, KeepAlive=${keepAliveConnections}, HttpProxy=${httpProxyConnections}. ` +
`Longest running: IN=${plugins.prettyMs(maxIncoming)}, OUT=${plugins.prettyMs(maxOutgoing)}. ` +
`Termination stats: ${JSON.stringify({
IN: terminationStats.incoming,
OUT: terminationStats.outgoing,
})}`
);
logger.log('info', 'Connection statistics', {
activeConnections: connectionRecords.size,
tls: {
total: tlsConnections,
completed: completedTlsHandshakes,
pending: pendingTlsHandshakes
},
nonTls: nonTlsConnections,
keepAlive: keepAliveConnections,
httpProxy: httpProxyConnections,
longestRunning: {
incoming: plugins.prettyMs(maxIncoming),
outgoing: plugins.prettyMs(maxOutgoing)
},
terminationStats: {
incoming: terminationStats.incoming,
outgoing: terminationStats.outgoing
},
component: 'connection-manager'
});
}, this.settings.inactivityCheckInterval || 60000);
// Make sure the interval doesn't keep the process alive
@ -439,19 +450,19 @@ export class SmartProxy extends plugins.EventEmitter {
* Stop the proxy server
*/
public async stop() {
console.log('SmartProxy shutting down...');
logger.log('info', 'SmartProxy shutting down...');
this.isShuttingDown = true;
this.portManager.setShuttingDown(true);
// Stop certificate manager
if (this.certManager) {
await this.certManager.stop();
console.log('Certificate manager stopped');
logger.log('info', 'Certificate manager stopped');
}
// Stop NFTablesManager
await this.nftablesManager.stop();
console.log('NFTablesManager stopped');
logger.log('info', 'NFTablesManager stopped');
// Stop the connection logger
if (this.connectionLogger) {
@ -461,7 +472,7 @@ export class SmartProxy extends plugins.EventEmitter {
// Stop all port listeners
await this.portManager.closeAll();
console.log('All servers closed. Cleaning up active connections...');
logger.log('info', 'All servers closed. Cleaning up active connections...');
// Clean up all active connections
this.connectionManager.clearConnections();
@ -472,7 +483,7 @@ export class SmartProxy extends plugins.EventEmitter {
// Clear ACME state manager
this.acmeStateManager.clear();
console.log('SmartProxy shutdown complete.');
logger.log('info', 'SmartProxy shutdown complete.');
}
/**
@ -481,7 +492,7 @@ export class SmartProxy extends plugins.EventEmitter {
* Note: This legacy method has been removed. Use updateRoutes instead.
*/
public async updateDomainConfigs(): Promise<void> {
console.warn('Method updateDomainConfigs() is deprecated. Use updateRoutes() instead.');
logger.log('warn', 'Method updateDomainConfigs() is deprecated. Use updateRoutes() instead.');
throw new Error('updateDomainConfigs() is deprecated - use updateRoutes() instead');
}
@ -497,7 +508,7 @@ export class SmartProxy extends plugins.EventEmitter {
const challengeRouteExists = this.settings.routes.some(r => r.name === 'acme-challenge');
if (!challengeRouteExists) {
console.log('Challenge route successfully removed from routes');
logger.log('info', 'Challenge route successfully removed from routes');
return;
}
@ -505,7 +516,9 @@ export class SmartProxy extends plugins.EventEmitter {
await plugins.smartdelay.delayFor(retryDelay);
}
throw new Error('Failed to verify challenge route removal after ' + maxRetries + ' attempts');
const error = `Failed to verify challenge route removal after ${maxRetries} attempts`;
logger.log('error', error);
throw new Error(error);
}
/**
@ -533,7 +546,7 @@ export class SmartProxy extends plugins.EventEmitter {
*/
public async updateRoutes(newRoutes: IRouteConfig[]): Promise<void> {
return this.routeUpdateLock.runExclusive(async () => {
console.log(`Updating routes (${newRoutes.length} routes)`);
logger.log('info', `Updating routes (${newRoutes.length} routes)`, { routeCount: newRoutes.length, component: 'route-manager' });
// Get existing routes that use NFTables
const oldNfTablesRoutes = this.settings.routes.filter(
@ -658,14 +671,14 @@ export class SmartProxy extends plugins.EventEmitter {
// Check for wildcard domains (they can't get ACME certs)
if (domain.includes('*')) {
console.log(`Wildcard domains like "${domain}" are not supported for ACME certificates`);
logger.log('warn', `Wildcard domains like "${domain}" are not supported for automatic ACME certificates`, { domain, component: 'certificate-manager' });
return false;
}
// Check if domain has at least one dot and no invalid characters
const validDomainRegex = /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
if (!validDomainRegex.test(domain)) {
console.log(`Domain "${domain}" has invalid format`);
logger.log('warn', `Domain "${domain}" has invalid format for certificate issuance`, { domain, component: 'certificate-manager' });
return false;
}