是否可以在 GLib 新结构化日志记录中为每个 domain/log_level 设置不同的编写器函数?
Is it possible to set different writer functions per domain/log_level in GLib new structured logging?
GLib 有一个有趣的功能:能够为每个不同的域和日志级别设置不同的日志记录(即:显示或保存等)功能,例如:
/* Set handler for warnings from empty (application) domain */
g_log_set_handler (NULL, G_LOG_LEVEL_WARNING, my_log_handler, NULL);
/* Set handler for critical messages from Gtk+ */
g_log_set_handler ("Gtk", G_LOG_LEVEL_CRITICAL, my_log_handler, NULL);
然而,正如文档所说:
This has no effect if structured logging is enabled; see Using
Structured Logging.
我没有找到与此功能相关的任何其他内容(即:per-domain/level 处理程序)。这不可能吗?为什么 GLib 会放弃这么有用的功能?
Is this not possible?
如果您真的想要,它仍然是,但根据用例,不这样做可能更明智(请参阅答案的第二部分)。
使用结构化日志记录实现自定义处理日志的新方法是 g_log_set_writer_func()
。
例如:
#define G_LOG_USE_STRUCTURED
#include <glib.h>
static GLogWriterOutput
my_log_writer_func (GLogLevelFlags log_level,
const GLogField *fields,
size_t n_fields,
void *user_data)
{
if (log_level & G_LOG_LEVEL_CRITICAL) {
// Do something special with criticals
// For example purposes, let's just log it to stdout/stderr
return g_log_writer_standard_streams (log_level, fields, n_fields, user_data);
}
if (log_level & G_LOG_LEVEL_DEBUG) {
// This is not something you should do since it will make
// debugging harder, but let's just do it for example purposes:
// by returning G_LOG_WRITER_HANDLED without actually logging it,
// the log message will not be outputted anywhere
return G_LOG_WRITER_HANDLED;
}
// If you _really_ want to, you can still check on the GLib domain,
// as it will be set in one of the GLogFields
// Default case: use the default logger
return g_log_writer_default (log_level, fields, n_fields, user_data);
}
int
main (int argc, char *argv[])
{
g_log_set_writer_func (my_log_writer_func, NULL, NULL);
// Run your application
}
Why would GLib resign of such an useful feature?
正如我之前提到的,GLib 并未硬性放弃对自定义日志实现的支持(请注意,这一切仅在您 显式 启用结构化日志记录时有效)。我相信一般的想法是越来越多的 GUI 应用程序从桌面(例如 GNOME Shell)或其他 UI 方式启动,因此要查看日志,您已经必须查看系统日志,例如使用 journalctl
.
到那时,当您可以使用系统日志时,在日志级别、日志域等方面过滤日志消息就容易多了。它还避免了必须告诉用户“再次运行它,但现在使用这些随机环境变量,如G_MESSAGES_DEBUG=all
”,因为他们可能不知道如何运行命令。它也可能是很难重现的东西,所以手边有调试日志会很有用。
journalctl 的一些示例命令是:(请注意,您可以轻松组合过滤器)
# Only show logs of the application with the given commandline name
$ journalctl _COMM=my-application-name
# Only show logs of your application with a given pid
$ journalctl _PID=$YOUR_APPS_PID
# Only show logs of your application with level WARNING or higher
$ journalctl -p warning
# Only show logs with with the given GLib domain
$ journalctl -f GLIB_DOMAIN=Gtk
GLib 有一个有趣的功能:能够为每个不同的域和日志级别设置不同的日志记录(即:显示或保存等)功能,例如:
/* Set handler for warnings from empty (application) domain */
g_log_set_handler (NULL, G_LOG_LEVEL_WARNING, my_log_handler, NULL);
/* Set handler for critical messages from Gtk+ */
g_log_set_handler ("Gtk", G_LOG_LEVEL_CRITICAL, my_log_handler, NULL);
然而,正如文档所说:
This has no effect if structured logging is enabled; see Using Structured Logging.
我没有找到与此功能相关的任何其他内容(即:per-domain/level 处理程序)。这不可能吗?为什么 GLib 会放弃这么有用的功能?
Is this not possible?
如果您真的想要,它仍然是,但根据用例,不这样做可能更明智(请参阅答案的第二部分)。
使用结构化日志记录实现自定义处理日志的新方法是 g_log_set_writer_func()
。
例如:
#define G_LOG_USE_STRUCTURED
#include <glib.h>
static GLogWriterOutput
my_log_writer_func (GLogLevelFlags log_level,
const GLogField *fields,
size_t n_fields,
void *user_data)
{
if (log_level & G_LOG_LEVEL_CRITICAL) {
// Do something special with criticals
// For example purposes, let's just log it to stdout/stderr
return g_log_writer_standard_streams (log_level, fields, n_fields, user_data);
}
if (log_level & G_LOG_LEVEL_DEBUG) {
// This is not something you should do since it will make
// debugging harder, but let's just do it for example purposes:
// by returning G_LOG_WRITER_HANDLED without actually logging it,
// the log message will not be outputted anywhere
return G_LOG_WRITER_HANDLED;
}
// If you _really_ want to, you can still check on the GLib domain,
// as it will be set in one of the GLogFields
// Default case: use the default logger
return g_log_writer_default (log_level, fields, n_fields, user_data);
}
int
main (int argc, char *argv[])
{
g_log_set_writer_func (my_log_writer_func, NULL, NULL);
// Run your application
}
Why would GLib resign of such an useful feature?
正如我之前提到的,GLib 并未硬性放弃对自定义日志实现的支持(请注意,这一切仅在您 显式 启用结构化日志记录时有效)。我相信一般的想法是越来越多的 GUI 应用程序从桌面(例如 GNOME Shell)或其他 UI 方式启动,因此要查看日志,您已经必须查看系统日志,例如使用 journalctl
.
到那时,当您可以使用系统日志时,在日志级别、日志域等方面过滤日志消息就容易多了。它还避免了必须告诉用户“再次运行它,但现在使用这些随机环境变量,如G_MESSAGES_DEBUG=all
”,因为他们可能不知道如何运行命令。它也可能是很难重现的东西,所以手边有调试日志会很有用。
journalctl 的一些示例命令是:(请注意,您可以轻松组合过滤器)
# Only show logs of the application with the given commandline name
$ journalctl _COMM=my-application-name
# Only show logs of your application with a given pid
$ journalctl _PID=$YOUR_APPS_PID
# Only show logs of your application with level WARNING or higher
$ journalctl -p warning
# Only show logs with with the given GLib domain
$ journalctl -f GLIB_DOMAIN=Gtk