π File detail
utils/diagLogs.ts
π― Use case
This file lives under βutils/β, which covers cross-cutting helpers (shell, tempfiles, settings, messages, process input, β¦). On the API surface it exposes logForDiagnosticsNoPII and withDiagnosticsTiming β mainly functions, hooks, or classes. Dependencies touch Node path helpers. It composes internal code from fsOperations and slowOperations (relative imports).
Generated from folder role, exports, dependency roots, and inline comments β not hand-reviewed for every path.
π§ Inline summary
import { dirname } from 'path' import { getFsImplementation } from './fsOperations.js' import { jsonStringify } from './slowOperations.js' type DiagnosticLogLevel = 'debug' | 'info' | 'warn' | 'error'
π€ Exports (heuristic)
logForDiagnosticsNoPIIwithDiagnosticsTiming
π External import roots
Package roots from from "β¦" (relative paths omitted).
path
π₯οΈ Source preview
import { dirname } from 'path'
import { getFsImplementation } from './fsOperations.js'
import { jsonStringify } from './slowOperations.js'
type DiagnosticLogLevel = 'debug' | 'info' | 'warn' | 'error'
type DiagnosticLogEntry = {
timestamp: string
level: DiagnosticLogLevel
event: string
data: Record<string, unknown>
}
/**
* Logs diagnostic information to a logfile. This information is sent
* via the environment manager to session-ingress to monitor issues from
* within the container.
*
* *Important* - this function MUST NOT be called with any PII, including
* file paths, project names, repo names, prompts, etc.
*
* @param level Log level. Only used for information, not filtering
* @param event A specific event: "started", "mcp_connected", etc.
* @param data Optional additional data to log
*/
// sync IO: called from sync context
export function logForDiagnosticsNoPII(
level: DiagnosticLogLevel,
event: string,
data?: Record<string, unknown>,
): void {
const logFile = getDiagnosticLogFile()
if (!logFile) {
return
}
const entry: DiagnosticLogEntry = {
timestamp: new Date().toISOString(),
level,
event,
data: data ?? {},
}
const fs = getFsImplementation()
const line = jsonStringify(entry) + '\n'
try {
fs.appendFileSync(logFile, line)
} catch {
// If append fails, try creating the directory first
try {
fs.mkdirSync(dirname(logFile))
fs.appendFileSync(logFile, line)
} catch {
// Silently fail if logging is not possible
}
}
}
function getDiagnosticLogFile(): string | undefined {
return process.env.CLAUDE_CODE_DIAGNOSTICS_FILE
}
/**
* Wraps an async function with diagnostic timing logs.
* Logs `{event}_started` before execution and `{event}_completed` after with duration_ms.
*
* @param event Event name prefix (e.g., "git_status" -> logs "git_status_started" and "git_status_completed")
* @param fn Async function to execute and time
* @param getData Optional function to extract additional data from the result for the completion log
* @returns The result of the wrapped function
*/
export async function withDiagnosticsTiming<T>(
event: string,
fn: () => Promise<T>,
getData?: (result: T) => Record<string, unknown>,
): Promise<T> {
const startTime = Date.now()
logForDiagnosticsNoPII('info', `${event}_started`)
try {
const result = await fn()
const additionalData = getData ? getData(result) : {}
logForDiagnosticsNoPII('info', `${event}_completed`, {
duration_ms: Date.now() - startTime,
...additionalData,
})
return result
} catch (error) {
logForDiagnosticsNoPII('error', `${event}_failed`, {
duration_ms: Date.now() - startTime,
})
throw error
}
}