Skip to content

Commit 9a58fc4

Browse files
committed
fix(diagnostics): scope ensured log directories
1 parent 7977ad3 commit 9a58fc4

3 files changed

Lines changed: 35 additions & 15 deletions

File tree

packages/platform-apple/src/runner/__tests__/runner-session-stale-bundles.test.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,19 +69,17 @@ vi.mock('../runner-io.ts', async () => {
6969
});
7070

7171
vi.mock('../runner-transport.ts', async () => {
72-
const actual = await vi.importActual<typeof import('../runner-transport.ts')>(
73-
'../runner-transport.ts',
74-
);
72+
const actual =
73+
await vi.importActual<typeof import('../runner-transport.ts')>('../runner-transport.ts');
7574
return {
7675
...actual,
7776
sendRunnerCommandOnce: mockSendRunnerCommandOnce,
7877
};
7978
});
8079

8180
vi.mock('../runner-xctestrun.ts', async () => {
82-
const actual = await vi.importActual<typeof import('../runner-xctestrun.ts')>(
83-
'../runner-xctestrun.ts',
84-
);
81+
const actual =
82+
await vi.importActual<typeof import('../runner-xctestrun.ts')>('../runner-xctestrun.ts');
8583
return {
8684
...actual,
8785
acquireXcodebuildSimulatorSetRedirect: mockAcquireXcodebuildSimulatorSetRedirect,

src/utils/__tests__/diagnostics.test.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,26 @@ test('appendDiagnosticLine ensures the log directory once across appended lines'
151151
mkdirSpy.mockRestore();
152152
}
153153
});
154+
155+
test('a later diagnostics scope recreates a removed log directory', async () => {
156+
const rootDir = mkdtempForTestSync('agent-device-diag-recreate-');
157+
const logDir = path.join(rootDir, 'nested');
158+
const logPath = path.join(logDir, 'request.ndjson');
159+
const mkdirSpy = vi.spyOn(fs, 'mkdirSync');
160+
try {
161+
await withDiagnosticsScope({ command: 'first', logPath, debug: true }, () => {
162+
emitDiagnostic({ phase: 'first_scope' });
163+
});
164+
fs.rmSync(logDir, { recursive: true, force: true });
165+
166+
await withDiagnosticsScope({ command: 'second', logPath, debug: true }, () => {
167+
emitDiagnostic({ phase: 'second_scope' });
168+
});
169+
170+
const callsForLogDir = mkdirSpy.mock.calls.filter(([dir]) => dir === logDir);
171+
assert.equal(callsForLogDir.length, 2);
172+
assert.match(fs.readFileSync(logPath, 'utf8'), /second_scope/);
173+
} finally {
174+
mkdirSpy.mockRestore();
175+
}
176+
});

src/utils/diagnostics.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ type DiagnosticsScope = DiagnosticsScopeOptions & {
4646
// events are streamed out and reset mid-flight.
4747
phaseCounts: Map<string, number>;
4848
sensitiveValues: Set<string>;
49+
ensuredDirectories: Set<string>;
4950
// Sorted-longest-first view of `sensitiveValues`, recomputed lazily after a
5051
// registration invalidates it so replacement order stays deterministic.
5152
sortedSensitiveValues?: string[];
@@ -72,6 +73,7 @@ export async function withDiagnosticsScope<T>(
7273
liveWrittenEventCount: 0,
7374
phaseCounts: new Map(),
7475
sensitiveValues: new Set(),
76+
ensuredDirectories: new Set(),
7577
};
7678
return await diagnosticsStorage.run(scope, fn);
7779
}
@@ -145,11 +147,11 @@ export function emitDiagnostic(event: {
145147
const fileLine = `${JSON.stringify(payload)}\n`;
146148
try {
147149
if (scope.debug && scope.logPath) {
148-
appendDiagnosticLine(scope.logPath, fileLine);
150+
appendDiagnosticLine(scope, scope.logPath, fileLine);
149151
scope.liveWrittenEventCount = scope.events.length;
150152
}
151153
if (scope.traceLogPath) {
152-
appendDiagnosticLine(scope.traceLogPath, fileLine);
154+
appendDiagnosticLine(scope, scope.traceLogPath, fileLine);
153155
}
154156
if (scope.debug && !scope.logPath && !scope.traceLogPath) {
155157
process.stderr.write(`[agent-device][diag] ${fileLine}`);
@@ -221,7 +223,7 @@ export function flushDiagnosticsToSessionFile(
221223
const lines = pendingEvents.map((entry) =>
222224
JSON.stringify(replaceSensitiveValues(entry, values)),
223225
);
224-
appendDiagnosticLine(scope.logPath, `${lines.join('\n')}\n`);
226+
appendDiagnosticLine(scope, scope.logPath, `${lines.join('\n')}\n`);
225227
}
226228
const logRecord = scope.logRecord;
227229
scope.events = [];
@@ -283,14 +285,11 @@ function sanitizePathPart(value: string): string {
283285
return value.replace(/[^a-zA-Z0-9._-]/g, '_');
284286
}
285287

286-
// Directories already ensured by appendDiagnosticLine; debug mode would mkdir per line otherwise.
287-
const ensuredDiagnosticDirs = new Set<string>();
288-
289-
function appendDiagnosticLine(logPath: string, line: string): void {
288+
function appendDiagnosticLine(scope: DiagnosticsScope, logPath: string, line: string): void {
290289
const dir = path.dirname(logPath);
291-
if (!ensuredDiagnosticDirs.has(dir)) {
290+
if (!scope.ensuredDirectories.has(dir)) {
292291
fs.mkdirSync(dir, { recursive: true });
293-
ensuredDiagnosticDirs.add(dir);
292+
scope.ensuredDirectories.add(dir);
294293
}
295294
fs.appendFileSync(logPath, line, 'utf8');
296295
}

0 commit comments

Comments
 (0)