9#include "../log/sink.hpp"
14#include <systemd/sd-daemon.h>
15#include <systemd/sd-journal.h>
19template <std::
size_t MessageCapacity, std::
size_t IdentifierCapacity>
class systemd_sink;
22template <std::
size_t MessageCapacity, std::
size_t IdentifierCapacity>
struct systemd_sink_tag {};
24template <std::
size_t MessageCapacity = 512, std::
size_t IdentifierCapacity = 64>
27 static_assert(MessageCapacity > 0,
"Message capacity must be at least 1 byte");
28 static_assert(IdentifierCapacity > 0,
"Identifier capacity must be at least 1 byte");
31 using write_fn_t = void (*)(
int priority, microfmt::string_view identifier, microfmt::string_view message)
noexcept;
41 write_fn_(priority_for(msg.lvl), msg.logger_name, msg.payload);
46 static void write_to_journal(
int priority, microfmt::string_view identifier, microfmt::string_view message)
noexcept {
47 if (::sd_booted() <= 0) {
48 write_to_stdio(identifier, message);
52 char priority_field[] =
"PRIORITY=0";
53 priority_field[9] =
static_cast<char>(
'0' + priority);
56 const auto identifier_out = identifier_field.
as_sink();
57 identifier_out.write(
"SYSLOG_IDENTIFIER=");
58 identifier_out.write(identifier.empty() ?
"microfmt" : identifier);
61 const auto message_out = message_field.
as_sink();
62 message_out.write(
"MESSAGE=");
63 message_out.write(message);
65 const auto identifier_view = identifier_field.
view();
66 const auto message_view = message_field.
view();
67 const iovec fields[] = {
68 {priority_field,
sizeof(priority_field) - 1},
69 {
const_cast<char *
>(identifier_view.data()), identifier_view.size()},
70 {
const_cast<char *
>(message_view.data()), message_view.size()},
72 if (::sd_journal_sendv(fields, 3) < 0) {
73 write_to_stdio(identifier, message);
77 static void write_to_stdio(microfmt::string_view identifier, microfmt::string_view message)
noexcept {
78 buffer_sink<MessageCapacity + IdentifierCapacity + 4> output;
79 const auto out = output.as_sink();
80 if (!identifier.empty()) {
87 static int priority_for(
level lvl)
noexcept {
115template <std::
size_t MessageCapacity, std::
size_t IdentifierCapacity>
119 static void log(value_ref<context_type> ctx,
const log_msg &msg)
noexcept { ctx->log_impl(msg); }
Output sink that stores formatted characters in an internal fixed-size stack/inline buffer.
Definition microfmt.hpp:185
constexpr microfmt::string_view view() const &noexcept RELOCO_LIFETIMEBOUND
Returns a string view over the characters written so far.
Definition microfmt.hpp:245
RELOCO_END_UNSAFE_BUFFER_USAGE RELOCO_CONSTEXPR20 sink as_sink() &noexcept RELOCO_LIFETIMEBOUND
Creates a type-erased sink adapter pointing to this instance.
Definition microfmt.hpp:236
Type-erased, two-word handle to a log sink backend, plus the severity threshold below which records a...
Definition sink.hpp:73
Adapter that writes structured records to the systemd journal.
Definition systemd_sink.hpp:26
void log_impl(const log_msg &msg) noexcept
Definition systemd_sink.hpp:39
void(*)(int priority, microfmt::string_view identifier, microfmt::string_view message) noexcept write_fn_t
Definition systemd_sink.hpp:31
log_sink as_sink() noexcept RELOCO_LIFETIMEBOUND
Definition systemd_sink.hpp:35
constexpr systemd_sink(write_fn_t write_fn=write_to_journal) noexcept
Definition systemd_sink.hpp:33
Definition default_log_sink.template.hpp:51
level
Shared log severity levels in ascending order.
Definition log_msg.hpp:22
systemd_sink() -> systemd_sink<>
RELOCO_END_UNSAFE_CODE sink stdout_sink() noexcept
Definition stdio.hpp:36
RELOCO_CONSTEXPR20 void format_to(const sink &out, microfmt::string_view fmt, const Args &...args) noexcept
Definition microfmt.hpp:1766
Structured log record forwarded by a logger to each sink.
Definition log_msg.hpp:69
static void log(value_ref< context_type > ctx, const log_msg &msg) noexcept
Definition systemd_sink.hpp:119
Static customization point describing a log sink backend.
Definition sink.hpp:46
Tag selecting systemd_sink<MessageCapacity, IdentifierCapacity> as a log_sink backend.
Definition systemd_sink.hpp:22