GLib had an interesting feature: ability to set different logging (i.e.: displaying or saving, etc.) functions per different domains and log-levels, e.g.:
/* 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);
However, as docs say:
This has no effect if structured logging is enabled; see Using Structured Logging.
I didn't find anything else related to this feature (i.e.: to per-domain/level handlers). Is this not possible? Why would GLib resign of such an useful feature?
Is this not possible?
It still is if you really want to, but depending on the use case, it might be wiser not to (see the second part of the answer).
The new way of implementing custom handling logs with structured logging is by g_log_set_writer_func()
.
For example:
#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?
As I mentioned earlier, GLib is not hard dropping support for custom log implementations (note that this all only works if you explicitly enable structured logging). I believe the general idea is that more and more GUI apps are being launched from the desktop (e.g. GNOME Shell) or other UI means, so to see logs, you already have to look at the system journal, for example using journalctl
.
At that point, when you can use the system journal, it's much easier to filter log messages on log level, log domain, and so on. It also prevents having to tell users to "run it again, but now use these random environment variables like G_MESSAGES_DEBUG=all
", as they might not have a clue how to run commands. It might also be something that is very hard to reproduce, so having the debug logs already at hand can be useful.
Some example commands with journalctl are: (note that you can easily combine filters)
# 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