OS X asl 日志记录:如何将多线程项目的消息重定向到单个文件中
OS X asl logging : how to re-direct messages of multi-threaded project into a single file
我有一个多线程项目,其中每个线程都使用 asl 生成一些日志消息。
为了简化调试,我决定将所有这些消息集中在一个单独的文件中(我们称之为 /tmp/aaa)。
因此,我将标准 asl_log 方法与对从该线程创建的第一条消息生成 asl_client 的惰性 c'tor 的调用包装在一起。
正如在下面的代码中所看到的,我已将 asl_client 消息目标配置为文件 /tmp/aaa,方法是打开具有写入和追加属性的文件。
我的问题是关于保持此代码线程安全。在同一个目标文件上为每个线程创建一个单独的 fd(file desc) 时我是对的吗?我了解到,当使用默认目标文件 (/var/log/system.log) 时,线程安全是有保证的,但在我的场景中是不是这样。
感谢
#define log_error(fmt, ...) do { \
lazy_asl_client_ctor(); \
log_per_level(ASL_LEVEL_CRIT ,fmt, ##__VA_ARGS__);\
} while (0)
void lazy_asl_client_ctor() {
if (__improbable(!log_asl_client_get())) {
// set aslmsg and with a new key named TID (thread-id)
asl_msg_set((aslmsg*) malloc(sizeof(aslmsg)));
*asl_msg_get() = asl_new(ASL_TYPE_MSG);
uint64_t tid;
pthread_threadid_np(NULL, &tid);
char tid_str[100];
sprintf(tid_str,"%llu",tid);
asl_set(*asl_msg_get(), "TID", tid_str);
// set log client
log_asl_client_set((aslclient*) malloc (sizeof(aslclient)));
*log_asl_client_get() = asl_open(ProcessName(),NULL,ASL_OPT_STDERR);
// set the file that will receive all thread messages
int fd = open("/tmp/aaa", O_RDWR | O_CREAT | O_APPEND, 0777);
asl_add_output_file(*log_asl_client_get(), fd, "$Time $Host $Sender [ $PID : $TID ] $Message",ASL_TIME_FMT_LCL, ASL_FILTER_MASK_UPTO(ASL_LEVEL_INFO), ASL_ENCODE_SAFE);
}
}
#define log_per_level(int_level, const_chars_fmt, ...) \
asl_log(*log_asl_client_get(), *asl_msg_get(), int_level, "[%s] (%s:%d):" const_chars_fmt, \
SRC_MODULE, __FILENAME__, __LINE__,##__VA_ARGS__)
经过一些研究,我发现了一种更简洁的方法来将我制作的多个软件组件的日志消息路由到一个单独的文件中:
asl 日志转到 syslogd,它根据 /etc/asl.conf 和 /etc/asl/
中规定的预定义配置决定如何处理消息
为了正确路由消息,已将一个新文件添加到 /etc/asl/,其内容如下:
> traps.log rotate=utc ttl=7 compress file_max=5M all_max=25M mode=0640
format=$((Time)(local.6))\ $Host\ $(Sender)[$(PID):$(TID)]\ <$((Level) (str))>:\ $(Message)
? [= Facility com.paloaltonetworks.traps] [<= Level info] file traps.log
此配置语法解释如下 link:
https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man5/asl.conf.5.html
我有一个多线程项目,其中每个线程都使用 asl 生成一些日志消息。
为了简化调试,我决定将所有这些消息集中在一个单独的文件中(我们称之为 /tmp/aaa)。
因此,我将标准 asl_log 方法与对从该线程创建的第一条消息生成 asl_client 的惰性 c'tor 的调用包装在一起。
正如在下面的代码中所看到的,我已将 asl_client 消息目标配置为文件 /tmp/aaa,方法是打开具有写入和追加属性的文件。
我的问题是关于保持此代码线程安全。在同一个目标文件上为每个线程创建一个单独的 fd(file desc) 时我是对的吗?我了解到,当使用默认目标文件 (/var/log/system.log) 时,线程安全是有保证的,但在我的场景中是不是这样。
感谢
#define log_error(fmt, ...) do { \
lazy_asl_client_ctor(); \
log_per_level(ASL_LEVEL_CRIT ,fmt, ##__VA_ARGS__);\
} while (0)
void lazy_asl_client_ctor() {
if (__improbable(!log_asl_client_get())) {
// set aslmsg and with a new key named TID (thread-id)
asl_msg_set((aslmsg*) malloc(sizeof(aslmsg)));
*asl_msg_get() = asl_new(ASL_TYPE_MSG);
uint64_t tid;
pthread_threadid_np(NULL, &tid);
char tid_str[100];
sprintf(tid_str,"%llu",tid);
asl_set(*asl_msg_get(), "TID", tid_str);
// set log client
log_asl_client_set((aslclient*) malloc (sizeof(aslclient)));
*log_asl_client_get() = asl_open(ProcessName(),NULL,ASL_OPT_STDERR);
// set the file that will receive all thread messages
int fd = open("/tmp/aaa", O_RDWR | O_CREAT | O_APPEND, 0777);
asl_add_output_file(*log_asl_client_get(), fd, "$Time $Host $Sender [ $PID : $TID ] $Message",ASL_TIME_FMT_LCL, ASL_FILTER_MASK_UPTO(ASL_LEVEL_INFO), ASL_ENCODE_SAFE);
}
}
#define log_per_level(int_level, const_chars_fmt, ...) \
asl_log(*log_asl_client_get(), *asl_msg_get(), int_level, "[%s] (%s:%d):" const_chars_fmt, \
SRC_MODULE, __FILENAME__, __LINE__,##__VA_ARGS__)
经过一些研究,我发现了一种更简洁的方法来将我制作的多个软件组件的日志消息路由到一个单独的文件中:
asl 日志转到 syslogd,它根据 /etc/asl.conf 和 /etc/asl/
中规定的预定义配置决定如何处理消息为了正确路由消息,已将一个新文件添加到 /etc/asl/,其内容如下:
> traps.log rotate=utc ttl=7 compress file_max=5M all_max=25M mode=0640
format=$((Time)(local.6))\ $Host\ $(Sender)[$(PID):$(TID)]\ <$((Level) (str))>:\ $(Message)
? [= Facility com.paloaltonetworks.traps] [<= Level info] file traps.log
此配置语法解释如下 link: https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man5/asl.conf.5.html