diff options
Diffstat (limited to 'src/logger.cc')
| -rw-r--r-- | src/logger.cc | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/src/logger.cc b/src/logger.cc new file mode 100644 index 0000000..21effff --- /dev/null +++ b/src/logger.cc @@ -0,0 +1,145 @@ +#include "logger.hh" + +#include <cstdint> +#include <iostream> +#include <memory> +#include <string> +#include <string_view> +#include <syslog.h> +#include <utility> + +namespace logger { + +namespace { + +class BaseLogger : public Logger { + protected: + enum class Level : uint8_t { + kError, + kWarning, + kInfo, + kDebug, + }; + + public: + void err(std::string_view message) final { write(Level::kError, message); } + + void warn(std::string_view message) final { write(Level::kWarning, message); } + + void info(std::string_view message) final { write(Level::kInfo, message); } + +#if !defined(NDEBUG) + void dbg(std::string_view message) final { write(Level::kDebug, message); } +#endif + + protected: + BaseLogger() = default; + + virtual void write(Level level, std::string_view message) = 0; +}; + +class NoopLogger : public BaseLogger { + public: + NoopLogger() = default; + + protected: + void write(Level /* level */, std::string_view /* message */) override {} +}; + +class SyslogLogger : public BaseLogger { + public: + SyslogLogger(std::string ident, bool verbose) + : ident_(std::move(ident)), verbose_(verbose) { + // NOLINTNEXTLINE(misc-include-cleaner) + openlog(ident_.c_str(), LOG_PID | LOG_CONS, LOG_DAEMON); + } + + ~SyslogLogger() override { + // NOLINTNEXTLINE(misc-include-cleaner) + closelog(); + } + + protected: + void write(Level level, std::string_view message) override { + // NOLINTNEXTLINE(misc-include-cleaner) + int prio = LOG_ERR; + switch (level) { + case Level::kError: + // NOLINTNEXTLINE(misc-include-cleaner) + prio = LOG_ERR; + break; + case Level::kWarning: + // NOLINTNEXTLINE(misc-include-cleaner) + prio = LOG_WARNING; + break; + case Level::kInfo: + if (!verbose_) + return; + // NOLINTNEXTLINE(misc-include-cleaner) + prio = LOG_INFO; + break; + case Level::kDebug: + if (!verbose_) + return; + // NOLINTNEXTLINE(misc-include-cleaner) + prio = LOG_DEBUG; + break; + } + // NOLINTNEXTLINE(misc-include-cleaner) + ::syslog(prio, "%*s", static_cast<int>(message.size()), message.data()); + } + + private: + std::string const ident_; + bool const verbose_; +}; + +class StderrLogger : public BaseLogger { + public: + explicit StderrLogger(bool verbose) : verbose_(verbose) {} + + protected: + void write(Level level, std::string_view message) override { + switch (level) { + case Level::kError: + std::cerr << "Error: "; + break; + case Level::kWarning: + std::cerr << "Warning: "; + break; + case Level::kInfo: + if (!verbose_) + return; + std::cerr << "Info: "; + break; + case Level::kDebug: + if (!verbose_) + return; + std::cerr << "Debug: "; + break; + } + std::cerr << message << '\n'; + } + + private: + bool const verbose_; +}; + +} // namespace + +[[nodiscard]] +std::unique_ptr<Logger> noop() { + return std::make_unique<NoopLogger>(); +} + +[[nodiscard]] +std::unique_ptr<Logger> syslog(std::string ident, bool verbose) { + return std::make_unique<SyslogLogger>(std::move(ident), verbose); +} + +[[nodiscard]] +std::unique_ptr<Logger> stderr(bool verbose) { + return std::make_unique<StderrLogger>(verbose); +} + +} // namespace logger |
