|
7 | 7 | #include <list> |
8 | 8 | #include <mutex> |
9 | 9 |
|
| 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 | + |
10 | 21 | #include "bar.hpp" |
11 | 22 | #include "client.hpp" |
12 | 23 | #include "util/SafeSignal.hpp" |
@@ -154,7 +165,48 @@ static void handleSignalMainThread(int signum, bool& reload) { |
154 | 165 | } |
155 | 166 | } |
156 | 167 |
|
| 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 | + |
157 | 207 | int main(int argc, char* argv[]) { |
| 208 | + logToJournalIfRunAsService(); |
| 209 | + |
158 | 210 | try { |
159 | 211 | auto* client = waybar::Client::inst(); |
160 | 212 |
|
|
0 commit comments