diff --git a/example/example.cpp b/example/example.cpp index 12dfe81c..1459633e 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -64,6 +64,10 @@ int main(int, char* []) SPDLOG_TRACE(file_logger, "This is a trace message (only #ifdef _DEBUG)", 123); + #ifdef __linux__ + auto syslog_logger = spd::syslog_logger("syslog"); + syslog_logger->warn("This is warning that will end up in syslog. This is Linux only!"); + #endif } catch (const spd::spdlog_ex& ex) { diff --git a/include/spdlog/common.h b/include/spdlog/common.h index bbfe7748..7b4a4220 100644 --- a/include/spdlog/common.h +++ b/include/spdlog/common.h @@ -46,17 +46,17 @@ namespace level { typedef enum { - TRACE, - DEBUG, - INFO, - NOTICE, - WARN, - ERR, - CRITICAL, - ALERT, - EMERG, - ALWAYS, - OFF + TRACE = 0, + DEBUG = 1, + INFO = 2, + NOTICE = 3, + WARN = 4, + ERR = 5, + CRITICAL = 6, + ALERT = 7, + EMERG = 8, + ALWAYS = 9, + OFF = 10 } level_enum; static const char* level_names[] { "trace", "debug", "info", "notice", "warning", "error", "critical", diff --git a/include/spdlog/details/fast_oss.h b/include/spdlog/details/fast_oss.h index 3ac35ded..447c1783 100644 --- a/include/spdlog/details/fast_oss.h +++ b/include/spdlog/details/fast_oss.h @@ -126,7 +126,7 @@ public: swap(first._dev, second._dev); } - std::string str() + std::string str() const { auto& buffer = _dev.buf(); const char*data = buffer.data(); diff --git a/include/spdlog/details/spdlog_impl.h b/include/spdlog/details/spdlog_impl.h index 13c9df06..1fe4566f 100644 --- a/include/spdlog/details/spdlog_impl.h +++ b/include/spdlog/details/spdlog_impl.h @@ -30,6 +30,7 @@ #include "registry.h" #include "../sinks/file_sinks.h" #include "../sinks/stdout_sinks.h" +#include "../sinks/syslog_sink.h" inline std::shared_ptr spdlog::get(const std::string& name) { @@ -81,6 +82,13 @@ inline std::shared_ptr spdlog::stderr_logger_st(const std::strin } +// Create syslog logger +inline std::shared_ptr spdlog::syslog_logger(const std::string& logger_name) +{ + return create(logger_name); +} + + inline std::shared_ptr spdlog::create(const std::string& logger_name, spdlog::sinks_init_list sinks) { return details::registry::instance().create(logger_name, sinks); diff --git a/include/spdlog/sinks/syslog_sink.h b/include/spdlog/sinks/syslog_sink.h new file mode 100644 index 00000000..56f9329e --- /dev/null +++ b/include/spdlog/sinks/syslog_sink.h @@ -0,0 +1,92 @@ +/*************************************************************************/ +/* spdlog - an extremely fast and easy to use c++11 logging library. */ +/* Copyright (c) 2014 Gabi Melman. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#pragma once + +#ifdef __linux__ + +#include +#include +#include +#include +#include +#include "./sink.h" +#include "../formatter.h" +#include "../common.h" +#include "../details/log_msg.h" + + +namespace spdlog +{ + namespace sinks + { + /** + * Sink that write to syslog using the `syscall()` library call. + * + * Locking is not needed, as `syslog()` itself is thread-safe. + */ + class syslog_sink : public sink + { + public: + syslog_sink() + { + _priorities[static_cast(level::TRACE)] = LOG_DEBUG; + _priorities[static_cast(level::DEBUG)] = LOG_DEBUG; + _priorities[static_cast(level::INFO)] = LOG_INFO; + _priorities[static_cast(level::NOTICE)] = LOG_NOTICE; + _priorities[static_cast(level::WARN)] = LOG_WARNING; + _priorities[static_cast(level::ERR)] = LOG_ERR; + _priorities[static_cast(level::CRITICAL)] = LOG_CRIT; + _priorities[static_cast(level::ALERT)] = LOG_ALERT; + _priorities[static_cast(level::EMERG)] = LOG_EMERG; + + _priorities[static_cast(level::ALWAYS)] = LOG_INFO; + _priorities[static_cast(level::OFF)] = LOG_INFO; + } + virtual ~syslog_sink() = default; + + syslog_sink(const syslog_sink&) = delete; + syslog_sink& operator=(const syslog_sink&) = delete; + + void log(const details::log_msg &msg) override + { + syslog(syslog_prio_from_level(msg), "%s", msg.formatted.str().c_str()); + }; + + protected: + /** + * Simply maps spdlog's log level to syslog priority level. + */ + int syslog_prio_from_level(const details::log_msg &msg) const + { + return _priorities[static_cast(msg.level)]; + } + + private: + std::array _priorities; + }; + } +} + +#endif diff --git a/include/spdlog/spdlog.h b/include/spdlog/spdlog.h index beb64164..42bff205 100644 --- a/include/spdlog/spdlog.h +++ b/include/spdlog/spdlog.h @@ -68,6 +68,11 @@ std::shared_ptr stderr_logger_mt(const std::string& logger_name); std::shared_ptr stderr_logger_st(const std::string& logger_name); +// Create a syslog logger +#ifdef __linux__ + std::shared_ptr syslog_logger(const std::string& logger_name); +#endif + // // Create a logger with multiple sinks