From 762cc48220d3708b4aeb6d5499e3c5a55dd56e4b Mon Sep 17 00:00:00 2001 From: okaestne Date: Sat, 1 Jun 2019 23:51:14 +0200 Subject: [PATCH] WIP --- Log.cpp | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Log.h | 136 +++--------------------------------------------------- 2 files changed, 148 insertions(+), 129 deletions(-) create mode 100644 Log.cpp diff --git a/Log.cpp b/Log.cpp new file mode 100644 index 0000000..24e758f --- /dev/null +++ b/Log.cpp @@ -0,0 +1,141 @@ +#include "Log.h" + +/* + class Log +*/ + +// static member +std::vector Log::outputs; + +void Log::init() { + // add default console logger + if (outputs.empty()) + outputs.push_back(new Log::ConsoleOutput()); +} + +void Log::stop() { + for (auto output : outputs) + delete output; + outputs.clear(); +} + +void Log::addLogfile(const std::string& filename, Level max) { + outputs.push_back(new Log::FileOutput(filename, max)); +} + +void Log::addLogfile(const std::string& filename, Level min, Level max) { + outputs.push_back(new Log::FileOutput(filename, min, max)); +} + +void Log::setConsoleLogLevel(Level lvl) { + outputs.at(0)->setLogLevel(lvl); // has to exist +} + +void Log::setColoredOutput(bool enabled) { + ((Log::ConsoleOutput*) outputs.at(0))->setColoredOutput(enabled); // has to exist +} + +void Log::log(Level lvl, std::stringbuf* strb) { + for (Output* out : outputs) { + out->log(lvl, strb); + // reset stringbuffer read pointer to the beginning + strb->pubseekpos(0); + } +} + +/* + * abstract class Output + * default implementations + */ + +Log::Output::Output() {} +Log::Output::Output(Log::Level lvl_max) : lvl_max(lvl_max) {} +Log::Output::~Output() {} + +void Log::Output::log(Log::Level lvl, std::stringbuf* sbuf) { + std::ostream* os = getOs(lvl); + if (os) { + printLogHeader(os, lvl); + *os << sbuf << std::endl; + } +} + +void Log::Output::setLogLevel(Log::Level lvl) { + lvl_max = lvl; +} + +void Log::Output::printLogHeader(std::ostream* os, Level lvl) { + static const char* LevelTag[] = {"", "[FATAL] ", "[ERROR] ", "[WARN ] ", + "[NOTE ] ", "[INFO ] ", "[DEBUG] ", "[TRACE] "}; + + // get current date/time + auto now = std::chrono::system_clock::now(); + std::time_t now_c = std::chrono::system_clock::to_time_t(now); + + *os << "[" << std::put_time(std::localtime(&now_c), "%F %T") << "]" << LevelTag[lvl]; +} + +/* + * class ConsoleOutput + */ + +Log::ConsoleOutput::ConsoleOutput() : Output() {} + +bool Log::ConsoleOutput::setColoredOutput(bool enabled) { + // TODO: check the terminals compatibility for colors + coloredOutput = enabled; + return true; +} + +void Log::ConsoleOutput::log(Log::Level lvl, std::stringbuf* sbuf) { + static const char* esc_seq_start = "\033["; + static const char* esc_seq_reset = "\033[0m"; + // OFF FATAL ERROR WARN NOTE INFO DEBUG TRACE + static const char* color_codes[] = {"", "1;31;40m", "31m", "33m", "96m", "32m", "0m", "0m"}; + + std::ostream* os = getOs(lvl); + + if (os) { + // print colors if enabled + if (coloredOutput) + *os << esc_seq_start << color_codes[lvl]; + + Output::printLogHeader(os, lvl); + *os << sbuf; + + // reset color at end of the line + if (coloredOutput) + *os << esc_seq_reset; + + *os << std::endl; + } +} + +std::ostream* Log::ConsoleOutput::getOs(Log::Level lvl) { + // out of scope? + if (!lvl || lvl > lvl_max) + return nullptr; + + // stderr for FATAL, ERROR, WARN + if (lvl <= Log::Level::WARN) + return osErr; + else + return osStd; +} + +/* + * class FileOutput + * logging to file + */ + +Log::FileOutput::FileOutput(const std::string& filename, Log::Level lvl_max) + : Output(lvl_max), filename(filename), ofs(filename, std::ofstream::out | std::ofstream::app) {} + +Log::FileOutput::FileOutput(const std::string& filename, Log::Level lvl_min, Log::Level lvl_max) + : Output(lvl_max), filename(filename), ofs(filename, std::ofstream::out | std::ofstream::app), lvl_min(lvl_min) {} + +std::ostream* Log::FileOutput::getOs(Log::Level lvl) { + if (lvl_min <= lvl && lvl <= lvl_max) + return &ofs; + return nullptr; +} \ No newline at end of file diff --git a/Log.h b/Log.h index e430597..284c88d 100644 --- a/Log.h +++ b/Log.h @@ -15,7 +15,7 @@ class Log { Log() = delete; Log(const Log&) = delete; Log& operator=(const Log&) = delete; - ~Log() = delete; + //~Log() = delete; // set up the logger with a ConsoleOutput static void init(); @@ -26,11 +26,11 @@ class Log { // abstract base class for a log sink class Output { public: - Output() {} - Output(Log::Level lvl_max) : lvl_max(lvl_max) {} - virtual ~Output() {} + Output(); + Output(Log::Level lvl_max); + virtual ~Output(); virtual void log(Log::Level lvl, std::stringbuf* sbuf); - virtual void setLogLevel(Log::Level lvl) { lvl_max = lvl; } + virtual void setLogLevel(Log::Level lvl); protected: Log::Level lvl_max = INFO; @@ -41,9 +41,9 @@ class Log { }; // logging to stdout/stderr - class ConsoleOutout : public Output { + class ConsoleOutput : public Output { public: - ConsoleOutout(); + ConsoleOutput(); virtual bool setColoredOutput(bool enabled); private: @@ -143,125 +143,3 @@ class Log { } static void log(Level lvl, std::stringbuf* strb); }; - -// static member -std::vector Log::outputs; - -void Log::init() { - // add default console logger - if (outputs.empty()) - outputs.push_back(new Log::ConsoleOutout()); -} - -void Log::stop() { - for (auto output : outputs) - delete output; -} - -void Log::addLogfile(const std::string& filename, Level max) { - outputs.push_back(new Log::FileOutput(filename, max)); -} - -void Log::addLogfile(const std::string& filename, Level min, Level max) { - outputs.push_back(new Log::FileOutput(filename, min, max)); -} - -void Log::setConsoleLogLevel(Level lvl) { - outputs.at(0)->setLogLevel(lvl); // has to exist -} - -void Log::setColoredOutput(bool enabled) { - ((Log::ConsoleOutout*) outputs.at(0))->setColoredOutput(enabled); // has to exist -} - -void Log::log(Level lvl, std::stringbuf* strb) { - for (Output* out : outputs) { - out->log(lvl, strb); - // reset stringbuffer read pointer to the beginning - strb->pubseekpos(0); - } -} - -/* - * abstract class Ouput - * default implementations - */ - -void Log::Output::log(Log::Level lvl, std::stringbuf* sbuf) { - std::ostream* os = getOs(lvl); - if (os) { - printLogHeader(os, lvl); - *os << sbuf << std::endl; - } -} - -void Log::Output::printLogHeader(std::ostream* os, Level lvl) { - static const char* LevelTag[] = {"", "[FATAL] ", "[ERROR] ", "[WARN ] ", - "[NOTE ] ", "[INFO ] ", "[DEBUG] ", "[TRACE] "}; - - // get current date/time - auto now = std::chrono::system_clock::now(); - std::time_t now_c = std::chrono::system_clock::to_time_t(now); - - *os << "[" << std::put_time(std::localtime(&now_c), "%F %T") << "]" << LevelTag[lvl]; -} - -/* ConsoleOutout */ - -Log::ConsoleOutout::ConsoleOutout() : Output() {} - -bool Log::ConsoleOutout::setColoredOutput(bool enabled) { - // TODO: check the terminals compatibility for colors - coloredOutput = enabled; - return true; -} - -void Log::ConsoleOutout::log(Log::Level lvl, std::stringbuf* sbuf) { - static const char* esc_seq_start = "\033["; - static const char* esc_seq_reset = "\033[0m"; - // OFF FATAL ERROR WARN NOTE INFO DEBUG TRACE - static const char* color_codes[] = {"", "1;31;40m", "31m", "33m", "96m", "32m", "0m", "0m"}; - - std::ostream* os = getOs(lvl); - - if (os) { - // print colors if enabled - if (coloredOutput) - *os << esc_seq_start << color_codes[lvl]; - - Output::printLogHeader(os, lvl); - *os << sbuf; - - // reset color at end of the line - if (coloredOutput) - *os << esc_seq_reset; - - *os << std::endl; - } -} - -std::ostream* Log::ConsoleOutout::getOs(Log::Level lvl) { - // out of scope? - if (!lvl || lvl > lvl_max) - return nullptr; - - // stderr for FATAL, ERROR, WARN - if (lvl <= Log::Level::WARN) - return osErr; - else - return osStd; -} - -/* FileOutput ( logging to file ) */ - -Log::FileOutput::FileOutput(const std::string& filename, Log::Level lvl_max) - : Output(lvl_max), filename(filename), ofs(filename, std::ofstream::out | std::ofstream::app) {} - -Log::FileOutput::FileOutput(const std::string& filename, Log::Level lvl_min, Log::Level lvl_max) - : Output(lvl_max), filename(filename), ofs(filename, std::ofstream::out | std::ofstream::app), lvl_min(lvl_min) {} - -std::ostream* Log::FileOutput::getOs(Log::Level lvl) { - if (lvl_min <= lvl && lvl <= lvl_max) - return &ofs; - return nullptr; -} \ No newline at end of file