Migrating to Unified Logging: Console and Instruments

In this tutorial, you’ll learn how to debug your iOS apps like a professional using unified logging with the Console and Instruments apps. By Keegan Rush.

Leave a rating/review
Download materials
Save for later

iOS developers have plenty of logging solutions. Apple provides some, whereas others are by third-party frameworks. However, there’s a relatively new logging solution on the block that leaves the rest in the dust: Apple’s unified logging system.

The unified logging system has been Apple’s standard for logging since iOS 10. Announced at WWDC 2016, it’s not that new. It comes with performance and privacy at the forefront. With unified logging, you can reduce the nasty side-effects of logging, maintain your user’s privacy and make debugging a breeze.

In this tutorial, you’ll convert an app’s old-fashioned print statements over to os_log and unleash the power of the unified logging system!

By the time you’re done with this tutorial, you’ll learn the purpose of unified logging and how to:

  • Protect your users’ sensitive data inside your logs.
  • Filter and categorize your log statements.
  • View your logs in Console.
  • Use signposts to debug performance issues.

Getting Started

To start off, download the sample project using the Download Materials button at the top or bottom of this tutorial. You’ll use a fun app from another great RayWenderlich tutorial, with some extra print statements sprinkled throughout the project.

The Chirper app is any bird watcher’s dream. Search for the name of the bird you’re interested in and the app searches a public database of recordings.

Chirper App

Open the project, run the app and take a look at the debug console output. You can see the logs printed in the output.

Print Statements in Debugger

It’s a good start, but not enough if you want to be confident that your app is doing the right thing. The print statements are all mixed together, so you have no good way to figure out what’s really going on in your app. By changing them to os_log calls from the unified logging system, you’ll be able to tag debugging messages depending on the type of activity happening in the app and also avoid showing sensitive personal data.

Adding Log Statements

To get the privacy, organization and performance of the unified logging system, you need to convert the app’s logs from print statements to os_log, the heart of Apple’s unified logging system.

Start off by opening MainViewController.swift and adding this code to the top of the file:

import os

The os framework provides the tools you’ll need for tracing activity and logging operations to make diagnosing problems in your app easier.

Several times throughout this tutorial, you’ll need to find a particular piece of code in a file. You could scroll through the file and look with your eyes, but it’s much easier to open the Find dialog. When you type the name of a method, you’ll see the occurrences of text highlighted.

With your cursor blinking in the editor, press Command-F and type the code you want to find, in this case, update. Next, press return on your keyboard to iterate through the different occurrences until you locate the update(response:) method definition. It contains the first print statements you’ll convert.

Note: If you’re looking for a specific declaration, use Control-6 to use the jump bar to find the method or property in the current file. If you need to search for a method in the project, you can use Open Quickly — the keyboard shortcut is Command-Shift-O (the letter “O”).

The first line of the method is a print statement. Change it to use os_log like so:

os_log("Updating with network response.")

Build and run to start using the new code. Congratulations, you’re now using unified logging!

Great! So now you have your first log message using unified logging, but what good does this change do? To understand the benefits further, you’ll move on to using the Console app. Console is an app on your Mac that shows all the logged messages for your computer. You can view logs from the Simulator there, not only for your app.

Open the Console app via Spotlight. You can also find it in your Applications folder, inside Utilities.

First, select the name of the iPhone simulator you’re using from the Devices pane on the left. Viewing a stream of log output can be overwhelming. At any given moment, your device is doing lots of work and you might lose track of your logs in the chaos.

Time to make it easier for you to keep track of your logs. Switch back to the Simulator. In Chirper, type rhea in the search box at the top and wait for the results to load:

searching the app for rhea

Look at the Console app and your logs will look something like this:


You need to find the log that you converted, so type Updating with network response in the search box in the upper right and press return on your keyboard:

Console Search

You can remove a lot of the noise by filtering the results. Right click on the log statement and choose Show Process ‘Chirper’. After that, remove the manual search criteria that you used before.

Your search bar should look like this now:

My console is still showing 426 messages. That’s a bit too much, but os_log can clean things up.

OSLog object

Each os_log statement uses an OSLog object. Your first os_log statement doesn’t specify an OSLog to use, so it uses a default shared OSLog. By using your own custom OSLog, you can specify the subsystem and category that your logs fall under.

You can usually think of the subsystem as your app and the category as the feature that the log statement falls under.

You’ll create your own OSLog objects to organize your logs. To start off, create a Swift file named Log.swift. Add the following to the end of the file:

import os

private let subsystem = "com.razeware.Chirper"

struct Log {
  static let table = OSLog(subsystem: subsystem, category: "table")

Log provides a namespace for the OSLog objects that you’ll use for your logging. For now, you only need one OSLog for the log statement you created earlier.

Next, open MainViewController.swift and swap out your new OSLog object for the os_log statement in update(response:):

os_log("Updating with network response.", log: Log.table)

The log message is still the same, but you add the log: parameter at the end of the statement.

Then, with Console still open, build and run the app. Find your log statement in Console. If you can’t find it, search for Updating with network response again.

Once you’ve found it, right click the log and choose Show subsystem ‘com.razeware.Chirper’:

Filter by Subsystem

Now your Console will only show the logs that you create under the com.razeware.Chirper subsystem. Very cool!

You can also right click on a log message and choose to filter by the category or any other identifying information to help you drill down into the logs.

Filtered Results in Console