log: use native journald protocol for when running as a service
When running waybar as a systemd service, allows a slighty more readable and searchable (in particular, by log level) using journal metadata.
This commit is contained in:
@@ -111,6 +111,10 @@ gtk_layer_shell = dependency('gtk-layer-shell-0', version: ['>=0.9.0'],
|
||||
default_options: ['introspection=false', 'vapi=false'],
|
||||
fallback: ['gtk-layer-shell', 'gtk_layer_shell'])
|
||||
systemd = dependency('systemd', required: get_option('systemd'))
|
||||
libsystemd = dependency('libsystemd', required: get_option('systemd'))
|
||||
if libsystemd.found()
|
||||
add_project_arguments('-DHAVE_LIBSYSTEMD', language: 'cpp')
|
||||
endif
|
||||
|
||||
cpp_lib_chrono = compiler.compute_int('__cpp_lib_chrono', prefix : '#include <chrono>')
|
||||
have_chrono_timezones = cpp_lib_chrono >= 201611
|
||||
@@ -541,6 +545,7 @@ executable(
|
||||
upower_glib,
|
||||
pipewire,
|
||||
playerctl,
|
||||
libsystemd,
|
||||
libpulse,
|
||||
libjack,
|
||||
libwireplumber,
|
||||
|
||||
@@ -7,6 +7,17 @@
|
||||
#include <list>
|
||||
#include <mutex>
|
||||
|
||||
#ifdef HAVE_LIBSYSTEMD
|
||||
#include <spdlog/sinks/systemd_sink.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <charconv>
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <system_error>
|
||||
#endif
|
||||
|
||||
#include "bar.hpp"
|
||||
#include "client.hpp"
|
||||
#include "util/SafeSignal.hpp"
|
||||
@@ -154,7 +165,48 @@ static void handleSignalMainThread(int signum, bool& reload) {
|
||||
}
|
||||
}
|
||||
|
||||
static void logToJournalIfRunAsService() {
|
||||
#ifdef HAVE_LIBSYSTEMD
|
||||
/* Implementation of automatic protocol upgrading (from stderr to journal)
|
||||
** as described in https://systemd.io/JOURNAL_NATIVE_PROTOCOL */
|
||||
char const* journal_stream = std::getenv("JOURNAL_STREAM");
|
||||
|
||||
if (journal_stream != nullptr) {
|
||||
dev_t device;
|
||||
ino_t inode;
|
||||
size_t len = std::strlen(journal_stream);
|
||||
|
||||
auto result = std::from_chars(journal_stream, journal_stream + len, device);
|
||||
if (result.ec == std::errc{})
|
||||
result = std::from_chars(result.ptr + 1, journal_stream + len, inode);
|
||||
if (result.ec != std::errc{}) {
|
||||
spdlog::warn("malformed JOURNAL_STREAM (\"{}\"): {}, logging to console", journal_stream,
|
||||
std::make_error_condition(result.ec).message());
|
||||
}
|
||||
|
||||
struct stat f_stderr;
|
||||
|
||||
if (fstat(STDERR_FILENO, &f_stderr) != 0) {
|
||||
spdlog::warn("unable to check stderr device and inode numbers: {}", strerror(errno));
|
||||
} else if (device == f_stderr.st_dev && inode == f_stderr.st_ino) {
|
||||
auto journald = spdlog::systemd_logger_st("native_journal", "waybar", false);
|
||||
/* systemd_logger_st is thread-safe with enable_formatter = false
|
||||
** thanks to underlying sd_journal_send being thread-safe
|
||||
** https://github.com/gabime/spdlog/issues/2320#issuecomment-1079766037
|
||||
*/
|
||||
spdlog::set_default_logger(journald);
|
||||
} else {
|
||||
spdlog::info("JOURNAL_STREAM does not point to stderr, logging to console");
|
||||
}
|
||||
} else {
|
||||
spdlog::info("no JOURNAL_STREAM, logging to console");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
logToJournalIfRunAsService();
|
||||
|
||||
try {
|
||||
auto* client = waybar::Client::inst();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user