Skip to content

Commit c146846

Browse files
committed
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.
1 parent 559079e commit c146846

File tree

2 files changed

+57
-0
lines changed

2 files changed

+57
-0
lines changed

meson.build

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ gtk_layer_shell = dependency('gtk-layer-shell-0', version: ['>=0.9.0'],
111111
default_options: ['introspection=false', 'vapi=false'],
112112
fallback: ['gtk-layer-shell', 'gtk_layer_shell'])
113113
systemd = dependency('systemd', required: get_option('systemd'))
114+
libsystemd = dependency('libsystemd', required: get_option('systemd'))
115+
if libsystemd.found()
116+
add_project_arguments('-DHAVE_LIBSYSTEMD', language: 'cpp')
117+
endif
114118

115119
cpp_lib_chrono = compiler.compute_int('__cpp_lib_chrono', prefix : '#include <chrono>')
116120
have_chrono_timezones = cpp_lib_chrono >= 201611
@@ -541,6 +545,7 @@ executable(
541545
upower_glib,
542546
pipewire,
543547
playerctl,
548+
libsystemd,
544549
libpulse,
545550
libjack,
546551
libwireplumber,

src/main.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,17 @@
77
#include <list>
88
#include <mutex>
99

10+
#ifdef HAVE_LIBSYSTEMD
11+
#include <spdlog/sinks/systemd_sink.h>
12+
#include <sys/stat.h>
13+
14+
#include <cassert>
15+
#include <charconv>
16+
#include <cstddef>
17+
#include <cstdlib>
18+
#include <system_error>
19+
#endif
20+
1021
#include "bar.hpp"
1122
#include "client.hpp"
1223
#include "util/SafeSignal.hpp"
@@ -154,7 +165,48 @@ static void handleSignalMainThread(int signum, bool& reload) {
154165
}
155166
}
156167

168+
static void logToJournalIfRunAsService() {
169+
#ifdef HAVE_LIBSYSTEMD
170+
/* Implementation of automatic protocol upgrading (from stderr to journal)
171+
** as described in https://systemd.io/JOURNAL_NATIVE_PROTOCOL */
172+
char const* journal_stream = std::getenv("JOURNAL_STREAM");
173+
174+
if (journal_stream != nullptr) {
175+
dev_t device;
176+
ino_t inode;
177+
size_t len = std::strlen(journal_stream);
178+
179+
auto result = std::from_chars(journal_stream, journal_stream + len, device);
180+
if (result.ec == std::errc{})
181+
result = std::from_chars(result.ptr + 1, journal_stream + len, inode);
182+
if (result.ec != std::errc{}) {
183+
spdlog::warn("malformed JOURNAL_STREAM (\"{}\"): {}, logging to console", journal_stream,
184+
std::make_error_condition(result.ec).message());
185+
}
186+
187+
struct stat f_stderr;
188+
189+
if (fstat(STDERR_FILENO, &f_stderr) != 0) {
190+
spdlog::warn("unable to check stderr device and inode numbers: {}", strerror(errno));
191+
} else if (device == f_stderr.st_dev && inode == f_stderr.st_ino) {
192+
auto journald = spdlog::systemd_logger_st("native_journal", "waybar", false);
193+
/* systemd_logger_st is thread-safe with enable_formatter = false
194+
** thanks to underlying sd_journal_send being thread-safe
195+
** https://github.com/gabime/spdlog/issues/2320#issuecomment-1079766037
196+
*/
197+
spdlog::set_default_logger(journald);
198+
} else {
199+
spdlog::info("JOURNAL_STREAM does not point to stderr, logging to console");
200+
}
201+
} else {
202+
spdlog::info("no JOURNAL_STREAM, logging to console");
203+
}
204+
#endif
205+
}
206+
157207
int main(int argc, char* argv[]) {
208+
logToJournalIfRunAsService();
209+
158210
try {
159211
auto* client = waybar::Client::inst();
160212

0 commit comments

Comments
 (0)