Full Metal Mac FullMetalMac.com
Logging & Diagnostics intermediate logging unified-log os_log troubleshooting

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

Published: Feb 14, 2026 15 min read

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:

LevelPersistencePurpose
DefaultPersisted to diskStandard operational messages. Survives reboots.
InfoMemory only (by default)Informational detail. Kept in the ring buffer but not written to disk unless a fault/error occurs nearby.
DebugDisabled by defaultVerbose developer-level output. Not even kept in memory unless explicitly enabled.
ErrorPersisted to diskIndicates something went wrong that may be recoverable. Always persisted.
FaultPersisted to disk + stack traceIndicates a serious failure. Captures a stack backtrace. Always persisted.

Key insight for Mac admins: By default, Info and Debug messages 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:

SubsystemWhat It Covers
com.apple.mdmclientMDM command processing and enrollment
com.apple.ManagedClientConfiguration profile installation and enforcement
com.apple.SoftwareUpdatemacOS software updates
com.apple.WiFiManagerWi-Fi connectivity and roaming
com.apple.bluetoothBluetooth connections
com.apple.loginwindowUser login and session lifecycle
com.apple.AuthorizationAuthorization and privilege escalation
com.apple.securitydKeychain, certificates, and code signing
com.apple.xpcXPC inter-process communication
com.apple.apsdApple 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

  1. Unified logging replaced everything. If you are still relying on /var/log/system.log, you are seeing a tiny fraction of available data.
  2. Log levels determine visibility. Most of the useful diagnostic data lives at Info or Debug level and is not persisted by default. Enable verbose logging before reproducing problems.
  3. Subsystems are your filter key. Learn the subsystem names for the Apple frameworks you troubleshoot most often.
  4. Always use predicates. Unfiltered log output is a firehose. Predicate-based filtering is the only practical way to work with unified logs at scale.
  5. Collect archives for offline analysis. Use log collect or sysdiagnose to capture a complete snapshot that can be analyzed on a different machine or at a later time.

Related Articles