Add tcp_syslog_client_sink

Support for sending messages to remote syslog server over TCP
pull/2093/head
Маркелов Максим 4 years ago
parent a1d9f501e3
commit 3bc49604d7

@ -20,6 +20,7 @@ void user_defined_example();
void err_handler_example();
void syslog_example();
void custom_flags_example();
void tcp_syslog_client_example();
#include "spdlog/spdlog.h"
#include "spdlog/cfg/env.h" // support for loading levels from the environment variable
@ -292,3 +293,10 @@ void custom_flags_example()
formatter->add_flag<my_formatter_flag>('*').set_pattern("[%n] [%*] [%^%l%$] %v");
spdlog::set_formatter(std::move(formatter));
}
#include "spdlog/sinks/syslog_client_sinks.h"
void tcp_syslog_client_example()
{
auto syslog_logger = spdlog::tcp_syslog_client_logger_mt("syslog_client", {"127.0.0.1", 514});
syslog_logger->warn("This message will be sended to syslog server");
}

@ -0,0 +1,51 @@
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
namespace spdlog {
namespace details {
// https://datatracker.ietf.org/doc/html/rfc5424#section-6.2.1
struct syslog_consts {
enum level {
SL_EMERG = 0,
SL_ALERT,
SL_CRIT,
SL_ERR,
SL_WARNING,
SL_NOTICE,
SL_INFO,
SL_DEBUG
};
enum facility {
SF_KERN = 0,
SF_USER,
SF_MAIL,
SF_DAEMON,
SF_AUTH,
SF_SYSLOG,
SF_LPR,
SF_NEWS,
SF_UUCP,
SF_CRON,
SF_AUTHPRIV,
SF_FTP,
SF_NTP,
SF_AUDIT,
SF_ALERT,
SF_CRON2,
SF_LOCAL0,
SF_LOCAL1,
SF_LOCAL2,
SF_LOCAL3,
SF_LOCAL4,
SF_LOCAL5,
SF_LOCAL6,
SF_LOCAL7
};
};
} // namespace details
} // namespace spdlog

@ -0,0 +1,90 @@
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
#include <spdlog/details/fmt_helper.h>
#include <spdlog/details/syslog_consts.h>
#include <spdlog/sinks/tcp_sink.h>
namespace spdlog {
namespace sinks {
/**
* Sink that sends messages to remote syslog server over TCP
*/
template<typename Mutex>
class tcp_syslog_client_sink : public spdlog::sinks::tcp_sink<Mutex>
{
private:
using syslog_facility_t = spdlog::details::syslog_consts::facility;
public:
explicit tcp_syslog_client_sink(tcp_sink_config &&sink_config, syslog_facility_t syslog_facility)
: spdlog::sinks::tcp_sink<Mutex>{std::move(sink_config)}
, syslog_levels_{
/* spdlog::level::trace */ spdlog::details::syslog_consts::SL_DEBUG,
/* spdlog::level::debug */ spdlog::details::syslog_consts::SL_DEBUG,
/* spdlog::level::info */ spdlog::details::syslog_consts::SL_INFO,
/* spdlog::level::warn */ spdlog::details::syslog_consts::SL_WARNING,
/* spdlog::level::err */ spdlog::details::syslog_consts::SL_ERR,
/* spdlog::level::critical */ spdlog::details::syslog_consts::SL_CRIT,
/* spdlog::level::off */ spdlog::details::syslog_consts::SL_INFO}
, syslog_facility_{syslog_facility}
{
}
protected:
void sink_it_(const spdlog::details::log_msg &msg) override
{
memory_buf_t formatted;
base_sink<Mutex>::formatter_->format(msg, formatted);
// https://datatracker.ietf.org/doc/html/rfc5424#section-6.2.1
std::string pri{"<" + std::to_string((syslog_facility_ << 3) + syslog_prio_from_level(msg)) + ">"};
memory_buf_t syslog_formatted;
syslog_formatted.append(pri);
syslog_formatted.append(formatted);
if (!spdlog::sinks::tcp_sink<Mutex>::client_.is_connected())
{
spdlog::sinks::tcp_sink<Mutex>::client_.connect(
spdlog::sinks::tcp_sink<Mutex>::config_.server_host,
spdlog::sinks::tcp_sink<Mutex>::config_.server_port);
}
spdlog::sinks::tcp_sink<Mutex>::client_.send(syslog_formatted.data(), syslog_formatted.size());
}
private:
using levels_array = std::array<int, 7>;
levels_array syslog_levels_;
syslog_facility_t syslog_facility_;
int syslog_prio_from_level(const details::log_msg &msg) const
{
return syslog_levels_.at(static_cast<levels_array::size_type>(msg.level));
}
};
using tcp_syslog_client_sink_mt = tcp_syslog_client_sink<std::mutex>;
using tcp_syslog_client_sink_st = tcp_syslog_client_sink<spdlog::details::null_mutex>;
} // namespace sinks
template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> tcp_syslog_client_logger_mt(const std::string &logger_name,
spdlog::sinks::tcp_sink_config sink_config,
spdlog::details::syslog_consts::facility syslog_facility = spdlog::details::syslog_consts::facility::SF_USER)
{
return Factory::template create<sinks::tcp_syslog_client_sink_mt>(logger_name, std::move(sink_config), syslog_facility);
}
template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> tcp_syslog_client_logger_st(const std::string &logger_name,
spdlog::sinks::tcp_sink_config sink_config,
spdlog::details::syslog_consts::facility syslog_facility = spdlog::details::syslog_consts::facility::SF_USER)
{
return Factory::template create<sinks::tcp_syslog_client_sink_st>(logger_name, std::move(sink_config), syslog_facility);
}
} // namespace spdlog
Loading…
Cancel
Save