Monitor multiple iOS simulator logs at the same time

May 19, 2021

Debugging iOS apps normally involves reading logs. If you are debugging on a simulator, logs can be viewed in the XCode's console.

When developing a watch app or share extension ( or any project that uses multiple environment ), it is handy to view the combined logs of all simulators at the same time.

XCode only prints logs for one simulator at a time ( at least per build scheme ). To view all logs simultaneously, we can use xcrun and log stream in terminal.

xcrun simctl spawn booted log stream --level debug\
        --predicate 'subsystem == "my.domain.name"'

This command above will stream all my logs for subsystem 'my.domain.name'. Subsystems are a handy way to identify components of your app ( a good example is networking )

Here is how I setup the logging in code:

import os
let logger = OSLog(subsystem: "my.domain.name", category: "some category")
os_log(.default, log: logger, "---- Hello world ----")

An example of logging in swift

Specifying multiple logs

When I run the command above, I only see output from one simulator (for example, watch simulator ). Maybe booted only works for the latest booted simulator. Nevertheless, we can fix that, by specifying the simulator UUID.

xcrun simctl spawn AC1D88DD-BB2F-4E26-B774-93027F6CCC07 log stream --level debug\
        --predicate 'subsystem == "my.domain.name"'

Run the above command for each simulator UUID.

The UUID AC1D88DD-BB2F-4E26-B774-93027F6CCC07 represents a specific simulator in my system. Different users should have different UUIDs.

To retrieve all the UUIDs of the simulator, we can use list command.

   xcrun simctl list

Simulators that are opened right now should be marked as (Booted). Like:

Watch: Apple Watch Series 6 - 40mm (AC1D88DD-BB2F-4E26-B774-93027F6CCC07) (Booted)

The UUID is marked in brackets (AC1D88DD-BB2F-4E26-B774-93027F6CCC07)

Automating

Since I will be dealing with logs regularly, here is a simple script to capture UUIDs of booted simulators and stream the logs as detached processes.

#/bin/bash

A=`xcrun simctl list | grep Booted | perl -ne 'print "$1\n" if / \(([0-9A-Z\-]+)\) /' | sort | uniq `
for UUID in $A
do
    xcrun simctl spawn $UUID log stream --level debug\
        --timeout 1h\
        --style compact \
        --predicate 'subsystem == "my.domain.name"' &
done

https://gist.github.com/xr1337/5ed82108c80742752af28d64e68ebd72