log: a primer on predicates

The log command, whether accessed directly in Terminal or through a GUI interface such as LogLogger2, uses Cocoa predicates to filter its output, for both its show and stream commands. This article is a short primer to help you use those predicates more fully, as they form quite a sophisticated query language which can greatly enhance your access to Sierra’s logs.

For the purposes of this primer, I will consider that we are trying to build a command to extract from the last hour of logs all entries which match the pattern specified in the given predicate, as
log show --style syslog --predicate [filter] --info --last 1h
where [filter] is what concerns us here.

Pattern clauses

The filter expression matches one or more of the following pattern clauses:

  • eventMessage – for this, you specify a text pattern, or text, within the message, or an activity name. These are very useful.
  • processImagePath – this matches the text pattern in the name of the process which originated the event, and can be very useful.
  • senderImagePath – this matches the text pattern in the name of the sender, which might be the name of a library, extension, or executable. These are very useful.
  • subsystem – this matches the subsystem specifier, e.g. com.apple.TimeMachine. Although potentially valuable, subsystems are not yet widely used, and discovering which is which is not easy. Use with caution.
  • category – this matches the category, and should normally be used in conjunction with the subsystem filter. Unlikely to be helpful at present.
  • eventType – these are the type of event responsible for the log entry, and are confined to logEvent, traceEvent, activityCreateEvent, and activityTransitionEvent. In user log analysis, you are unlikely to use these.
  • messageType – this matches the type of message for logEvent and traceEvent, and includes strings like “info”, “debug”. These are of limited used in user log analysis.

Operators

The following comparisons and other operators are available:

  • == (or =) for equality
  • != or <> for inequality
  • >= or => for greater than or equal to
  • <= or =< for less than or equal to
  • > for greater than
  • < for less than
  • AND or && for logical and
  • OR or || for logical or
  • NOT or ! for logical not
  • BEGINSWITH, CONTAINS, ENDSWITH, LIKE, MATCHES for string comparisons, using regex expressions when desired; strings can be compared with case insensitivity and diacritic insensitivity by appending [cd] to the operator, e.g. CONTAINS[c] means case-insensitive comparison
  • UTI-CONFORMS-TO, UTI-EQUALS support comparison of UTIs like com.adobe.pdf
  • ANY, SOME, NONE, IN, and array operators are available but unlikely to be used
  • FALSE, TRUE, NULL have their expected literal meanings.

Example filters

log show --style syslog --predicate '(subsystem == "com.apple.TimeMachine") && (eventMessage CONTAINS[c] "backup")' --info --last 1h
will return entries from the Time Machine subsystem whose message content includes (case insensitive) the string “backup”.

Within the same command harness, the predicate
(processImagePath CONTAINS[c] "backupd") && (eventMessage CONTAINS[c] "backup")
will return the same set of entries, this type avoiding the use of a subsystem identifier.

(processImagePath CONTAINS[c] "powerd") && (eventMessage CONTAINS[c] "battery")
will return messages from the powerd process which contain (case insensitive) the text ‘battery’.

(processImagePath CONTAINS[c] "kernel") && (eventMessage CONTAINS[c] "bluetooth")
will return messages from the kernel concerning Bluetooth, which will include most significant Bluetooth issues.

(processImagePath CONTAINS[c] "apsd") && (eventMessage CONTAINS[c] "sleep")
will return messages concerning preparations for sleep, from the apsd daemon.

A useful strategy is to limit the source of the messages using processImagePath or subsystem, then to select from those only messages containing a relevant keyword, such as backup or sleep.

References

man log
Apple’s Predicate Programming Guide