diff --git a/LLMD/resources/live-components.md b/LLMD/resources/live-components.md index 09c449e..d5236ff 100644 --- a/LLMD/resources/live-components.md +++ b/LLMD/resources/live-components.md @@ -27,7 +27,7 @@ import type { CounterDemo as _Client } from '@client/src/live/CounterDemo' export class LiveCounter extends LiveComponent { static componentName = 'LiveCounter' static publicActions = ['increment', 'decrement', 'reset'] as const // ๐Ÿ”’ REQUIRED - static logging = ['lifecycle', 'messages'] as const // Per-component logging (optional) + // static logging = ['lifecycle', 'messages'] as const // Console logging (optional, prefer DEBUG_LIVE) static defaultState = { count: 0 } @@ -609,7 +609,7 @@ Each server file contains: - `static componentName` - Component identifier - `static publicActions` - **REQUIRED** whitelist of client-callable methods - `static defaultState` - Initial state object -- `static logging` - Per-component log control (optional, see [Live Logging](./live-logging.md)) +- `static logging` - Per-component console log control (optional, prefer `DEBUG_LIVE=true` for debug panel โ€” see [Live Logging](./live-logging.md)) - Component class extending `LiveComponent` - Client link via `import type { Demo as _Client }` diff --git a/LLMD/resources/live-logging.md b/LLMD/resources/live-logging.md index 8823e1a..12186e7 100644 --- a/LLMD/resources/live-logging.md +++ b/LLMD/resources/live-logging.md @@ -1,56 +1,100 @@ # Live Logging -**Version:** 1.12.0 | **Updated:** 2025-02-12 +**Version:** 1.12.1 | **Updated:** 2025-02-22 ## Quick Facts - Per-component logging control โ€” silent by default -- Opt-in via `static logging` property on LiveComponent subclasses +- Two output channels: **console** (`LIVE_LOGGING`) and **debug panel** (`DEBUG_LIVE`) +- Both off by default โ€” opt-in only - 6 categories: `lifecycle`, `messages`, `state`, `performance`, `rooms`, `websocket` -- Global (non-component) logs controlled by `LIVE_LOGGING` env var - `console.error` always visible regardless of config +- All `liveLog`/`liveWarn` calls are forwarded to the Live Debugger as `LOG` events when `DEBUG_LIVE=true` -## Usage +## Two Logging Channels -### Enable Logging on a Component +| Channel | Env Var | Default | Purpose | +|---------|---------|---------|---------| +| **Console** | `LIVE_LOGGING` | `false` | Server terminal output | +| **Debug Panel** | `DEBUG_LIVE` | `false` | Live Debugger WebSocket stream | + +The debug panel receives **all** `liveLog`/`liveWarn` calls as `LOG` events (with `category`, `level`, `message`, and `details`) regardless of the `LIVE_LOGGING` console setting. This keeps the console clean while making everything visible in the debug panel. + +### Recommended Workflow + +- **Normal development**: both off โ€” clean console, no debug overhead +- **Debugging live components**: `DEBUG_LIVE=true` โ€” open the debug panel at `/api/live/debug/ws` +- **Quick console debugging**: `LIVE_LOGGING=lifecycle,state` โ€” targeted categories to console +- **Per-component debugging**: `static logging = true` on the specific component class + +## Console Logging + +### Per-Component (static logging) ```typescript -// app/server/live/LiveCounter.ts -export class LiveCounter extends LiveComponent { - static componentName = 'LiveCounter' +// app/server/live/LiveChat.ts +export class LiveChat extends LiveComponent { + static componentName = 'LiveChat' - // โœ… All categories + // โœ… All categories to console static logging = true // โœ… Specific categories only - static logging = ['lifecycle', 'messages', 'state', 'rooms'] as const + static logging = ['lifecycle', 'rooms'] as const // โœ… Silent (default โ€” omit property or set false) - // static logging = false + // No static logging needed } ``` -### Global Logs (Non-Component) +### Global (LIVE_LOGGING env var) -Logs not tied to a specific component (room cleanup, key rotation, etc.) are controlled by the `LIVE_LOGGING` env var: +Logs not tied to a specific component (connection cleanup, key rotation, etc.): ```bash # .env -LIVE_LOGGING=true # All global logs +LIVE_LOGGING=true # All global logs to console LIVE_LOGGING=lifecycle,rooms # Specific categories only # (unset or 'false') # Silent (default) ``` +## Debug Panel (DEBUG_LIVE) + +When `DEBUG_LIVE=true`, all `liveLog`/`liveWarn` calls emit `LOG` events to the Live Debugger, regardless of `LIVE_LOGGING` or `static logging` settings. + +```bash +# .env +DEBUG_LIVE=true # Enable debug panel events +``` + +Each `LOG` event contains: + +```typescript +{ + type: 'LOG', + componentId: string | null, + componentName: null, + data: { + category: 'lifecycle' | 'messages' | 'state' | 'performance' | 'rooms' | 'websocket', + level: 'info' | 'warn', + message: string, + details?: unknown // Extra args passed to liveLog/liveWarn + } +} +``` + +The debug panel also receives all other debug events (`COMPONENT_MOUNT`, `STATE_CHANGE`, `ACTION_CALL`, etc.) โ€” see [Live Components](./live-components.md) for the full event list. + ## Categories | Category | What It Logs | |----------|-------------| | `lifecycle` | Mount, unmount, rehydration, recovery, migration | -| `messages` | Received/sent WebSocket messages, file uploads | +| `messages` | Received/sent WebSocket messages, file uploads, queue operations | | `state` | Signing, backup, compression, encryption, validation | | `performance` | Monitoring init, alerts, optimization suggestions | | `rooms` | Room create/join/leave, emit, broadcast | -| `websocket` | Connection open/close, auth | +| `websocket` | Connection open/close/cleanup, pool management, auth | ## Type Definition @@ -69,12 +113,12 @@ static logging = ['lifecycle', 'messages'] as const ## API (Framework Internal) -These functions are used by the framework โ€” app developers only need `static logging`: +These functions are used by the framework โ€” app developers only need `static logging` or env vars: ```typescript import { liveLog, liveWarn, registerComponentLogging, unregisterComponentLogging } from '@core/server/live' -// Log gated by component config +// Log gated by component config (console) + always forwarded to debug panel liveLog('lifecycle', componentId, '๐Ÿš€ Mounted component') liveLog('rooms', componentId, `๐Ÿ“ก Joined room '${roomId}'`) @@ -89,70 +133,88 @@ unregisterComponentLogging(componentId) ## How It Works 1. **Mount**: `ComponentRegistry` reads `static logging` from the class and calls `registerComponentLogging(componentId, config)` -2. **Runtime**: All `liveLog()`/`liveWarn()` calls check the registry before emitting +2. **Runtime**: All `liveLog()`/`liveWarn()` calls: + - Forward to the Live Debugger as `LOG` events (when `DEBUG_LIVE=true`) + - Check the registry before emitting to console (when `LIVE_LOGGING` or `static logging` is active) 3. **Unmount**: `unregisterComponentLogging(componentId)` removes the entry 4. **Global logs**: Fall back to `LIVE_LOGGING` env var when `componentId` is `null` ## Examples -### Debug a Specific Component +### Debug via Panel (Recommended) + +```bash +# .env +DEBUG_LIVE=true +# No LIVE_LOGGING needed โ€” console stays clean +``` + +Open the debug panel WebSocket at `/api/live/debug/ws` to see all events in real-time. + +### Debug a Specific Component (Console) ```typescript -// Only this component will show logs +// Only this component will show console logs export class LiveChat extends LiveComponent { static componentName = 'LiveChat' - static logging = true // See everything for this component + static logging = true // See everything for this component in console } -// All other components remain silent +// All other components remain silent in console export class LiveCounter extends LiveComponent { static componentName = 'LiveCounter' - // No static logging โ†’ silent + // No static logging โ†’ silent in console } ``` -### Monitor Only Room Activity +### Monitor Only Room Activity (Console) ```typescript export class LiveChat extends LiveComponent { static componentName = 'LiveChat' - static logging = ['rooms'] as const // Only room events + static logging = ['rooms'] as const // Only room events in console } ``` ### Production: Silent Everywhere ```bash -# .env (no LIVE_LOGGING set) -# All components without static logging โ†’ silent -# Components with static logging still log (remove for production) +# .env (no LIVE_LOGGING, no DEBUG_LIVE) +# Console: silent +# Debug panel: disabled ``` ## Files Reference | File | Purpose | |------|---------| -| `core/server/live/LiveLogger.ts` | Logger implementation, registry, shouldLog logic | -| `core/server/live/ComponentRegistry.ts` | Reads `static logging` on mount/unmount | +| `core/server/live/LiveLogger.ts` | Logger implementation, registry, shouldLog logic, debugger forwarding | +| `core/server/live/LiveDebugger.ts` | Debug event bus, `LOG` event type, debug client management | +| `core/server/live/ComponentRegistry.ts` | Reads `static logging` on mount/unmount, uses `liveLog` | | `core/server/live/websocket-plugin.ts` | Uses `liveLog` for WebSocket events | +| `core/server/live/WebSocketConnectionManager.ts` | Uses `liveLog`/`liveWarn` for connection pool management | +| `core/server/live/FileUploadManager.ts` | Uses `liveLog`/`liveWarn` for upload operations | | `core/server/live/StateSignature.ts` | Uses `liveLog`/`liveWarn` for state operations | | `core/server/live/LiveRoomManager.ts` | Uses `liveLog` for room lifecycle | | `core/server/live/LiveComponentPerformanceMonitor.ts` | Uses `liveLog`/`liveWarn` for perf | +| `config/system/runtime.config.ts` | `DEBUG_LIVE` env var config | | `core/types/types.ts` | `LiveComponent` base class with `static logging` property | ## Critical Rules **ALWAYS:** - Use `as const` on logging arrays for type safety -- Keep components silent by default in production +- Keep components silent by default (no `static logging`) +- Use `DEBUG_LIVE=true` for debugging instead of `static logging` on components - Use specific categories instead of `true` when possible **NEVER:** - Use `console.log` directly in Live Component code โ€” use `liveLog()` - Forget that `console.error` is always visible (not gated) +- Enable `LIVE_LOGGING` or `DEBUG_LIVE` in production ## Related - [Live Components](./live-components.md) - Base component system - [Live Rooms](./live-rooms.md) - Room system (logged under `rooms` category) -- [Environment Variables](../config/environment-vars.md) - `LIVE_LOGGING` reference +- [Environment Variables](../config/environment-vars.md) - `LIVE_LOGGING` and `DEBUG_LIVE` reference diff --git a/app/client/src/live/CounterDemo.tsx b/app/client/src/live/CounterDemo.tsx index fd26a33..02dfeb9 100644 --- a/app/client/src/live/CounterDemo.tsx +++ b/app/client/src/live/CounterDemo.tsx @@ -47,7 +47,7 @@ export function CounterDemo() { } return ( -
+

{title}

@@ -74,7 +74,7 @@ export function CounterDemo() {
-
+
{counter.$state.count}
@@ -139,7 +139,7 @@ export function CounterDemo() { } return ( -
+

Contador Local (sem Room)

@@ -147,7 +147,7 @@ export function CounterDemo() { Estado local do componente, sem eventos de sala.

-
+
{localCounter.$state.count}
@@ -189,7 +189,7 @@ export function CounterDemo() { } return ( -
+
{renderLocalCounter()} {renderCounter( 'Contador Isolado', diff --git a/app/server/live/LiveCounter.ts b/app/server/live/LiveCounter.ts index 652dcce..1cf1ca6 100644 --- a/app/server/live/LiveCounter.ts +++ b/app/server/live/LiveCounter.ts @@ -8,7 +8,6 @@ import type { CounterDemo as _Client } from '@client/src/live/CounterDemo' export class LiveCounter extends LiveComponent { static componentName = 'LiveCounter' static publicActions = ['increment', 'decrement', 'reset'] as const - static logging = ['lifecycle', 'messages', 'state', 'rooms'] as const static defaultState = { count: 0, lastUpdatedBy: null as string | null, diff --git a/config/system/runtime.config.ts b/config/system/runtime.config.ts index d378bda..9a3a45a 100644 --- a/config/system/runtime.config.ts +++ b/config/system/runtime.config.ts @@ -17,11 +17,8 @@ export const appRuntimeConfig = defineReactiveConfig({ enableDebugMode: config.boolean('DEBUG', false), // Live Component Debugger - // Defaults to true in development, false otherwise - debugLive: config.boolean( - 'DEBUG_LIVE', - (process.env.NODE_ENV || 'development') === 'development' - ), + // Defaults to false โ€” opt-in via DEBUG_LIVE=true + debugLive: config.boolean('DEBUG_LIVE', false), // Rate limiting rateLimitEnabled: config.boolean('RATE_LIMIT_ENABLED', true), diff --git a/core/server/live/FileUploadManager.ts b/core/server/live/FileUploadManager.ts index fc38f12..bcb983d 100644 --- a/core/server/live/FileUploadManager.ts +++ b/core/server/live/FileUploadManager.ts @@ -1,6 +1,7 @@ import { writeFile, mkdir, unlink } from 'fs/promises' import { existsSync } from 'fs' import { join, extname, basename } from 'path' +import { liveLog, liveWarn } from './LiveLogger' import type { ActiveUpload, FileUploadStartMessage, @@ -139,7 +140,7 @@ export class FileUploadManager { this.userUploadBytes.set(userId, currentUsage + fileSize) } - console.log('๐Ÿ“ค Upload started:', { + liveLog('messages', componentId, '๐Ÿ“ค Upload started:', { uploadId, componentId, filename, @@ -173,7 +174,7 @@ export class FileUploadManager { // Check if chunk already received if (upload.receivedChunks.has(chunkIndex)) { - console.log(`๐Ÿ“ฆ Chunk ${chunkIndex} already received for upload ${uploadId}`) + liveLog('messages', upload.componentId, `๐Ÿ“ฆ Chunk ${chunkIndex} already received for upload ${uploadId}`) } else { // Store chunk data - use binary data if available, otherwise use base64 string let chunkBytes: number @@ -191,7 +192,7 @@ export class FileUploadManager { upload.lastChunkTime = Date.now() upload.bytesReceived += chunkBytes - console.log(`๐Ÿ“ฆ Received chunk ${chunkIndex + 1}/${totalChunks} for upload ${uploadId} (${chunkBytes} bytes, total: ${upload.bytesReceived}/${upload.fileSize})${binaryData ? ' [binary]' : ' [base64]'}`) + liveLog('messages', upload.componentId, `๐Ÿ“ฆ Received chunk ${chunkIndex + 1}/${totalChunks} for upload ${uploadId} (${chunkBytes} bytes, total: ${upload.bytesReceived}/${upload.fileSize})${binaryData ? ' [binary]' : ' [base64]'}`) } // Calculate progress based on actual bytes received (supports adaptive chunking) @@ -200,7 +201,7 @@ export class FileUploadManager { // Log completion status (but don't finalize until COMPLETE message) if (upload.bytesReceived >= upload.fileSize) { - console.log(`โœ… All bytes received for upload ${uploadId} (${upload.bytesReceived}/${upload.fileSize}), waiting for COMPLETE message`) + liveLog('messages', upload.componentId, `โœ… All bytes received for upload ${uploadId} (${upload.bytesReceived}/${upload.fileSize}), waiting for COMPLETE message`) } return { @@ -223,7 +224,7 @@ export class FileUploadManager { private async finalizeUpload(upload: ActiveUpload): Promise { try { - console.log(`โœ… Upload completed: ${upload.uploadId}`) + liveLog('messages', upload.componentId, `โœ… Upload completed: ${upload.uploadId}`) // Assemble file from chunks const fileUrl = await this.assembleFile(upload) @@ -246,7 +247,7 @@ export class FileUploadManager { throw new Error(`Upload ${uploadId} not found`) } - console.log(`โœ… Upload completion requested: ${uploadId}`) + liveLog('messages', upload.componentId, `โœ… Upload completion requested: ${uploadId}`) // Validate bytes received (supports adaptive chunking) if (upload.bytesReceived !== upload.fileSize) { @@ -257,7 +258,7 @@ export class FileUploadManager { // ๐Ÿ”’ Content validation: verify file magic bytes match claimed MIME type this.validateContentMagicBytes(upload) - console.log(`โœ… Upload validation passed: ${uploadId} (${upload.bytesReceived} bytes)`) + liveLog('messages', upload.componentId, `โœ… Upload validation passed: ${uploadId} (${upload.bytesReceived} bytes)`) // Assemble file from chunks const fileUrl = await this.assembleFile(upload) @@ -320,7 +321,7 @@ export class FileUploadManager { const fileBuffer = Buffer.concat(chunks) await writeFile(filePath, fileBuffer) - console.log(`๐Ÿ“ File assembled: ${filePath}`) + liveLog('messages', upload.componentId, `๐Ÿ“ File assembled: ${filePath}`) return `/uploads/${safeFilename}` } catch (error) { @@ -343,11 +344,11 @@ export class FileUploadManager { for (const uploadId of staleUploads) { this.activeUploads.delete(uploadId) - console.log(`๐Ÿงน Cleaned up stale upload: ${uploadId}`) + liveLog('messages', null, `๐Ÿงน Cleaned up stale upload: ${uploadId}`) } if (staleUploads.length > 0) { - console.log(`๐Ÿงน Cleaned up ${staleUploads.length} stale uploads`) + liveLog('messages', null, `๐Ÿงน Cleaned up ${staleUploads.length} stale uploads`) } } @@ -396,7 +397,7 @@ export class FileUploadManager { } if (!matched) { - console.warn(`๐Ÿ”’ Content validation failed for upload ${upload.uploadId}: ` + + liveWarn('messages', upload.componentId, `๐Ÿ”’ Content validation failed for upload ${upload.uploadId}: ` + `claimed type ${upload.fileType} does not match file magic bytes`) throw new Error( `File content does not match claimed type '${upload.fileType}'. ` + @@ -412,7 +413,7 @@ export class FileUploadManager { const userCount = this.userUploadBytes.size this.userUploadBytes.clear() if (userCount > 0) { - console.log(`๐Ÿ”’ Reset upload quotas for ${userCount} users`) + liveLog('messages', null, `๐Ÿ”’ Reset upload quotas for ${userCount} users`) } } diff --git a/core/server/live/LiveDebugger.ts b/core/server/live/LiveDebugger.ts index 2b27316..1913bfc 100644 --- a/core/server/live/LiveDebugger.ts +++ b/core/server/live/LiveDebugger.ts @@ -35,6 +35,7 @@ export type DebugEventType = | 'WS_CONNECT' | 'WS_DISCONNECT' | 'ERROR' + | 'LOG' export interface DebugEvent { id: string diff --git a/core/server/live/LiveLogger.ts b/core/server/live/LiveLogger.ts index aaf6210..cad3786 100644 --- a/core/server/live/LiveLogger.ts +++ b/core/server/live/LiveLogger.ts @@ -14,10 +14,16 @@ // rooms โ€” room create/join/leave, emit, broadcast // websocket โ€” connection open/close, auth // -// Global (non-component) logs controlled by LIVE_LOGGING env var: -// LIVE_LOGGING=true โ†’ all global logs -// LIVE_LOGGING=lifecycle,rooms โ†’ only these categories globally -// (unset or 'false') โ†’ silent (default) +// Console output controlled by LIVE_LOGGING env var: +// LIVE_LOGGING=true โ†’ all global logs to console +// LIVE_LOGGING=lifecycle,rooms โ†’ only these categories to console +// (unset or 'false') โ†’ silent console (default) +// +// Debug panel: All liveLog/liveWarn calls are always forwarded to the Live Debugger +// (when DEBUG_LIVE is enabled) as LOG events, regardless of LIVE_LOGGING setting. +// This way the console stays clean but all details are visible in the debug panel. + +import { liveDebugger } from './LiveDebugger' export type LiveLogCategory = 'lifecycle' | 'messages' | 'state' | 'performance' | 'rooms' | 'websocket' @@ -79,8 +85,26 @@ function shouldLog(componentId: string | null, category: LiveLogCategory): boole return cfg.includes(category) } +/** + * Forward a log entry to the Live Debugger as a LOG event. + * Always emits when the debugger is enabled, regardless of console logging config. + */ +function emitToDebugger(category: LiveLogCategory, level: 'info' | 'warn', componentId: string | null, message: string, args: unknown[]): void { + if (!liveDebugger.enabled) return + + const data: Record = { category, level, message } + if (args.length === 1 && typeof args[0] === 'object' && args[0] !== null) { + data.details = args[0] + } else if (args.length > 0) { + data.details = args + } + + liveDebugger.emit('LOG', componentId, null, data) +} + /** * Log a message gated by the component's logging config. + * Always forwarded to the Live Debugger when active (DEBUG_LIVE). * * @param category - Log category * @param componentId - Component ID, or null for global logs @@ -88,6 +112,10 @@ function shouldLog(componentId: string | null, category: LiveLogCategory): boole * @param args - Extra arguments (objects, etc.) */ export function liveLog(category: LiveLogCategory, componentId: string | null, message: string, ...args: unknown[]): void { + // Always forward to debug panel + emitToDebugger(category, 'info', componentId, message, args) + + // Console output gated by config if (shouldLog(componentId, category)) { if (args.length > 0) { console.log(message, ...args) @@ -98,9 +126,14 @@ export function liveLog(category: LiveLogCategory, componentId: string | null, m } /** - * Warn-level log gated by config (for non-error informational warnings like perf alerts) + * Warn-level log gated by config (for non-error informational warnings like perf alerts). + * Always forwarded to the Live Debugger when active (DEBUG_LIVE). */ export function liveWarn(category: LiveLogCategory, componentId: string | null, message: string, ...args: unknown[]): void { + // Always forward to debug panel + emitToDebugger(category, 'warn', componentId, message, args) + + // Console output gated by config if (shouldLog(componentId, category)) { if (args.length > 0) { console.warn(message, ...args) diff --git a/core/server/live/WebSocketConnectionManager.ts b/core/server/live/WebSocketConnectionManager.ts index ececacb..5a72f28 100644 --- a/core/server/live/WebSocketConnectionManager.ts +++ b/core/server/live/WebSocketConnectionManager.ts @@ -3,6 +3,7 @@ import { EventEmitter } from 'events' import type { FluxStackWebSocket } from '@core/types/types' +import { liveLog, liveWarn } from './LiveLogger' export interface ConnectionConfig { maxConnections: number @@ -123,7 +124,7 @@ export class WebSocketConnectionManager extends EventEmitter { // Setup connection event handlers this.setupConnectionHandlers(ws, connectionId) - console.log(`๐Ÿ”Œ Connection registered: ${connectionId} (Pool: ${poolId || 'default'})`) + liveLog('websocket', null, `๐Ÿ”Œ Connection registered: ${connectionId} (Pool: ${poolId || 'default'})`) this.emit('connectionRegistered', { connectionId, poolId }) } @@ -193,7 +194,7 @@ export class WebSocketConnectionManager extends EventEmitter { } this.connectionPools.get(poolId)!.add(connectionId) - console.log(`๐ŸŠ Connection ${connectionId} added to pool ${poolId}`) + liveLog('websocket', null, `๐ŸŠ Connection ${connectionId} added to pool ${poolId}`) } /** @@ -331,7 +332,7 @@ export class WebSocketConnectionManager extends EventEmitter { queue.splice(insertIndex, 0, queuedMessage) } - console.log(`๐Ÿ“ฌ Message queued for ${connectionId}: ${queuedMessage.id}`) + liveLog('messages', null, `๐Ÿ“ฌ Message queued for ${connectionId}: ${queuedMessage.id}`) return true } @@ -361,10 +362,10 @@ export class WebSocketConnectionManager extends EventEmitter { // Re-queue for retry queue.push(queuedMessage) } else { - console.warn(`โŒ Message ${queuedMessage.id} exceeded max retries`) + liveWarn('messages', null, `โŒ Message ${queuedMessage.id} exceeded max retries`) } } else { - console.log(`โœ… Queued message delivered: ${queuedMessage.id}`) + liveLog('messages', null, `โœ… Queued message delivered: ${queuedMessage.id}`) } } catch (error) { console.error(`โŒ Error processing queued message ${queuedMessage.id}:`, error) @@ -445,7 +446,7 @@ export class WebSocketConnectionManager extends EventEmitter { * Handle connection close */ private handleConnectionClose(connectionId: string): void { - console.log(`๐Ÿ”Œ Connection closed: ${connectionId}`) + liveLog('websocket', null, `๐Ÿ”Œ Connection closed: ${connectionId}`) // Update metrics const metrics = this.connectionMetrics.get(connectionId) @@ -573,7 +574,7 @@ export class WebSocketConnectionManager extends EventEmitter { * Handle unhealthy connection */ private async handleUnhealthyConnection(connectionId: string): Promise { - console.warn(`โš ๏ธ Handling unhealthy connection: ${connectionId}`) + liveWarn('websocket', null, `โš ๏ธ Handling unhealthy connection: ${connectionId}`) const ws = this.connections.get(connectionId) if (ws) { @@ -606,7 +607,7 @@ export class WebSocketConnectionManager extends EventEmitter { } } - console.log(`๐Ÿงน Connection cleaned up: ${connectionId}`) + liveLog('websocket', null, `๐Ÿงน Connection cleaned up: ${connectionId}`) } /** @@ -679,7 +680,7 @@ export class WebSocketConnectionManager extends EventEmitter { * Shutdown connection manager */ shutdown(): void { - console.log('๐Ÿ”Œ Shutting down WebSocket Connection Manager...') + liveLog('websocket', null, '๐Ÿ”Œ Shutting down WebSocket Connection Manager...') // Clear intervals if (this.healthCheckInterval) { @@ -701,7 +702,7 @@ export class WebSocketConnectionManager extends EventEmitter { this.connectionPools.clear() this.messageQueues.clear() - console.log('โœ… WebSocket Connection Manager shutdown complete') + liveLog('websocket', null, 'โœ… WebSocket Connection Manager shutdown complete') } }