ASL: Client connections

2008-01-21 12:20:20 UTC

As you saw, both asl_log and asl_send can take an aslclient object or not. The aslclient type represents a connection to the ASL server; when you pass NULL, it uses a default connection.

A client connection has two useful properties:

  • A filter mask, which tells the connection which priority levels it should ignore
  • A set of file descriptors, to which ASL will mirror any messages send through the connection

When you send a message (whether with asl_log or with asl_send directly), the ASL library checks the message’s priority against the filter mask; if the bit for that priority level is not set, then the library does not forward the message on to syslogd (in other words, the message will not truly be sent). However, the library will write the message to every file in the set of FDs, regardless of the filter mask; the filter mask only governs sending messages to syslogd.

You create a client connection of your own with asl_open, and close the connection with asl_close:

aslclient asl_open(const char *ident, const char *facility, uint32_t opts);
void asl_close(aslclient asl);

The ident argument to asl_open, which defaults to your process name, becomes the default sender name (ASL_KEY_SENDER) on every message sent through the connection. Similarly, the facility argument, which defaults to “user”, becomes the default facility name (ASL_KEY_FACILITY) of every message sent through the connection. You can set these on a per-message basis using asl_set.

The last argument is a set of option flags. As of Tiger and Leopard, three flags are available:

ASL_OPT_STDERR
Immediately add STDERR_FILENO to the connection’s set of file descriptors to mirror to.
ASL_OPT_NO_DELAY
BugThe documentation tersely defines this as “connect to the server immediately”. I’ve filed a documentation bug to ask for clarification, but thanks to the source, I can provide a much better explanation. By default, the ASL library will connect to syslogd lazily—specifically, in asl_send. This option tells the ASL library to connect to syslogd immediately, in asl_open, rather than wait until asl_send. Unfortunately, the source did not tell me why you would care.
ASL_OPT_NO_REMOTE
Tells the library to ignore the two server-side filter masks, leaving only the client connection’s own (client-side) filter mask. The manpages for asl(3) and syslogd goes into more detail. I don’t think most of you will need this, especially since both server-side filter masks are off by default anyway.

There are two reasons to create your own client connection:

  • The more common reason is that you have a multithreaded program wherein multiple threads will log to ASL. The manpage warns you not to share connections among threads; instead, you must create one connection for every thread that will log to ASL.
  • The less common reason is that you want to configure your connection:
    • You can set your own identity and/or default facility string. There are few reasons to change the identity; your process name should be good enough. The facility, however, should be useful: You could put your class names into it (as I suggested above), or, since Console shows all messages with a facility of "com.apple.console", you could create a connection with that as its facility, and all your logging (well, all your logging through that connection) would show up in Console. (You can always set the facility for each message, or in a template message; I explained both techniques in the previous post.)
    • You can disable the remote-control filter masks by including the ASL_OPT_NO_REMOTE option, as I mentioned above.
    • You can have multiple client connections with different filter masks or different sets of output files.

Once you’ve created a client connection, you can set its filter mask with asl_set_filter:

int asl_set_filter(aslclient asl, int f);

The filter mask is simply a bitmask, where the priority constants are indices into its bits. asl.h provides two macros with which you can easily create new filter mask values:

  • ASL_FILTER_MASK takes one of the priority constants and returns a filter mask with only that priority level enabled.
  • ASL_FILTER_MASK_UPTO takes one of the priority constants and returns a filter mask “for all priorities up to and including” that priority level, as the header puts it.

Note that priority levels are sorted the wrong way around, so “up to Emergency” is the same as “Emergency only”, since Emergency is numerically the lowest priority.

Additionally, there are predefined filter-mask values for each of the predefined priority levels:

  • ASL_FILTER_MASK_EMERG
  • ASL_FILTER_MASK_ALERT
  • ASL_FILTER_MASK_CRIT
  • ASL_FILTER_MASK_ERR
  • ASL_FILTER_MASK_WARNING
  • ASL_FILTER_MASK_NOTICE
  • ASL_FILTER_MASK_INFO
  • ASL_FILTER_MASK_DEBUG

Hopefully, there will never be a priority level named “UPTO”.

The default filter mask of every connection, according to asl.h, is ASL_FILTER_MASK_UPTO(ASL_LEVEL_NOTICE); i.e., everything but ASL_LEVEL_INFO and ASL_LEVEL_DEBUG.

The asl_set_filter function returns the previously-set filter mask, so if you want to modify the existing filter mask, you’ll have to do something like this:

int mask = asl_set_filter(client, 0);
mask = /*modify mask in some way*/;
asl_set_filter(client, mask);

If Apple’s own admonition not to share a client connection between threads wasn’t enough for you, that should convince you.

There’s no function to get the filter mask, so in order to do that, you must do the same jig, only without the step in the middle:

//Get the mask
int mask = asl_set_filter(client, 0);
asl_set_filter(client, mask);

//Do whatever you wanted to do with mask

There are actually four filter masks:

  • The library-side filter, which is the one you configure with asl_set_filter
  • The master filter for all processes
  • The data store filter
  • The per-process remote-controllable filter

The latter two are also configurable, using the syslog(1) utility. I’ll tell you more about that in one of the later posts.

In any case, you probably won’t need to worry about filter masks, as I said above. The library-side filter mask includes all the priority levels that you care about most of the time; the server-side filter masks are disabled by default; and logging to a file (including stderr) includes all messages, regardless of any filter masks.


Next in the ASL series: Logging to a file

2 Responses to “ASL: Client connections”

  1. Robbie Hanson Says:

    Concerning ASL_OPT_NO_DELAY:

    To quote the “Advanced Mac OS X Programming” book:
    “This is useful for programs that need to manage the order in which file descriptors are allocated.”

    I’m not sure how helpful this is.

    In a later part of the book they go on to describe how “when you open a file, the file descriptor returned is guaranteed to be the lowest numbered unused descriptor.” And by default stdin=0, stdout=1, and stderr=2. Perhaps there were applications that were making assumptions about file descriptor numbers…

  2. Marc Lindahl Says:

    unfortunately it appears that unlike NSLog, asl_log message do not appear at the console (as viewable by several apps e.g. System Console, iConsole, etc.) in iOS… regardless of setting facility to “com.apple.console”… unless I’m missing something.

Leave a Reply

Do not delete the second sentence.