diff --git a/src/api/core/logging/api-logger.ts b/src/api/core/logging/api-logger.ts index 673e33daea..ba3988dd43 100644 --- a/src/api/core/logging/api-logger.ts +++ b/src/api/core/logging/api-logger.ts @@ -18,11 +18,17 @@ import type { } from "./types" import { isLoggingEnabled } from "./env-config" +/** Maximum age for tracked timestamps before automatic cleanup (5 minutes) */ +const TIMESTAMP_TTL_MS = 5 * 60 * 1000 + +/** Interval for running cleanup (1 minute) */ +const CLEANUP_INTERVAL_MS = 60 * 1000 + /** * Centralized API logging service * Singleton instance that all providers route through for consistent logging * - * When ROO_CODE_API_LOGGING=true, logs are output via console.log/console.error + * When ROO_CODE_API_LOGGING=true or ROO_CODE_LOGGING=true, logs are output via console.log/console.error * for visibility in VS Code's Output panel and Debug Console. */ class ApiLoggerService { @@ -36,6 +42,41 @@ class ApiLoggerService { /** Maps request IDs to their start timestamps for duration calculation */ private requestTimestamps = new Map() + /** Cleanup interval handle */ + private cleanupInterval: ReturnType | null = null + + constructor() { + // Start periodic cleanup of stale timestamps to prevent memory leaks + this.startCleanupInterval() + } + + /** + * Start the periodic cleanup interval for stale timestamps + */ + private startCleanupInterval(): void { + if (this.cleanupInterval) { + return + } + this.cleanupInterval = setInterval(() => this.cleanupStaleTimestamps(), CLEANUP_INTERVAL_MS) + // Allow the process to exit even if the interval is running + if (this.cleanupInterval.unref) { + this.cleanupInterval.unref() + } + } + + /** + * Remove timestamps older than TIMESTAMP_TTL_MS + * This prevents memory leaks if logResponse/logError is never called + */ + private cleanupStaleTimestamps(): void { + const now = Date.now() + for (const [requestId, timestamp] of this.requestTimestamps) { + if (now - timestamp > TIMESTAMP_TTL_MS) { + this.requestTimestamps.delete(requestId) + } + } + } + /** * Configure the logger behavior * @param config Partial configuration to merge with current settings diff --git a/src/api/core/logging/env-config.ts b/src/api/core/logging/env-config.ts index af0d619cc7..1163085ea6 100644 --- a/src/api/core/logging/env-config.ts +++ b/src/api/core/logging/env-config.ts @@ -89,18 +89,20 @@ function getEnvLocalValues(): Record { * Check if API logging is enabled * * Checks in order: - * 1. Workspace .env.local: ROO_CODE_API_LOGGING=true (for user's workspace) + * 1. Workspace .env.local: ROO_CODE_API_LOGGING=true or ROO_CODE_LOGGING=true (for user's workspace) * 2. Process env (loaded from extension's .env.local via envFile in launch.json) + * + * Note: Both ROO_CODE_API_LOGGING and ROO_CODE_LOGGING are accepted for backward compatibility */ export function isLoggingEnabled(): boolean { // Check workspace .env.local first (user's current workspace) const envLocal = getEnvLocalValues() - if (envLocal["ROO_CODE_API_LOGGING"] === "true") { + if (envLocal["ROO_CODE_API_LOGGING"] === "true" || envLocal["ROO_CODE_LOGGING"] === "true") { return true } // Fallback to process.env (populated from extension's .env.local via launch.json envFile) - return process.env.ROO_CODE_API_LOGGING === "true" + return process.env.ROO_CODE_API_LOGGING === "true" || process.env.ROO_CODE_LOGGING === "true" } /**