spdlog
Loading...
Searching...
No Matches
systemd_sink.h
Go to the documentation of this file.
1// Copyright(c) 2019 ZVYAGIN.Alexander@gmail.com
2// Distributed under the MIT License (http://opensource.org/licenses/MIT)
3
4#pragma once
5
9
10#include <array>
11#ifndef SD_JOURNAL_SUPPRESS_LOCATION
12# define SD_JOURNAL_SUPPRESS_LOCATION
13#endif
14#include <systemd/sd-journal.h>
15
16namespace spdlog {
17namespace sinks {
18
19/**
20 * Sink that write to systemd journal using the `sd_journal_send()` library call.
21 *
22 * Locking is not needed, as `sd_journal_send()` itself is thread-safe.
23 */
24template<typename Mutex>
25class systemd_sink : public base_sink<Mutex>
26{
27public:
28 //
30 : syslog_levels_{{/* spdlog::level::trace */ LOG_DEBUG,
31 /* spdlog::level::debug */ LOG_DEBUG,
32 /* spdlog::level::info */ LOG_INFO,
33 /* spdlog::level::warn */ LOG_WARNING,
34 /* spdlog::level::err */ LOG_ERR,
35 /* spdlog::level::critical */ LOG_CRIT,
36 /* spdlog::level::off */ LOG_INFO}}
37 {}
38
39 ~systemd_sink() override {}
40
41 systemd_sink(const systemd_sink &) = delete;
43
44protected:
47
48 void sink_it_(const details::log_msg &msg) override
49 {
50 int err;
51
52 size_t length = msg.payload.size();
53 // limit to max int
54 if (length > static_cast<size_t>(std::numeric_limits<int>::max()))
55 {
56 length = static_cast<size_t>(std::numeric_limits<int>::max());
57 }
58
59 // Do not send source location if not available
60 if (msg.source.empty())
61 {
62 // Note: function call inside '()' to avoid macro expansion
63 err = (sd_journal_send)("MESSAGE=%.*s", static_cast<int>(length), msg.payload.data(), "PRIORITY=%d", syslog_level(msg.level),
64 "SYSLOG_IDENTIFIER=%.*s", static_cast<int>(msg.logger_name.size()), msg.logger_name.data(), nullptr);
65 }
66 else
67 {
68 err = (sd_journal_send)("MESSAGE=%.*s", static_cast<int>(length), msg.payload.data(), "PRIORITY=%d", syslog_level(msg.level),
69 "SYSLOG_IDENTIFIER=%.*s", static_cast<int>(msg.logger_name.size()), msg.logger_name.data(), "CODE_FILE=%s",
70 msg.source.filename, "CODE_LINE=%d", msg.source.line, "CODE_FUNC=%s", msg.source.funcname, nullptr);
71 }
72
73 if (err)
74 {
75 throw_spdlog_ex("Failed writing to systemd", errno);
76 }
77 }
78
80 {
81 return syslog_levels_.at(static_cast<levels_array::size_type>(l));
82 }
83
84 void flush_() override {}
85};
86
89} // namespace sinks
90
91// Create and register a syslog logger
92template<typename Factory = spdlog::synchronous_factory>
94{
95 return Factory::template create<sinks::systemd_sink_mt>(logger_name);
96}
97
98template<typename Factory = spdlog::synchronous_factory>
100{
101 return Factory::template create<sinks::systemd_sink_st>(logger_name);
102}
103} // namespace spdlog
T at(T... args)
int syslog_level(level::level_enum l)
void sink_it_(const details::log_msg &msg) override
systemd_sink(const systemd_sink &)=delete
systemd_sink & operator=(const systemd_sink &)=delete
T max(T... args)
Definition async.h:25
std::shared_ptr< logger > systemd_logger_mt(const std::string &logger_name)
std::shared_ptr< logger > systemd_logger_st(const std::string &logger_name)
SPDLOG_INLINE void throw_spdlog_ex(const std::string &msg, int last_errno)
Definition common-inl.h:68
string_view_t payload
Definition log_msg.h:30
level::level_enum level
Definition log_msg.h:21
string_view_t logger_name
Definition log_msg.h:20
const char * funcname
Definition common.h:255
SPDLOG_CONSTEXPR bool empty() const SPDLOG_NOEXCEPT
Definition common.h:249
const char * filename
Definition common.h:253