>From 425058f3b187a3afe6339306bd6f2fca9ec3fbfd Mon Sep 17 00:00:00 2001
From: Stephen Gallagher <sgallagh@redhat.com>
Date: Fri, 20 Dec 2013 16:14:25 -0500
Subject: [PATCH 2/4] DEBUG: Enable sending structured debug logs to journald

We are now able to send structured debug logs to journald, tagged with
the code file, line number and domain that the log pertains to. To
enable this functionality, SSSD must be configured at build-time with
--with-syslog=journald and must be launched without -f/--debug-to-files

This behavior is nearly identical to how SSSD will function today on a
systemd-based system if --debug-to-files is disabled, since it will
redirect stdout and stderr into journald. This patch merely enhances
the situation to send structured logs instead of simple string messages.
---
 src/util/debug.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 90 insertions(+)

diff --git a/src/util/debug.c b/src/util/debug.c
index 601641c2ddf2f8b3d8b6ceb6499cfd4dfd5c2e9d..d17e388c2f840bde01fdd5020182d20d8aaa60b5 100644
--- a/src/util/debug.c
+++ b/src/util/debug.c
@@ -30,6 +30,10 @@
 #include <sys/stat.h>
 #include <sys/time.h>
 
+#ifdef WITH_JOURNALD
+#include <systemd/sd-journal.h>
+#endif
+
 #include "util/util.h"
 
 const char *debug_prg_name = "sssd";
@@ -129,6 +133,69 @@ static void debug_printf(const char *format, ...)
     va_end(ap);
 }
 
+#ifdef WITH_JOURNALD
+static errno_t journal_send(const char *file,
+                           long line,
+                           const char *function,
+                           int newlevel,
+                           const char *format,
+                           va_list ap)
+{
+    errno_t ret;
+    int res;
+    char *message = NULL;
+    char *code_file = NULL;
+    char *code_line = NULL;
+    const char *domain;
+
+    /* First, evaluate the message to be sent */
+    ret = vasprintf(&message, format, ap);
+    if (ret == -1) {
+        /* ENOMEM, just return */
+        return ENOMEM;
+    }
+
+    res = asprintf(&code_file, "CODE_FILE=%s", file);
+    if (res == -1) {
+        ret = ENOMEM;
+        goto journal_done;
+    }
+
+    res = asprintf(&code_line, "CODE_LINE=%ld", line);
+    if (res == -1) {
+        ret = ENOMEM;
+        goto journal_done;
+    }
+
+    /* If this log message was sent from a provider,
+     * track the domain.
+     */
+    domain = getenv(SSS_DOM_ENV);
+    if (domain == NULL) {
+        domain = "";
+    }
+
+    /* Send the log message to journald, specifying the
+     * source code location and other tracking data.
+     */
+    res = sd_journal_send_with_location(
+            code_file, code_line, function,
+            "MESSAGE=%s", message,
+            "PRIORITY=%i", LOG_DEBUG,
+            "SSSD_DOMAIN=%s", domain,
+            "SSSD_PRG_NAME=%s", debug_prg_name,
+            "SSSD_DEBUG_LEVEL=%x", newlevel,
+            NULL);
+    ret = -res;
+
+journal_done:
+    free(code_line);
+    free(code_file);
+    free(message);
+    return ret;
+}
+#endif /* WiTH_JOURNALD */
+
 void debug_fn(const char *file,
               long line,
               const char *function,
@@ -136,6 +203,29 @@ void debug_fn(const char *file,
               const char *format, ...)
 {
     va_list ap;
+
+#ifdef WITH_JOURNALD
+    errno_t ret;
+    if (!debug_file) {
+        /* If we are not outputting logs to files, we should be sending them
+         * to journald.
+         * NOTE: on modern systems, this is where stdout/stderr will end up
+         * from system services anyway. The only difference here is that we
+         * can also provide extra structuring data to make it more easily
+         * searchable.
+         */
+        va_start(ap, format);
+        ret = journal_send(file, line, function, newlevel, format, ap);
+        if (ret != EOK) {
+            /* Emergency fallback, send to STDERR */
+            debug_vprintf(format, ap);
+            debug_fflush();
+        }
+        va_end(ap);
+        return;
+    }
+#endif
+
     if (debug_timestamps) {
         struct timeval tv;
         struct tm *tm;
-- 
1.8.4.2

