Philip Withnall
philip.withnall@collabora.co.uk 2015

This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.

As a special exception, the copyright holders give you permission to copy, modify, and distribute the example code contained in this document under the terms of your choosing, without restriction.

Registro de depuración y salida de información de bibliotecas y programas
Daniel Mustieles
daniel.mustieles@gmail.com 2016-2020
Javier Mazorra
mazi.debian@gmail.com 2016, 2020

# Registro

#

        Resumen

        El registro de la depuración y la salida informativa de bibliotecas y programas es un problema abierto, y existen varios métodos para convertir múltiples flujos de salida de registro en los flujos stdout y stderr habituales. A continuación se presentan algunas sugerencias sobre cómo implementar el registro. Sin embargo, lo más importante es garantizar que el registro sea coherente, de modo que se pueda acceder a los datos de registro y buscarlos con un mínimo de esfuerzo, ya que para eso se utilizan. El uso de diferentes mecanismos y formatos de registro en diferentes proyectos no es el enfoque correcto.

            Use the GLib logging framework instead of logging directly to stderr and
            stdout. ()

            If systemd can be a dependency of the project, consider logging directly
            to the journal. ()

            Do not implement log rotation and deletion; leave that to system
            services. ()

# Entorno de trabajo de registro de GLib

GLib provides a logging framework based around the `g_log()` function, with convenience wrappers `g_debug()`, `g_message()`, `g_warning()` and `g_error()`. The GLib logging framework has a few useful features:

Programmatic redirection of log messages using `g_log_set_handler()`.

Multiple logging domains, which can be processed separately.

Multiple log levels, which can be processed separately. For example, this allows debug messages to be turned on and off at runtime.

Support for automatically aborting a program on ‘fatal’ messages.

These should be used in preference to functions like `printf()`, `g_print()` and `g_printerr()`, due to their enhanced flexibility. The logging functions allow log processing to be done in code, rather than by external shell scripting, which simplifies everything.

A key reason to use the logging framework is that it is used in GLib and other related libraries already; by using it, all log messages are then going through the same system and can be processed similarly.

To use the GLib logging framework, define `G_LOG_DOMAIN` for the project so it’s unique from all other projects. Call `g_debug("Message")` to log a debug message.

If the default GLib log handlers are not sufficient, for example if log messages need to be in a custom format or journald integration is needed, set up a log handler with the following code:

static const gchar * log_level_to_string (GLogLevelFlags level) { switch (level) { case G_LOG_LEVEL_ERROR: return "ERROR"; case G_LOG_LEVEL_CRITICAL: return "CRITICAL"; case G_LOG_LEVEL_WARNING: return "WARNING"; case G_LOG_LEVEL_MESSAGE: return "MESSAGE"; case G_LOG_LEVEL_INFO: return "INFO"; case G_LOG_LEVEL_DEBUG: return "DEBUG"; default: return "UNKNOWN"; } }

static void log_handler_cb (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data) { const gchar *log_level_str;

/* Ignore debug messages if disabled. */ if (!debug_enabled && (log_level & G_LOG_LEVEL_DEBUG)) { return; }

log_level_str = log_level_to_string (log_level & G_LOG_LEVEL_MASK);

/* Use g_printerr() for warnings and g_print() otherwise. */ if (flags <= G_LOG_LEVEL_WARNING) { g_printerr ("%s: %s: %s\n", log_domain, log_level_str, message); } else { g_print ("%s: %s: %s\n", log_domain, log_level_str, message); } }

g_log_set_handler ("log-domain", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION, log_handler_cb, NULL);

## Excepciones

Do not use `g_message()` in normal code to print output. Printing output should be done at the top level of an application, using `g_print()`, and should be quite rare; i.e. only done in command line applications.

Do not use `g_warning()` in library code. Use `GError`s instead.

Del mismo modo, no configure controladores de registro en el código de la biblioteca. Los mensajes de registro deben propagarse a través del código de la biblioteca y manejarse en un controlador de registro en el nivel superior de una aplicación.

# Integración con journald

Compared to conventional syslog-style logs, journald supports storage of structured logging data, which can make post-hoc analysis of logs much easier. If it’s possible to add `systemd-journal` as a dependency to a project, the project’s log handling function could be extended to use `sd_journal_print()` and `sd_journal_send()` instead of `g_print()` and `g_printerr()`.

For more information, see this article on logging to the journal.

# Rotación de registros

Log file rotation is one feature which is out of scope of the GLib logging system. It should be handled by the normal system logging mechanisms, such as logrotate or systemd-journald.