feat: implement structured logging across server components

- Integrated a centralized logging system using createLogger from @automaker/utils, replacing console.log and console.error statements with logger methods for consistent log formatting and improved readability.
- Updated various modules, including auth, events, and services, to utilize the new logging system, enhancing error tracking and operational visibility.
- Refactored logging messages to provide clearer context and information, ensuring better maintainability and debugging capabilities.

This update significantly enhances the observability of the server components, facilitating easier troubleshooting and monitoring.
This commit is contained in:
Shirone
2026-01-02 15:40:15 +01:00
parent 8c04e0028f
commit 96a999817f
23 changed files with 284 additions and 275 deletions

View File

@@ -17,6 +17,9 @@ import dotenv from 'dotenv';
import { createEventEmitter, type EventEmitter } from './lib/events.js';
import { initAllowedPaths } from '@automaker/platform';
import { createLogger } from '@automaker/utils';
const logger = createLogger('Server');
import { authMiddleware, validateWsConnectionToken, checkRawAuthentication } from './lib/auth.js';
import { requireJsonContentType } from './middleware/require-json-content-type.js';
import { createAuthRoutes } from './routes/auth/index.js';
@@ -70,7 +73,7 @@ const ENABLE_REQUEST_LOGGING = process.env.ENABLE_REQUEST_LOGGING !== 'false'; /
const hasAnthropicKey = !!process.env.ANTHROPIC_API_KEY;
if (!hasAnthropicKey) {
console.warn(`
logger.warn(`
╔═══════════════════════════════════════════════════════════════════════╗
║ ⚠️ WARNING: No Claude authentication configured ║
║ ║
@@ -83,7 +86,7 @@ if (!hasAnthropicKey) {
╚═══════════════════════════════════════════════════════════════════════╝
`);
} else {
console.log('[Server] ✓ ANTHROPIC_API_KEY detected (API key auth)');
logger.info('✓ ANTHROPIC_API_KEY detected (API key auth)');
}
// Initialize security
@@ -166,7 +169,7 @@ const mcpTestService = new MCPTestService(settingsService);
// Initialize services
(async () => {
await agentService.initialize();
console.log('[Server] Agent service initialized');
logger.info('Agent service initialized');
})();
// Run stale validation cleanup every hour to prevent memory leaks from crashed validations
@@ -174,7 +177,7 @@ const VALIDATION_CLEANUP_INTERVAL_MS = 60 * 60 * 1000; // 1 hour
setInterval(() => {
const cleaned = cleanupStaleValidations();
if (cleaned > 0) {
console.log(`[Server] Cleaned up ${cleaned} stale validation entries`);
logger.info(`Cleaned up ${cleaned} stale validation entries`);
}
}, VALIDATION_CLEANUP_INTERVAL_MS);
@@ -267,7 +270,7 @@ server.on('upgrade', (request, socket, head) => {
// Authenticate all WebSocket connections
if (!authenticateWebSocket(request)) {
console.log('[WebSocket] Authentication failed, rejecting connection');
logger.info('Authentication failed, rejecting connection');
socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
socket.destroy();
return;
@@ -288,11 +291,11 @@ server.on('upgrade', (request, socket, head) => {
// Events WebSocket connection handler
wss.on('connection', (ws: WebSocket) => {
console.log('[WebSocket] Client connected, ready state:', ws.readyState);
logger.info('Client connected, ready state:', ws.readyState);
// Subscribe to all events and forward to this client
const unsubscribe = events.subscribe((type, payload) => {
console.log('[WebSocket] Event received:', {
logger.info('Event received:', {
type,
hasPayload: !!payload,
payloadKeys: payload ? Object.keys(payload) : [],
@@ -302,27 +305,24 @@ wss.on('connection', (ws: WebSocket) => {
if (ws.readyState === WebSocket.OPEN) {
const message = JSON.stringify({ type, payload });
console.log('[WebSocket] Sending event to client:', {
logger.info('Sending event to client:', {
type,
messageLength: message.length,
sessionId: (payload as any)?.sessionId,
});
ws.send(message);
} else {
console.log(
'[WebSocket] WARNING: Cannot send event, WebSocket not open. ReadyState:',
ws.readyState
);
logger.info('WARNING: Cannot send event, WebSocket not open. ReadyState:', ws.readyState);
}
});
ws.on('close', () => {
console.log('[WebSocket] Client disconnected');
logger.info('Client disconnected');
unsubscribe();
});
ws.on('error', (error) => {
console.error('[WebSocket] ERROR:', error);
logger.error('ERROR:', error);
unsubscribe();
});
});
@@ -349,24 +349,24 @@ terminalWss.on('connection', (ws: WebSocket, req: import('http').IncomingMessage
const sessionId = url.searchParams.get('sessionId');
const token = url.searchParams.get('token');
console.log(`[Terminal WS] Connection attempt for session: ${sessionId}`);
logger.info(`Connection attempt for session: ${sessionId}`);
// Check if terminal is enabled
if (!isTerminalEnabled()) {
console.log('[Terminal WS] Terminal is disabled');
logger.info('Terminal is disabled');
ws.close(4003, 'Terminal access is disabled');
return;
}
// Validate token if password is required
if (isTerminalPasswordRequired() && !validateTerminalToken(token || undefined)) {
console.log('[Terminal WS] Invalid or missing token');
logger.info('Invalid or missing token');
ws.close(4001, 'Authentication required');
return;
}
if (!sessionId) {
console.log('[Terminal WS] No session ID provided');
logger.info('No session ID provided');
ws.close(4002, 'Session ID required');
return;
}
@@ -374,12 +374,12 @@ terminalWss.on('connection', (ws: WebSocket, req: import('http').IncomingMessage
// Check if session exists
const session = terminalService.getSession(sessionId);
if (!session) {
console.log(`[Terminal WS] Session ${sessionId} not found`);
logger.info(`Session ${sessionId} not found`);
ws.close(4004, 'Session not found');
return;
}
console.log(`[Terminal WS] Client connected to session ${sessionId}`);
logger.info(`Client connected to session ${sessionId}`);
// Track this connection
if (!terminalConnections.has(sessionId)) {
@@ -495,15 +495,15 @@ terminalWss.on('connection', (ws: WebSocket, req: import('http').IncomingMessage
break;
default:
console.warn(`[Terminal WS] Unknown message type: ${msg.type}`);
logger.warn(`Unknown message type: ${msg.type}`);
}
} catch (error) {
console.error('[Terminal WS] Error processing message:', error);
logger.error('Error processing message:', error);
}
});
ws.on('close', () => {
console.log(`[Terminal WS] Client disconnected from session ${sessionId}`);
logger.info(`Client disconnected from session ${sessionId}`);
unsubscribeData();
unsubscribeExit();
@@ -522,7 +522,7 @@ terminalWss.on('connection', (ws: WebSocket, req: import('http').IncomingMessage
});
ws.on('error', (error) => {
console.error(`[Terminal WS] Error on session ${sessionId}:`, error);
logger.error(`Error on session ${sessionId}:`, error);
unsubscribeData();
unsubscribeExit();
});
@@ -537,7 +537,7 @@ const startServer = (port: number) => {
: 'enabled'
: 'disabled';
const portStr = port.toString().padEnd(4);
console.log(`
logger.info(`
╔═══════════════════════════════════════════════════════╗
║ Automaker Backend Server ║
╠═══════════════════════════════════════════════════════╣
@@ -552,7 +552,7 @@ const startServer = (port: number) => {
server.on('error', (error: NodeJS.ErrnoException) => {
if (error.code === 'EADDRINUSE') {
console.error(`
logger.error(`
╔═══════════════════════════════════════════════════════╗
║ ❌ ERROR: Port ${port} is already in use ║
╠═══════════════════════════════════════════════════════╣
@@ -572,7 +572,7 @@ const startServer = (port: number) => {
`);
process.exit(1);
} else {
console.error('[Server] Error starting server:', error);
logger.error('Error starting server:', error);
process.exit(1);
}
});
@@ -582,19 +582,19 @@ startServer(PORT);
// Graceful shutdown
process.on('SIGTERM', () => {
console.log('SIGTERM received, shutting down...');
logger.info('SIGTERM received, shutting down...');
terminalService.cleanup();
server.close(() => {
console.log('Server closed');
logger.info('Server closed');
process.exit(0);
});
});
process.on('SIGINT', () => {
console.log('SIGINT received, shutting down...');
logger.info('SIGINT received, shutting down...');
terminalService.cleanup();
server.close(() => {
console.log('Server closed');
logger.info('Server closed');
process.exit(0);
});
});