How to set up GLib log output

,

Hi folks.

I am a new user of the GLib C library, which I have started using recently for a new project. Let me first say that it is awesome, thanks A LOT to the devs for this.

I have a few questions about the logging features of GLib. What I have understood so far is that it is better to use the structured logs, because it allows for better filtering. So what I am currently doing is to define G_LOG_STRUCTURED before including the headers, then I use g_info(), g_debug(), g_error(), etc. to avoid using directly g_log_structured().

  • My main confusion is on filtering the output of my program depending on the log level I need. I understand that by default, info and debug logs are not displayed, unless setting G_MESSAGES_DEBUG=all at runtime. What I could not figure out however, is how to show the info logs, but not the debug logs. And in general, I can’t figure out how to set the log level of my program’s output. Can someone give some pointers on how to set the output log level inside the source code, as well as at runtime ? For example, I’m looking for a behavior similar to GStreamer’s GST_DEBUG environment variable, as described here : https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html?gi-language=c

  • Second question : when I use g_log_set_writer_func() by passing it either g_log_writer_standard_streams, or g_log_writer_journald, it looks like the info and debug logs are always outputted, no matter the value of G_DEBUG_MESSAGES. Is that an expected behavior ?

  • And my last question : If I leave the log writer func to g_log_writer_default(), I understand from the documentation that it should decide on its own whether to output to stdout/stderr or to journald. On what basis does it decide to switch to journald ? I could only get stdout/stderr output so far. But I may not have tried all the possible ways of launching my programs.

Thanks for your time.

Robin

Maybe it is interesting for you. Hm, GTK+3.94 Inspector has login support.

Hi Josef, I’m not sure to understand what you mean ?.. Besides I’m not using GTK, only GLib.

Hey Robin,

Structured logging is definitely the way to go. I assume you’ve read the docs, including the HOWTO, and the intro at the top of the API docs. If you haven’t seen it, this blog post is useful as well.

Anyway, to answer your questions:

  1. If you have a look at the source for g_log_structured_array, which is the main function that all the others end up calling, you can see it doesn’t do anything except just pass the log data on to the writer. So if you want to control logging levels from within the app, you need to do it from the log writer function itself. One approach would be to write your own custom writer function that filters out log messages you don’t want to see and pass the rest to one of the standard writers.

  2. If you look at the API docs for g_log_writer_default (the default writer), you’ll see it drops info and debug messages unless G_MESSAGES_DEBUG is set. Likewise as the API docs for g_log_writer_standard_streams and g_log_writer_journald state, they log all messages. So yes, that’s both the documented and expected behaviour. :slight_smile:

  3. Looking at the source for the default writer is useful here, too. You can see that calls g_log_writer_is_journald(), which checks to see if stderr is connected to the journal. If so, g_log_writer_journald is used. So if you are using the default handler, the program will need to be launched via systemd to log to the journal.

Hope that helps.

2 Likes

Hi Michael,

Thanks for the detailed answer. All is clear regarding 2) and 3).

About 1) :

If I understand correctly, I should create a function of type GLogWriterFunc, which basically does the following :

if(actualLogLevel > wantedLogLevel)
    do_nothing();
else
    g_log_writer_standard_streams(ALL_THE_ARGUMENTS); //or journald

And pass it to g_log_set_writer_func(), is that right ?

I’ll try as soon as I can.

Thanks !

That’s the basic idea, yup! How did it it work out?

Hi Michael,

Sorry for this late answer. I just tried it and it looks like it works as I wanted. Thanks for your help !

Here is my GLogWriterFunc in case it is of help to someone else :

GLogWriterOutput logWriter
(
    GLogLevelFlags LogLevel,
    const GLogField *Fields,
    gsize NumberOfFields,
    gpointer Data
)
{
    if(LogLevel > G_LOG_LEVEL_INFO)
        return G_LOG_WRITER_HANDLED;

    if(((DiscoveryCLIParameters*) Data)->DiscoverTerminal)
        g_log_writer_standard_streams(LogLevel, Fields, NumberOfFields, NULL);
    else
        g_log_writer_journald(LogLevel, Fields, NumberOfFields, NULL);

    return G_LOG_WRITER_HANDLED;
} 

I did not yet include a switch to choose the log level, but it’s a cakewalk from now on.

Thanks again !

3 Likes

No problem, glad it worked! :slight_smile:

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.