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:
Max Gautier
2025-12-11 21:58:09 +01:00
parent 161367d961
commit 2c9e83441a
2 changed files with 57 additions and 0 deletions
+5
View File
@@ -111,6 +111,10 @@ gtk_layer_shell = dependency('gtk-layer-shell-0', version: ['>=0.9.0'],
default_options: ['introspection=false', 'vapi=false'], default_options: ['introspection=false', 'vapi=false'],
fallback: ['gtk-layer-shell', 'gtk_layer_shell']) fallback: ['gtk-layer-shell', 'gtk_layer_shell'])
systemd = dependency('systemd', required: get_option('systemd')) 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>') cpp_lib_chrono = compiler.compute_int('__cpp_lib_chrono', prefix : '#include <chrono>')
have_chrono_timezones = cpp_lib_chrono >= 201611 have_chrono_timezones = cpp_lib_chrono >= 201611
@@ -541,6 +545,7 @@ executable(
upower_glib, upower_glib,
pipewire, pipewire,
playerctl, playerctl,
libsystemd,
libpulse, libpulse,
libjack, libjack,
libwireplumber, libwireplumber,
+52
View File
@@ -7,6 +7,17 @@
#include <list> #include <list>
#include <mutex> #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 "bar.hpp"
#include "client.hpp" #include "client.hpp"
#include "util/SafeSignal.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[]) { int main(int argc, char* argv[]) {
logToJournalIfRunAsService();
try { try {
auto* client = waybar::Client::inst(); auto* client = waybar::Client::inst();