Using os_log and log streaming on iOS
|Log Level||A log level is essentially a "score" or "severity" for the message that is being generated. Log levels enable filtering by severity, and come with some special consideration for
|Log Subsystem||A subsystem is an identifier for a specific area of your app, and can be configured as is reasonable to your particular architecture. These should be specified in reverse DNS notation, following your apps bundle identifier as an example. For example, if my bundle identifier was
|Log Category||Within a subsystem, log categories provide additional granularity and filtering. Following our previous example, some categories we might choose for networking could be:
os_log Log Level Hierarchy
Each level includes the levels below itself, so setting "debug" will include all logs, while "default" would only include itself, error and fault levels.
debug info default - When no settings are changed, only these and below show up outside of Xcode error fault
Examples of each of these levels in our networking example could be:
|Debug||Connection information, Configuration Output, Etc.|
|Default||A request started, a request finished|
|Error||An error response was received from the server|
|Fault||A malformed response was received, or JSON decoding failed and the app may be about to crash|
Debugging errors by log level
To catch calls to error or fault login and open the debugger, set a symbolic breakpoint on these symbols:
Getting the current logging configuration
# For the whole logging system xcrun simctl spawn booted log config --status # For a specific subsystem xcrun simctl spawn booted log config --status --subsystem net.davelyon.oslog # For a specific subsystem and category xcrun simctl spawn booted log config --status --subsystem net.davelyon.oslog --category network
Setting the logging configuration
"Level" is the level that is enabled and stored in memory "Persist" is the level of logs that are both stored in memory and forwarded to the file backed store
# Set the level for the whole logging system xcrun simctl spawn booted log config --mode "level:debug" xcrun simctl spawn booted log config --mode "persist:debug" # Set the level for a specific subsystem xcrun simctl spawn booted log config --mode "level:debug" --subsystem net.davelyon.oslog xcrun simctl spawn booted log config --mode "persist:debug" --subsystem net.davelyon.oslog # Set the level for a specific subsystem and category xcrun simctl spawn booted log config --mode "level:debug" --subsystem net.davelyon.oslog --category network xcrun simctl spawn booted log config --mode "persist:debug" --subsystem net.davelyon.oslog --category network
Viewing logs in Xcode
By default, when the debugger is attached all logs are streamed within Xcode.
Viewing logs in Console.app
If you open
Console.app, you should see your simulator(s) in the list of sources. You can then apply filtering to focus on the specific subsystems you want to see.
If you don't see
info level logs, check the
Action menu, and make sure
Include Info Messages is enabled.
If you don't see
debug level logs, that's because the "system" log level is set to
info and can't be changed, so you're only able to see them by specifically using
Streaming logs from the simulator to Terminal
You can manage the log level, as well as use the
log command line tool within the simulator, including streaming logs from any running simulator, filtering for any specific subsystem you might want to focus on.
To stream logs for a specific subsystem you've created within your app, you can use
log as follows:
xcrun simctl spawn booted log stream\ --level debug\ --style syslog\ --color none\ --predicate 'subsystem contains "net.davelyon"'
"net.davelyon" with your own log subsystem name. Note that it's not the entire name, which does a partial match and lets other similarly named subsystems come through as well. You can be more specific if you only want one of your own subsystems.
man log for more options on how to filter with predicates.