Mac maintenance
Mac System Logs Explained (and What They Can Tell You)
Mac system logs hold the full story of what your machine did and when. Here's how the unified log works, what's worth looking at, and how to actually find the signal.
A kernel panic last Tuesday. An app that quit silently while you were in a meeting. A USB device that’s been intermittently dropping. The answers to all of these are sitting in your Mac’s system logs right now — they have been the whole time. The problem isn’t access. The problem is that macOS produces something like 50,000 log entries per hour on an idle machine, and finding the one that matters is its own skill.
Apple replaced the old /var/log text-file logging system in macOS Sierra with the unified log, a structured database that captures messages from the kernel, system services, frameworks, and applications all in one place. It’s enormously more powerful than the old approach. It’s also enormously more confusing if you’re used to tail -f /var/log/system.log and reading lines.
What the Unified Log Is
The unified log is a single backing store at /var/db/diagnostics that holds compressed, structured log entries from every process on your Mac. Each entry has a timestamp, the process that emitted it, a category, a subsystem, and a message. The structure is what makes it useful — you can filter by process, by subsystem, by time window, by log level — without grepping through millions of lines of text.
The log is rotated automatically: the most recent few days of detail-level messages, plus weeks of higher-level messages, plus months of error-only entries. The total on-disk size hovers around 1–3 GB on most Macs.
Two CLI tools and one GUI app are how you get at it:
log show— query the unified loglog stream— tail the live log- Console.app — Apple’s GUI for browsing logs
Each one exposes the same underlying data with different ergonomics.
What Old Logs Still Exist
Even with the unified log, some legacy text logs still get written. They live at:
/var/log/install.log— software installations and updates/var/log/system.log— historically, almost everything; now mostly empty/Library/Logs/DiagnosticReports/— crash reports, hangs, panics, and shutdown stalls~/Library/Logs/— per-user app logs/Library/Logs/— system-wide app logs
The DiagnosticReports folder is especially valuable. Every kernel panic, every app crash, and every spin (an app pegging the CPU) generates a report there with a stack trace, often enough to identify the bad actor.
ls -lt /Library/Logs/DiagnosticReports/ | head
That shows the most recent reports. Filenames encode the process name and timestamp.
Querying the Unified Log
The simplest log show invocation:
log show --last 1h
That dumps all log entries from the last hour. You’ll get a wall of output. The point of log show is the filtering.
To see only entries from a specific process:
log show --last 1h --predicate 'process == "Safari"'
To see only errors:
log show --last 1h --predicate 'eventType == logEvent AND messageType == error'
To combine — only Safari errors:
log show --last 1h --predicate 'process == "Safari" AND messageType == error'
To see entries about a specific subsystem (subsystems group related logging across processes):
log show --last 1h --predicate 'subsystem == "com.apple.network"'
The --last flag accepts various time formats: 30m, 2h, 1d. Or use specific times:
log show --start "2026-04-19 14:00:00" --end "2026-04-19 14:30:00"
Reading the Output
A typical line of log show output looks like:
2026-04-19 14:23:15.234567+0000 0x4f5c0 Default 0x0 421 0 Safari: (CoreFoundation) [com.apple.foundation:default] Read failed because the file path was invalid
Decoding it:
- Timestamp — UTC by default
- Activity ID (
0x4f5c0) — connects related entries across processes - Type (
Default) — log level: Default, Info, Debug, Error, Fault - Thread (
0x0) - PID (
421) - TTL or other metadata (
0) - Process and module (
Safari: (CoreFoundation)) - Subsystem and category (
[com.apple.foundation:default]) - Message
The activity ID is underrated. When something interesting happens, it often spans multiple processes — your click in an app triggers an XPC message to a daemon which calls into a framework which logs an error. The activity ID lets you trace the whole sequence.
Live Tailing with log stream
For real-time debugging, log stream is the equivalent of tail -f:
log stream --predicate 'process == "Mail"'
That’ll print every new log entry from Mail as it happens. Great for catching what an app does when you click a button, or what happens in the moments before a crash.
You can also filter by level:
log stream --level info
Console.app: The GUI
Console at /System/Applications/Utilities/Console.app (or /Applications/Utilities/ on older systems) is the GUI front-end. The left sidebar lists devices (your Mac, plus any iOS/iPad devices connected) and a “Crash Reports” section.
The main view shows a live stream of log entries. The search bar at the top accepts the same predicate syntax as log show, but most users just type a process name into the regular search field.
The Crash Reports tab is where the diagnostic reports live. Each report includes:
- The process that crashed
- The exception type (
EXC_BAD_ACCESS,EXC_CRASH, etc.) - The stack trace at the moment of crash
- Loaded libraries
- Hardware info
For a kernel panic, look for files starting with kernel_ in /Library/Logs/DiagnosticReports/. Open one and search for “Panicked task” to find the offending process.
Categories That Actually Matter
Subsystems give you a way to filter by topic. Useful ones:
com.apple.network— networking, DNS, VPN, anything about reachabilitycom.apple.security— keychain, code signing, Gatekeepercom.apple.kernel— kernel-level events, drivers, panicscom.apple.bluetooth— Bluetooth pairing, audio routing, dropoutscom.apple.coreservices— Spotlight, file metadata, Findercom.apple.WindowServer— graphics, display, the WindowServer processcom.apple.timemachine— Time Machine backup status and errorscom.apple.cloudd— iCloud sync enginecom.apple.SoftwareUpdate— system update checks and installs
If you’re tracking down why your VPN won’t connect, subsystem == "com.apple.network" plus your VPN app’s name is a productive starting point.
Crash Reports and Hang Reports
The diagnostic reports folder has a few file types worth knowing:
.ips— modern crash reports (a JSON-ish format).crash— older crash report format (plain text).hang— a process became unresponsive, the system sampled its threads.panic— kernel panic.shutdownStall— a process delayed shutdown
When your Mac feels weird after an unexplained restart, check for a .panic file from around that time. Open it (TextEdit works fine) and look near the top for “Panicked task” or “OS version” — usually within the first 30 lines, you’ll see what triggered it.
If you see consistent panics from a specific kext (kernel extension), that third-party driver is your culprit. Common offenders historically: VPN clients with kext components, hardware drivers, virtualization tools, anti-virus software.
Reducing Log Noise
If you’re trying to debug something specific and the firehose is overwhelming, narrow the predicate as much as possible. A surprisingly useful one when something goes wrong system-wide:
log show --last 30m --predicate 'messageType == error OR messageType == fault'
That filters out the chatty info-level entries and shows only what the system itself flagged as wrong.
For broader exploration, try filtering by process and viewing in chronological order:
log show --last 1h --predicate 'process == "MyApp"' --info --debug
The --info and --debug flags include lower-level entries that are filtered out by default.
There’s a faster waySweep does this kind of cleanup automatically. Try Sweep free →
What Logs Reveal That Other Tools Don’t
Some examples of questions only the log can answer:
- Why did my Mac wake up at 3 AM? Filter by
process == "powerd"for the time window. You’ll see what triggered the wake. - Why is my VPN dropping? Combine
process == "your-vpn-app"withsubsystem == "com.apple.network". - Why does Photos seem to fail to sync?
subsystem == "com.apple.cloudd"pluscategory == "photos". - What did the last system update do?
cat /var/log/install.logfor installer-level steps; unified log for runtime behavior. - What happened in the 10 seconds before that crash?
--startand--endaround the crash time, with no process filter.
The unified log is also the tool of choice when you suspect malware. Filter by process == "<unfamiliar process name>" and watch what it talks to and when.
Privacy of Logs
Logs can include sensitive information — file paths, URLs, sometimes message contents — depending on what processes choose to log and at what level. Apple distinguishes between “public” and “private” log content. By default, log show redacts private content as <private>.
To unredact (only on a Mac you trust, with admin access):
sudo log show --last 1h --predicate 'process == "Mail"' --debug --info | grep "<private>"
You can configure private data to log unredacted by installing a configuration profile, but this is a developer/debugging move, not something to leave on. The redaction exists for a reason.
Cleaning Up Logs
The unified log manages its own retention and rotation. You don’t need to (and shouldn’t try to) clean it up manually — /var/db/diagnostics is managed by logd.
What you can clean up:
- Old crash reports in
/Library/Logs/DiagnosticReports/(months-old.ipsfiles for crashes you don’t care about) - Per-app logs in
~/Library/Logs/that have grown out of control - App-specific log paths inside
~/Library/Application Support/
Some apps log irresponsibly. A noisy Electron app can write hundreds of MB to ~/Library/Logs/<App>/ over time. Check there if you’re hunting for disk space.
What This Buys You
The system log is overwhelming on first contact and indispensable once you can navigate it. With the basics — log show with a smart predicate, Console.app for browsing, the DiagnosticReports folder for crash analysis — most “my Mac is acting weird” mysteries become tractable. You stop guessing and start reading.