ASL: Console

2008-01-24 15:20:48 UTC

In Leopard, Console changed radically.

Previously, it was nothing more than a text-file reader (a pager, in UNIX terminology) designed for reading log files. It defaulted to reading console.log, although you also had the option of reading system.log or your crash logs.

Here's a screenshot of Console in Tiger. There's a source list on the left, and a plain text view on the right.

That functionality still exists in Leopard, but its default view is very different. Most obvious is the fact that it’s now a table view:

Here's a screenshot of Console in Leopard. The  source list on the left now has two “database queries”, named “All messages” and “Console messages”, in addition to the plain-text log files, and the text view on the right is replaced with a table view.

Note that if you click on one of the log files in the source list at left, it changes to a text view.

It’s easy to miss the fact that the table view is a source, too. Specifically, it’s a “log database query”.

Hmmm. Where have we heard those terms before?

Yes, dear readers, Console drinks from the ASL hose. It also provides a way for you to create new queries graphically:

The “New Log Database Query” dialog box provides the interface for you to create and edit rules that will match keys in ASL messages.

Unfortunately, this dialog box is very limited. You are limited to the stock keys, and you don’t even get all of them:

  • Message (ASL_KEY_MESSAGE)
  • Sender (ASL_KEY_SENDER)
  • Facility (ASL_KEY_FACILITY)
  • Host (ASL_KEY_HOST)
  • Time (ASL_KEY_TIME)
  • Level (ASL_KEY_LEVEL)

No PID, no UID, no GID—and no custom keys. You can’t even search for those undocumented keys that I’m going to tell you about tomorrow.

Your choice of operators is restricted, too. The options are:

  • is equal to (ASL_QUERY_OP_EQUAL)
  • contains (ASL_QUERY_OP_EQUAL | ASL_QUERY_OP_SUBSTRING)
  • starts with (ASL_QUERY_OP_EQUAL | ASL_QUERY_OP_PREFIX)
  • ends with (ASL_QUERY_OP_EQUAL | ASL_QUERY_OP_SUFFIX)
  • matches regex (ASL_QUERY_OP_EQUAL | ASL_QUERY_OP_REGEX)

No numeric search, no comparative searches (e.g., ASL_QUERY_LESS_THAN), and no negative searches (e.g., “is not equal”/ASL_QUERY_OP_NOT_EQUAL). You also don’t get to specify whether you want to be case-insensitive (ASL_QUERY_OP_CASEFOLD) or not.

But I have good news.

First, I just saved a bunch of money on my car insurance.

The other good news is that Console actually does let you search for any keys you want with any operator you want. The trick is that you have to create the query manually.

This is easy to do. You see, every Console database query is just a file. When you create a query in Console, Console creates a .aslquery file in ~/Library/Application\ Support/Console/ASLQueries. You can create these files yourself.

The format of these files is plist-based. Currently, they’re XML plists. Here’s one example:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
    <dict>
        <key>key</key>
        <string>Sender</string>
        <key>op</key>
        <integer>1</integer>
        <key>value</key>
        <string>Adium</string>
    </dict>
</array>
</plist>

If you were to assemble this query in code, it would be:

aslmsg query = asl_new(ASL_TYPE_QUERY);
asl_set(query, ASL_KEY_SENDER, "Adium", ASL_QUERY_OP_EQUAL);

Note that ASL_QUERY_OP_EQUAL is currently defined to 1 in asl.h; hence that value as the “op” value in the dictionary.

Console’s editor lets you create OR searches as well as AND searches. You may be wondering how to do this, given that the ASL API provides no way to do this (every search is AND-only). Well, here’s what the file looks like:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
    <dict>
        <key>key</key>
        <string>Sender</string>
        <key>op</key>
        <integer>1</integer>
        <key>value</key>
        <string>Fred</string>
    </dict>
    <string>or</string>
    <dict>
        <key>key</key>
        <string>Sender</string>
        <key>op</key>
        <integer>1</integer>
        <key>value</key>
        <string>Barney</string>
    </dict>
</array>
</plist>

It’s just the word “or” between two runs of property dictionaries. So, I think it’s a safe bet that Console simply runs multiple searches and unions the results together (probably using the ASL_KEY_MSG_ID property, which I’ll explain in tomorrow’s post).

So, anyway, to use keys and operators not endorsed by Console, we must create our own aslquery file. You can probably guess the rest, but I’ll go ahead and show you a couple now:

File: CFLog.aslquery.bz2

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
    <dict>
        <key>key</key>
        <string>CFLog Local Time</string>
        <key>op</key>
        <integer>7</integer>
        <key>value</key>
        <string/>
    </dict>
    <string>or</string>
    <dict>
        <key>key</key>
        <string>CFLog Thread</string>
        <key>op</key>
        <integer>7</integer>
        <key>value</key>
        <string/>
    </dict>
</array>
</plist>

This query returns all NSLogs, using a couple of the undocumented keys that it leaves behind in each message. (Presumably, NSLog works by calling CFLog.) We use Console’s OR functionality, just in case one of the keys goes away.

The operator is ASL_QUERY_OP_TRUE. Note that we specify a value, even though we’re not comparing anything to it; if you omit the value key, Console seems to return every message. I’m not sure why.

Here’s another one:

File: No daemons.aslquery.bz2

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
    <dict>
        <key>key</key>
        <string>Sender</string>
        <key>op</key>
        <integer>70</integer>
        <key>value</key>
        <string>d</string>
    </dict>
</array>
</plist>

Here, we see a does-not-end-with operator (ASL_QUERY_OP_NOT_EQUAL | ASL_QUERY_OP_SUFFIX). Note that the number in the integer element is decimal; the operator is, in fact, 0x46 (NOT_EQUAL being 0x6, and SUFFIX being 0x40).

Once you’ve obtained or created a .aslquery file, you’ll want to add it to Console’s source list, so you can use it. There are two ways to do this.

One is to move, link (either kind), or copy it into the ~/Library/Application\ Support/Console/ASLQueries folder, then relaunch Console. Console adds an alphabetized list of the folder’s .aslquery files to its source list on launch.

The other way is to open the File with Console.

You can’t just double-click on the .aslquery file, unfortunately. You’ll get this:

A dialog box that says ‘There is no default application specified to open the document “CFLog.aslquery”.’

You’ll need to either use that button, or simply drag the .aslquery file onto Console instead of double-clicking. Alternatively, you can use open(1) or launch.

When Console opens the file, it will add it to its source list. Note, however, that it won’t copy it to your ASLQueries folder, and that you can’t remove the query from the source list without deleting it (using either the “Move to Trash” toolbar item, or the “Move to Trash” menu item in the query’s contextual menu). And don’t even think of renaming, moving, or deleting the file out from under Console—it will get horribly confused, and probably pinwheel.

Clearly, Console is implemented around the assumption that the ASLQueries folder is simply Console’s private storage for queries created within Console.

Note: If you try to use Console’s editor to edit one of your hand-rolled queries that uses unapproved keys or operators, Console will only show you all criteria up to and excluding the first criterion it doesn’t recognize. That criterion, and all criteria after it, won’t show up.

The UTI for .aslquery files is com.apple.aslquery. Unfortunately, Apple didn’t actually import this type into Console by putting a UTImportedTypeDeclarations property in Console’s Info.plist, so Launch Services rejects Console’s claim to be able to open the file (and it does have one). That’s why you have to jump through hoops to open a .aslquery file with Console. Furthermore, Apple didn’t even export it from any bundle. This is more evidence that Apple considers .aslquery files private to Console.


Next in the ASL series: Undocumented keys

3 Responses to “ASL: Console”

  1. mandaris Says:

    There seems to be an un-closed tag on this page.

  2. Peter Hosey Says:

    Thanks, mandaris. There were actually two; I’ve fixed both.

  3. David Says:

    Is there any way to change the time format from the default 12-hour one to 24?

Leave a Reply

Do not delete the second sentence.