(scope: string)
| 246 | }>; |
| 247 | |
| 248 | export function createFrameAuditLogger(scope: string): FrameAuditLogger { |
| 249 | if (!FRAME_AUDIT_ENABLED) { |
| 250 | return Object.freeze({ |
| 251 | enabled: false, |
| 252 | emit: () => {}, |
| 253 | }); |
| 254 | } |
| 255 | |
| 256 | const writeLine = (line: string): void => { |
| 257 | try { |
| 258 | if (FRAME_AUDIT_LOG_PATH !== null) { |
| 259 | appendFileSync(FRAME_AUDIT_LOG_PATH, `${line}\n`, "utf8"); |
| 260 | if (!FRAME_AUDIT_STDERR_MIRROR) { |
| 261 | return; |
| 262 | } |
| 263 | } else if (!FRAME_AUDIT_STDERR_MIRROR) { |
| 264 | return; |
| 265 | } |
| 266 | process.stderr.write(`${line}\n`); |
| 267 | } catch { |
| 268 | // Optional diagnostics must never affect runtime behavior. |
| 269 | } |
| 270 | }; |
| 271 | const g = globalThis as { |
| 272 | __reziFrameAuditSink?: (line: string) => void; |
| 273 | __reziFrameAuditContext?: () => Readonly<Record<string, unknown>>; |
| 274 | }; |
| 275 | if (typeof g.__reziFrameAuditSink !== "function") { |
| 276 | g.__reziFrameAuditSink = writeLine; |
| 277 | } |
| 278 | |
| 279 | return Object.freeze({ |
| 280 | enabled: true, |
| 281 | emit: (stage: string, fields: AuditRecord = Object.freeze({})) => { |
| 282 | try { |
| 283 | const context = |
| 284 | typeof g.__reziFrameAuditContext === "function" ? g.__reziFrameAuditContext() : null; |
| 285 | const line = JSON.stringify({ |
| 286 | ts: new Date().toISOString(), |
| 287 | tUs: nowUs(), |
| 288 | pid: process.pid, |
| 289 | layer: "node", |
| 290 | scope, |
| 291 | stage, |
| 292 | ...(context ?? {}), |
| 293 | ...fields, |
| 294 | }); |
| 295 | writeLine(line); |
| 296 | } catch { |
| 297 | // Optional diagnostics must never affect runtime behavior. |
| 298 | } |
| 299 | }, |
| 300 | }); |
| 301 | } |
no test coverage detected