summaryrefslogtreecommitdiff
path: root/src/logger.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/logger.cc')
-rw-r--r--src/logger.cc145
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