In OSX 10.8 output to stdout and stderr no longer ends up in Console.app. I'd like to get output in Console.app without using NSLog because I need to support code that uses basic print statements to print debug information (see https://bitbucket.org/ronaldoussoren/py2app/issue/77 for some background information).
NSLog output ends up in the ASL (Apple System Log) log "somehow", as you can view those loglines using "syslog -C". That's why I tried adding this code to my application:
aslclient c = asl_open("py2app", "com.apple.console", ASL_OPT_NO_DELAY);
int fd = dup(2);
asl_set_filter(c, ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG));
asl_add_log_file(c, fd);
asl_log(c, NULL, ASL_LEVEL_INFO, "Hello world from py2app launcher");
asl_log_descriptor(c, NULL, ASL_LEVEL_INFO, 1, ASL_LOG_DESCRIPTOR_WRITE);
asl_log_descriptor(c, NULL, ASL_LEVEL_INFO, 2, ASL_LOG_DESCRIPTOR_WRITE);
This somewhat works: when I write lines to the stdout stream those lines get transformed by ASL: the output is now prefixed by usual logging prefix:
Nov 20 13:46:14 Gondolin.local py2app[43722] <Info>: Hello world from py2app launcher
The logfile does not end up in the ASL datastore or Console.app though.
Does anyone know what I'm doing wrong?
The following C code appears to do what I want:
#include <asl.h>
#include <unistd.h>
#include <stdio.h>
static void
setup_logging(void)
{
aslmsg msg;
aslclient c = asl_open("py2app", "com.apple.console", 0);
msg = asl_new(ASL_TYPE_MSG);
asl_set(msg, ASL_KEY_FACILITY, "com.apple.console");
asl_set(msg, ASL_KEY_LEVEL, ASL_STRING_NOTICE);
asl_set(msg, ASL_KEY_READ_UID, "-1");
int fd = dup(2);
//asl_set_filter(c, ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG));
asl_add_log_file(c, fd);
asl_log(c, NULL, ASL_LEVEL_INFO, "Hello world from py2app launcher");
asl_log_descriptor(c, msg, ASL_LEVEL_INFO, 1, ASL_LOG_DESCRIPTOR_WRITE);
asl_log_descriptor(c, msg, ASL_LEVEL_INFO, 2, ASL_LOG_DESCRIPTOR_WRITE);
}
int main(void)
{
setup_logging();
printf("hello world, this is a printf\n");
}
Compared with my first attempt this contains a single change: it explicitly sets the ASL Facility, Level and ReadUID using an "aslmsg" argument to asl_log_descriptor. Without these arguments the messages won't end up in Console.app. The ReadUID in particular is needed to be able to read the log entries without having super user privileges.
Note: to easily test you can use "syslog -C | tail" to read the console log. Without ReadUID my program's output only was visible when I used "sudo syslog -C".
There's no need to do the asl_add_log_file(c, dup(2)).
Also, you can just set the log level in the call to asl_log_descriptor rather than in the asl_msg. Note that the reason you weren't seeing your messages in syslog when at the info level was because messages that are below notice are filtered out by default (see /etc/asl.conf).
Example:
#include <asl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
asl_log_descriptor(NULL, NULL, ASL_LEVEL_INFO, STDOUT_FILENO, ASL_LOG_DESCRIPTOR_WRITE);
asl_log_descriptor(NULL, NULL, ASL_LEVEL_NOTICE, STDERR_FILENO, ASL_LOG_DESCRIPTOR_WRITE);
fprintf(stdout, "This is written to stdout which will be at log level info.");
fprintf(stderr, "This is written to stderr which will be at log level notice.");
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With