fix(api-logging): unify env var names and add TTL cleanup for timestamps

- Accept both ROO_CODE_API_LOGGING and ROO_CODE_LOGGING for backward compatibility
- Add automatic cleanup of stale request timestamps (5 min TTL)
- Prevents potential memory leaks if logResponse/logError is never called
This commit is contained in:
Hannes Rudolph 2025-12-18 09:35:36 -07:00 committed by daniel-lxs
parent a110c3b36e
commit 13674b28fd
No known key found for this signature in database
GPG key ID: 21C74479048B3AA6
2 changed files with 47 additions and 4 deletions

View file

@ -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<string, number>()
/** Cleanup interval handle */
private cleanupInterval: ReturnType<typeof setInterval> | 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

View file

@ -89,18 +89,20 @@ function getEnvLocalValues(): Record<string, string> {
* 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"
}
/**