Explainer: subsystems

macOS commonly uses names for processes that use reverse DNS notation, like com.apple.SafariServices. Those appear in Activity Monitor and other glimpses we get of operating system internals. In most cases, they’re straightforward to decode: com.apple.siri.embeddedspeech is a process concerned with handling embedded speech within Siri. One place where they can become critically important is in the log, where they’re formally known as subsystems.

Apple explains that “A log categorizes the messages you write [to the Unified log] and makes it easy to sort and filter them. Each log [entry] contains a subsystem and a category, which you define. A subsystem identifies a major functional area of your app, which you specify using reverse DNS notation, such as com.your_company.your_subsystem_name. A category segregates specific areas within a subsystem.”

When the Unified log was introduced in macOS Sierra, subsystems were used infrequently. To find entries from different processes you often had to guess the processes involved, and construct search predicates looking for them in the senderImagePath or processImagePath, or even worse work out a process ID number.

Over the years since then, the great majority of processes making log entries have been using their subsystem to ease identification. Most of the search predicates I use in Ulbow rely on well-known subsystems. For example, to view the majority of entries concerning Time Machine, list those with the subsystem com.apple.TimeMachine, in a predicate like
subsystem == "com.apple.TimeMachine"

Software Update includes several different subsystems, including com.apple.MobileSoftwareUpdate, com.apple.mobileassetd and com.apple.SoftwareUpdate, which you can combine into a single predicate
subsystem == "com.apple.MobileSoftwareUpdate" || subsystem == "com.apple.mobileassetd" || subsystem == "com.apple.SoftwareUpdate"

The most important creator of log entries that never gives a subsystem is the kernel. Instead, if you want to include log entries made by the kernel, look for a processID (field 9) of 0 (zero), or kernel as the processImagePath (field 11).

Most other log entries should now include both subsystem (field 4) and category (field 3); to make most sense from these, it’s a good idea to include them in styled log extracts in that order, for instance as in the starters+ standard style, where they appear as
4b 3
which displays the subsystem in blue, followed by the category in black/white.

Subsystems are dynamic, in that they can change across minor versions of macOS or different app releases. As no one has seriously attempted to track even the major subsystems, and Apple doesn’t maintain a registry, discovering which subsystems do what is a matter of observation, trial and error. To get a broad idea of just how many subsystems are now invoked in system processes, capture an extract of the whole log using Ulbow, without any predicate and upwards of 5,000 entries, then open the popup list in its Chart View from the Windows menu. You’re likely to see dozens of different subsystems listed there, from com.apple.AppKit to com.apple.xpc.remote. Listings in that popup menu are more extensive than I’ve seen anywhere else.

A recent trend in the latest versions of macOS is to prefix the reverse DNS identifier with additional information, such as

  • gui/[userID]/ such as gui/501/ for user processes and apps,
  • pid/[processID]/ such as pid/3081/ for processes that are part of user apps,
  • user/[userID]/ such as user/501/ for user-owned background processes.

Suffixes can additionally be used to further qualify the text given for the subsystem. For example, a complete subsystem field could become as complex as
gui/501/application.co.eclecticlight.Ulbow.523801.523825 [3081]
There are always a few subsystems that don’t comply with the reverse DNS rule, including powerd, which may identify itself simply as powerd rather than com.apple.powerd.

Subsystem names are also rich with Apple internal nicknames, such as FuseBoard, SkyLight, coreduet, and duetactivityscheduler. Although not intended to obscure the function of those subsystems, they can have that effect. Even if you’re conversant with Apple’s terminology in its developer documentation, many subsystems remain opaque. This is because the primary purpose of the Unified log is to assist Apple’s engineers in their work, and with their diagnosis of bugs. If we decide that we want to use it too, then we’re out on our own.