source dump of claude code
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 94 lines 2.8 kB view raw
1import { dirname } from 'path' 2import { getFsImplementation } from './fsOperations.js' 3import { jsonStringify } from './slowOperations.js' 4 5type DiagnosticLogLevel = 'debug' | 'info' | 'warn' | 'error' 6 7type DiagnosticLogEntry = { 8 timestamp: string 9 level: DiagnosticLogLevel 10 event: string 11 data: Record<string, unknown> 12} 13 14/** 15 * Logs diagnostic information to a logfile. This information is sent 16 * via the environment manager to session-ingress to monitor issues from 17 * within the container. 18 * 19 * *Important* - this function MUST NOT be called with any PII, including 20 * file paths, project names, repo names, prompts, etc. 21 * 22 * @param level Log level. Only used for information, not filtering 23 * @param event A specific event: "started", "mcp_connected", etc. 24 * @param data Optional additional data to log 25 */ 26// sync IO: called from sync context 27export function logForDiagnosticsNoPII( 28 level: DiagnosticLogLevel, 29 event: string, 30 data?: Record<string, unknown>, 31): void { 32 const logFile = getDiagnosticLogFile() 33 if (!logFile) { 34 return 35 } 36 37 const entry: DiagnosticLogEntry = { 38 timestamp: new Date().toISOString(), 39 level, 40 event, 41 data: data ?? {}, 42 } 43 44 const fs = getFsImplementation() 45 const line = jsonStringify(entry) + '\n' 46 try { 47 fs.appendFileSync(logFile, line) 48 } catch { 49 // If append fails, try creating the directory first 50 try { 51 fs.mkdirSync(dirname(logFile)) 52 fs.appendFileSync(logFile, line) 53 } catch { 54 // Silently fail if logging is not possible 55 } 56 } 57} 58 59function getDiagnosticLogFile(): string | undefined { 60 return process.env.CLAUDE_CODE_DIAGNOSTICS_FILE 61} 62 63/** 64 * Wraps an async function with diagnostic timing logs. 65 * Logs `{event}_started` before execution and `{event}_completed` after with duration_ms. 66 * 67 * @param event Event name prefix (e.g., "git_status" -> logs "git_status_started" and "git_status_completed") 68 * @param fn Async function to execute and time 69 * @param getData Optional function to extract additional data from the result for the completion log 70 * @returns The result of the wrapped function 71 */ 72export async function withDiagnosticsTiming<T>( 73 event: string, 74 fn: () => Promise<T>, 75 getData?: (result: T) => Record<string, unknown>, 76): Promise<T> { 77 const startTime = Date.now() 78 logForDiagnosticsNoPII('info', `${event}_started`) 79 80 try { 81 const result = await fn() 82 const additionalData = getData ? getData(result) : {} 83 logForDiagnosticsNoPII('info', `${event}_completed`, { 84 duration_ms: Date.now() - startTime, 85 ...additionalData, 86 }) 87 return result 88 } catch (error) { 89 logForDiagnosticsNoPII('error', `${event}_failed`, { 90 duration_ms: Date.now() - startTime, 91 }) 92 throw error 93 } 94}