diff --git a/component/config.cpp b/component/config.cpp index 0dfb9af..a729912 100644 --- a/component/config.cpp +++ b/component/config.cpp @@ -23,15 +23,21 @@ std::string Config::getFullJID() const { return getBareJID() + "/" + getResource(); } -gloox::LogLevel Config::getLogLevel() const { - std::string level = root["logLevel"].as("warning"); +Logger::Level Config::getLogLevel() const { + std::string level = root["logLevel"].as("info"); - if (level == "debug") - return gloox::LogLevelDebug; + if (level == "trace") + return Logger::trace; + else if (level == "debug") + return Logger::debug; + else if (level == "info") + return Logger::info; + else if (level == "warn" || level == "warning") + return Logger::warning; else if (level == "error") - return gloox::LogLevelError; + return Logger::error; else - return gloox::LogLevelWarning; + return Logger::info; } gloox::TLSPolicy Config::getTLSPolicy() const { diff --git a/component/config.h b/component/config.h index f238a75..0aae50d 100644 --- a/component/config.h +++ b/component/config.h @@ -10,6 +10,8 @@ #include "yaml-cpp/yaml.h" +#include "logger.h" + class Config { public: struct Module { @@ -31,7 +33,7 @@ public: std::string getPassword() const; std::string getResource() const; std::map getActors() const; - gloox::LogLevel getLogLevel() const; + Logger::Level getLogLevel() const; gloox::TLSPolicy getTLSPolicy() const; Module getModuleConfig(const std::string& name) const; diff --git a/component/core.cpp b/component/core.cpp index 995a64c..0b40d79 100644 --- a/component/core.cpp +++ b/component/core.cpp @@ -6,5 +6,5 @@ Core::Core(const std::string& configPath): config(configPath), router(), - logger() + logger(config.getLogLevel()) {} diff --git a/component/logger.cpp b/component/logger.cpp index 050d520..8ab3548 100644 --- a/component/logger.cpp +++ b/component/logger.cpp @@ -7,15 +7,21 @@ #include static constexpr std::string_view logLevelMap[] = { - "DEBUG", // 0 - "WARNING", // 1 - "ERROR", // 2 + "TRACE", + "DEBUG", + "INFO", + "WARNING", + "ERROR", + "FATAL", }; static constexpr std::string_view colorMap[] = { - "\033[32m", // DEBUG (Green) + "\033[90m", // TRACE (Gray) + "\033[34m", // DEBUG (Blue) + "\033[32m", // INFO (Green) "\033[33m", // WARNING (Yellow) "\033[31m", // ERROR (Red) + "\033[35m", // FATAL (Magenta) }; static constexpr std::string_view clear = "\033[0m"; @@ -33,11 +39,11 @@ void writeTimestamp() { } constexpr std::string_view getLogLevel(gloox::LogLevel level) { - return (level >= 0 && level < 3) ? logLevelMap[level] : "UNKNOWN"; + return (level >= 0 && level < 3) ? logLevelMap[Logger::convert(level)] : "UNKNOWN"; } constexpr std::string_view getColor(gloox::LogLevel level) { - return (level >= 0 && level < 3) ? colorMap[level] : ""; + return (level >= 0 && level < 3) ? colorMap[Logger::convert(level)] : ""; } void writeTags(gloox::LogArea area) { @@ -78,14 +84,73 @@ void writeTags(gloox::LogArea area) { std::cout << '\t'; } -Logger::Logger() +Logger::Level Logger::convert(gloox::LogLevel level) { + switch (level) { + case gloox::LogLevelDebug: + return trace; + case gloox::LogLevelError: + return error; + case gloox::LogLevelWarning: + return warning; + }; + + return warning; +} + +gloox::LogLevel Logger::convert(Level level) { + switch (level) { + case trace: + return gloox::LogLevelDebug; + case debug: + return gloox::LogLevelWarning; + case info: + return gloox::LogLevelWarning; + case warning: + return gloox::LogLevelWarning; + case error: + return gloox::LogLevelError; + case fatal: + return gloox::LogLevelError; + } + + return gloox::LogLevelWarning; +} + +Logger::Logger(Level level): + level(level) {} Logger::~Logger() {} void Logger::handleLog(gloox::LogLevel level, gloox::LogArea area, const std::string& message) { writeTimestamp(); - std::cout << getColor(level) << bold << "[" << getLogLevel(level) << "]" << clear << bold; + std::cout << getColor(level) << bold << '[' << getLogLevel(level) << ']' << clear << bold; writeTags(area); std::cout << clear << '\t' << message << clear << std::endl; } + +void Logger::log(Level lvl, const std::string& message, const std::vector& domain) { + if (lvl < level) + return; + + writeTimestamp(); + std::cout << colorMap[lvl] << bold << '[' << logLevelMap[lvl] << ']' << clear; + + if (!domain.empty()) { + std::cout << ' ' << bold << '['; + + bool first = true; + for (const std::string& tag : domain) { + if (first) + first = false; + else + std::cout << ' '; + + std::cout << tag; + } + + std::cout << ']' << clear; + } + std::cout << '\t' << message << clear << std::endl; +} + diff --git a/component/logger.h b/component/logger.h index ca470d9..d14b473 100644 --- a/component/logger.h +++ b/component/logger.h @@ -3,13 +3,33 @@ #pragma once +#include + #include #include class Logger: public gloox::LogHandler { public: - Logger(); + enum Level { + trace, + debug, + info, + warning, + error, + fatal + }; + +public: + Logger(Level level = info); ~Logger(); void handleLog(gloox::LogLevel level, gloox::LogArea area, const std::string& message) override; + + void log(Level level, const std::string& message, const std::vector& domain = {}); + + static gloox::LogLevel convert(Level level); + static Level convert(gloox::LogLevel level); + +private: + Level level; }; diff --git a/connection/connection.cpp b/connection/connection.cpp index b5ced9e..f704b22 100644 --- a/connection/connection.cpp +++ b/connection/connection.cpp @@ -21,7 +21,8 @@ void Connection::initiialize() { gloox->registerConnectionListener(this); gloox->registerMessageHandler(this); - gloox->logInstance().registerLogHandler(core->config.getLogLevel(), gloox::LogAreaAll, &core->logger); + ::gloox::LogLevel level = Logger::convert(core->config.getLogLevel()); + gloox->logInstance().registerLogHandler(level, gloox::LogAreaAll, &core->logger); gloox::Disco* disco = gloox->disco(); disco->setVersion("Jay", "0.0.1"); @@ -38,6 +39,7 @@ void Connection::deinitialize() { if (state == initial) return; + core->logger.log(Logger::debug, "deinitializing", {"Connection"}); gloox->logInstance().removeLogHandler(&core->logger); gloox->removeMessageHandler(this); @@ -51,21 +53,96 @@ void Connection::connect() { if (state != disconnected) return; + core->logger.log(Logger::debug, "connecting", {"Connection"}); state = connected; gloox->connect(true); state = disconnected; } void Connection::send(const std::string& jid, const std::string& body) { + core->logger.log(Logger::debug, "sending message \"" + body + "\" to " + jid, {"Connection"}); gloox->send(gloox::Message(gloox::Message::Chat, jid, body)); } void Connection::handleMessage(const gloox::Message& message, gloox::MessageSession* session) { - core->router.routeMessage(message.from().bare(), message.body()); + std::string jid = message.from().bare(); + core->logger.log(Logger::debug, "received message \"" + message.body() + "\" from " + jid, {"Connection"}); + core->router.routeMessage(jid, message.body()); } -void Connection::onConnect() {} -void Connection::onDisconnect(gloox::ConnectionError e) {} -bool Connection::onTLSConnect(const gloox::CertInfo&) { return true; } +void Connection::onConnect() { + core->logger.log(Logger::info, "connection established", {"Connection"}); +} +void Connection::onDisconnect(gloox::ConnectionError e) { + std::string error; + + switch (e) { + case gloox::ConnNoError: + break; + case gloox::ConnStreamError: //TODO Use ClientBase::streamError() to find the reason. */ + error = "stream error occured"; + break; + case gloox::ConnStreamVersionError: + error = "incoming stream's version is not supported"; + break; + case gloox::ConnStreamClosed: + error = "stream has been closed (by the server)"; + break; + case gloox::ConnProxyAuthRequired: + error = "HTTP/SOCKS5 proxy requires authentication"; + break; + case gloox::ConnProxyAuthFailed: + error = "HTTP/SOCKS5 proxy authentication failed"; + break; + case gloox::ConnProxyNoSupportedAuth: + error = "HTTP/SOCKS5 proxy requires an unsupported auth mechanism"; + break; + case gloox::ConnIoError: + error = "I/O error occured"; + break; + case gloox::ConnParseError: + error = "XML parse error occurred"; + break; + case gloox::ConnConnectionRefused: + error = "connection was refused by the server (on the socket level)"; + break; + case gloox::ConnDnsError: + error = "resolving the server's hostname failed"; + break; + case gloox::ConnOutOfMemory: + error = "connection out of memory"; + break; + case gloox::ConnNoSupportedAuth: + error = "auth mechanisms the server offers are not supported"; + break; + case gloox::ConnTlsFailed: + error = "server's certificate could not be verified or the TLS"; + break; + case gloox::ConnTlsNotAvailable: + error = "server didn't offer TLS while it was set to be required"; + break; + case gloox::ConnCompressionFailed: + error = "negotiating/initializing compression failed"; + break; + case gloox::ConnAuthenticationFailed: //TODO use ClientBase::authError() to find the reason. */ + error = "authentication failed"; + break; + + case gloox::ConnUserDisconnected: + error = "user (or higher-level protocol) requested a disconnect"; + break; + case gloox::ConnNotConnected: + error = "there is no active connection"; + } + + if (error.empty()) + core->logger.log(Logger::info, "disconnected" , {"Connection"}); + else + core->logger.log(Logger::error, "disconnected: " + error , {"Connection"}); +} +bool Connection::onTLSConnect(const gloox::CertInfo&) { + core->logger.log(Logger::info, "TLS established", {"Connection"}); + return true; +} diff --git a/jay.cpp b/jay.cpp index 179c5c3..8001488 100644 --- a/jay.cpp +++ b/jay.cpp @@ -43,8 +43,10 @@ void Jay::initialize() { } void Jay::createActors() { - for (const std::pair& pair : core->config.getActors()) + for (const std::pair& pair : core->config.getActors()) { + core->logger.log(Logger::info, "registering actor " + pair.first + " as " + pair.second, {"Jay"}); core->router.registerActor(pair.first, pair.second); + } } void Jay::createModules() { @@ -53,6 +55,7 @@ void Jay::createModules() { if (!conf.enabled) continue; + core->logger.log(Logger::info, "enabling module " + pair.first, {"Jay"}); modules.emplace_back(pair.second(core, connection)); core->router.registerModule(pair.first, modules.back()); }