From c5d6a386b68a477369373cf8bf55eb0ffabb3e9f Mon Sep 17 00:00:00 2001 From: Adrien BLANCHET Date: Sun, 25 Apr 2021 23:38:04 +0200 Subject: [PATCH] - Improving speed - Minor improvements --- include/Logger.h | 5 +- include/implementation/Logger.impl.h | 123 +++++++++++++++------------ include/implementation/LoggerUtils.h | 39 +++++---- 3 files changed, 97 insertions(+), 70 deletions(-) diff --git a/include/Logger.h b/include/Logger.h index 74286e6..e36e200 100644 --- a/include/Logger.h +++ b/include/Logger.h @@ -83,10 +83,11 @@ namespace { protected: static void buildCurrentPrefix(); + static void getFormattedUserHeaderStr(std::string &formattedUserHeaderBuffer_); static void hookStreamBuffer(); - static std::string getTagColorStr(LogLevel selectedLogLevel_); - static std::string getTagStr(LogLevel selectedLogLevel_); + static std::string getLogLevelColorStr(const LogLevel &selectedLogLevel_); + static std::string getLogLevelStr(const LogLevel &selectedLogLevel_); template static void printFormat(const char *fmt_str, Args ... args ); diff --git a/include/implementation/Logger.impl.h b/include/implementation/Logger.impl.h index 3b3bc02..0b1b518 100644 --- a/include/implementation/Logger.impl.h +++ b/include/implementation/Logger.impl.h @@ -130,86 +130,104 @@ namespace { // Protected Methods void Logger::buildCurrentPrefix() { + std::string strBuffer; + + // RESET THE PREFIX + _currentPrefix_ = ""; + + // Nothing else -> NONE level + if( Logger::_prefixLevel_ == Logger::PrefixLevel::NONE ){ + if( not _userHeaderStr_.empty() ){ + Logger::getFormattedUserHeaderStr(_currentPrefix_); + _currentPrefix_ += " "; // extra space + } + return; + } + // default: // _prefixFormat_ = "{TIME} {USER_HEADER} {SEVERITY} {FILELINE} {THREAD}"; if( _prefixFormat_.empty() ) _prefixFormat_ = LOGGER_PREFIX_FORMAT; // Reset the prefix _currentPrefix_ = LoggerUtils::stripStringUnicode(_prefixFormat_); // remove potential colors - std::string contentStrBuffer; - // "{THREAD}" - if(Logger::_prefixLevel_ >= Logger::PrefixLevel::FULL){ + // {SEVERITY} -> at least MINIMAL level -> LATER, can introduce repeated space in the prefix! + + // {TIME} -> at least PRODUCTION level + strBuffer = ""; + if (Logger::_prefixLevel_ >= Logger::PrefixLevel::PRODUCTION) { + time_t rawTime = std::time(nullptr); + struct tm timeInfo = *localtime(&rawTime); std::stringstream ss; - ss << "\x1b[90m(thread: " << std::this_thread::get_id() << ")\033[0m"; - contentStrBuffer = ss.str(); + ss << std::put_time(&timeInfo, "%H:%M:%S"); + strBuffer += ss.str(); } - _currentPrefix_ = LoggerUtils::replaceSubstringInString(_currentPrefix_, "{THREAD}", contentStrBuffer); - contentStrBuffer = ""; + LoggerUtils::replaceSubstringInsideInputString(_currentPrefix_, "{TIME}", strBuffer); - // {FILE} and {LINE} + // {FILE} and {LINE} -> at least DEBUG level + strBuffer = ""; if(Logger::_prefixLevel_ >= Logger::PrefixLevel::DEBUG){ - contentStrBuffer = "\x1b[90m"; - contentStrBuffer += _currentFileName_; - contentStrBuffer += ":"; - contentStrBuffer += std::to_string(_currentLineNumber_); - contentStrBuffer += "\033[0m"; + strBuffer += "\x1b[90m"; // grey + strBuffer += _currentFileName_; + strBuffer += ":"; + strBuffer += std::to_string(_currentLineNumber_); + strBuffer += "\033[0m"; } - _currentPrefix_ = LoggerUtils::replaceSubstringInString(_currentPrefix_, "{FILELINE}", contentStrBuffer); - contentStrBuffer = ""; + LoggerUtils::replaceSubstringInsideInputString(_currentPrefix_, "{FILELINE}", strBuffer); - // {TIME} - if (Logger::_prefixLevel_ >= Logger::PrefixLevel::PRODUCTION) { - time_t rawTime = std::time(nullptr); - struct tm timeInfo = *localtime(&rawTime); + // "{THREAD}" -> at least FULL level + strBuffer = ""; + if(Logger::_prefixLevel_ >= Logger::PrefixLevel::FULL){ std::stringstream ss; - ss << std::put_time(&timeInfo, "%H:%M:%S"); - contentStrBuffer = ss.str(); + ss << "\x1b[90m(thread: " << std::this_thread::get_id() << ")\033[0m"; + strBuffer = ss.str(); } - _currentPrefix_ = LoggerUtils::replaceSubstringInString(_currentPrefix_, "{TIME}", contentStrBuffer); - contentStrBuffer = ""; - - // {SEVERITY} - if (Logger::_prefixLevel_ >= Logger::PrefixLevel::MINIMAL) { - if (_enableColors_) contentStrBuffer += getTagColorStr(_currentLogLevel_); - char buffer[6]; - snprintf(buffer, 6, "%5.5s", getTagStr(_currentLogLevel_).c_str()); - contentStrBuffer += buffer; - if (_enableColors_) contentStrBuffer += "\033[0m"; + LoggerUtils::replaceSubstringInsideInputString(_currentPrefix_, "{THREAD}", strBuffer); + + + if( _userHeaderStr_.empty() ){ + LoggerUtils::replaceSubstringInsideInputString(_currentPrefix_, "{USER_HEADER}", ""); } - _currentPrefix_ = LoggerUtils::replaceSubstringInString(_currentPrefix_, "{SEVERITY}", contentStrBuffer); - contentStrBuffer = ""; // Remove extra spaces left by non-applied tags - _currentPrefix_ = LoggerUtils::removeRepeatedCharacters(_currentPrefix_, " "); - - // cleanup - while(_currentPrefix_[_currentPrefix_.size()-1] == ' ') _currentPrefix_ = _currentPrefix_.substr(0, _currentPrefix_.size()-1); + LoggerUtils::removeRepeatedCharInsideInputStr(_currentPrefix_, " "); while(_currentPrefix_[0] == ' ') _currentPrefix_ = _currentPrefix_.substr(1, _currentPrefix_.size()); - // {USER_HEADER} -> can contain multiple spaces - if(not _userHeaderStr_.empty()){ - if(_enableColors_ and _propagateColorsOnUserHeader_) contentStrBuffer += getTagColorStr(_currentLogLevel_); - contentStrBuffer += _userHeaderStr_; - if(_enableColors_ and _propagateColorsOnUserHeader_) contentStrBuffer += "\033[0m"; - _currentPrefix_ = LoggerUtils::replaceSubstringInString(_currentPrefix_, "{USER_HEADER}", contentStrBuffer); + // User prefix can have doubled spaces + // "{USER_HEADER}" -> + if( not _userHeaderStr_.empty() ){ + strBuffer = ""; + Logger::getFormattedUserHeaderStr(strBuffer); + LoggerUtils::replaceSubstringInsideInputString(_currentPrefix_, "{USER_HEADER}", strBuffer); } - else{ - _currentPrefix_ = LoggerUtils::replaceSubstringInString(_currentPrefix_, "{USER_HEADER}", contentStrBuffer); - _currentPrefix_ = LoggerUtils::removeRepeatedCharacters(_currentPrefix_, " "); - while(_currentPrefix_[0] == ' ') _currentPrefix_ = _currentPrefix_.substr(1, _currentPrefix_.size()); + + // {SEVERITY} -> at least MINIMAL level + strBuffer = ""; + if( Logger::_prefixLevel_ >= Logger::PrefixLevel::MINIMAL ) { + if (_enableColors_){ strBuffer += getLogLevelColorStr(_currentLogLevel_); } + strBuffer += LoggerUtils::padString(getLogLevelStr(_currentLogLevel_), 5); + if (_enableColors_){ strBuffer += "\033[0m"; } } - contentStrBuffer = ""; + LoggerUtils::replaceSubstringInsideInputString(_currentPrefix_, "{SEVERITY}", strBuffer); + + // cleanup (make sure there's no trailing spaces) + while(_currentPrefix_[_currentPrefix_.size()-1] == ' ') _currentPrefix_ = _currentPrefix_.substr(0, _currentPrefix_.size()-1); // Add ": " to separate the header from the message if (not _currentPrefix_.empty()){ _currentPrefix_ += ": "; } } - std::string Logger::getTagColorStr(LogLevel selectedLogLevel_) { + void Logger::getFormattedUserHeaderStr(std::string &formattedUserHeaderBuffer_) { + if( not _userHeaderStr_.empty() ){ + if(_enableColors_ and _propagateColorsOnUserHeader_) formattedUserHeaderBuffer_ += getLogLevelColorStr(_currentLogLevel_); + formattedUserHeaderBuffer_ += _userHeaderStr_; + if(_enableColors_ and _propagateColorsOnUserHeader_) formattedUserHeaderBuffer_ += "\033[0m"; + } + } + std::string Logger::getLogLevelColorStr(const LogLevel &selectedLogLevel_) { switch (selectedLogLevel_) { - case Logger::LogLevel::FATAL: return "\033[41m"; case Logger::LogLevel::ERROR: @@ -226,11 +244,10 @@ namespace { return "\x1b[36m"; default: return ""; - } } - std::string Logger::getTagStr(LogLevel selectedLogLevel_) { + std::string Logger::getLogLevelStr(const LogLevel &selectedLogLevel_) { switch (selectedLogLevel_) { @@ -318,7 +335,7 @@ namespace { } if (_enableColors_ and _currentLogLevel_ == LogLevel::FATAL) - _outputStream_ << LoggerUtils::formatString("%s", getTagColorStr(LogLevel::FATAL).c_str()); + _outputStream_ << LoggerUtils::formatString("%s", getLogLevelColorStr(LogLevel::FATAL).c_str()); _outputStream_ << formattedString; diff --git a/include/implementation/LoggerUtils.h b/include/implementation/LoggerUtils.h index 54bec44..62d3027 100644 --- a/include/implementation/LoggerUtils.h +++ b/include/implementation/LoggerUtils.h @@ -71,15 +71,17 @@ namespace LoggerUtils{ //! String Utils inline bool doesStringContainsSubstring(std::string string_, std::string substring_, bool ignoreCase_ = false); - inline std::string toLowerCase(std::string& inputStr_); + inline std::string padString(const std::string& inputStr_, unsigned int padSize_, const char& padChar = ' '); + inline std::string toLowerCase(const std::string &inputStr_); inline std::string stripStringUnicode(const std::string &inputStr_); inline std::string repeatString(const std::string &inputStr_, int amount_); - inline std::string removeRepeatedCharacters(const std::string &inputStr_, const std::string &doubledChar_); - inline std::string replaceSubstringInString(const std::string &input_str_, const std::string &substr_to_look_for_, const std::string &substr_to_replace_); + inline void replaceSubstringInsideInputString(std::string &input_str_, const std::string &substr_to_look_for_, const std::string &substr_to_replace_); inline std::vector splitString(const std::string& input_string_, const std::string& delimiter_); inline std::string formatString( const std::string& strToFormat_ ); // 0 args overrider template inline std::string formatString( const std::string& strToFormat_, const Args& ... args ); + inline void removeRepeatedCharInsideInputStr(std::string &inputStr_, const std::string &doubledChar_); + // Hardware Utils inline int getTerminalWidth(); @@ -98,7 +100,18 @@ namespace LoggerUtils{ if(string_.find(substring_) != std::string::npos) return true; else return false; } - inline std::string toLowerCase(std::string& inputStr_){ + inline std::string padString(const std::string& inputStr_, unsigned int padSize_, const char& padChar){ + std::string outputString; + int padDelta = int(inputStr_.size()) - int(padSize_); + while( padDelta < 0 ){ + // add extra chars if needed + outputString += padChar; + padDelta++; + } + outputString += inputStr_; + return outputString.substr(0, outputString.size() - padDelta); + } + inline std::string toLowerCase(const std::string &inputStr_){ std::string output_str(inputStr_); std::transform(output_str.begin(), output_str.end(), output_str.begin(), [](unsigned char c) { return std::tolower(c); }); @@ -151,24 +164,20 @@ namespace LoggerUtils{ } return outputStr; } - inline std::string removeRepeatedCharacters(const std::string &inputStr_, const std::string &doubledChar_) { + inline void removeRepeatedCharInsideInputStr(std::string &inputStr_, const std::string &doubledChar_){ std::string doubledCharStr = doubledChar_+doubledChar_; - std::string outStr = inputStr_; std::string lastStr; do{ - lastStr = outStr; - outStr = LoggerUtils::replaceSubstringInString(outStr, doubledCharStr, doubledChar_); - } while( lastStr != outStr ); - return outStr; + lastStr = inputStr_; + LoggerUtils::replaceSubstringInsideInputString(inputStr_, doubledCharStr, doubledChar_); + } while( lastStr != inputStr_ ); } - inline std::string replaceSubstringInString(const std::string &input_str_, const std::string &substr_to_look_for_, const std::string &substr_to_replace_) { - std::string stripped_str = input_str_; + inline void replaceSubstringInsideInputString(std::string &input_str_, const std::string &substr_to_look_for_, const std::string &substr_to_replace_){ size_t index = 0; - while ((index = stripped_str.find(substr_to_look_for_, index)) != std::string::npos) { - stripped_str.replace(index, substr_to_look_for_.length(), substr_to_replace_); + while ((index = input_str_.find(substr_to_look_for_, index)) != std::string::npos) { + input_str_.replace(index, substr_to_look_for_.length(), substr_to_replace_); index += substr_to_replace_.length(); } - return stripped_str; } inline std::vector splitString(const std::string& input_string_, const std::string& delimiter_) {