macOS Unified Logging: The Complete Guide
Deep dive into Apple's unified logging system — subsystems, categories, log levels, and how to effectively query logs for troubleshooting
A Brief History of macOS Logging
Before macOS 10.12 Sierra, Apple relied on two separate logging systems: Apple System Logger (ASL) and the legacy BSD syslog. ASL wrote structured messages to /var/log/asl/ in binary format, while syslog dumped plain text to files like /var/log/system.log. Each application could also maintain its own log files wherever it pleased, leading to a fragmented landscape where diagnosing problems meant hunting through dozens of locations.
With Sierra in 2016, Apple introduced the Unified Logging System (os_log), replacing ASL and syslog with a single, high-performance framework. This was not a minor refactor. Apple rebuilt logging from the ground up around a compressed binary store, structured metadata, and the concept of per-message log levels that control what actually persists to disk versus what gets silently dropped.
For Mac admins, this shift was seismic. The old approach of tail -f /var/log/system.log stopped showing the full picture. Understanding the unified logging architecture is now a prerequisite for any serious macOS troubleshooting.
Architecture: How Unified Logging Works
The unified logging system consists of several interconnected components:
logd (the log daemon)
The central process that receives log messages from all processes on the system. It manages the in-memory log buffer and decides which messages persist to the on-disk log store based on configured log levels and system profiles.
tracer
A subsystem within logd that handles live streaming of log messages. When you run log stream or connect Console.app, tracer delivers messages in real time without touching the persistent store.
The Log Store
Persistent logs are written to /var/db/diagnostics/ in a compressed binary format (.tracev3 files), with supporting metadata in /var/db/uuidtext/. These are not human-readable files. You must use log show, Console.app, or the OSLogStore API to read them.
# See the log store on disk
ls -lh /var/db/diagnostics/Persist/
ls -lh /var/db/diagnostics/Special/
Signposts and Activity Tracing
Beyond simple messages, unified logging supports signposts (for measuring time intervals) and activity IDs (for correlating related messages across subsystems). These are powerful for performance analysis but beyond daily admin use.
Log Levels: What Gets Stored and What Gets Dropped
This is the single most important concept in unified logging. Not all log messages are treated equally:
| Level | Persistence | Purpose |
|---|---|---|
| Default | Persisted to disk | Standard operational messages. Survives reboots. |
| Info | Memory only (by default) | Informational detail. Kept in the ring buffer but not written to disk unless a fault/error occurs nearby. |
| Debug | Disabled by default | Verbose developer-level output. Not even kept in memory unless explicitly enabled. |
| Error | Persisted to disk | Indicates something went wrong that may be recoverable. Always persisted. |
| Fault | Persisted to disk + stack trace | Indicates a serious failure. Captures a stack backtrace. Always persisted. |
Key insight for Mac admins: By default,
InfoandDebugmessages disappear. If you are troubleshooting a transient issue, you often need to enable debug or info logging for a specific subsystem before reproducing the problem.
Enabling Debug and Info Logging
# Enable debug and info messages for a specific subsystem
sudo log config --mode "level:debug" --subsystem com.apple.ManagedClient
# Reset back to default
sudo log config --mode "level:default" --subsystem com.apple.ManagedClient
# Check the current mode for a subsystem
sudo log config --status --subsystem com.apple.ManagedClient
Subsystems and Categories
Every log message in the unified system is tagged with a subsystem (reverse-DNS identifier) and optionally a category. These form the primary axes for filtering:
- Subsystem: Identifies the software component (e.g.,
com.apple.WiFiManager,com.apple.mdmclient) - Category: A finer subdivision within the subsystem (e.g.,
connection,authentication)
Common subsystems every Mac admin should know:
| Subsystem | What It Covers |
|---|---|
com.apple.mdmclient | MDM command processing and enrollment |
com.apple.ManagedClient | Configuration profile installation and enforcement |
com.apple.SoftwareUpdate | macOS software updates |
com.apple.WiFiManager | Wi-Fi connectivity and roaming |
com.apple.bluetooth | Bluetooth connections |
com.apple.loginwindow | User login and session lifecycle |
com.apple.Authorization | Authorization and privilege escalation |
com.apple.securityd | Keychain, certificates, and code signing |
com.apple.xpc | XPC inter-process communication |
com.apple.apsd | Apple Push Notification service daemon |
Querying Logs: The log Command
The log command-line tool is your primary interface. Here are the essential operations:
Show Historical Logs
# Show logs from the last 5 minutes
log show --last 5m
# Show logs from a specific time window
log show --start "2026-02-14 09:00:00" --end "2026-02-14 09:30:00"
# Filter by subsystem
log show --last 1h --predicate 'subsystem == "com.apple.mdmclient"'
# Filter by process name
log show --last 30m --predicate 'process == "softwareupdated"'
# Show only errors and faults
log show --last 1h --predicate 'messageType == error OR messageType == fault'
Stream Live Logs
# Stream all logs in real time
log stream
# Stream only MDM-related messages
log stream --predicate 'subsystem == "com.apple.mdmclient"' --level debug
# Stream with compact output (easier to scan)
log stream --style compact --predicate 'process == "jamf"'
Collect a Diagnostic Archive
# Collect a sysdiagnose (comprehensive system snapshot)
sudo sysdiagnose -f ~/Desktop/
# Collect a log archive for a specific time range
sudo log collect --last 2h --output ~/Desktop/logs.logarchive
The .logarchive bundle can be opened in Console.app on another Mac or queried with log show:
log show ~/Desktop/logs.logarchive --predicate 'subsystem == "com.apple.securityd"'
The OSLogStore API
For programmatic access (useful in scripts or Swift-based admin tools), Apple provides OSLogStore:
# Python can't access OSLogStore directly, but Swift command-line tools can.
# For scripting, pipe log output to standard Unix tools:
log show --last 1h --style ndjson --predicate 'subsystem == "com.apple.mdmclient"' | python3 -c "
import sys, json
for line in sys.stdin:
try:
entry = json.loads(line)
if 'error' in entry.get('eventMessage', '').lower():
print(f\"{entry['timestamp']} [{entry['processImagePath']}] {entry['eventMessage']}\")
except: pass
"
Practical Mac Admin Scenarios
MDM Enrollment Troubleshooting
# Watch MDM enrollment in real time
log stream --predicate 'subsystem == "com.apple.mdmclient" OR subsystem == "com.apple.ManagedClient"' --level info
# Check recent MDM command history
log show --last 2h --predicate 'subsystem == "com.apple.mdmclient" AND eventMessage CONTAINS "command"' --style compact
Software Update Failures
# Review the entire software update process
log show --last 4h --predicate 'subsystem == "com.apple.SoftwareUpdate" OR process == "softwareupdated"' --style compact
# Look specifically for errors
log show --last 4h --predicate 'subsystem == "com.apple.SoftwareUpdate" AND messageType == error'
Network Connectivity Issues
# Wi-Fi association and roaming events
log show --last 1h --predicate 'subsystem == "com.apple.WiFiManager" AND category == "default"' --style compact
# DNS resolution problems
log show --last 30m --predicate 'subsystem == "com.apple.mDNSResponder"' --level info
# Check APNS connectivity (push notifications for MDM)
log show --last 1h --predicate 'subsystem == "com.apple.apsd"' --level info
Kernel and System Stability
# Look for kernel panics and system-level faults
log show --last 24h --predicate 'process == "kernel" AND messageType == fault'
# Check for I/O throttling or disk issues
log show --last 1h --predicate 'subsystem == "com.apple.iokit" AND eventMessage CONTAINS "throttl"'
Key Takeaways
- Unified logging replaced everything. If you are still relying on
/var/log/system.log, you are seeing a tiny fraction of available data. - Log levels determine visibility. Most of the useful diagnostic data lives at
InfoorDebuglevel and is not persisted by default. Enable verbose logging before reproducing problems. - Subsystems are your filter key. Learn the subsystem names for the Apple frameworks you troubleshoot most often.
- Always use predicates. Unfiltered log output is a firehose. Predicate-based filtering is the only practical way to work with unified logs at scale.
- Collect archives for offline analysis. Use
log collectorsysdiagnoseto capture a complete snapshot that can be analyzed on a different machine or at a later time.