(prefix: string, message: string, ...args: unknown[])
| 200 | } |
| 201 | |
| 202 | private logToFile(prefix: string, message: string, ...args: unknown[]): void { |
| 203 | const logLine = `${prefix} ${message} ${args.map(arg => |
| 204 | typeof arg === 'string' ? arg : JSON.stringify(arg) |
| 205 | ).join(' ')}\n` |
| 206 | |
| 207 | // Send to remote server if configured |
| 208 | if (this.dangerouslyUnencryptedServerLoggingUrl) { |
| 209 | // Determine log level from prefix |
| 210 | let level = 'info' |
| 211 | if (prefix.includes(this.localTimezoneTimestamp())) { |
| 212 | level = 'debug' |
| 213 | } |
| 214 | // Fire and forget, with explicit .catch to prevent unhandled rejection |
| 215 | this.sendToRemoteServer(level, message, ...args).catch(() => { |
| 216 | // Silently ignore remote logging errors to prevent loops |
| 217 | }) |
| 218 | } |
| 219 | |
| 220 | // Handle async file path |
| 221 | try { |
| 222 | appendFileSync(this.logFilePath, logLine) |
| 223 | } catch (appendError) { |
| 224 | if (process.env.DEBUG) { |
| 225 | console.error('[DEV MODE ONLY THROWING] Failed to append to log file:', appendError) |
| 226 | throw appendError |
| 227 | } |
| 228 | // In production, fail silently to avoid disturbing Claude session |
| 229 | } |
| 230 | } |
| 231 | } |
| 232 | |
| 233 | // Will be initialized immideately on startup |
no test coverage detected