Syslog API:如何在 C 中获取亚秒级时间戳(适用于 Python3)
Syslog API: How to get subsecond timestamps in C (works in Python3)
我有两个写入系统日志的测试程序,一个用 C 语言,一个用 Python3。这是一些示例输出(来自 /var/log/messages):
Dec 9 11:27:55.000 0c6e58933c36 c-logtest[206]: hello
Dec 9 11:27:55.000 0c6e58933c36 c-logtest[206]: world
Dec 9 11:27:59.584 0c6e58933c36 py-logtest[208]: hello
Dec 9 11:27:59.590 0c6e58933c36 py-logtest[208]: world
对于 c-logtest 程序,毫秒数 始终为 000,而显然适用于 py-logtest。我做错了什么?
c-logtest.c:
#include <syslog.h>
#include <unistd.h> //usleep
int main() {
openlog("c-logtest", LOG_CONS | LOG_NDELAY, LOG_USER);
syslog(LOG_INFO, "hello");
usleep(5000);
syslog(LOG_INFO, "world");
closelog();
return 0;
}
py-logtest.py
#!/usr/bin/env python3
import time
import logging
import logging.handlers
logger = logging.getLogger('')
handler = logging.handlers.SysLogHandler(address = '/dev/log')
handler.setFormatter(logging.Formatter('py-logtest %(message)s'))
logger.addHandler(handler)
logger.setLevel(logging.INFO)
logger.info("hello")
time.sleep(0.005)
logger.info("world")
我正在使用 syslog-ng,我已将其配置为生成毫秒分辨率时间戳,方法是将其添加到 syslog-ng.conf:
options{ frac-digits(3); };
提示:可以使用 docker run --rm -it fedora bash
以独立的方式重现此内容,然后从那里安装和配置 syslog-ng,运行 这两个程序,以及 tail -F /var/log/messages.
根据 this thread 系统日志的 glibc 实现 API 不会生成亚秒级时间戳精度。
你可以做的可能是使用 keep-timestamp(no)
syslog-ng 选项。这将使 syslog-ng 忽略与消息一起发送的时间戳,而是使用消息接收时间。这是否可以接受取决于您的用例。在大多数情况下,当 syslog 在本地运行时,这应该不是问题。但是 documentation 中有以下警告:
To use the S_ macros, the keep-timestamp() option must be enabled (this is the default behavior of syslog-ng PE).
我做了我自己的日志实现,它是这样做的:
(C++)
static void writeTimestamp(std::ofstream& out)
{
struct timeval now;
gettimeofday(&now, nullptr);
out << std::put_time(std::localtime(&now.tv_sec), "%F %T.");
char usecbuf[6+1];
snprintf(usecbuf, sizeof(usecbuf), "%06lu", now.tv_usec);
out << usecbuf;
}
要获得完整的解决方案,我需要重新实现系统日志库,但我没有。
我有两个写入系统日志的测试程序,一个用 C 语言,一个用 Python3。这是一些示例输出(来自 /var/log/messages):
Dec 9 11:27:55.000 0c6e58933c36 c-logtest[206]: hello
Dec 9 11:27:55.000 0c6e58933c36 c-logtest[206]: world
Dec 9 11:27:59.584 0c6e58933c36 py-logtest[208]: hello
Dec 9 11:27:59.590 0c6e58933c36 py-logtest[208]: world
对于 c-logtest 程序,毫秒数 始终为 000,而显然适用于 py-logtest。我做错了什么?
c-logtest.c:
#include <syslog.h>
#include <unistd.h> //usleep
int main() {
openlog("c-logtest", LOG_CONS | LOG_NDELAY, LOG_USER);
syslog(LOG_INFO, "hello");
usleep(5000);
syslog(LOG_INFO, "world");
closelog();
return 0;
}
py-logtest.py
#!/usr/bin/env python3
import time
import logging
import logging.handlers
logger = logging.getLogger('')
handler = logging.handlers.SysLogHandler(address = '/dev/log')
handler.setFormatter(logging.Formatter('py-logtest %(message)s'))
logger.addHandler(handler)
logger.setLevel(logging.INFO)
logger.info("hello")
time.sleep(0.005)
logger.info("world")
我正在使用 syslog-ng,我已将其配置为生成毫秒分辨率时间戳,方法是将其添加到 syslog-ng.conf:
options{ frac-digits(3); };
提示:可以使用 docker run --rm -it fedora bash
以独立的方式重现此内容,然后从那里安装和配置 syslog-ng,运行 这两个程序,以及 tail -F /var/log/messages.
根据 this thread 系统日志的 glibc 实现 API 不会生成亚秒级时间戳精度。
你可以做的可能是使用 keep-timestamp(no)
syslog-ng 选项。这将使 syslog-ng 忽略与消息一起发送的时间戳,而是使用消息接收时间。这是否可以接受取决于您的用例。在大多数情况下,当 syslog 在本地运行时,这应该不是问题。但是 documentation 中有以下警告:
To use the S_ macros, the keep-timestamp() option must be enabled (this is the default behavior of syslog-ng PE).
我做了我自己的日志实现,它是这样做的:
(C++)
static void writeTimestamp(std::ofstream& out)
{
struct timeval now;
gettimeofday(&now, nullptr);
out << std::put_time(std::localtime(&now.tv_sec), "%F %T.");
char usecbuf[6+1];
snprintf(usecbuf, sizeof(usecbuf), "%06lu", now.tv_usec);
out << usecbuf;
}
要获得完整的解决方案,我需要重新实现系统日志库,但我没有。