diff options
-rw-r--r-- | bbot/buildfile | 2 | ||||
-rw-r--r-- | bbot/diagnostics.cxx | 77 |
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 // |