File indexing completed on 2025-01-18 10:02:33
0001 #pragma once
0002
0003 #include <iostream>
0004 #include <memory>
0005 #include <syslog.h>
0006
0007 namespace nopayloadclient {
0008 namespace logging {
0009
0010 enum class LogLevel {
0011 DEBUG,
0012 INFO,
0013 WARNING,
0014 ERROR
0015 };
0016
0017
0018 class ILogger {
0019 public:
0020 virtual ~ILogger() {}
0021 virtual void log(LogLevel level, const std::string& message) = 0;
0022
0023 void setLogLevel(LogLevel level) {
0024 log_level_ = level;
0025 }
0026
0027 void setLogLevel(const std::string& level_string) {
0028 LogLevel level = stringToLogLevel(level_string);
0029 setLogLevel(level);
0030 }
0031
0032 protected:
0033 LogLevel log_level_ = LogLevel::INFO;
0034 std::string mode_ = "terminal";
0035
0036 std::string logLevelToString(LogLevel level) {
0037 switch(level) {
0038 case LogLevel::DEBUG: return "DEBUG";
0039 case LogLevel::INFO: return "INFO";
0040 case LogLevel::WARNING: return "WARNING";
0041 case LogLevel::ERROR: return "ERROR";
0042 default: return "UNKNOWN";
0043 }
0044 }
0045
0046 LogLevel stringToLogLevel(const std::string& level_string) {
0047 if (level_string == "DEBUG") return LogLevel::DEBUG;
0048 else if (level_string == "INFO") return LogLevel::INFO;
0049 else if (level_string == "WARNING") return LogLevel::WARNING;
0050 else if (level_string == "ERROR") return LogLevel::ERROR;
0051 throw std::invalid_argument("Invalid LogLevel string");
0052 }
0053 };
0054
0055
0056 class TerminalLogger : public ILogger {
0057 public:
0058 void log(LogLevel level, const std::string& message) override {
0059 if (level < log_level_) return;
0060 std::cout << "[" + logLevelToString(level) + "] " + message << std::endl;
0061 }
0062 };
0063
0064
0065 class SyslogLogger : public ILogger {
0066 private:
0067 bool is_open_ = false;
0068
0069 public:
0070 ~SyslogLogger() {
0071 if (is_open_) closelog();
0072 }
0073
0074 void log(LogLevel level, const std::string& message) override {
0075 if (!is_open_) {
0076 openlog("nopayloadclient", LOG_PID | LOG_CONS, LOG_USER);
0077 is_open_ = true;
0078 }
0079 int sys_log_level;
0080 switch(level) {
0081 case LogLevel::DEBUG: sys_log_level = LOG_DEBUG; break;
0082 case LogLevel::INFO: sys_log_level = LOG_INFO; break;
0083 case LogLevel::WARNING: sys_log_level = LOG_WARNING; break;
0084 case LogLevel::ERROR: sys_log_level = LOG_ERR; break;
0085 default: sys_log_level = LOG_WARNING; break;
0086 }
0087 syslog(sys_log_level, "%s", message.c_str());
0088 }
0089 };
0090
0091
0092 class LoggerManager {
0093 private:
0094 static std::unique_ptr<ILogger>& getLoggerInstance() {
0095 static std::unique_ptr<ILogger> logger = std::make_unique<TerminalLogger>();
0096 return logger;
0097 }
0098
0099 public:
0100 static void setLogger(std::unique_ptr<ILogger> newLogger) {
0101 getLoggerInstance() = std::move(newLogger);
0102 }
0103
0104 static ILogger& getLogger() {
0105 return *getLoggerInstance();
0106 }
0107 };
0108
0109
0110 inline void info(const std::string& msg) {
0111 LoggerManager::getLogger().log(LogLevel::INFO, msg);
0112 }
0113 inline void warning(const std::string& msg) {
0114 LoggerManager::getLogger().log(LogLevel::WARNING, msg);
0115 }
0116 inline void error(const std::string& msg) {
0117 LoggerManager::getLogger().log(LogLevel::ERROR, msg);
0118 }
0119 inline void debug(const std::string& msg) {
0120 LoggerManager::getLogger().log(LogLevel::DEBUG, msg);
0121 }
0122
0123 inline void setLogger(const std::string& name) {
0124 if (name == "terminal") {
0125 LoggerManager::setLogger(std::make_unique<TerminalLogger>());
0126 }
0127 else if (name == "syslog") {
0128 LoggerManager::setLogger(std::make_unique<SyslogLogger>());
0129 }
0130 else {
0131 throw std::invalid_argument("Invalid logger choice");
0132 }
0133 }
0134
0135 inline void setLogLevel(const std::string& level_string) {
0136 LoggerManager::getLogger().setLogLevel(level_string);
0137 }
0138
0139 }
0140 }