<?xml version="1.0" encoding="utf-8"?>
<page xmlns="http://projectmallard.org/1.0/" xmlns:its="http://www.w3.org/2005/11/its" xmlns:xi="http://www.w3.org/2003/XInclude" type="topic" id="logging" xml:lang="sv">

  <info>
    <link type="guide" xref="index#specific-how-tos"/>

    <credit type="author copyright">
      <name>Philip Withnall</name>
      <email its:translate="no">philip.withnall@collabora.co.uk</email>
      <years>2015</years>
    </credit>

    <include xmlns="http://www.w3.org/2001/XInclude" href="cc-by-sa-3-0.xml"/>

    <desc>Logga felsöknings- och informationsutdata från bibliotek och program</desc>
  
    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
      <mal:name>Anders Jonsson</mal:name>
      <mal:email>anders.jonsson@norsjovallen.se</mal:email>
      <mal:years>2018</mal:years>
    </mal:credit>
  </info>

  <title>Loggning</title>

  <synopsis>
    <title>Sammanfattning</title>

    <p>
      Logging debug and informational output from libraries and programs is an
      open problem, and there are various methods for converting multiple
      streams of log output into the customary stdout and stderr streams. Below
      are some suggestions for how to implement logging. However, the most
      important thing is to ensure that logging is consistent, so that log data
      can be accessed and searched with a minimum of effort, since that’s what
      it’s used for. Using different logging mechanisms and formats in different
      projects is not the right approach.
    </p>

    <list>
      <item><p>Använd GLibs ramverk för loggning istället för att logga direkt till stderr och stdout. (<link xref="#glib-logging-framework"/>)</p></item>
      <item><p>
        If systemd can be a dependency of the project, consider logging directly
        to the journal. (<link xref="#journald-integration"/>)
      </p></item>
      <item><p>Implementera inte rotation och borttagning av loggar, lämna det till systemtjänster. (<link xref="#log-rotation"/>)</p></item>
    </list>
  </synopsis>

  <section id="glib-logging-framework">
    <title>GLib-ramverk för loggning</title>

    <p>
      GLib provides
      <link href="https://developer.gnome.org/glib/stable/glib-Message-Logging.html">a
      logging framework</link> based around the
      <link href="https://developer.gnome.org/glib/stable/glib-Message-Logging.html#g-log"><code>g_log()</code></link>
      function, with convenience wrappers
      <link href="https://developer.gnome.org/glib/stable/glib-Message-Logging.html#g-debug"><code>g_debug()</code></link>,
      <link href="https://developer.gnome.org/glib/stable/glib-Message-Logging.html#g-message"><code>g_message()</code></link>,
      <link href="https://developer.gnome.org/glib/stable/glib-Message-Logging.html#g-warning"><code>g_warning()</code></link>
      and
      <link href="https://developer.gnome.org/glib/stable/glib-Message-Logging.html#g-error"><code>g_error()</code></link>.
      The GLib logging framework has a few useful features:
    </p>
    <list>
      <item><p>
        Programmatic redirection of log messages using
        <link href="https://developer.gnome.org/glib/stable/glib-Message-Logging.html#g-log-set-handler"><code>g_log_set_handler()</code></link>.
      </p></item>
      <item><p>
        Multiple logging domains, which can be processed separately.
      </p></item>
      <item><p>
        Multiple log levels, which can be processed separately. For example,
        this allows debug messages to be turned on and off at runtime.
      </p></item>
      <item><p>
        Support for automatically aborting a program on ‘fatal’ messages.
      </p></item>
    </list>

    <p>
      These should be used in preference to functions like
      <code>printf()</code>,
      <link href="https://developer.gnome.org/glib/stable/glib-Warnings-and-Assertions.html#g-print"><code>g_print()</code></link>
      and
      <link href="https://developer.gnome.org/glib/stable/glib-Warnings-and-Assertions.html#g-printerr"><code>g_printerr()</code></link>,
      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.
    </p>

    <p>
      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.
    </p>

    <p>
      To use the GLib logging framework, define
      <link href="https://developer.gnome.org/glib/stable/glib-Message-Logging.html#G-LOG-DOMAIN:CAPS"><code>G_LOG_DOMAIN</code></link>
      for the project so it’s unique from all other projects. Call
      <code>g_debug("Message")</code> to log a debug message.
    </p>

    <p>
      If the default GLib log handlers are not sufficient, for example if log
      messages need to be in a custom format or
      <link xref="#journald-integration">journald integration</link> is needed,
      set up a log handler with the following code:
    </p>
    <code mime="text/x-csrc">
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 &amp;&amp; (log_level &amp; G_LOG_LEVEL_DEBUG))
    {
      return;
    }

  log_level_str = log_level_to_string (log_level &amp; G_LOG_LEVEL_MASK);

  /* Use g_printerr() for warnings and g_print() otherwise. */
  if (flags &lt;= 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);</code>

    <section id="exceptions">
      <title>Undantag</title>

      <list>
        <item><p>
          Do not use <code>g_message()</code> in normal code to print output.
          Printing output should be done at the top level of an application,
          using <code>g_print()</code>, and should be quite rare; i.e. only done
          in command line applications.
        </p></item>
        <item><p>Använd inte <code>g_warning()</code> i bibliotekskod. Använd <link xref="gerror"><code>GError</code></link> istället.</p></item>
        <item><p>
          Similarly, do not set up log handlers in library code. Log messages
          should propagate through library code and be handled in a log handler
          at the top level of an application.
        </p></item>
      </list>
    </section>
  </section>

  <section id="journald-integration">
    <title>journald-integration</title>

    <p>
      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 <code>systemd-journal</code> as a
      dependency to a project, the project’s log handling function could be
      extended to use
      <link href="http://0pointer.de/public/systemd-man/sd_journal_send.html"><code>sd_journal_print()</code>
      and <code>sd_journal_send()</code></link> instead of
      <code>g_print()</code> and <code>g_printerr()</code>.
    </p>

    <p>För mer information, se denna <link href="http://0pointer.de/blog/projects/journal-submit.html">artikel om att logga till journalen</link>.</p>
  </section>

  <section id="log-rotation">
    <title>Rotation av loggar</title>

    <p>
      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 <cmd>logrotate</cmd> or <cmd>systemd-journald</cmd>.
    </p>
  </section>
</page>
