[gnome-devel-docs] programming-guidelines: Add a page on log output
- From: Philip Withnall <pwithnall src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-devel-docs] programming-guidelines: Add a page on log output
- Date: Wed, 11 Feb 2015 10:23:47 +0000 (UTC)
commit 100e4c37125e49d036450123e624c3a35be6f91c
Author: Philip Withnall <philip withnall collabora co uk>
Date: Mon Feb 9 16:47:01 2015 +0000
programming-guidelines: Add a page on log output
https://bugzilla.gnome.org/show_bug.cgi?id=376123
programming-guidelines/C/logging.page | 219 +++++++++++++++++++++++++++++++++
programming-guidelines/Makefile.am | 1 +
2 files changed, 220 insertions(+), 0 deletions(-)
---
diff --git a/programming-guidelines/C/logging.page b/programming-guidelines/C/logging.page
new file mode 100644
index 0000000..b0354f1
--- /dev/null
+++ b/programming-guidelines/C/logging.page
@@ -0,0 +1,219 @@
+<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">
+
+ <info>
+ <link type="guide" xref="index#coding-style"/>
+
+ <credit type="author copyright">
+ <name>Philip Withnall</name>
+ <email its:translate="no">philip withnall collabora co uk</email>
+ <years>2015</years>
+ </credit>
+
+ <include href="cc-by-sa-3-0.xml" xmlns="http://www.w3.org/2001/XInclude"/>
+
+ <desc>
+ Logging debug and information output from libraries and programs
+ </desc>
+ </info>
+
+ <title>Logging</title>
+
+ <synopsis>
+ <title>Summary</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>
+ Use the GLib logging framework instead of logging directly to stderr and
+ 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>
+ Do not implement log rotation and deletion; leave that to system
+ services. (<link xref="#log-rotation"/>)
+ </p></item>
+ </list>
+ </synopsis>
+
+ <section id="glib-logging-framework">
+ <title>GLib Logging Framework</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 && (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);</code>
+
+ <section id="exceptions">
+ <title>Exceptions</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>
+ Do not use <code>g_warning()</code> in library code. Use
+ <link xref="coding-conventions#gerror-usage"><code>GError</code>s</link>
+ instead.
+ </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>
+ For more information, see this
+ <link href="http://0pointer.de/blog/projects/journal-submit.html">article
+ on logging to the journal</link>.
+ </p>
+ </section>
+
+ <section id="log-rotation">
+ <title>Log Rotation</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>
diff --git a/programming-guidelines/Makefile.am b/programming-guidelines/Makefile.am
index 910aec9..44428b8 100644
--- a/programming-guidelines/Makefile.am
+++ b/programming-guidelines/Makefile.am
@@ -14,6 +14,7 @@ HELP_FILES = \
documentation.page \
file-system.page \
index.page \
+ logging.page \
memory-management.page \
namespacing.page \
parallel-installability.page \
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]