( simulatorUuid: string, bundleId: string, logsDir: ResolvedSimulatorLogDir, spawner: ProcessSpawner, )
| 336 | } |
| 337 | |
| 338 | async function startTrackedOsLogStream( |
| 339 | simulatorUuid: string, |
| 340 | bundleId: string, |
| 341 | logsDir: ResolvedSimulatorLogDir, |
| 342 | spawner: ProcessSpawner, |
| 343 | ): Promise<string | undefined> { |
| 344 | const ts = formatLogTimestamp(); |
| 345 | const suffix = shortRandomSuffix(); |
| 346 | let osLogFilePath = path.join( |
| 347 | logsDir.path, |
| 348 | `${bundleId}_oslog_${ts}_ownerpid${process.pid}_${suffix}.log`, |
| 349 | ); |
| 350 | |
| 351 | let fd: number | undefined; |
| 352 | try { |
| 353 | const cleanupResult = await stopSimulatorLaunchOsLogSessionsForApp( |
| 354 | simulatorUuid, |
| 355 | bundleId, |
| 356 | 1000, |
| 357 | ); |
| 358 | if (cleanupResult.errorCount > 0) { |
| 359 | log( |
| 360 | 'warn', |
| 361 | `Skipping OSLog stream start after cleanup failure: ${cleanupResult.errors.join('; ')}`, |
| 362 | ); |
| 363 | return undefined; |
| 364 | } |
| 365 | |
| 366 | scheduleArtifactCreatedSweep(logsDir); |
| 367 | fd = fs.openSync(osLogFilePath, 'wx'); |
| 368 | |
| 369 | const child = spawner( |
| 370 | 'xcrun', |
| 371 | [ |
| 372 | 'simctl', |
| 373 | 'spawn', |
| 374 | simulatorUuid, |
| 375 | 'log', |
| 376 | 'stream', |
| 377 | '--level=debug', |
| 378 | '--predicate', |
| 379 | `subsystem == "${bundleId}"`, |
| 380 | ], |
| 381 | { |
| 382 | stdio: ['ignore', fd, fd], |
| 383 | detached: true, |
| 384 | }, |
| 385 | ); |
| 386 | if (child.pid && Number.isInteger(child.pid)) { |
| 387 | const helperOsLogFilePath = path.join( |
| 388 | logsDir.path, |
| 389 | `${bundleId}_oslog_${ts}_helperpid${child.pid}_ownerpid${process.pid}_${suffix}.log`, |
| 390 | ); |
| 391 | osLogFilePath = renameHelperLogPathOrThrow(osLogFilePath, helperOsLogFilePath, child); |
| 392 | } |
| 393 | |
| 394 | try { |
| 395 | await registerSimulatorLaunchOsLogSession({ |
no test coverage detected