aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bbot/buildfile2
-rw-r--r--bbot/diagnostics.cxx77
2 files changed, 75 insertions, 4 deletions
diff --git a/bbot/buildfile b/bbot/buildfile
index 8da2b70..f57edcb 100644
--- a/bbot/buildfile
+++ b/bbot/buildfile
@@ -36,6 +36,8 @@ if ($cxx.target.class == "linux")
{hxx ixx cxx}{agent-options} \
../libue{bbot}
}
+
+ cxx.libs += -ldl
}
./: exe{bbot-worker}: worker/{hxx ixx txx cxx}{+worker} worker/libue{bbot}
diff --git a/bbot/diagnostics.cxx b/bbot/diagnostics.cxx
index bbdef3b..e5f5747 100644
--- a/bbot/diagnostics.cxx
+++ b/bbot/diagnostics.cxx
@@ -4,6 +4,15 @@
#include <bbot/diagnostics.hxx>
+#ifdef __linux__
+# define BBOT_SYSTEMD
+#endif
+
+#ifdef BBOT_SYSTEMD
+# include <dlfcn.h>
+# include <syslog.h> // LOG_*
+#endif
+
#include <bbot/utility.hxx>
using namespace std;
@@ -51,14 +60,73 @@ namespace bbot
const fail_end endf;
- // We used the right arrow Unicode character to signal line continuation.
- // It only looked cute when displayed properly.
- //
- const char systemd_indent[] = " \\\n";
+#ifndef BBOT_SYSTEMD
+ void
+ systemd_diagnostics (bool)
+ {
+ fail << "systemd mode only supported on Linux";
+ }
+#else
+
+ static const char systemd_indent[] = "\n";
+
+ static const char libsystemd[] = "libsystemd.so.0";
+ static int (*sd_journal_print) (int priority, const char *format, ...);
+
+ static void (*default_writer) (const diag_record&);
+
+ static void
+ systemd_writer (const diag_record& dr)
+ {
+ const string& s (dr.os.str ());
+
+ // Map "<N>..." prefix to priority.
+ //
+ int p (-1);
+ if (s.size () > 2 && s[0] == '<' && s[2] == '>')
+ {
+ char c (s[1]);
+ p = (c == '0' ? LOG_EMERG :
+ c == '1' ? LOG_ALERT :
+ c == '2' ? LOG_CRIT :
+ c == '3' ? LOG_ERR :
+ c == '4' ? LOG_WARNING :
+ c == '5' ? LOG_NOTICE :
+ c == '6' ? LOG_INFO :
+ c == '7' ? LOG_DEBUG : p);
+ }
+
+ if (p == -1 || sd_journal_print (p, "%s", s.c_str () + 3) != 0)
+ default_writer (dr);
+ }
void
systemd_diagnostics (bool with_critical)
{
+ // Using sd_journal_print() allows us to print multi-line records nicely.
+ // However, requiring libsystemd-dev (or equivalent) is a bit of a schlep
+ // so we use the dynamic loading trick.
+ //
+ // Note that we could also fallback to stderr output (which is how it
+ // worked before) if we cannot load the library or resolve the symbol for
+ // some reason. But for now we fail to keep things simple.
+ //
+ void* libsd (dlopen (libsystemd, RTLD_LAZY | RTLD_GLOBAL));
+
+ if (libsd == nullptr)
+ fail << "unable to load " << libsystemd << ": " << dlerror ();
+
+ sd_journal_print =
+ function_cast<decltype(sd_journal_print)> (
+ dlsym (libsd, "sd_journal_print"));
+
+ if (sd_journal_print == nullptr)
+ fail << "unable to lookup sd_journal_print() in " << libsystemd << ": "
+ << dlerror ();
+
+ default_writer = diag_record::writer;
+ diag_record::writer = &systemd_writer;
+
trace_indent =
fail.indent_ =
error.indent_ =
@@ -74,6 +142,7 @@ namespace bbot
info.type_ = "<6>";
trace_type = "<7>";
}
+#endif
// tracer
//