aboutsummaryrefslogtreecommitdiffstats
path: root/third_party/easyloggingpp/easylogging++.cc
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/easyloggingpp/easylogging++.cc')
-rw-r--r--third_party/easyloggingpp/easylogging++.cc3526
1 files changed, 0 insertions, 3526 deletions
diff --git a/third_party/easyloggingpp/easylogging++.cc b/third_party/easyloggingpp/easylogging++.cc
deleted file mode 100644
index 7451a3c1..00000000
--- a/third_party/easyloggingpp/easylogging++.cc
+++ /dev/null
@@ -1,3526 +0,0 @@
-//
-// Bismillah ar-Rahmaan ar-Raheem
-//
-// Easylogging++ v9.96.7
-// Cross-platform logging library for C++ applications
-//
-// Copyright (c) 2012-2018 Amrayn Web Services
-// Copyright (c) 2012-2018 @abumusamq
-//
-// This library is released under the MIT Licence.
-// https://github.com/amrayn/easyloggingpp/blob/master/LICENSE
-//
-// https://amrayn.com
-// http://muflihun.com
-//
-
-#include "easylogging++.h"
-
-#if defined(AUTO_INITIALIZE_EASYLOGGINGPP)
-INITIALIZE_EASYLOGGINGPP
-#endif
-
-namespace el {
-
-// el::base
-namespace base {
-// el::base::consts
-namespace consts {
-
-// Level log values - These are values that are replaced in place of %level
-// format specifier Extra spaces after format specifiers are only for
-// readability purposes in log files
-static const base::type::char_t *kInfoLevelLogValue = ELPP_LITERAL("INFO");
-static const base::type::char_t *kDebugLevelLogValue = ELPP_LITERAL("DEBUG");
-static const base::type::char_t *kWarningLevelLogValue =
- ELPP_LITERAL("WARNING");
-static const base::type::char_t *kErrorLevelLogValue = ELPP_LITERAL("ERROR");
-static const base::type::char_t *kFatalLevelLogValue = ELPP_LITERAL("FATAL");
-static const base::type::char_t *kVerboseLevelLogValue =
- ELPP_LITERAL("VERBOSE"); // will become VERBOSE-x where x = verbose level
-static const base::type::char_t *kTraceLevelLogValue = ELPP_LITERAL("TRACE");
-static const base::type::char_t *kInfoLevelShortLogValue = ELPP_LITERAL("I");
-static const base::type::char_t *kDebugLevelShortLogValue = ELPP_LITERAL("D");
-static const base::type::char_t *kWarningLevelShortLogValue = ELPP_LITERAL("W");
-static const base::type::char_t *kErrorLevelShortLogValue = ELPP_LITERAL("E");
-static const base::type::char_t *kFatalLevelShortLogValue = ELPP_LITERAL("F");
-static const base::type::char_t *kVerboseLevelShortLogValue = ELPP_LITERAL("V");
-static const base::type::char_t *kTraceLevelShortLogValue = ELPP_LITERAL("T");
-// Format specifiers - These are used to define log format
-static const base::type::char_t *kAppNameFormatSpecifier = ELPP_LITERAL("%app");
-static const base::type::char_t *kLoggerIdFormatSpecifier =
- ELPP_LITERAL("%logger");
-static const base::type::char_t *kThreadIdFormatSpecifier =
- ELPP_LITERAL("%thread");
-static const base::type::char_t *kSeverityLevelFormatSpecifier =
- ELPP_LITERAL("%level");
-static const base::type::char_t *kSeverityLevelShortFormatSpecifier =
- ELPP_LITERAL("%levshort");
-static const base::type::char_t *kDateTimeFormatSpecifier =
- ELPP_LITERAL("%datetime");
-static const base::type::char_t *kLogFileFormatSpecifier =
- ELPP_LITERAL("%file");
-static const base::type::char_t *kLogFileBaseFormatSpecifier =
- ELPP_LITERAL("%fbase");
-static const base::type::char_t *kLogLineFormatSpecifier =
- ELPP_LITERAL("%line");
-static const base::type::char_t *kLogLocationFormatSpecifier =
- ELPP_LITERAL("%loc");
-static const base::type::char_t *kLogFunctionFormatSpecifier =
- ELPP_LITERAL("%func");
-static const base::type::char_t *kCurrentUserFormatSpecifier =
- ELPP_LITERAL("%user");
-static const base::type::char_t *kCurrentHostFormatSpecifier =
- ELPP_LITERAL("%host");
-static const base::type::char_t *kMessageFormatSpecifier = ELPP_LITERAL("%msg");
-static const base::type::char_t *kVerboseLevelFormatSpecifier =
- ELPP_LITERAL("%vlevel");
-static const char *kDateTimeFormatSpecifierForFilename = "%datetime";
-// Date/time
-static const char *kDays[7] = {"Sunday", "Monday", "Tuesday", "Wednesday",
- "Thursday", "Friday", "Saturday"};
-static const char *kDaysAbbrev[7] = {"Sun", "Mon", "Tue", "Wed",
- "Thu", "Fri", "Sat"};
-static const char *kMonths[12] = {
- "January", "February", "March", "April", "May", "June",
- "July", "August", "September", "October", "November", "December"};
-static const char *kMonthsAbbrev[12] = {"Jan", "Feb", "Mar", "Apr",
- "May", "Jun", "Jul", "Aug",
- "Sep", "Oct", "Nov", "Dec"};
-static const char *kDefaultDateTimeFormat = "%Y-%M-%d %H:%m:%s,%g";
-static const char *kDefaultDateTimeFormatInFilename = "%Y-%M-%d_%H-%m";
-static const int kYearBase = 1900;
-static const char *kAm = "AM";
-static const char *kPm = "PM";
-// Miscellaneous constants
-
-static const char *kNullPointer = "nullptr";
-#if ELPP_VARIADIC_TEMPLATES_SUPPORTED
-#endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED
-static const base::type::VerboseLevel kMaxVerboseLevel = 9;
-static const char *kUnknownUser = "unknown-user";
-static const char *kUnknownHost = "unknown-host";
-
-//---------------- DEFAULT LOG FILE -----------------------
-
-#if defined(ELPP_NO_DEFAULT_LOG_FILE)
-#if ELPP_OS_UNIX
-static const char *kDefaultLogFile = "/dev/null";
-#elif ELPP_OS_WINDOWS
-static const char *kDefaultLogFile = "nul";
-#endif // ELPP_OS_UNIX
-#elif defined(ELPP_DEFAULT_LOG_FILE)
-static const char *kDefaultLogFile = ELPP_DEFAULT_LOG_FILE;
-#else
-static const char *kDefaultLogFile = "myeasylog.log";
-#endif // defined(ELPP_NO_DEFAULT_LOG_FILE)
-
-#if !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG)
-static const char *kDefaultLogFileParam = "--default-log-file";
-#endif // !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG)
-#if defined(ELPP_LOGGING_FLAGS_FROM_ARG)
-static const char *kLoggingFlagsParam = "--logging-flags";
-#endif // defined(ELPP_LOGGING_FLAGS_FROM_ARG)
-static const char *kValidLoggerIdSymbols =
- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._";
-static const char *kConfigurationComment = "##";
-static const char *kConfigurationLevel = "*";
-static const char *kConfigurationLoggerId = "--";
-} // namespace consts
-// el::base::utils
-namespace utils {
-
-/// @brief Aborts application due with user-defined status
-static void abort(int status, const std::string &reason) {
- // Both status and reason params are there for debugging with tools like gdb
- // etc
- ELPP_UNUSED(status);
- ELPP_UNUSED(reason);
-#if defined(ELPP_COMPILER_MSVC) && defined(_M_IX86) && defined(_DEBUG)
- // Ignore msvc critical error dialog - break instead (on debug mode)
- _asm int 3
-#else
- ::abort();
-#endif // defined(ELPP_COMPILER_MSVC) && defined(_M_IX86) && defined(_DEBUG)
-}
-
-} // namespace utils
-} // namespace base
-
-// el
-
-// LevelHelper
-
-const char *LevelHelper::convertToString(Level level) {
- // Do not use switch over strongly typed enums because Intel C++ compilers
- // dont support them yet.
- if (level == Level::Global)
- return "GLOBAL";
- if (level == Level::Debug)
- return "DEBUG";
- if (level == Level::Info)
- return "INFO";
- if (level == Level::Warning)
- return "WARNING";
- if (level == Level::Error)
- return "ERROR";
- if (level == Level::Fatal)
- return "FATAL";
- if (level == Level::Verbose)
- return "VERBOSE";
- if (level == Level::Trace)
- return "TRACE";
- return "UNKNOWN";
-}
-
-struct StringToLevelItem {
- const char *levelString;
- Level level;
-};
-
-static struct StringToLevelItem stringToLevelMap[] = {
- {"global", Level::Global}, {"debug", Level::Debug},
- {"info", Level::Info}, {"warning", Level::Warning},
- {"error", Level::Error}, {"fatal", Level::Fatal},
- {"verbose", Level::Verbose}, {"trace", Level::Trace}};
-
-Level LevelHelper::convertFromString(const char *levelStr) {
- for (auto &item : stringToLevelMap) {
- if (base::utils::Str::cStringCaseEq(levelStr, item.levelString)) {
- return item.level;
- }
- }
- return Level::Unknown;
-}
-
-void LevelHelper::forEachLevel(base::type::EnumType *startIndex,
- const std::function<bool(void)> &fn) {
- base::type::EnumType lIndexMax = LevelHelper::kMaxValid;
- do {
- if (fn()) {
- break;
- }
- *startIndex = static_cast<base::type::EnumType>(*startIndex << 1);
- } while (*startIndex <= lIndexMax);
-}
-
-// ConfigurationTypeHelper
-
-const char *
-ConfigurationTypeHelper::convertToString(ConfigurationType configurationType) {
- // Do not use switch over strongly typed enums because Intel C++ compilers
- // dont support them yet.
- if (configurationType == ConfigurationType::Enabled)
- return "ENABLED";
- if (configurationType == ConfigurationType::Filename)
- return "FILENAME";
- if (configurationType == ConfigurationType::Format)
- return "FORMAT";
- if (configurationType == ConfigurationType::ToFile)
- return "TO_FILE";
- if (configurationType == ConfigurationType::ToStandardOutput)
- return "TO_STANDARD_OUTPUT";
- if (configurationType == ConfigurationType::SubsecondPrecision)
- return "SUBSECOND_PRECISION";
- if (configurationType == ConfigurationType::PerformanceTracking)
- return "PERFORMANCE_TRACKING";
- if (configurationType == ConfigurationType::MaxLogFileSize)
- return "MAX_LOG_FILE_SIZE";
- if (configurationType == ConfigurationType::LogFlushThreshold)
- return "LOG_FLUSH_THRESHOLD";
- return "UNKNOWN";
-}
-
-struct ConfigurationStringToTypeItem {
- const char *configString;
- ConfigurationType configType;
-};
-
-static struct ConfigurationStringToTypeItem configStringToTypeMap[] = {
- {"enabled", ConfigurationType::Enabled},
- {"to_file", ConfigurationType::ToFile},
- {"to_standard_output", ConfigurationType::ToStandardOutput},
- {"format", ConfigurationType::Format},
- {"filename", ConfigurationType::Filename},
- {"subsecond_precision", ConfigurationType::SubsecondPrecision},
- {"milliseconds_width", ConfigurationType::MillisecondsWidth},
- {"performance_tracking", ConfigurationType::PerformanceTracking},
- {"max_log_file_size", ConfigurationType::MaxLogFileSize},
- {"log_flush_threshold", ConfigurationType::LogFlushThreshold},
-};
-
-ConfigurationType
-ConfigurationTypeHelper::convertFromString(const char *configStr) {
- for (auto &item : configStringToTypeMap) {
- if (base::utils::Str::cStringCaseEq(configStr, item.configString)) {
- return item.configType;
- }
- }
- return ConfigurationType::Unknown;
-}
-
-void ConfigurationTypeHelper::forEachConfigType(
- base::type::EnumType *startIndex, const std::function<bool(void)> &fn) {
- base::type::EnumType cIndexMax = ConfigurationTypeHelper::kMaxValid;
- do {
- if (fn()) {
- break;
- }
- *startIndex = static_cast<base::type::EnumType>(*startIndex << 1);
- } while (*startIndex <= cIndexMax);
-}
-
-// Configuration
-
-Configuration::Configuration(const Configuration &c)
- : m_level(c.m_level), m_configurationType(c.m_configurationType),
- m_value(c.m_value) {}
-
-Configuration &Configuration::operator=(const Configuration &c) {
- if (&c != this) {
- m_level = c.m_level;
- m_configurationType = c.m_configurationType;
- m_value = c.m_value;
- }
- return *this;
-}
-
-/// @brief Full constructor used to sets value of configuration
-Configuration::Configuration(Level level, ConfigurationType configurationType,
- const std::string &value)
- : m_level(level), m_configurationType(configurationType), m_value(value) {}
-
-void Configuration::log(el::base::type::ostream_t &os) const {
- os << LevelHelper::convertToString(m_level) << ELPP_LITERAL(" ")
- << ConfigurationTypeHelper::convertToString(m_configurationType)
- << ELPP_LITERAL(" = ") << m_value.c_str();
-}
-
-/// @brief Used to find configuration from configuration (pointers) repository.
-/// Avoid using it.
-Configuration::Predicate::Predicate(Level level,
- ConfigurationType configurationType)
- : m_level(level), m_configurationType(configurationType) {}
-
-bool Configuration::Predicate::operator()(const Configuration *conf) const {
- return ((conf != nullptr) && (conf->level() == m_level) &&
- (conf->configurationType() == m_configurationType));
-}
-
-// Configurations
-
-Configurations::Configurations(void)
- : m_configurationFile(std::string()), m_isFromFile(false) {}
-
-Configurations::Configurations(const std::string &configurationFile,
- bool useDefaultsForRemaining,
- Configurations *base)
- : m_configurationFile(configurationFile), m_isFromFile(false) {
- parseFromFile(configurationFile, base);
- if (useDefaultsForRemaining) {
- setRemainingToDefault();
- }
-}
-
-bool Configurations::parseFromFile(const std::string &configurationFile,
- Configurations *base) {
- // We initial assertion with true because if we have assertion disabled, we
- // want to pass this check and if assertion is enabled we will have values
- // re-assigned any way.
- bool assertionPassed = true;
- ELPP_ASSERT((assertionPassed = base::utils::File::pathExists(
- configurationFile.c_str(), true)) == true,
- "Configuration file [" << configurationFile
- << "] does not exist!");
- if (!assertionPassed) {
- return false;
- }
- bool success = Parser::parseFromFile(configurationFile, this, base);
- m_isFromFile = success;
- return success;
-}
-
-bool Configurations::parseFromText(const std::string &configurationsString,
- Configurations *base) {
- bool success = Parser::parseFromText(configurationsString, this, base);
- if (success) {
- m_isFromFile = false;
- }
- return success;
-}
-
-void Configurations::setFromBase(Configurations *base) {
- if (base == nullptr || base == this) {
- return;
- }
- base::threading::ScopedLock scopedLock(base->lock());
- for (Configuration *&conf : base->list()) {
- set(conf);
- }
-}
-
-bool Configurations::hasConfiguration(ConfigurationType configurationType) {
- base::type::EnumType lIndex = LevelHelper::kMinValid;
- bool result = false;
- LevelHelper::forEachLevel(&lIndex, [&](void) -> bool {
- if (hasConfiguration(LevelHelper::castFromInt(lIndex), configurationType)) {
- result = true;
- }
- return result;
- });
- return result;
-}
-
-bool Configurations::hasConfiguration(Level level,
- ConfigurationType configurationType) {
- base::threading::ScopedLock scopedLock(lock());
-#if ELPP_COMPILER_INTEL
- // We cant specify template types here, Intel C++ throws compilation error
- // "error: type name is not allowed"
- return RegistryWithPred::get(level, configurationType) != nullptr;
-#else
- return RegistryWithPred<Configuration, Configuration::Predicate>::get(
- level, configurationType) != nullptr;
-#endif // ELPP_COMPILER_INTEL
-}
-
-void Configurations::set(Level level, ConfigurationType configurationType,
- const std::string &value) {
- base::threading::ScopedLock scopedLock(lock());
- unsafeSet(level, configurationType,
- value); // This is not unsafe anymore as we have locked mutex
- if (level == Level::Global) {
- unsafeSetGlobally(configurationType, value,
- false); // Again this is not unsafe either
- }
-}
-
-void Configurations::set(Configuration *conf) {
- if (conf == nullptr) {
- return;
- }
- set(conf->level(), conf->configurationType(), conf->value());
-}
-
-void Configurations::setToDefault(void) {
- setGlobally(ConfigurationType::Enabled, std::string("true"), true);
- setGlobally(ConfigurationType::Filename,
- std::string(base::consts::kDefaultLogFile), true);
-#if defined(ELPP_NO_LOG_TO_FILE)
- setGlobally(ConfigurationType::ToFile, std::string("false"), true);
-#else
- setGlobally(ConfigurationType::ToFile, std::string("true"), true);
-#endif // defined(ELPP_NO_LOG_TO_FILE)
- setGlobally(ConfigurationType::ToStandardOutput, std::string("true"), true);
- setGlobally(ConfigurationType::SubsecondPrecision, std::string("3"), true);
- setGlobally(ConfigurationType::PerformanceTracking, std::string("true"),
- true);
- setGlobally(ConfigurationType::MaxLogFileSize, std::string("0"), true);
- setGlobally(ConfigurationType::LogFlushThreshold, std::string("0"), true);
-
- setGlobally(ConfigurationType::Format,
- std::string("%datetime %level [%logger] %msg"), true);
- set(Level::Debug, ConfigurationType::Format,
- std::string(
- "%datetime %level [%logger] [%user@%host] [%func] [%loc] %msg"));
- // INFO and WARNING are set to default by Level::Global
- set(Level::Error, ConfigurationType::Format,
- std::string("%datetime %level [%logger] %msg"));
- set(Level::Fatal, ConfigurationType::Format,
- std::string("%datetime %level [%logger] %msg"));
- set(Level::Verbose, ConfigurationType::Format,
- std::string("%datetime %level-%vlevel [%logger] %msg"));
- set(Level::Trace, ConfigurationType::Format,
- std::string("%datetime %level [%logger] [%func] [%loc] %msg"));
-}
-
-void Configurations::setRemainingToDefault(void) {
- base::threading::ScopedLock scopedLock(lock());
-#if defined(ELPP_NO_LOG_TO_FILE)
- unsafeSetIfNotExist(Level::Global, ConfigurationType::Enabled,
- std::string("false"));
-#else
- unsafeSetIfNotExist(Level::Global, ConfigurationType::Enabled,
- std::string("true"));
-#endif // defined(ELPP_NO_LOG_TO_FILE)
- unsafeSetIfNotExist(Level::Global, ConfigurationType::Filename,
- std::string(base::consts::kDefaultLogFile));
- unsafeSetIfNotExist(Level::Global, ConfigurationType::ToStandardOutput,
- std::string("true"));
- unsafeSetIfNotExist(Level::Global, ConfigurationType::SubsecondPrecision,
- std::string("3"));
- unsafeSetIfNotExist(Level::Global, ConfigurationType::PerformanceTracking,
- std::string("true"));
- unsafeSetIfNotExist(Level::Global, ConfigurationType::MaxLogFileSize,
- std::string("0"));
- unsafeSetIfNotExist(Level::Global, ConfigurationType::Format,
- std::string("%datetime %level [%logger] %msg"));
- unsafeSetIfNotExist(
- Level::Debug, ConfigurationType::Format,
- std::string(
- "%datetime %level [%logger] [%user@%host] [%func] [%loc] %msg"));
- // INFO and WARNING are set to default by Level::Global
- unsafeSetIfNotExist(Level::Error, ConfigurationType::Format,
- std::string("%datetime %level [%logger] %msg"));
- unsafeSetIfNotExist(Level::Fatal, ConfigurationType::Format,
- std::string("%datetime %level [%logger] %msg"));
- unsafeSetIfNotExist(Level::Verbose, ConfigurationType::Format,
- std::string("%datetime %level-%vlevel [%logger] %msg"));
- unsafeSetIfNotExist(
- Level::Trace, ConfigurationType::Format,
- std::string("%datetime %level [%logger] [%func] [%loc] %msg"));
-}
-
-bool Configurations::Parser::parseFromFile(const std::string &configurationFile,
- Configurations *sender,
- Configurations *base) {
- sender->setFromBase(base);
- std::ifstream fileStream_(configurationFile.c_str(), std::ifstream::in);
- ELPP_ASSERT(fileStream_.is_open(), "Unable to open configuration file ["
- << configurationFile
- << "] for parsing.");
- bool parsedSuccessfully = false;
- std::string line = std::string();
- Level currLevel = Level::Unknown;
- std::string currConfigStr = std::string();
- std::string currLevelStr = std::string();
- while (fileStream_.good()) {
- std::getline(fileStream_, line);
- parsedSuccessfully =
- parseLine(&line, &currConfigStr, &currLevelStr, &currLevel, sender);
- ELPP_ASSERT(parsedSuccessfully,
- "Unable to parse configuration line: " << line);
- }
- return parsedSuccessfully;
-}
-
-bool Configurations::Parser::parseFromText(
- const std::string &configurationsString, Configurations *sender,
- Configurations *base) {
- sender->setFromBase(base);
- bool parsedSuccessfully = false;
- std::stringstream ss(configurationsString);
- std::string line = std::string();
- Level currLevel = Level::Unknown;
- std::string currConfigStr = std::string();
- std::string currLevelStr = std::string();
- while (std::getline(ss, line)) {
- parsedSuccessfully =
- parseLine(&line, &currConfigStr, &currLevelStr, &currLevel, sender);
- ELPP_ASSERT(parsedSuccessfully,
- "Unable to parse configuration line: " << line);
- }
- return parsedSuccessfully;
-}
-
-void Configurations::Parser::ignoreComments(std::string *line) {
- std::size_t foundAt = 0;
- std::size_t quotesStart = line->find("\"");
- std::size_t quotesEnd = std::string::npos;
- if (quotesStart != std::string::npos) {
- quotesEnd = line->find("\"", quotesStart + 1);
- while (quotesEnd != std::string::npos && line->at(quotesEnd - 1) == '\\') {
- // Do not erase slash yet - we will erase it in parseLine(..) while loop
- quotesEnd = line->find("\"", quotesEnd + 2);
- }
- }
- if ((foundAt = line->find(base::consts::kConfigurationComment)) !=
- std::string::npos) {
- if (foundAt < quotesEnd) {
- foundAt = line->find(base::consts::kConfigurationComment, quotesEnd + 1);
- }
- *line = line->substr(0, foundAt);
- }
-}
-
-bool Configurations::Parser::isLevel(const std::string &line) {
- return base::utils::Str::startsWith(
- line, std::string(base::consts::kConfigurationLevel));
-}
-
-bool Configurations::Parser::isComment(const std::string &line) {
- return base::utils::Str::startsWith(
- line, std::string(base::consts::kConfigurationComment));
-}
-
-bool Configurations::Parser::isConfig(const std::string &line) {
- std::size_t assignment = line.find('=');
- return line != "" &&
- ((line[0] >= 'A' && line[0] <= 'Z') ||
- (line[0] >= 'a' && line[0] <= 'z')) &&
- (assignment != std::string::npos) && (line.size() > assignment);
-}
-
-bool Configurations::Parser::parseLine(std::string *line,
- std::string *currConfigStr,
- std::string *currLevelStr,
- Level *currLevel, Configurations *conf) {
- ConfigurationType currConfig = ConfigurationType::Unknown;
- std::string currValue = std::string();
- *line = base::utils::Str::trim(*line);
- if (isComment(*line))
- return true;
- ignoreComments(line);
- *line = base::utils::Str::trim(*line);
- if (line->empty()) {
- // Comment ignored
- return true;
- }
- if (isLevel(*line)) {
- if (line->size() <= 2) {
- return true;
- }
- *currLevelStr = line->substr(1, line->size() - 2);
- *currLevelStr = base::utils::Str::toUpper(*currLevelStr);
- *currLevelStr = base::utils::Str::trim(*currLevelStr);
- *currLevel = LevelHelper::convertFromString(currLevelStr->c_str());
- return true;
- }
- if (isConfig(*line)) {
- std::size_t assignment = line->find('=');
- *currConfigStr = line->substr(0, assignment);
- *currConfigStr = base::utils::Str::toUpper(*currConfigStr);
- *currConfigStr = base::utils::Str::trim(*currConfigStr);
- currConfig =
- ConfigurationTypeHelper::convertFromString(currConfigStr->c_str());
- currValue = line->substr(assignment + 1);
- currValue = base::utils::Str::trim(currValue);
- std::size_t quotesStart = currValue.find("\"", 0);
- std::size_t quotesEnd = std::string::npos;
- if (quotesStart != std::string::npos) {
- quotesEnd = currValue.find("\"", quotesStart + 1);
- while (quotesEnd != std::string::npos &&
- currValue.at(quotesEnd - 1) == '\\') {
- currValue = currValue.erase(quotesEnd - 1, 1);
- quotesEnd = currValue.find("\"", quotesEnd + 2);
- }
- }
- if (quotesStart != std::string::npos && quotesEnd != std::string::npos) {
- // Quote provided - check and strip if valid
- ELPP_ASSERT((quotesStart < quotesEnd),
- "Configuration error - No ending quote found in ["
- << currConfigStr << "]");
- ELPP_ASSERT((quotesStart + 1 != quotesEnd),
- "Empty configuration value for [" << currConfigStr << "]");
- if ((quotesStart != quotesEnd) && (quotesStart + 1 != quotesEnd)) {
- // Explicit check in case if assertion is disabled
- currValue = currValue.substr(quotesStart + 1, quotesEnd - 1);
- }
- }
- }
- ELPP_ASSERT(*currLevel != Level::Unknown,
- "Unrecognized severity level [" << *currLevelStr << "]");
- ELPP_ASSERT(currConfig != ConfigurationType::Unknown,
- "Unrecognized configuration [" << *currConfigStr << "]");
- if (*currLevel == Level::Unknown ||
- currConfig == ConfigurationType::Unknown) {
- return false; // unrecognizable level or config
- }
- conf->set(*currLevel, currConfig, currValue);
- return true;
-}
-
-void Configurations::unsafeSetIfNotExist(Level level,
- ConfigurationType configurationType,
- const std::string &value) {
- Configuration *conf =
- RegistryWithPred<Configuration, Configuration::Predicate>::get(
- level, configurationType);
- if (conf == nullptr) {
- unsafeSet(level, configurationType, value);
- }
-}
-
-void Configurations::unsafeSet(Level level, ConfigurationType configurationType,
- const std::string &value) {
- Configuration *conf =
- RegistryWithPred<Configuration, Configuration::Predicate>::get(
- level, configurationType);
- if (conf == nullptr) {
- registerNew(new Configuration(level, configurationType, value));
- } else {
- conf->setValue(value);
- }
- if (level == Level::Global) {
- unsafeSetGlobally(configurationType, value, false);
- }
-}
-
-void Configurations::setGlobally(ConfigurationType configurationType,
- const std::string &value,
- bool includeGlobalLevel) {
- if (includeGlobalLevel) {
- set(Level::Global, configurationType, value);
- }
- base::type::EnumType lIndex = LevelHelper::kMinValid;
- LevelHelper::forEachLevel(&lIndex, [&](void) -> bool {
- set(LevelHelper::castFromInt(lIndex), configurationType, value);
- return false; // Do not break lambda function yet as we need to set all
- // levels regardless
- });
-}
-
-void Configurations::unsafeSetGlobally(ConfigurationType configurationType,
- const std::string &value,
- bool includeGlobalLevel) {
- if (includeGlobalLevel) {
- unsafeSet(Level::Global, configurationType, value);
- }
- base::type::EnumType lIndex = LevelHelper::kMinValid;
- LevelHelper::forEachLevel(&lIndex, [&](void) -> bool {
- unsafeSet(LevelHelper::castFromInt(lIndex), configurationType, value);
- return false; // Do not break lambda function yet as we need to set all
- // levels regardless
- });
-}
-
-// LogBuilder
-
-void LogBuilder::convertToColoredOutput(base::type::string_t *logLine,
- Level level) {
- if (!m_termSupportsColor)
- return;
- const base::type::char_t *resetColor = ELPP_LITERAL("\x1b[0m");
- if (level == Level::Error || level == Level::Fatal)
- *logLine = ELPP_LITERAL("\x1b[31m") + *logLine + resetColor;
- else if (level == Level::Warning)
- *logLine = ELPP_LITERAL("\x1b[33m") + *logLine + resetColor;
- else if (level == Level::Debug)
- *logLine = ELPP_LITERAL("\x1b[32m") + *logLine + resetColor;
- else if (level == Level::Info)
- *logLine = ELPP_LITERAL("\x1b[36m") + *logLine + resetColor;
- else if (level == Level::Trace)
- *logLine = ELPP_LITERAL("\x1b[35m") + *logLine + resetColor;
-}
-
-// Logger
-
-Logger::Logger(const std::string &id,
- base::LogStreamsReferenceMapPtr logStreamsReference)
- : m_id(id), m_typedConfigurations(nullptr),
- m_parentApplicationName(std::string()), m_isConfigured(false),
- m_logStreamsReference(logStreamsReference) {
- initUnflushedCount();
-}
-
-Logger::Logger(const std::string &id, const Configurations &configurations,
- base::LogStreamsReferenceMapPtr logStreamsReference)
- : m_id(id), m_typedConfigurations(nullptr),
- m_parentApplicationName(std::string()), m_isConfigured(false),
- m_logStreamsReference(logStreamsReference) {
- initUnflushedCount();
- configure(configurations);
-}
-
-Logger::Logger(const Logger &logger) {
- base::utils::safeDelete(m_typedConfigurations);
- m_id = logger.m_id;
- m_typedConfigurations = logger.m_typedConfigurations;
- m_parentApplicationName = logger.m_parentApplicationName;
- m_isConfigured = logger.m_isConfigured;
- m_configurations = logger.m_configurations;
- m_unflushedCount = logger.m_unflushedCount;
- m_logStreamsReference = logger.m_logStreamsReference;
-}
-
-Logger &Logger::operator=(const Logger &logger) {
- if (&logger != this) {
- base::utils::safeDelete(m_typedConfigurations);
- m_id = logger.m_id;
- m_typedConfigurations = logger.m_typedConfigurations;
- m_parentApplicationName = logger.m_parentApplicationName;
- m_isConfigured = logger.m_isConfigured;
- m_configurations = logger.m_configurations;
- m_unflushedCount = logger.m_unflushedCount;
- m_logStreamsReference = logger.m_logStreamsReference;
- }
- return *this;
-}
-
-void Logger::configure(const Configurations &configurations) {
- m_isConfigured = false; // we set it to false in case if we fail
- initUnflushedCount();
- if (m_typedConfigurations != nullptr) {
- Configurations *c =
- const_cast<Configurations *>(m_typedConfigurations->configurations());
- if (c->hasConfiguration(Level::Global, ConfigurationType::Filename)) {
- flush();
- }
- }
- base::threading::ScopedLock scopedLock(lock());
- if (m_configurations != configurations) {
- m_configurations.setFromBase(const_cast<Configurations *>(&configurations));
- }
- base::utils::safeDelete(m_typedConfigurations);
- m_typedConfigurations =
- new base::TypedConfigurations(&m_configurations, m_logStreamsReference);
- resolveLoggerFormatSpec();
- m_isConfigured = true;
-}
-
-void Logger::reconfigure(void) {
- ELPP_INTERNAL_INFO(1, "Reconfiguring logger [" << m_id << "]");
- configure(m_configurations);
-}
-
-bool Logger::isValidId(const std::string &id) {
- for (std::string::const_iterator it = id.begin(); it != id.end(); ++it) {
- if (!base::utils::Str::contains(base::consts::kValidLoggerIdSymbols, *it)) {
- return false;
- }
- }
- return true;
-}
-
-void Logger::flush(void) {
- ELPP_INTERNAL_INFO(3, "Flushing logger [" << m_id << "] all levels");
- base::threading::ScopedLock scopedLock(lock());
- base::type::EnumType lIndex = LevelHelper::kMinValid;
- LevelHelper::forEachLevel(&lIndex, [&](void) -> bool {
- flush(LevelHelper::castFromInt(lIndex), nullptr);
- return false;
- });
-}
-
-void Logger::flush(Level level, base::type::fstream_t *fs) {
- if (fs == nullptr && m_typedConfigurations->toFile(level)) {
- fs = m_typedConfigurations->fileStream(level);
- }
- if (fs != nullptr) {
- fs->flush();
- std::unordered_map<Level, unsigned int>::iterator iter =
- m_unflushedCount.find(level);
- if (iter != m_unflushedCount.end()) {
- iter->second = 0;
- }
- Helpers::validateFileRolling(this, level);
- }
-}
-
-void Logger::initUnflushedCount(void) {
- m_unflushedCount.clear();
- base::type::EnumType lIndex = LevelHelper::kMinValid;
- LevelHelper::forEachLevel(&lIndex, [&](void) -> bool {
- m_unflushedCount.insert(
- std::make_pair(LevelHelper::castFromInt(lIndex), 0));
- return false;
- });
-}
-
-void Logger::resolveLoggerFormatSpec(void) const {
- base::type::EnumType lIndex = LevelHelper::kMinValid;
- LevelHelper::forEachLevel(&lIndex, [&](void) -> bool {
- base::LogFormat *logFormat = const_cast<base::LogFormat *>(
- &m_typedConfigurations->logFormat(LevelHelper::castFromInt(lIndex)));
- base::utils::Str::replaceFirstWithEscape(
- logFormat->m_format, base::consts::kLoggerIdFormatSpecifier, m_id);
- return false;
- });
-}
-
-// el::base
-namespace base {
-
-// el::base::utils
-namespace utils {
-
-// File
-
-base::type::fstream_t *File::newFileStream(const std::string &filename) {
- base::type::fstream_t *fs = new base::type::fstream_t(
- filename.c_str(), base::type::fstream_t::out
-#if !defined(ELPP_FRESH_LOG_FILE)
- | base::type::fstream_t::app
-#endif
- );
-#if defined(ELPP_UNICODE)
- std::locale elppUnicodeLocale("");
-#if ELPP_OS_WINDOWS
- std::locale elppUnicodeLocaleWindows(elppUnicodeLocale,
- new std::codecvt_utf8_utf16<wchar_t>);
- elppUnicodeLocale = elppUnicodeLocaleWindows;
-#endif // ELPP_OS_WINDOWS
- fs->imbue(elppUnicodeLocale);
-#endif // defined(ELPP_UNICODE)
- if (fs->is_open()) {
- fs->flush();
- } else {
- base::utils::safeDelete(fs);
- ELPP_INTERNAL_ERROR("Bad file [" << filename << "]", true);
- }
- return fs;
-}
-
-std::size_t File::getSizeOfFile(base::type::fstream_t *fs) {
- if (fs == nullptr) {
- return 0;
- }
- // Since the file stream is appended to or truncated, the current
- // offset is the file size.
- std::size_t size = static_cast<std::size_t>(fs->tellg());
- return size;
-}
-
-bool File::pathExists(const char *path, bool considerFile) {
- if (path == nullptr) {
- return false;
- }
-#if ELPP_OS_UNIX
- ELPP_UNUSED(considerFile);
- struct stat st;
- return (stat(path, &st) == 0);
-#elif ELPP_OS_WINDOWS
- DWORD fileType = GetFileAttributesA(path);
- if (fileType == INVALID_FILE_ATTRIBUTES) {
- return false;
- }
- return considerFile
- ? true
- : ((fileType & FILE_ATTRIBUTE_DIRECTORY) == 0 ? false : true);
-#endif // ELPP_OS_UNIX
-}
-
-bool File::createPath(const std::string &path) {
- if (path.empty()) {
- return false;
- }
- if (base::utils::File::pathExists(path.c_str())) {
- return true;
- }
- int status = -1;
-
- char *currPath = const_cast<char *>(path.c_str());
- std::string builtPath = std::string();
-#if ELPP_OS_UNIX
- if (path[0] == '/') {
- builtPath = "/";
- }
- currPath = STRTOK(currPath, base::consts::kFilePathSeparator, 0);
-#elif ELPP_OS_WINDOWS
- // Use secure functions API
- char *nextTok_ = nullptr;
- currPath = STRTOK(currPath, base::consts::kFilePathSeparator, &nextTok_);
- ELPP_UNUSED(nextTok_);
-#endif // ELPP_OS_UNIX
- while (currPath != nullptr) {
- builtPath.append(currPath);
- builtPath.append(base::consts::kFilePathSeparator);
-#if ELPP_OS_UNIX
- status = mkdir(builtPath.c_str(), ELPP_LOG_PERMS);
- currPath = STRTOK(nullptr, base::consts::kFilePathSeparator, 0);
-#elif ELPP_OS_WINDOWS
- status = _mkdir(builtPath.c_str());
- currPath = STRTOK(nullptr, base::consts::kFilePathSeparator, &nextTok_);
-#endif // ELPP_OS_UNIX
- }
- if (status == -1) {
- ELPP_INTERNAL_ERROR("Error while creating path [" << path << "]", true);
- return false;
- }
- return true;
-}
-
-std::string File::extractPathFromFilename(const std::string &fullPath,
- const char *separator) {
- if ((fullPath == "") || (fullPath.find(separator) == std::string::npos)) {
- return fullPath;
- }
- std::size_t lastSlashAt = fullPath.find_last_of(separator);
- if (lastSlashAt == 0) {
- return std::string(separator);
- }
- return fullPath.substr(0, lastSlashAt + 1);
-}
-
-void File::buildStrippedFilename(const char *filename, char buff[],
- std::size_t limit) {
- std::size_t sizeOfFilename = strlen(filename);
- if (sizeOfFilename >= limit) {
- filename += (sizeOfFilename - limit);
- if (filename[0] != '.' && filename[1] != '.') { // prepend if not already
- filename += 3; // 3 = '..'
- STRCAT(buff, "..", limit);
- }
- }
- STRCAT(buff, filename, limit);
-}
-
-void File::buildBaseFilename(const std::string &fullPath, char buff[],
- std::size_t limit, const char *separator) {
- const char *filename = fullPath.c_str();
- std::size_t lastSlashAt = fullPath.find_last_of(separator);
- filename += lastSlashAt ? lastSlashAt + 1 : 0;
- std::size_t sizeOfFilename = strlen(filename);
- if (sizeOfFilename >= limit) {
- filename += (sizeOfFilename - limit);
- if (filename[0] != '.' && filename[1] != '.') { // prepend if not already
- filename += 3; // 3 = '..'
- STRCAT(buff, "..", limit);
- }
- }
- STRCAT(buff, filename, limit);
-}
-
-// Str
-
-bool Str::wildCardMatch(const char *str, const char *pattern) {
- while (*pattern) {
- switch (*pattern) {
- case '?':
- if (!*str)
- return false;
- ++str;
- ++pattern;
- break;
- case '*':
- if (wildCardMatch(str, pattern + 1))
- return true;
- if (*str && wildCardMatch(str + 1, pattern))
- return true;
- return false;
- default:
- if (*str++ != *pattern++)
- return false;
- break;
- }
- }
- return !*str && !*pattern;
-}
-
-std::string &Str::ltrim(std::string &str) {
- str.erase(str.begin(), std::find_if(str.begin(), str.end(),
- [](char c) { return !std::isspace(c); }));
- return str;
-}
-
-std::string &Str::rtrim(std::string &str) {
- str.erase(std::find_if(str.rbegin(), str.rend(),
- [](char c) { return !std::isspace(c); })
- .base(),
- str.end());
- return str;
-}
-
-std::string &Str::trim(std::string &str) { return ltrim(rtrim(str)); }
-
-bool Str::startsWith(const std::string &str, const std::string &start) {
- return (str.length() >= start.length()) &&
- (str.compare(0, start.length(), start) == 0);
-}
-
-bool Str::endsWith(const std::string &str, const std::string &end) {
- return (str.length() >= end.length()) &&
- (str.compare(str.length() - end.length(), end.length(), end) == 0);
-}
-
-std::string &Str::replaceAll(std::string &str, char replaceWhat,
- char replaceWith) {
- std::replace(str.begin(), str.end(), replaceWhat, replaceWith);
- return str;
-}
-
-std::string &Str::replaceAll(std::string &str, const std::string &replaceWhat,
- const std::string &replaceWith) {
- if (replaceWhat == replaceWith)
- return str;
- std::size_t foundAt = std::string::npos;
- while ((foundAt = str.find(replaceWhat, foundAt + 1)) != std::string::npos) {
- str.replace(foundAt, replaceWhat.length(), replaceWith);
- }
- return str;
-}
-
-void Str::replaceFirstWithEscape(base::type::string_t &str,
- const base::type::string_t &replaceWhat,
- const base::type::string_t &replaceWith) {
- std::size_t foundAt = base::type::string_t::npos;
- while ((foundAt = str.find(replaceWhat, foundAt + 1)) !=
- base::type::string_t::npos) {
- if (foundAt > 0 && str[foundAt - 1] == base::consts::kFormatSpecifierChar) {
- str.erase(foundAt - 1, 1);
- ++foundAt;
- } else {
- str.replace(foundAt, replaceWhat.length(), replaceWith);
- return;
- }
- }
-}
-#if defined(ELPP_UNICODE)
-void Str::replaceFirstWithEscape(base::type::string_t &str,
- const base::type::string_t &replaceWhat,
- const std::string &replaceWith) {
- replaceFirstWithEscape(
- str, replaceWhat,
- base::type::string_t(replaceWith.begin(), replaceWith.end()));
-}
-#endif // defined(ELPP_UNICODE)
-
-std::string &Str::toUpper(std::string &str) {
- std::transform(str.begin(), str.end(), str.begin(),
- [](char c) { return static_cast<char>(::toupper(c)); });
- return str;
-}
-
-bool Str::cStringEq(const char *s1, const char *s2) {
- if (s1 == nullptr && s2 == nullptr)
- return true;
- if (s1 == nullptr || s2 == nullptr)
- return false;
- return strcmp(s1, s2) == 0;
-}
-
-bool Str::cStringCaseEq(const char *s1, const char *s2) {
- if (s1 == nullptr && s2 == nullptr)
- return true;
- if (s1 == nullptr || s2 == nullptr)
- return false;
-
- // With thanks to cygwin for this code
- int d = 0;
-
- while (true) {
- const int c1 = toupper(*s1++);
- const int c2 = toupper(*s2++);
-
- if (((d = c1 - c2) != 0) || (c2 == '\0')) {
- break;
- }
- }
-
- return d == 0;
-}
-
-bool Str::contains(const char *str, char c) {
- for (; *str; ++str) {
- if (*str == c)
- return true;
- }
- return false;
-}
-
-char *Str::convertAndAddToBuff(std::size_t n, int len, char *buf,
- const char *bufLim, bool zeroPadded) {
- char localBuff[10] = "";
- char *p = localBuff + sizeof(localBuff) - 2;
- if (n > 0) {
- for (; n > 0 && p > localBuff && len > 0; n /= 10, --len)
- *--p = static_cast<char>(n % 10 + '0');
- } else {
- *--p = '0';
- --len;
- }
- if (zeroPadded)
- while (p > localBuff && len-- > 0)
- *--p = static_cast<char>('0');
- return addToBuff(p, buf, bufLim);
-}
-
-char *Str::addToBuff(const char *str, char *buf, const char *bufLim) {
- while ((buf < bufLim) && ((*buf = *str++) != '\0'))
- ++buf;
- return buf;
-}
-
-char *Str::clearBuff(char buff[], std::size_t lim) {
- STRCPY(buff, "", lim);
- ELPP_UNUSED(
- lim); // For *nix we dont have anything using lim in above STRCPY macro
- return buff;
-}
-
-/// @brief Converts wchar* to char*
-/// NOTE: Need to free return value after use!
-char *Str::wcharPtrToCharPtr(const wchar_t *line) {
- std::size_t len_ = wcslen(line) + 1;
- char *buff_ = static_cast<char *>(malloc(len_ + 1));
-#if ELPP_OS_UNIX || (ELPP_OS_WINDOWS && !ELPP_CRT_DBG_WARNINGS)
- std::wcstombs(buff_, line, len_);
-#elif ELPP_OS_WINDOWS
- std::size_t convCount_ = 0;
- mbstate_t mbState_;
- ::memset(static_cast<void *>(&mbState_), 0, sizeof(mbState_));
- wcsrtombs_s(&convCount_, buff_, len_, &line, len_, &mbState_);
-#endif // ELPP_OS_UNIX || (ELPP_OS_WINDOWS && !ELPP_CRT_DBG_WARNINGS)
- return buff_;
-}
-
-// OS
-
-#if ELPP_OS_WINDOWS
-/// @brief Gets environment variables for Windows based OS.
-/// We are not using <code>getenv(const char*)</code> because of CRT
-/// deprecation
-/// @param varname Variable name to get environment variable value for
-/// @return If variable exist the value of it otherwise nullptr
-const char *OS::getWindowsEnvironmentVariable(const char *varname) {
- const DWORD bufferLen = 50;
- static char buffer[bufferLen];
- if (GetEnvironmentVariableA(varname, buffer, bufferLen)) {
- return buffer;
- }
- return nullptr;
-}
-#endif // ELPP_OS_WINDOWS
-#if ELPP_OS_ANDROID
-std::string OS::getProperty(const char *prop) {
- char propVal[PROP_VALUE_MAX + 1];
- int ret = __system_property_get(prop, propVal);
- return ret == 0 ? std::string() : std::string(propVal);
-}
-
-std::string OS::getDeviceName(void) {
- std::stringstream ss;
- std::string manufacturer = getProperty("ro.product.manufacturer");
- std::string model = getProperty("ro.product.model");
- if (manufacturer.empty() || model.empty()) {
- return std::string();
- }
- ss << manufacturer << "-" << model;
- return ss.str();
-}
-#endif // ELPP_OS_ANDROID
-
-const std::string OS::getBashOutput(const char *command) {
-#if (ELPP_OS_UNIX && !ELPP_OS_ANDROID && !ELPP_CYGWIN)
- if (command == nullptr) {
- return std::string();
- }
- FILE *proc = nullptr;
- if ((proc = popen(command, "r")) == nullptr) {
- ELPP_INTERNAL_ERROR("\nUnable to run command [" << command << "]", true);
- return std::string();
- }
- char hBuff[4096];
- if (fgets(hBuff, sizeof(hBuff), proc) != nullptr) {
- pclose(proc);
- const std::size_t buffLen = strlen(hBuff);
- if (buffLen > 0 && hBuff[buffLen - 1] == '\n') {
- hBuff[buffLen - 1] = '\0';
- }
- return std::string(hBuff);
- } else {
- pclose(proc);
- }
- return std::string();
-#else
- ELPP_UNUSED(command);
- return std::string();
-#endif // (ELPP_OS_UNIX && !ELPP_OS_ANDROID && !ELPP_CYGWIN)
-}
-
-std::string OS::getEnvironmentVariable(const char *variableName,
- const char *defaultVal,
- const char *alternativeBashCommand) {
-#if ELPP_OS_UNIX
- const char *val = getenv(variableName);
-#elif ELPP_OS_WINDOWS
- const char *val = getWindowsEnvironmentVariable(variableName);
-#endif // ELPP_OS_UNIX
- if ((val == nullptr) || ((strcmp(val, "") == 0))) {
-#if ELPP_OS_UNIX && defined(ELPP_FORCE_ENV_VAR_FROM_BASH)
- // Try harder on unix-based systems
- std::string valBash =
- base::utils::OS::getBashOutput(alternativeBashCommand);
- if (valBash.empty()) {
- return std::string(defaultVal);
- } else {
- return valBash;
- }
-#elif ELPP_OS_WINDOWS || ELPP_OS_UNIX
- ELPP_UNUSED(alternativeBashCommand);
- return std::string(defaultVal);
-#endif // ELPP_OS_UNIX && defined(ELPP_FORCE_ENV_VAR_FROM_BASH)
- }
- return std::string(val);
-}
-
-std::string OS::currentUser(void) {
-#if ELPP_OS_UNIX && !ELPP_OS_ANDROID
- return getEnvironmentVariable("USER", base::consts::kUnknownUser, "whoami");
-#elif ELPP_OS_WINDOWS
- return getEnvironmentVariable("USERNAME", base::consts::kUnknownUser);
-#elif ELPP_OS_ANDROID
- ELPP_UNUSED(base::consts::kUnknownUser);
- return std::string("android");
-#else
- return std::string();
-#endif // ELPP_OS_UNIX && !ELPP_OS_ANDROID
-}
-
-std::string OS::currentHost(void) {
-#if ELPP_OS_UNIX && !ELPP_OS_ANDROID
- return getEnvironmentVariable("HOSTNAME", base::consts::kUnknownHost,
- "hostname");
-#elif ELPP_OS_WINDOWS
- return getEnvironmentVariable("COMPUTERNAME", base::consts::kUnknownHost);
-#elif ELPP_OS_ANDROID
- ELPP_UNUSED(base::consts::kUnknownHost);
- return getDeviceName();
-#else
- return std::string();
-#endif // ELPP_OS_UNIX && !ELPP_OS_ANDROID
-}
-
-bool OS::termSupportsColor(void) {
- std::string term = getEnvironmentVariable("TERM", "");
- return term == "xterm" || term == "xterm-color" || term == "xterm-256color" ||
- term == "screen" || term == "linux" || term == "cygwin" ||
- term == "screen-256color";
-}
-
-// DateTime
-
-void DateTime::gettimeofday(struct timeval *tv) {
-#if ELPP_OS_WINDOWS
- if (tv != nullptr) {
-#if ELPP_COMPILER_MSVC || defined(_MSC_EXTENSIONS)
- const unsigned __int64 delta_ = 11644473600000000Ui64;
-#else
- const unsigned __int64 delta_ = 11644473600000000ULL;
-#endif // ELPP_COMPILER_MSVC || defined(_MSC_EXTENSIONS)
- const double secOffSet = 0.000001;
- const unsigned long usecOffSet = 1000000;
- FILETIME fileTime;
- GetSystemTimeAsFileTime(&fileTime);
- unsigned __int64 present = 0;
- present |= fileTime.dwHighDateTime;
- present = present << 32;
- present |= fileTime.dwLowDateTime;
- present /= 10; // mic-sec
- // Subtract the difference
- present -= delta_;
- tv->tv_sec = static_cast<long>(present * secOffSet);
- tv->tv_usec = static_cast<long>(present % usecOffSet);
- }
-#else
- ::gettimeofday(tv, nullptr);
-#endif // ELPP_OS_WINDOWS
-}
-
-std::string DateTime::getDateTime(const char *format,
- const base::SubsecondPrecision *ssPrec) {
- struct timeval currTime;
- gettimeofday(&currTime);
- return timevalToString(currTime, format, ssPrec);
-}
-
-std::string
-DateTime::timevalToString(struct timeval tval, const char *format,
- const el::base::SubsecondPrecision *ssPrec) {
- struct ::tm timeInfo;
- buildTimeInfo(&tval, &timeInfo);
- const int kBuffSize = 30;
- char buff_[kBuffSize] = "";
- parseFormat(buff_, kBuffSize, format, &timeInfo,
- static_cast<std::size_t>(tval.tv_usec / ssPrec->m_offset),
- ssPrec);
- return std::string(buff_);
-}
-
-base::type::string_t DateTime::formatTime(unsigned long long time,
- base::TimestampUnit timestampUnit) {
- base::type::EnumType start = static_cast<base::type::EnumType>(timestampUnit);
- const base::type::char_t *unit = base::consts::kTimeFormats[start].unit;
- for (base::type::EnumType i = start; i < base::consts::kTimeFormatsCount - 1;
- ++i) {
- if (time <= base::consts::kTimeFormats[i].value) {
- break;
- }
- if (base::consts::kTimeFormats[i].value == 1000.0f &&
- time / 1000.0f < 1.9f) {
- break;
- }
- time /= static_cast<decltype(time)>(base::consts::kTimeFormats[i].value);
- unit = base::consts::kTimeFormats[i + 1].unit;
- }
- base::type::stringstream_t ss;
- ss << time << " " << unit;
- return ss.str();
-}
-
-unsigned long long
-DateTime::getTimeDifference(const struct timeval &endTime,
- const struct timeval &startTime,
- base::TimestampUnit timestampUnit) {
- if (timestampUnit == base::TimestampUnit::Microsecond) {
- return static_cast<unsigned long long>(
- static_cast<unsigned long long>(1000000 * endTime.tv_sec +
- endTime.tv_usec) -
- static_cast<unsigned long long>(1000000 * startTime.tv_sec +
- startTime.tv_usec));
- }
- // milliseconds
- auto conv = [](const struct timeval &tim) {
- return static_cast<unsigned long long>((tim.tv_sec * 1000) +
- (tim.tv_usec / 1000));
- };
- return static_cast<unsigned long long>(conv(endTime) - conv(startTime));
-}
-
-struct ::tm *DateTime::buildTimeInfo(struct timeval *currTime,
- struct ::tm *timeInfo) {
-#if ELPP_OS_UNIX
- time_t rawTime = currTime->tv_sec;
- ::elpptime_r(&rawTime, timeInfo);
- return timeInfo;
-#else
-#if ELPP_COMPILER_MSVC
- ELPP_UNUSED(currTime);
- time_t t;
-#if defined(_USE_32BIT_TIME_T)
- _time32(&t);
-#else
- _time64(&t);
-#endif
- elpptime_s(timeInfo, &t);
- return timeInfo;
-#else
- // For any other compilers that don't have CRT warnings issue e.g, MinGW or
- // TDM GCC- we use different method
- time_t rawTime = currTime->tv_sec;
- struct tm *tmInf = elpptime(&rawTime);
- *timeInfo = *tmInf;
- return timeInfo;
-#endif // ELPP_COMPILER_MSVC
-#endif // ELPP_OS_UNIX
-}
-
-char *DateTime::parseFormat(char *buf, std::size_t bufSz, const char *format,
- const struct tm *tInfo, std::size_t msec,
- const base::SubsecondPrecision *ssPrec) {
- const char *bufLim = buf + bufSz;
- for (; *format; ++format) {
- if (*format == base::consts::kFormatSpecifierChar) {
- switch (*++format) {
- case base::consts::kFormatSpecifierChar: // Escape
- break;
- case '\0': // End
- --format;
- break;
- case 'd': // Day
- buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_mday, 2, buf,
- bufLim);
- continue;
- case 'a': // Day of week (short)
- buf = base::utils::Str::addToBuff(
- base::consts::kDaysAbbrev[tInfo->tm_wday], buf, bufLim);
- continue;
- case 'A': // Day of week (long)
- buf = base::utils::Str::addToBuff(base::consts::kDays[tInfo->tm_wday],
- buf, bufLim);
- continue;
- case 'M': // month
- buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_mon + 1, 2, buf,
- bufLim);
- continue;
- case 'b': // month (short)
- buf = base::utils::Str::addToBuff(
- base::consts::kMonthsAbbrev[tInfo->tm_mon], buf, bufLim);
- continue;
- case 'B': // month (long)
- buf = base::utils::Str::addToBuff(base::consts::kMonths[tInfo->tm_mon],
- buf, bufLim);
- continue;
- case 'y': // year (two digits)
- buf = base::utils::Str::convertAndAddToBuff(
- tInfo->tm_year + base::consts::kYearBase, 2, buf, bufLim);
- continue;
- case 'Y': // year (four digits)
- buf = base::utils::Str::convertAndAddToBuff(
- tInfo->tm_year + base::consts::kYearBase, 4, buf, bufLim);
- continue;
- case 'h': // hour (12-hour)
- buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_hour % 12, 2, buf,
- bufLim);
- continue;
- case 'H': // hour (24-hour)
- buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_hour, 2, buf,
- bufLim);
- continue;
- case 'm': // minute
- buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_min, 2, buf,
- bufLim);
- continue;
- case 's': // second
- buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_sec, 2, buf,
- bufLim);
- continue;
- case 'z': // subsecond part
- case 'g':
- buf = base::utils::Str::convertAndAddToBuff(msec, ssPrec->m_width, buf,
- bufLim);
- continue;
- case 'F': // AM/PM
- buf = base::utils::Str::addToBuff(
- (tInfo->tm_hour >= 12) ? base::consts::kPm : base::consts::kAm, buf,
- bufLim);
- continue;
- default:
- continue;
- }
- }
- if (buf == bufLim)
- break;
- *buf++ = *format;
- }
- return buf;
-}
-
-// CommandLineArgs
-
-void CommandLineArgs::setArgs(int argc, char **argv) {
- m_params.clear();
- m_paramsWithValue.clear();
- if (argc == 0 || argv == nullptr) {
- return;
- }
- m_argc = argc;
- m_argv = argv;
- for (int i = 1; i < m_argc; ++i) {
- const char *v = (strstr(m_argv[i], "="));
- if (v != nullptr && strlen(v) > 0) {
- std::string key = std::string(m_argv[i]);
- key = key.substr(0, key.find_first_of('='));
- if (hasParamWithValue(key.c_str())) {
- ELPP_INTERNAL_INFO(1, "Skipping ["
- << key << "] arg since it already has value ["
- << getParamValue(key.c_str()) << "]");
- } else {
- m_paramsWithValue.insert(std::make_pair(key, std::string(v + 1)));
- }
- }
- if (v == nullptr) {
- if (hasParam(m_argv[i])) {
- ELPP_INTERNAL_INFO(1, "Skipping [" << m_argv[i]
- << "] arg since it already exists");
- } else {
- m_params.push_back(std::string(m_argv[i]));
- }
- }
- }
-}
-
-bool CommandLineArgs::hasParamWithValue(const char *paramKey) const {
- return m_paramsWithValue.find(std::string(paramKey)) !=
- m_paramsWithValue.end();
-}
-
-const char *CommandLineArgs::getParamValue(const char *paramKey) const {
- std::unordered_map<std::string, std::string>::const_iterator iter =
- m_paramsWithValue.find(std::string(paramKey));
- return iter != m_paramsWithValue.end() ? iter->second.c_str() : "";
-}
-
-bool CommandLineArgs::hasParam(const char *paramKey) const {
- return std::find(m_params.begin(), m_params.end(), std::string(paramKey)) !=
- m_params.end();
-}
-
-bool CommandLineArgs::empty(void) const {
- return m_params.empty() && m_paramsWithValue.empty();
-}
-
-std::size_t CommandLineArgs::size(void) const {
- return m_params.size() + m_paramsWithValue.size();
-}
-
-base::type::ostream_t &operator<<(base::type::ostream_t &os,
- const CommandLineArgs &c) {
- for (int i = 1; i < c.m_argc; ++i) {
- os << ELPP_LITERAL("[") << c.m_argv[i] << ELPP_LITERAL("]");
- if (i < c.m_argc - 1) {
- os << ELPP_LITERAL(" ");
- }
- }
- return os;
-}
-
-} // namespace utils
-
-// el::base::threading
-namespace threading {
-
-#if ELPP_THREADING_ENABLED
-#if ELPP_USE_STD_THREADING
-#if ELPP_ASYNC_LOGGING
-static void msleep(int ms) {
- // Only when async logging enabled - this is because async is strict on
- // compiler
-#if defined(ELPP_NO_SLEEP_FOR)
- usleep(ms * 1000);
-#else
- std::this_thread::sleep_for(std::chrono::milliseconds(ms));
-#endif // defined(ELPP_NO_SLEEP_FOR)
-}
-#endif // ELPP_ASYNC_LOGGING
-#endif // !ELPP_USE_STD_THREADING
-#endif // ELPP_THREADING_ENABLED
-
-} // namespace threading
-
-// el::base
-
-// SubsecondPrecision
-
-void SubsecondPrecision::init(int width) {
- if (width < 1 || width > 6) {
- width = base::consts::kDefaultSubsecondPrecision;
- }
- m_width = width;
- switch (m_width) {
- case 3:
- m_offset = 1000;
- break;
- case 4:
- m_offset = 100;
- break;
- case 5:
- m_offset = 10;
- break;
- case 6:
- m_offset = 1;
- break;
- default:
- m_offset = 1000;
- break;
- }
-}
-
-// LogFormat
-
-LogFormat::LogFormat(void)
- : m_level(Level::Unknown), m_userFormat(base::type::string_t()),
- m_format(base::type::string_t()), m_dateTimeFormat(std::string()),
- m_flags(0x0), m_currentUser(base::utils::OS::currentUser()),
- m_currentHost(base::utils::OS::currentHost()) {}
-
-LogFormat::LogFormat(Level level, const base::type::string_t &format)
- : m_level(level), m_userFormat(format),
- m_currentUser(base::utils::OS::currentUser()),
- m_currentHost(base::utils::OS::currentHost()) {
- parseFromFormat(m_userFormat);
-}
-
-LogFormat::LogFormat(const LogFormat &logFormat)
- : m_level(logFormat.m_level), m_userFormat(logFormat.m_userFormat),
- m_format(logFormat.m_format),
- m_dateTimeFormat(logFormat.m_dateTimeFormat), m_flags(logFormat.m_flags),
- m_currentUser(logFormat.m_currentUser),
- m_currentHost(logFormat.m_currentHost) {}
-
-LogFormat::LogFormat(LogFormat &&logFormat) {
- m_level = std::move(logFormat.m_level);
- m_userFormat = std::move(logFormat.m_userFormat);
- m_format = std::move(logFormat.m_format);
- m_dateTimeFormat = std::move(logFormat.m_dateTimeFormat);
- m_flags = std::move(logFormat.m_flags);
- m_currentUser = std::move(logFormat.m_currentUser);
- m_currentHost = std::move(logFormat.m_currentHost);
-}
-
-LogFormat &LogFormat::operator=(const LogFormat &logFormat) {
- if (&logFormat != this) {
- m_level = logFormat.m_level;
- m_userFormat = logFormat.m_userFormat;
- m_dateTimeFormat = logFormat.m_dateTimeFormat;
- m_flags = logFormat.m_flags;
- m_currentUser = logFormat.m_currentUser;
- m_currentHost = logFormat.m_currentHost;
- }
- return *this;
-}
-
-bool LogFormat::operator==(const LogFormat &other) {
- return m_level == other.m_level && m_userFormat == other.m_userFormat &&
- m_format == other.m_format &&
- m_dateTimeFormat == other.m_dateTimeFormat && m_flags == other.m_flags;
-}
-
-/// @brief Updates format to be used while logging.
-/// @param userFormat User provided format
-void LogFormat::parseFromFormat(const base::type::string_t &userFormat) {
- // We make copy because we will be changing the format
- // i.e, removing user provided date format from original format
- // and then storing it.
- base::type::string_t formatCopy = userFormat;
- m_flags = 0x0;
- auto conditionalAddFlag = [&](const base::type::char_t *specifier,
- base::FormatFlags flag) {
- std::size_t foundAt = base::type::string_t::npos;
- while ((foundAt = formatCopy.find(specifier, foundAt + 1)) !=
- base::type::string_t::npos) {
- if (foundAt > 0 &&
- formatCopy[foundAt - 1] == base::consts::kFormatSpecifierChar) {
- if (hasFlag(flag)) {
- // If we already have flag we remove the escape chars so that '%%' is
- // turned to '%' even after specifier resolution - this is because we
- // only replaceFirst specifier
- formatCopy.erase(foundAt - 1, 1);
- ++foundAt;
- }
- } else {
- if (!hasFlag(flag))
- addFlag(flag);
- }
- }
- };
- conditionalAddFlag(base::consts::kAppNameFormatSpecifier,
- base::FormatFlags::AppName);
- conditionalAddFlag(base::consts::kSeverityLevelFormatSpecifier,
- base::FormatFlags::Level);
- conditionalAddFlag(base::consts::kSeverityLevelShortFormatSpecifier,
- base::FormatFlags::LevelShort);
- conditionalAddFlag(base::consts::kLoggerIdFormatSpecifier,
- base::FormatFlags::LoggerId);
- conditionalAddFlag(base::consts::kThreadIdFormatSpecifier,
- base::FormatFlags::ThreadId);
- conditionalAddFlag(base::consts::kLogFileFormatSpecifier,
- base::FormatFlags::File);
- conditionalAddFlag(base::consts::kLogFileBaseFormatSpecifier,
- base::FormatFlags::FileBase);
- conditionalAddFlag(base::consts::kLogLineFormatSpecifier,
- base::FormatFlags::Line);
- conditionalAddFlag(base::consts::kLogLocationFormatSpecifier,
- base::FormatFlags::Location);
- conditionalAddFlag(base::consts::kLogFunctionFormatSpecifier,
- base::FormatFlags::Function);
- conditionalAddFlag(base::consts::kCurrentUserFormatSpecifier,
- base::FormatFlags::User);
- conditionalAddFlag(base::consts::kCurrentHostFormatSpecifier,
- base::FormatFlags::Host);
- conditionalAddFlag(base::consts::kMessageFormatSpecifier,
- base::FormatFlags::LogMessage);
- conditionalAddFlag(base::consts::kVerboseLevelFormatSpecifier,
- base::FormatFlags::VerboseLevel);
- // For date/time we need to extract user's date format first
- std::size_t dateIndex = std::string::npos;
- if ((dateIndex = formatCopy.find(base::consts::kDateTimeFormatSpecifier)) !=
- std::string::npos) {
- while (dateIndex != std::string::npos && dateIndex > 0 &&
- formatCopy[dateIndex - 1] == base::consts::kFormatSpecifierChar) {
- dateIndex = formatCopy.find(base::consts::kDateTimeFormatSpecifier,
- dateIndex + 1);
- }
- if (dateIndex != std::string::npos) {
- addFlag(base::FormatFlags::DateTime);
- updateDateFormat(dateIndex, formatCopy);
- }
- }
- m_format = formatCopy;
- updateFormatSpec();
-}
-
-void LogFormat::updateDateFormat(std::size_t index,
- base::type::string_t &currFormat) {
- if (hasFlag(base::FormatFlags::DateTime)) {
- index += ELPP_STRLEN(base::consts::kDateTimeFormatSpecifier);
- }
- const base::type::char_t *ptr = currFormat.c_str() + index;
- if ((currFormat.size() > index) && (ptr[0] == '{')) {
- // User has provided format for date/time
- ++ptr;
- int count = 1; // Start by 1 in order to remove starting brace
- std::stringstream ss;
- for (; *ptr; ++ptr, ++count) {
- if (*ptr == '}') {
- ++count; // In order to remove ending brace
- break;
- }
- ss << static_cast<char>(*ptr);
- }
- currFormat.erase(index, count);
- m_dateTimeFormat = ss.str();
- } else {
- // No format provided, use default
- if (hasFlag(base::FormatFlags::DateTime)) {
- m_dateTimeFormat = std::string(base::consts::kDefaultDateTimeFormat);
- }
- }
-}
-
-void LogFormat::updateFormatSpec(void) {
- // Do not use switch over strongly typed enums because Intel C++ compilers
- // dont support them yet.
- if (m_level == Level::Debug) {
- base::utils::Str::replaceFirstWithEscape(
- m_format, base::consts::kSeverityLevelFormatSpecifier,
- base::consts::kDebugLevelLogValue);
- base::utils::Str::replaceFirstWithEscape(
- m_format, base::consts::kSeverityLevelShortFormatSpecifier,
- base::consts::kDebugLevelShortLogValue);
- } else if (m_level == Level::Info) {
- base::utils::Str::replaceFirstWithEscape(
- m_format, base::consts::kSeverityLevelFormatSpecifier,
- base::consts::kInfoLevelLogValue);
- base::utils::Str::replaceFirstWithEscape(
- m_format, base::consts::kSeverityLevelShortFormatSpecifier,
- base::consts::kInfoLevelShortLogValue);
- } else if (m_level == Level::Warning) {
- base::utils::Str::replaceFirstWithEscape(
- m_format, base::consts::kSeverityLevelFormatSpecifier,
- base::consts::kWarningLevelLogValue);
- base::utils::Str::replaceFirstWithEscape(
- m_format, base::consts::kSeverityLevelShortFormatSpecifier,
- base::consts::kWarningLevelShortLogValue);
- } else if (m_level == Level::Error) {
- base::utils::Str::replaceFirstWithEscape(
- m_format, base::consts::kSeverityLevelFormatSpecifier,
- base::consts::kErrorLevelLogValue);
- base::utils::Str::replaceFirstWithEscape(
- m_format, base::consts::kSeverityLevelShortFormatSpecifier,
- base::consts::kErrorLevelShortLogValue);
- } else if (m_level == Level::Fatal) {
- base::utils::Str::replaceFirstWithEscape(
- m_format, base::consts::kSeverityLevelFormatSpecifier,
- base::consts::kFatalLevelLogValue);
- base::utils::Str::replaceFirstWithEscape(
- m_format, base::consts::kSeverityLevelShortFormatSpecifier,
- base::consts::kFatalLevelShortLogValue);
- } else if (m_level == Level::Verbose) {
- base::utils::Str::replaceFirstWithEscape(
- m_format, base::consts::kSeverityLevelFormatSpecifier,
- base::consts::kVerboseLevelLogValue);
- base::utils::Str::replaceFirstWithEscape(
- m_format, base::consts::kSeverityLevelShortFormatSpecifier,
- base::consts::kVerboseLevelShortLogValue);
- } else if (m_level == Level::Trace) {
- base::utils::Str::replaceFirstWithEscape(
- m_format, base::consts::kSeverityLevelFormatSpecifier,
- base::consts::kTraceLevelLogValue);
- base::utils::Str::replaceFirstWithEscape(
- m_format, base::consts::kSeverityLevelShortFormatSpecifier,
- base::consts::kTraceLevelShortLogValue);
- }
- if (hasFlag(base::FormatFlags::User)) {
- base::utils::Str::replaceFirstWithEscape(
- m_format, base::consts::kCurrentUserFormatSpecifier, m_currentUser);
- }
- if (hasFlag(base::FormatFlags::Host)) {
- base::utils::Str::replaceFirstWithEscape(
- m_format, base::consts::kCurrentHostFormatSpecifier, m_currentHost);
- }
- // Ignore Level::Global and Level::Unknown
-}
-
-// TypedConfigurations
-
-TypedConfigurations::TypedConfigurations(
- Configurations *configurations,
- LogStreamsReferenceMapPtr logStreamsReference) {
- m_configurations = configurations;
- m_logStreamsReference = logStreamsReference;
- build(m_configurations);
-}
-
-TypedConfigurations::TypedConfigurations(const TypedConfigurations &other) {
- this->m_configurations = other.m_configurations;
- this->m_logStreamsReference = other.m_logStreamsReference;
- build(m_configurations);
-}
-
-bool TypedConfigurations::enabled(Level level) {
- return getConfigByVal<bool>(level, &m_enabledMap, "enabled");
-}
-
-bool TypedConfigurations::toFile(Level level) {
- return getConfigByVal<bool>(level, &m_toFileMap, "toFile");
-}
-
-const std::string &TypedConfigurations::filename(Level level) {
- return getConfigByRef<std::string>(level, &m_filenameMap, "filename");
-}
-
-bool TypedConfigurations::toStandardOutput(Level level) {
- return getConfigByVal<bool>(level, &m_toStandardOutputMap,
- "toStandardOutput");
-}
-
-const base::LogFormat &TypedConfigurations::logFormat(Level level) {
- return getConfigByRef<base::LogFormat>(level, &m_logFormatMap, "logFormat");
-}
-
-const base::SubsecondPrecision &
-TypedConfigurations::subsecondPrecision(Level level) {
- return getConfigByRef<base::SubsecondPrecision>(
- level, &m_subsecondPrecisionMap, "subsecondPrecision");
-}
-
-const base::MillisecondsWidth &
-TypedConfigurations::millisecondsWidth(Level level) {
- return getConfigByRef<base::MillisecondsWidth>(
- level, &m_subsecondPrecisionMap, "millisecondsWidth");
-}
-
-bool TypedConfigurations::performanceTracking(Level level) {
- return getConfigByVal<bool>(level, &m_performanceTrackingMap,
- "performanceTracking");
-}
-
-base::type::fstream_t *TypedConfigurations::fileStream(Level level) {
- return getConfigByRef<base::FileStreamPtr>(level, &m_fileStreamMap,
- "fileStream")
- .get();
-}
-
-std::size_t TypedConfigurations::maxLogFileSize(Level level) {
- return getConfigByVal<std::size_t>(level, &m_maxLogFileSizeMap,
- "maxLogFileSize");
-}
-
-std::size_t TypedConfigurations::logFlushThreshold(Level level) {
- return getConfigByVal<std::size_t>(level, &m_logFlushThresholdMap,
- "logFlushThreshold");
-}
-
-void TypedConfigurations::build(Configurations *configurations) {
- base::threading::ScopedLock scopedLock(lock());
- auto getBool = [](std::string boolStr) -> bool { // Pass by value for trimming
- base::utils::Str::trim(boolStr);
- return (boolStr == "TRUE" || boolStr == "true" || boolStr == "1");
- };
- std::vector<Configuration *> withFileSizeLimit;
- for (Configurations::const_iterator it = configurations->begin();
- it != configurations->end(); ++it) {
- Configuration *conf = *it;
- // We cannot use switch on strong enums because Intel C++ dont support them
- // yet
- if (conf->configurationType() == ConfigurationType::Enabled) {
- setValue(conf->level(), getBool(conf->value()), &m_enabledMap);
- } else if (conf->configurationType() == ConfigurationType::ToFile) {
- setValue(conf->level(), getBool(conf->value()), &m_toFileMap);
- } else if (conf->configurationType() ==
- ConfigurationType::ToStandardOutput) {
- setValue(conf->level(), getBool(conf->value()), &m_toStandardOutputMap);
- } else if (conf->configurationType() == ConfigurationType::Filename) {
- // We do not yet configure filename but we will configure in another
- // loop. This is because if file cannot be created, we will force ToFile
- // to be false. Because configuring logger is not necessarily performance
- // sensitive operation, we can live with another loop; (by the way this
- // loop is not very heavy either)
- } else if (conf->configurationType() == ConfigurationType::Format) {
- setValue(conf->level(),
- base::LogFormat(conf->level(),
- base::type::string_t(conf->value().begin(),
- conf->value().end())),
- &m_logFormatMap);
- } else if (conf->configurationType() ==
- ConfigurationType::SubsecondPrecision) {
- setValue(
- Level::Global,
- base::SubsecondPrecision(static_cast<int>(getULong(conf->value()))),
- &m_subsecondPrecisionMap);
- } else if (conf->configurationType() ==
- ConfigurationType::PerformanceTracking) {
- setValue(Level::Global, getBool(conf->value()),
- &m_performanceTrackingMap);
- } else if (conf->configurationType() == ConfigurationType::MaxLogFileSize) {
- auto v = getULong(conf->value());
- setValue(conf->level(), static_cast<std::size_t>(v),
- &m_maxLogFileSizeMap);
- if (v != 0) {
- withFileSizeLimit.push_back(conf);
- }
- } else if (conf->configurationType() ==
- ConfigurationType::LogFlushThreshold) {
- setValue(conf->level(), static_cast<std::size_t>(getULong(conf->value())),
- &m_logFlushThresholdMap);
- }
- }
- // As mentioned earlier, we will now set filename configuration in separate
- // loop to deal with non-existent files
- for (Configurations::const_iterator it = configurations->begin();
- it != configurations->end(); ++it) {
- Configuration *conf = *it;
- if (conf->configurationType() == ConfigurationType::Filename) {
- insertFile(conf->level(), conf->value());
- }
- }
- for (std::vector<Configuration *>::iterator conf = withFileSizeLimit.begin();
- conf != withFileSizeLimit.end(); ++conf) {
- // This is not unsafe as mutex is locked in currect scope
- unsafeValidateFileRolling((*conf)->level(),
- base::defaultPreRollOutCallback);
- }
-}
-
-unsigned long TypedConfigurations::getULong(std::string confVal) {
- bool valid = true;
- base::utils::Str::trim(confVal);
- valid = !confVal.empty() &&
- std::find_if(confVal.begin(), confVal.end(), [](char c) {
- return !base::utils::Str::isDigit(c);
- }) == confVal.end();
- if (!valid) {
- valid = false;
- ELPP_ASSERT(valid,
- "Configuration value not a valid integer [" << confVal << "]");
- return 0;
- }
- return atol(confVal.c_str());
-}
-
-std::string TypedConfigurations::resolveFilename(const std::string &filename) {
- std::string resultingFilename = filename;
- std::size_t dateIndex = std::string::npos;
- std::string dateTimeFormatSpecifierStr =
- std::string(base::consts::kDateTimeFormatSpecifierForFilename);
- if ((dateIndex = resultingFilename.find(
- dateTimeFormatSpecifierStr.c_str())) != std::string::npos) {
- while (dateIndex > 0 && resultingFilename[dateIndex - 1] ==
- base::consts::kFormatSpecifierChar) {
- dateIndex = resultingFilename.find(dateTimeFormatSpecifierStr.c_str(),
- dateIndex + 1);
- }
- if (dateIndex != std::string::npos) {
- const char *ptr = resultingFilename.c_str() + dateIndex;
- // Goto end of specifier
- ptr += dateTimeFormatSpecifierStr.size();
- std::string fmt;
- if ((resultingFilename.size() > dateIndex) && (ptr[0] == '{')) {
- // User has provided format for date/time
- ++ptr;
- int count = 1; // Start by 1 in order to remove starting brace
- std::stringstream ss;
- for (; *ptr; ++ptr, ++count) {
- if (*ptr == '}') {
- ++count; // In order to remove ending brace
- break;
- }
- ss << *ptr;
- }
- resultingFilename.erase(dateIndex + dateTimeFormatSpecifierStr.size(),
- count);
- fmt = ss.str();
- } else {
- fmt = std::string(base::consts::kDefaultDateTimeFormatInFilename);
- }
- base::SubsecondPrecision ssPrec(3);
- std::string now =
- base::utils::DateTime::getDateTime(fmt.c_str(), &ssPrec);
- base::utils::Str::replaceAll(
- now, '/',
- '-'); // Replace path element since we are dealing with filename
- base::utils::Str::replaceAll(resultingFilename,
- dateTimeFormatSpecifierStr, now);
- }
- }
- return resultingFilename;
-}
-
-void TypedConfigurations::insertFile(Level level,
- const std::string &fullFilename) {
- std::string resolvedFilename = resolveFilename(fullFilename);
- if (resolvedFilename.empty()) {
- std::cerr << "Could not load empty file for logging, please re-check your "
- "configurations for level ["
- << LevelHelper::convertToString(level) << "]";
- }
- std::string filePath = base::utils::File::extractPathFromFilename(
- resolvedFilename, base::consts::kFilePathSeparator);
- if (filePath.size() < resolvedFilename.size()) {
- base::utils::File::createPath(filePath);
- }
- auto create = [&](Level level) {
- base::LogStreamsReferenceMap::iterator filestreamIter =
- m_logStreamsReference->find(resolvedFilename);
- base::type::fstream_t *fs = nullptr;
- if (filestreamIter == m_logStreamsReference->end()) {
- // We need a completely new stream, nothing to share with
- fs = base::utils::File::newFileStream(resolvedFilename);
- m_filenameMap.insert(std::make_pair(level, resolvedFilename));
- m_fileStreamMap.insert(std::make_pair(level, base::FileStreamPtr(fs)));
- m_logStreamsReference->insert(std::make_pair(
- resolvedFilename, base::FileStreamPtr(m_fileStreamMap.at(level))));
- } else {
- // Woops! we have an existing one, share it!
- m_filenameMap.insert(std::make_pair(level, filestreamIter->first));
- m_fileStreamMap.insert(
- std::make_pair(level, base::FileStreamPtr(filestreamIter->second)));
- fs = filestreamIter->second.get();
- }
- if (fs == nullptr) {
- // We display bad file error from newFileStream()
- ELPP_INTERNAL_ERROR("Setting [TO_FILE] of ["
- << LevelHelper::convertToString(level)
- << "] to FALSE",
- false);
- setValue(level, false, &m_toFileMap);
- }
- };
- // If we dont have file conf for any level, create it for Level::Global first
- // otherwise create for specified level
- create(m_filenameMap.empty() && m_fileStreamMap.empty() ? Level::Global
- : level);
-}
-
-bool TypedConfigurations::unsafeValidateFileRolling(
- Level level, const PreRollOutCallback &preRollOutCallback) {
- base::type::fstream_t *fs =
- unsafeGetConfigByRef(level, &m_fileStreamMap, "fileStream").get();
- if (fs == nullptr) {
- return true;
- }
- std::size_t maxLogFileSize =
- unsafeGetConfigByVal(level, &m_maxLogFileSizeMap, "maxLogFileSize");
- std::size_t currFileSize = base::utils::File::getSizeOfFile(fs);
- if (maxLogFileSize != 0 && currFileSize >= maxLogFileSize) {
- std::string fname = unsafeGetConfigByRef(level, &m_filenameMap, "filename");
- ELPP_INTERNAL_INFO(1, "Truncating log file ["
- << fname
- << "] as a result of configurations for level ["
- << LevelHelper::convertToString(level) << "]");
- fs->close();
- preRollOutCallback(fname.c_str(), currFileSize);
- fs->open(fname, std::fstream::out | std::fstream::trunc);
- return true;
- }
- return false;
-}
-
-// RegisteredHitCounters
-
-bool RegisteredHitCounters::validateEveryN(const char *filename,
- base::type::LineNumber lineNumber,
- std::size_t n) {
- base::threading::ScopedLock scopedLock(lock());
- base::HitCounter *counter = get(filename, lineNumber);
- if (counter == nullptr) {
- registerNew(counter = new base::HitCounter(filename, lineNumber));
- }
- counter->validateHitCounts(n);
- bool result =
- (n >= 1 && counter->hitCounts() != 0 && counter->hitCounts() % n == 0);
- return result;
-}
-
-/// @brief Validates counter for hits >= N, i.e, registers new if does not exist
-/// otherwise updates original one
-/// @return True if validation resulted in triggering hit. Meaning logs should
-/// be written everytime true is returned
-bool RegisteredHitCounters::validateAfterN(const char *filename,
- base::type::LineNumber lineNumber,
- std::size_t n) {
- base::threading::ScopedLock scopedLock(lock());
- base::HitCounter *counter = get(filename, lineNumber);
- if (counter == nullptr) {
- registerNew(counter = new base::HitCounter(filename, lineNumber));
- }
- // Do not use validateHitCounts here since we do not want to reset counter
- // here Note the >= instead of > because we are incrementing after this check
- if (counter->hitCounts() >= n)
- return true;
- counter->increment();
- return false;
-}
-
-/// @brief Validates counter for hits are <= n, i.e, registers new if does not
-/// exist otherwise updates original one
-/// @return True if validation resulted in triggering hit. Meaning logs should
-/// be written everytime true is returned
-bool RegisteredHitCounters::validateNTimes(const char *filename,
- base::type::LineNumber lineNumber,
- std::size_t n) {
- base::threading::ScopedLock scopedLock(lock());
- base::HitCounter *counter = get(filename, lineNumber);
- if (counter == nullptr) {
- registerNew(counter = new base::HitCounter(filename, lineNumber));
- }
- counter->increment();
- // Do not use validateHitCounts here since we do not want to reset counter
- // here
- if (counter->hitCounts() <= n)
- return true;
- return false;
-}
-
-// RegisteredLoggers
-
-RegisteredLoggers::RegisteredLoggers(const LogBuilderPtr &defaultLogBuilder)
- : m_defaultLogBuilder(defaultLogBuilder) {
- m_defaultConfigurations.setToDefault();
- m_logStreamsReference = std::make_shared<base::LogStreamsReferenceMap>();
-}
-
-Logger *RegisteredLoggers::get(const std::string &id, bool forceCreation) {
- base::threading::ScopedLock scopedLock(lock());
- Logger *logger_ = base::utils::Registry<Logger, std::string>::get(id);
- if (logger_ == nullptr && forceCreation) {
- bool validId = Logger::isValidId(id);
- if (!validId) {
- ELPP_ASSERT(validId, "Invalid logger ID ["
- << id << "]. Not registering this logger.");
- return nullptr;
- }
- logger_ = new Logger(id, m_defaultConfigurations, m_logStreamsReference);
- logger_->m_logBuilder = m_defaultLogBuilder;
- registerNew(id, logger_);
- LoggerRegistrationCallback *callback = nullptr;
- for (const std::pair<std::string, base::type::LoggerRegistrationCallbackPtr>
- h : m_loggerRegistrationCallbacks) {
- callback = h.second.get();
- if (callback != nullptr && callback->enabled()) {
- callback->handle(logger_);
- }
- }
- }
- return logger_;
-}
-
-bool RegisteredLoggers::remove(const std::string &id) {
- if (id == base::consts::kDefaultLoggerId) {
- return false;
- }
- // get has internal lock
- Logger *logger = base::utils::Registry<Logger, std::string>::get(id);
- if (logger != nullptr) {
- // unregister has internal lock
- unregister(logger);
- }
- return true;
-}
-
-void RegisteredLoggers::unsafeFlushAll(void) {
- ELPP_INTERNAL_INFO(1, "Flushing all log files");
- for (base::LogStreamsReferenceMap::iterator it =
- m_logStreamsReference->begin();
- it != m_logStreamsReference->end(); ++it) {
- if (it->second.get() == nullptr)
- continue;
- it->second->flush();
- }
-}
-
-// VRegistry
-
-VRegistry::VRegistry(base::type::VerboseLevel level,
- base::type::EnumType *pFlags)
- : m_level(level), m_pFlags(pFlags) {}
-
-/// @brief Sets verbose level. Accepted range is 0-9
-void VRegistry::setLevel(base::type::VerboseLevel level) {
- base::threading::ScopedLock scopedLock(lock());
- if (level > 9)
- m_level = base::consts::kMaxVerboseLevel;
- else
- m_level = level;
-}
-
-void VRegistry::setModules(const char *modules) {
- base::threading::ScopedLock scopedLock(lock());
- auto addSuffix = [](std::stringstream &ss, const char *sfx,
- const char *prev) {
- if (prev != nullptr &&
- base::utils::Str::endsWith(ss.str(), std::string(prev))) {
- std::string chr(ss.str().substr(0, ss.str().size() - strlen(prev)));
- ss.str(std::string(""));
- ss << chr;
- }
- if (base::utils::Str::endsWith(ss.str(), std::string(sfx))) {
- std::string chr(ss.str().substr(0, ss.str().size() - strlen(sfx)));
- ss.str(std::string(""));
- ss << chr;
- }
- ss << sfx;
- };
- auto insert = [&](std::stringstream &ss, base::type::VerboseLevel level) {
- if (!base::utils::hasFlag(LoggingFlag::DisableVModulesExtensions,
- *m_pFlags)) {
- addSuffix(ss, ".h", nullptr);
- m_modules.insert(std::make_pair(ss.str(), level));
- addSuffix(ss, ".c", ".h");
- m_modules.insert(std::make_pair(ss.str(), level));
- addSuffix(ss, ".cpp", ".c");
- m_modules.insert(std::make_pair(ss.str(), level));
- addSuffix(ss, ".cc", ".cpp");
- m_modules.insert(std::make_pair(ss.str(), level));
- addSuffix(ss, ".cxx", ".cc");
- m_modules.insert(std::make_pair(ss.str(), level));
- addSuffix(ss, ".-inl.h", ".cxx");
- m_modules.insert(std::make_pair(ss.str(), level));
- addSuffix(ss, ".hxx", ".-inl.h");
- m_modules.insert(std::make_pair(ss.str(), level));
- addSuffix(ss, ".hpp", ".hxx");
- m_modules.insert(std::make_pair(ss.str(), level));
- addSuffix(ss, ".hh", ".hpp");
- }
- m_modules.insert(std::make_pair(ss.str(), level));
- };
- bool isMod = true;
- bool isLevel = false;
- std::stringstream ss;
- int level = -1;
- for (; *modules; ++modules) {
- switch (*modules) {
- case '=':
- isLevel = true;
- isMod = false;
- break;
- case ',':
- isLevel = false;
- isMod = true;
- if (!ss.str().empty() && level != -1) {
- insert(ss, static_cast<base::type::VerboseLevel>(level));
- ss.str(std::string(""));
- level = -1;
- }
- break;
- default:
- if (isMod) {
- ss << *modules;
- } else if (isLevel) {
- if (isdigit(*modules)) {
- level = static_cast<base::type::VerboseLevel>(*modules) - 48;
- }
- }
- break;
- }
- }
- if (!ss.str().empty() && level != -1) {
- insert(ss, static_cast<base::type::VerboseLevel>(level));
- }
-}
-
-bool VRegistry::allowed(base::type::VerboseLevel vlevel, const char *file) {
- base::threading::ScopedLock scopedLock(lock());
- if (m_modules.empty() || file == nullptr) {
- return vlevel <= m_level;
- } else {
- char baseFilename[base::consts::kSourceFilenameMaxLength] = "";
- base::utils::File::buildBaseFilename(file, baseFilename);
- std::unordered_map<std::string, base::type::VerboseLevel>::iterator it =
- m_modules.begin();
- for (; it != m_modules.end(); ++it) {
- if (base::utils::Str::wildCardMatch(baseFilename, it->first.c_str())) {
- return vlevel <= it->second;
- }
- }
- if (base::utils::hasFlag(LoggingFlag::AllowVerboseIfModuleNotSpecified,
- *m_pFlags)) {
- return true;
- }
- return false;
- }
-}
-
-void VRegistry::setFromArgs(
- const base::utils::CommandLineArgs *commandLineArgs) {
- if (commandLineArgs->hasParam("-v") ||
- commandLineArgs->hasParam("--verbose") ||
- commandLineArgs->hasParam("-V") ||
- commandLineArgs->hasParam("--VERBOSE")) {
- setLevel(base::consts::kMaxVerboseLevel);
- } else if (commandLineArgs->hasParamWithValue("--v")) {
- setLevel(static_cast<base::type::VerboseLevel>(
- atoi(commandLineArgs->getParamValue("--v"))));
- } else if (commandLineArgs->hasParamWithValue("--V")) {
- setLevel(static_cast<base::type::VerboseLevel>(
- atoi(commandLineArgs->getParamValue("--V"))));
- } else if ((commandLineArgs->hasParamWithValue("-vmodule")) &&
- vModulesEnabled()) {
- setModules(commandLineArgs->getParamValue("-vmodule"));
- } else if (commandLineArgs->hasParamWithValue("-VMODULE") &&
- vModulesEnabled()) {
- setModules(commandLineArgs->getParamValue("-VMODULE"));
- }
-}
-
-#if !defined(ELPP_DEFAULT_LOGGING_FLAGS)
-#define ELPP_DEFAULT_LOGGING_FLAGS 0x0
-#endif // !defined(ELPP_DEFAULT_LOGGING_FLAGS)
-// Storage
-#if ELPP_ASYNC_LOGGING
-Storage::Storage(const LogBuilderPtr &defaultLogBuilder,
- base::IWorker *asyncDispatchWorker)
- :
-#else
-Storage::Storage(const LogBuilderPtr &defaultLogBuilder)
- :
-#endif // ELPP_ASYNC_LOGGING
- m_registeredHitCounters(new base::RegisteredHitCounters()),
- m_registeredLoggers(new base::RegisteredLoggers(defaultLogBuilder)),
- m_flags(ELPP_DEFAULT_LOGGING_FLAGS),
- m_vRegistry(new base::VRegistry(0, &m_flags)),
-
-#if ELPP_ASYNC_LOGGING
- m_asyncLogQueue(new base::AsyncLogQueue()),
- m_asyncDispatchWorker(asyncDispatchWorker),
-#endif // ELPP_ASYNC_LOGGING
-
- m_preRollOutCallback(base::defaultPreRollOutCallback) {
- // Register default logger
- m_registeredLoggers->get(std::string(base::consts::kDefaultLoggerId));
- // We register default logger anyway (worse case it's not going to register)
- // just in case
- m_registeredLoggers->get("default");
-
-#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING)
- // Register performance logger and reconfigure format
- Logger *performanceLogger =
- m_registeredLoggers->get(std::string(base::consts::kPerformanceLoggerId));
- m_registeredLoggers->get("performance");
- performanceLogger->configurations()->setGlobally(
- ConfigurationType::Format, std::string("%datetime %level %msg"));
- performanceLogger->reconfigure();
-#endif // defined(ELPP_FEATURE_ALL) ||
- // defined(ELPP_FEATURE_PERFORMANCE_TRACKING)
-
-#if defined(ELPP_SYSLOG)
- // Register syslog logger and reconfigure format
- Logger *sysLogLogger =
- m_registeredLoggers->get(std::string(base::consts::kSysLogLoggerId));
- sysLogLogger->configurations()->setGlobally(ConfigurationType::Format,
- std::string("%level: %msg"));
- sysLogLogger->reconfigure();
-#endif // defined(ELPP_SYSLOG)
- addFlag(LoggingFlag::AllowVerboseIfModuleNotSpecified);
-#if ELPP_ASYNC_LOGGING
- installLogDispatchCallback<base::AsyncLogDispatchCallback>(
- std::string("AsyncLogDispatchCallback"));
-#else
- installLogDispatchCallback<base::DefaultLogDispatchCallback>(
- std::string("DefaultLogDispatchCallback"));
-#endif // ELPP_ASYNC_LOGGING
-#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING)
- installPerformanceTrackingCallback<base::DefaultPerformanceTrackingCallback>(
- std::string("DefaultPerformanceTrackingCallback"));
-#endif // defined(ELPP_FEATURE_ALL) ||
- // defined(ELPP_FEATURE_PERFORMANCE_TRACKING)
- ELPP_INTERNAL_INFO(1, "Easylogging++ has been initialized");
-#if ELPP_ASYNC_LOGGING
- m_asyncDispatchWorker->start();
-#endif // ELPP_ASYNC_LOGGING
-}
-
-Storage::~Storage(void) {
- ELPP_INTERNAL_INFO(4, "Destroying storage");
-#if ELPP_ASYNC_LOGGING
- ELPP_INTERNAL_INFO(5, "Replacing log dispatch callback to synchronous");
- uninstallLogDispatchCallback<base::AsyncLogDispatchCallback>(
- std::string("AsyncLogDispatchCallback"));
- installLogDispatchCallback<base::DefaultLogDispatchCallback>(
- std::string("DefaultLogDispatchCallback"));
- ELPP_INTERNAL_INFO(5, "Destroying asyncDispatchWorker");
- base::utils::safeDelete(m_asyncDispatchWorker);
- ELPP_INTERNAL_INFO(5, "Destroying asyncLogQueue");
- base::utils::safeDelete(m_asyncLogQueue);
-#endif // ELPP_ASYNC_LOGGING
- ELPP_INTERNAL_INFO(5, "Destroying registeredHitCounters");
- base::utils::safeDelete(m_registeredHitCounters);
- ELPP_INTERNAL_INFO(5, "Destroying registeredLoggers");
- base::utils::safeDelete(m_registeredLoggers);
- ELPP_INTERNAL_INFO(5, "Destroying vRegistry");
- base::utils::safeDelete(m_vRegistry);
-}
-
-bool Storage::hasCustomFormatSpecifier(const char *formatSpecifier) {
- base::threading::ScopedLock scopedLock(customFormatSpecifiersLock());
- return std::find(m_customFormatSpecifiers.begin(),
- m_customFormatSpecifiers.end(),
- formatSpecifier) != m_customFormatSpecifiers.end();
-}
-
-void Storage::installCustomFormatSpecifier(
- const CustomFormatSpecifier &customFormatSpecifier) {
- if (hasCustomFormatSpecifier(customFormatSpecifier.formatSpecifier())) {
- return;
- }
- base::threading::ScopedLock scopedLock(customFormatSpecifiersLock());
- m_customFormatSpecifiers.push_back(customFormatSpecifier);
-}
-
-bool Storage::uninstallCustomFormatSpecifier(const char *formatSpecifier) {
- base::threading::ScopedLock scopedLock(customFormatSpecifiersLock());
- std::vector<CustomFormatSpecifier>::iterator it =
- std::find(m_customFormatSpecifiers.begin(),
- m_customFormatSpecifiers.end(), formatSpecifier);
- if (it != m_customFormatSpecifiers.end() &&
- strcmp(formatSpecifier, it->formatSpecifier()) == 0) {
- m_customFormatSpecifiers.erase(it);
- return true;
- }
- return false;
-}
-
-void Storage::setApplicationArguments(int argc, char **argv) {
- m_commandLineArgs.setArgs(argc, argv);
- m_vRegistry->setFromArgs(commandLineArgs());
- // default log file
-#if !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG)
- if (m_commandLineArgs.hasParamWithValue(base::consts::kDefaultLogFileParam)) {
- Configurations c;
- c.setGlobally(ConfigurationType::Filename,
- std::string(m_commandLineArgs.getParamValue(
- base::consts::kDefaultLogFileParam)));
- registeredLoggers()->setDefaultConfigurations(c);
- for (base::RegisteredLoggers::iterator it = registeredLoggers()->begin();
- it != registeredLoggers()->end(); ++it) {
- it->second->configure(c);
- }
- }
-#endif // !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG)
-#if defined(ELPP_LOGGING_FLAGS_FROM_ARG)
- if (m_commandLineArgs.hasParamWithValue(base::consts::kLoggingFlagsParam)) {
- int userInput =
- atoi(m_commandLineArgs.getParamValue(base::consts::kLoggingFlagsParam));
- if (ELPP_DEFAULT_LOGGING_FLAGS == 0x0) {
- m_flags = userInput;
- } else {
- base::utils::addFlag<base::type::EnumType>(userInput, &m_flags);
- }
- }
-#endif // defined(ELPP_LOGGING_FLAGS_FROM_ARG)
-}
-
-} // namespace base
-
-// LogDispatchCallback
-#if defined(ELPP_THREAD_SAFE)
-void LogDispatchCallback::handle(const LogDispatchData *data) {
- base::threading::ScopedLock scopedLock(m_fileLocksMapLock);
- std::string filename =
- data->logMessage()->logger()->typedConfigurations()->filename(
- data->logMessage()->level());
- auto lock = m_fileLocks.find(filename);
- if (lock == m_fileLocks.end()) {
- m_fileLocks.emplace(std::make_pair(
- filename,
- std::unique_ptr<base::threading::Mutex>(new base::threading::Mutex)));
- }
-}
-#else
-void LogDispatchCallback::handle(const LogDispatchData * /*data*/) {}
-#endif
-
-base::threading::Mutex &
-LogDispatchCallback::fileHandle(const LogDispatchData *data) {
- auto it = m_fileLocks.find(
- data->logMessage()->logger()->typedConfigurations()->filename(
- data->logMessage()->level()));
- return *(it->second.get());
-}
-
-namespace base {
-// DefaultLogDispatchCallback
-
-void DefaultLogDispatchCallback::handle(const LogDispatchData *data) {
-#if defined(ELPP_THREAD_SAFE)
- LogDispatchCallback::handle(data);
- base::threading::ScopedLock scopedLock(fileHandle(data));
-#endif
- m_data = data;
- dispatch(m_data->logMessage()->logger()->logBuilder()->build(
- m_data->logMessage(),
- m_data->dispatchAction() == base::DispatchAction::NormalLog));
-}
-
-void DefaultLogDispatchCallback::dispatch(base::type::string_t &&logLine) {
- if (m_data->dispatchAction() == base::DispatchAction::NormalLog) {
- if (m_data->logMessage()->logger()->m_typedConfigurations->toFile(
- m_data->logMessage()->level())) {
- base::type::fstream_t *fs =
- m_data->logMessage()->logger()->m_typedConfigurations->fileStream(
- m_data->logMessage()->level());
- if (fs != nullptr) {
- fs->write(logLine.c_str(), logLine.size());
- if (fs->fail()) {
- ELPP_INTERNAL_ERROR(
- "Unable to write log to file ["
- << m_data->logMessage()
- ->logger()
- ->m_typedConfigurations->filename(
- m_data->logMessage()->level())
- << "].\n"
- << "Few possible reasons (could be something else):\n"
- << " * Permission denied\n"
- << " * Disk full\n"
- << " * Disk is not writable",
- true);
- } else {
- if (ELPP->hasFlag(LoggingFlag::ImmediateFlush) ||
- (m_data->logMessage()->logger()->isFlushNeeded(
- m_data->logMessage()->level()))) {
- m_data->logMessage()->logger()->flush(m_data->logMessage()->level(),
- fs);
- }
- }
- } else {
- ELPP_INTERNAL_ERROR(
- "Log file for ["
- << LevelHelper::convertToString(m_data->logMessage()->level())
- << "] "
- << "has not been configured but [TO_FILE] is configured to "
- "TRUE. [Logger ID: "
- << m_data->logMessage()->logger()->id() << "]",
- false);
- }
- }
- if (m_data->logMessage()->logger()->m_typedConfigurations->toStandardOutput(
- m_data->logMessage()->level())) {
- if (ELPP->hasFlag(LoggingFlag::ColoredTerminalOutput))
- m_data->logMessage()->logger()->logBuilder()->convertToColoredOutput(
- &logLine, m_data->logMessage()->level());
- ELPP_COUT << ELPP_COUT_LINE(logLine);
- }
- }
-#if defined(ELPP_SYSLOG)
- else if (m_data->dispatchAction() == base::DispatchAction::SysLog) {
- // Determine syslog priority
- int sysLogPriority = 0;
- if (m_data->logMessage()->level() == Level::Fatal)
- sysLogPriority = LOG_EMERG;
- else if (m_data->logMessage()->level() == Level::Error)
- sysLogPriority = LOG_ERR;
- else if (m_data->logMessage()->level() == Level::Warning)
- sysLogPriority = LOG_WARNING;
- else if (m_data->logMessage()->level() == Level::Info)
- sysLogPriority = LOG_INFO;
- else if (m_data->logMessage()->level() == Level::Debug)
- sysLogPriority = LOG_DEBUG;
- else
- sysLogPriority = LOG_NOTICE;
-#if defined(ELPP_UNICODE)
- char *line = base::utils::Str::wcharPtrToCharPtr(logLine.c_str());
- syslog(sysLogPriority, "%s", line);
- free(line);
-#else
- syslog(sysLogPriority, "%s", logLine.c_str());
-#endif
- }
-#endif // defined(ELPP_SYSLOG)
-}
-
-#if ELPP_ASYNC_LOGGING
-
-// AsyncLogDispatchCallback
-
-void AsyncLogDispatchCallback::handle(const LogDispatchData *data) {
- base::type::string_t logLine =
- data->logMessage()->logger()->logBuilder()->build(
- data->logMessage(),
- data->dispatchAction() == base::DispatchAction::NormalLog);
- if (data->dispatchAction() == base::DispatchAction::NormalLog &&
- data->logMessage()->logger()->typedConfigurations()->toStandardOutput(
- data->logMessage()->level())) {
- if (ELPP->hasFlag(LoggingFlag::ColoredTerminalOutput))
- data->logMessage()->logger()->logBuilder()->convertToColoredOutput(
- &logLine, data->logMessage()->level());
- ELPP_COUT << ELPP_COUT_LINE(logLine);
- }
- // Save resources and only queue if we want to write to file otherwise just
- // ignore handler
- if (data->logMessage()->logger()->typedConfigurations()->toFile(
- data->logMessage()->level())) {
- ELPP->asyncLogQueue()->push(
- AsyncLogItem(*(data->logMessage()), *data, logLine));
- }
-}
-
-// AsyncDispatchWorker
-AsyncDispatchWorker::AsyncDispatchWorker() { setContinueRunning(false); }
-
-AsyncDispatchWorker::~AsyncDispatchWorker() {
- setContinueRunning(false);
- ELPP_INTERNAL_INFO(6, "Stopping dispatch worker - Cleaning log queue");
- clean();
- ELPP_INTERNAL_INFO(6, "Log queue cleaned");
-}
-
-bool AsyncDispatchWorker::clean(void) {
- std::mutex m;
- std::unique_lock<std::mutex> lk(m);
- cv.wait(lk, [] { return !ELPP->asyncLogQueue()->empty(); });
- emptyQueue();
- lk.unlock();
- cv.notify_one();
- return ELPP->asyncLogQueue()->empty();
-}
-
-void AsyncDispatchWorker::emptyQueue(void) {
- while (!ELPP->asyncLogQueue()->empty()) {
- AsyncLogItem data = ELPP->asyncLogQueue()->next();
- handle(&data);
- base::threading::msleep(100);
- }
-}
-
-void AsyncDispatchWorker::start(void) {
- base::threading::msleep(5000); // 5s (why?)
- setContinueRunning(true);
- std::thread t1(&AsyncDispatchWorker::run, this);
- t1.join();
-}
-
-void AsyncDispatchWorker::handle(AsyncLogItem *logItem) {
- LogDispatchData *data = logItem->data();
- LogMessage *logMessage = logItem->logMessage();
- Logger *logger = logMessage->logger();
- base::TypedConfigurations *conf = logger->typedConfigurations();
- base::type::string_t logLine = logItem->logLine();
- if (data->dispatchAction() == base::DispatchAction::NormalLog) {
- if (conf->toFile(logMessage->level())) {
- base::type::fstream_t *fs = conf->fileStream(logMessage->level());
- if (fs != nullptr) {
- fs->write(logLine.c_str(), logLine.size());
- if (fs->fail()) {
- ELPP_INTERNAL_ERROR(
- "Unable to write log to file ["
- << conf->filename(logMessage->level()) << "].\n"
- << "Few possible reasons (could be something else):\n"
- << " * Permission denied\n"
- << " * Disk full\n"
- << " * Disk is not writable",
- true);
- } else {
- if (ELPP->hasFlag(LoggingFlag::ImmediateFlush) ||
- (logger->isFlushNeeded(logMessage->level()))) {
- logger->flush(logMessage->level(), fs);
- }
- }
- } else {
- ELPP_INTERNAL_ERROR(
- "Log file for ["
- << LevelHelper::convertToString(logMessage->level()) << "] "
- << "has not been configured but [TO_FILE] is configured to "
- "TRUE. [Logger ID: "
- << logger->id() << "]",
- false);
- }
- }
- }
-#if defined(ELPP_SYSLOG)
- else if (data->dispatchAction() == base::DispatchAction::SysLog) {
- // Determine syslog priority
- int sysLogPriority = 0;
- if (logMessage->level() == Level::Fatal)
- sysLogPriority = LOG_EMERG;
- else if (logMessage->level() == Level::Error)
- sysLogPriority = LOG_ERR;
- else if (logMessage->level() == Level::Warning)
- sysLogPriority = LOG_WARNING;
- else if (logMessage->level() == Level::Info)
- sysLogPriority = LOG_INFO;
- else if (logMessage->level() == Level::Debug)
- sysLogPriority = LOG_DEBUG;
- else
- sysLogPriority = LOG_NOTICE;
-#if defined(ELPP_UNICODE)
- char *line = base::utils::Str::wcharPtrToCharPtr(logLine.c_str());
- syslog(sysLogPriority, "%s", line);
- free(line);
-#else
- syslog(sysLogPriority, "%s", logLine.c_str());
-#endif
- }
-#endif // defined(ELPP_SYSLOG)
-}
-
-void AsyncDispatchWorker::run(void) {
- while (continueRunning()) {
- emptyQueue();
- base::threading::msleep(10); // 10ms
- }
-}
-#endif // ELPP_ASYNC_LOGGING
-
-// DefaultLogBuilder
-
-base::type::string_t DefaultLogBuilder::build(const LogMessage *logMessage,
- bool appendNewLine) const {
- base::TypedConfigurations *tc = logMessage->logger()->typedConfigurations();
- const base::LogFormat *logFormat = &tc->logFormat(logMessage->level());
- base::type::string_t logLine = logFormat->format();
- char buff[base::consts::kSourceFilenameMaxLength +
- base::consts::kSourceLineMaxLength] = "";
- const char *bufLim = buff + sizeof(buff);
- if (logFormat->hasFlag(base::FormatFlags::AppName)) {
- // App name
- base::utils::Str::replaceFirstWithEscape(
- logLine, base::consts::kAppNameFormatSpecifier,
- logMessage->logger()->parentApplicationName());
- }
- if (logFormat->hasFlag(base::FormatFlags::ThreadId)) {
- // Thread ID
- base::utils::Str::replaceFirstWithEscape(
- logLine, base::consts::kThreadIdFormatSpecifier,
- ELPP->getThreadName(base::threading::getCurrentThreadId()));
- }
- if (logFormat->hasFlag(base::FormatFlags::DateTime)) {
- // DateTime
- base::utils::Str::replaceFirstWithEscape(
- logLine, base::consts::kDateTimeFormatSpecifier,
- base::utils::DateTime::getDateTime(
- logFormat->dateTimeFormat().c_str(),
- &tc->subsecondPrecision(logMessage->level())));
- }
- if (logFormat->hasFlag(base::FormatFlags::Function)) {
- // Function
- base::utils::Str::replaceFirstWithEscape(
- logLine, base::consts::kLogFunctionFormatSpecifier, logMessage->func());
- }
- if (logFormat->hasFlag(base::FormatFlags::File)) {
- // File
- base::utils::Str::clearBuff(buff, base::consts::kSourceFilenameMaxLength);
- base::utils::File::buildStrippedFilename(logMessage->file().c_str(), buff);
- base::utils::Str::replaceFirstWithEscape(
- logLine, base::consts::kLogFileFormatSpecifier, std::string(buff));
- }
- if (logFormat->hasFlag(base::FormatFlags::FileBase)) {
- // FileBase
- base::utils::Str::clearBuff(buff, base::consts::kSourceFilenameMaxLength);
- base::utils::File::buildBaseFilename(logMessage->file(), buff);
- base::utils::Str::replaceFirstWithEscape(
- logLine, base::consts::kLogFileBaseFormatSpecifier, std::string(buff));
- }
- if (logFormat->hasFlag(base::FormatFlags::Line)) {
- // Line
- char *buf =
- base::utils::Str::clearBuff(buff, base::consts::kSourceLineMaxLength);
- buf = base::utils::Str::convertAndAddToBuff(
- logMessage->line(), base::consts::kSourceLineMaxLength, buf, bufLim,
- false);
- base::utils::Str::replaceFirstWithEscape(
- logLine, base::consts::kLogLineFormatSpecifier, std::string(buff));
- }
- if (logFormat->hasFlag(base::FormatFlags::Location)) {
- // Location
- char *buf = base::utils::Str::clearBuff(
- buff, base::consts::kSourceFilenameMaxLength +
- base::consts::kSourceLineMaxLength);
- base::utils::File::buildStrippedFilename(logMessage->file().c_str(), buff);
- buf = base::utils::Str::addToBuff(buff, buf, bufLim);
- buf = base::utils::Str::addToBuff(":", buf, bufLim);
- buf = base::utils::Str::convertAndAddToBuff(
- logMessage->line(), base::consts::kSourceLineMaxLength, buf, bufLim,
- false);
- base::utils::Str::replaceFirstWithEscape(
- logLine, base::consts::kLogLocationFormatSpecifier, std::string(buff));
- }
- if (logMessage->level() == Level::Verbose &&
- logFormat->hasFlag(base::FormatFlags::VerboseLevel)) {
- // Verbose level
- char *buf = base::utils::Str::clearBuff(buff, 1);
- buf = base::utils::Str::convertAndAddToBuff(logMessage->verboseLevel(), 1,
- buf, bufLim, false);
- base::utils::Str::replaceFirstWithEscape(
- logLine, base::consts::kVerboseLevelFormatSpecifier, std::string(buff));
- }
- if (logFormat->hasFlag(base::FormatFlags::LogMessage)) {
- // Log message
- base::utils::Str::replaceFirstWithEscape(
- logLine, base::consts::kMessageFormatSpecifier, logMessage->message());
- }
-#if !defined(ELPP_DISABLE_CUSTOM_FORMAT_SPECIFIERS)
- el::base::threading::ScopedLock lock_(ELPP->customFormatSpecifiersLock());
- ELPP_UNUSED(lock_);
- for (std::vector<CustomFormatSpecifier>::const_iterator it =
- ELPP->customFormatSpecifiers()->begin();
- it != ELPP->customFormatSpecifiers()->end(); ++it) {
- std::string fs(it->formatSpecifier());
- base::type::string_t wcsFormatSpecifier(fs.begin(), fs.end());
- base::utils::Str::replaceFirstWithEscape(logLine, wcsFormatSpecifier,
- it->resolver()(logMessage));
- }
-#endif // !defined(ELPP_DISABLE_CUSTOM_FORMAT_SPECIFIERS)
- if (appendNewLine)
- logLine += ELPP_LITERAL("\n");
- return logLine;
-}
-
-// LogDispatcher
-
-void LogDispatcher::dispatch(void) {
- if (m_proceed && m_dispatchAction == base::DispatchAction::None) {
- m_proceed = false;
- }
- if (!m_proceed) {
- return;
- }
-#ifndef ELPP_NO_GLOBAL_LOCK
- // see https://github.com/muflihun/easyloggingpp/issues/580
- // global lock is turned on by default unless
- // ELPP_NO_GLOBAL_LOCK is defined
- base::threading::ScopedLock scopedLock(ELPP->lock());
-#endif
- base::TypedConfigurations *tc = m_logMessage->logger()->m_typedConfigurations;
- if (ELPP->hasFlag(LoggingFlag::StrictLogFileSizeCheck)) {
- tc->validateFileRolling(m_logMessage->level(), ELPP->preRollOutCallback());
- }
- LogDispatchCallback *callback = nullptr;
- LogDispatchData data;
- for (const std::pair<std::string, base::type::LogDispatchCallbackPtr> h :
- ELPP->m_logDispatchCallbacks) {
- callback = h.second.get();
- if (callback != nullptr && callback->enabled()) {
- data.setLogMessage(m_logMessage);
- data.setDispatchAction(m_dispatchAction);
- callback->handle(&data);
- }
- }
-}
-
-// MessageBuilder
-
-void MessageBuilder::initialize(Logger *logger) {
- m_logger = logger;
- m_containerLogSeparator = ELPP->hasFlag(LoggingFlag::NewLineForContainer)
- ? ELPP_LITERAL("\n ")
- : ELPP_LITERAL(", ");
-}
-
-MessageBuilder &MessageBuilder::operator<<(const wchar_t *msg) {
- if (msg == nullptr) {
- m_logger->stream() << base::consts::kNullPointer;
- return *this;
- }
-#if defined(ELPP_UNICODE)
- m_logger->stream() << msg;
-#else
- char *buff_ = base::utils::Str::wcharPtrToCharPtr(msg);
- m_logger->stream() << buff_;
- free(buff_);
-#endif
- if (ELPP->hasFlag(LoggingFlag::AutoSpacing)) {
- m_logger->stream() << " ";
- }
- return *this;
-}
-
-// Writer
-
-Writer &Writer::construct(Logger *logger, bool needLock) {
- m_logger = logger;
- initializeLogger(logger->id(), false, needLock);
- m_messageBuilder.initialize(m_logger);
- return *this;
-}
-
-Writer &Writer::construct(int count, const char *loggerIds, ...) {
- if (ELPP->hasFlag(LoggingFlag::MultiLoggerSupport)) {
- va_list loggersList;
- va_start(loggersList, loggerIds);
- const char *id = loggerIds;
- m_loggerIds.reserve(count);
- for (int i = 0; i < count; ++i) {
- m_loggerIds.push_back(std::string(id));
- id = va_arg(loggersList, const char *);
- }
- va_end(loggersList);
- initializeLogger(m_loggerIds.at(0));
- } else {
- initializeLogger(std::string(loggerIds));
- }
- m_messageBuilder.initialize(m_logger);
- return *this;
-}
-
-void Writer::initializeLogger(const std::string &loggerId, bool lookup,
- bool needLock) {
- if (lookup) {
- m_logger = ELPP->registeredLoggers()->get(
- loggerId, ELPP->hasFlag(LoggingFlag::CreateLoggerAutomatically));
- }
- if (m_logger == nullptr) {
- {
- if (!ELPP->registeredLoggers()->has(
- std::string(base::consts::kDefaultLoggerId))) {
- // Somehow default logger has been unregistered. Not good! Register
- // again
- ELPP->registeredLoggers()->get(
- std::string(base::consts::kDefaultLoggerId));
- }
- }
- Writer(Level::Debug, m_file, m_line, m_func)
- .construct(1, base::consts::kDefaultLoggerId)
- << "Logger [" << loggerId << "] is not registered yet!";
- m_proceed = false;
- } else {
- if (needLock) {
- m_logger->acquireLock(); // This should not be unlocked by checking
- // m_proceed because
- // m_proceed can be changed by lines below
- }
- if (ELPP->hasFlag(LoggingFlag::HierarchicalLogging)) {
- m_proceed = m_level == Level::Verbose
- ? m_logger->enabled(m_level)
- : LevelHelper::castToInt(m_level) >=
- LevelHelper::castToInt(ELPP->m_loggingLevel);
- } else {
- m_proceed = m_logger->enabled(m_level);
- }
- }
-}
-
-void Writer::processDispatch() {
-#if ELPP_LOGGING_ENABLED
- if (ELPP->hasFlag(LoggingFlag::MultiLoggerSupport)) {
- bool firstDispatched = false;
- base::type::string_t logMessage;
- std::size_t i = 0;
- do {
- if (m_proceed) {
- if (firstDispatched) {
- m_logger->stream() << logMessage;
- } else {
- firstDispatched = true;
- if (m_loggerIds.size() > 1) {
- logMessage = m_logger->stream().str();
- }
- }
- triggerDispatch();
- } else if (m_logger != nullptr) {
- m_logger->stream().str(ELPP_LITERAL(""));
- m_logger->releaseLock();
- }
- if (i + 1 < m_loggerIds.size()) {
- initializeLogger(m_loggerIds.at(i + 1));
- }
- } while (++i < m_loggerIds.size());
- } else {
- if (m_proceed) {
- triggerDispatch();
- } else if (m_logger != nullptr) {
- m_logger->stream().str(ELPP_LITERAL(""));
- m_logger->releaseLock();
- }
- }
-#else
- if (m_logger != nullptr) {
- m_logger->stream().str(ELPP_LITERAL(""));
- m_logger->releaseLock();
- }
-#endif // ELPP_LOGGING_ENABLED
-}
-
-void Writer::triggerDispatch(void) {
- try {
- if (m_proceed) {
- if (m_msg == nullptr) {
- LogMessage msg(m_level, m_file, m_line, m_func, m_verboseLevel,
- m_logger);
- base::LogDispatcher(m_proceed, &msg, m_dispatchAction).dispatch();
- } else {
- base::LogDispatcher(m_proceed, m_msg, m_dispatchAction).dispatch();
- }
- }
- if (m_logger != nullptr) {
- m_logger->stream().str(ELPP_LITERAL(""));
- m_logger->releaseLock();
- }
- if (m_proceed && m_level == Level::Fatal &&
- !ELPP->hasFlag(LoggingFlag::DisableApplicationAbortOnFatalLog)) {
- base::Writer(Level::Warning, m_file, m_line, m_func)
- .construct(1, base::consts::kDefaultLoggerId)
- << "Aborting application. Reason: Fatal log at [" << m_file << ":"
- << m_line << "]";
- std::stringstream reasonStream;
- reasonStream << "Fatal log at [" << m_file << ":" << m_line << "]"
- << " If you wish to disable 'abort on fatal log' please use "
- << "el::Loggers::addFlag(el::LoggingFlag::"
- "DisableApplicationAbortOnFatalLog)";
- base::utils::abort(1, reasonStream.str());
- }
- m_proceed = false;
- } catch (std::exception &ex) {
- // Extremely low memory situation; don't let exception be unhandled.
- }
-}
-
-// PErrorWriter
-
-PErrorWriter::~PErrorWriter(void) {
- if (m_proceed) {
-#if ELPP_COMPILER_MSVC
- char buff[256];
- strerror_s(buff, 256, errno);
- m_logger->stream() << ": " << buff << " [" << errno << "]";
-#else
- m_logger->stream() << ": " << strerror(errno) << " [" << errno << "]";
-#endif
- }
-}
-
-// PerformanceTracker
-
-#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING)
-
-PerformanceTracker::PerformanceTracker(const std::string &blockName,
- base::TimestampUnit timestampUnit,
- const std::string &loggerId,
- bool scopedLog, Level level)
- : m_blockName(blockName), m_timestampUnit(timestampUnit),
- m_loggerId(loggerId), m_scopedLog(scopedLog), m_level(level),
- m_hasChecked(false), m_lastCheckpointId(std::string()), m_enabled(false) {
-#if !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED
- // We store it locally so that if user happen to change configuration by the
- // end of scope or before calling checkpoint, we still depend on state of
- // configuration at time of construction
- el::Logger *loggerPtr = ELPP->registeredLoggers()->get(loggerId, false);
- m_enabled = loggerPtr != nullptr &&
- loggerPtr->m_typedConfigurations->performanceTracking(m_level);
- if (m_enabled) {
- base::utils::DateTime::gettimeofday(&m_startTime);
- }
-#endif // !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED
-}
-
-PerformanceTracker::~PerformanceTracker(void) {
-#if !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED
- if (m_enabled) {
- base::threading::ScopedLock scopedLock(lock());
- if (m_scopedLog) {
- base::utils::DateTime::gettimeofday(&m_endTime);
- base::type::string_t formattedTime = getFormattedTimeTaken();
- PerformanceTrackingData data(PerformanceTrackingData::DataType::Complete);
- data.init(this);
- data.m_formattedTimeTaken = formattedTime;
- PerformanceTrackingCallback *callback = nullptr;
- for (const std::pair<std::string,
- base::type::PerformanceTrackingCallbackPtr> &h :
- ELPP->m_performanceTrackingCallbacks) {
- callback = h.second.get();
- if (callback != nullptr && callback->enabled()) {
- callback->handle(&data);
- }
- }
- }
- }
-#endif // !defined(ELPP_DISABLE_PERFORMANCE_TRACKING)
-}
-
-void PerformanceTracker::checkpoint(const std::string &id, const char *file,
- base::type::LineNumber line,
- const char *func) {
-#if !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED
- if (m_enabled) {
- base::threading::ScopedLock scopedLock(lock());
- base::utils::DateTime::gettimeofday(&m_endTime);
- base::type::string_t formattedTime =
- m_hasChecked ? getFormattedTimeTaken(m_lastCheckpointTime)
- : ELPP_LITERAL("");
- PerformanceTrackingData data(PerformanceTrackingData::DataType::Checkpoint);
- data.init(this);
- data.m_checkpointId = id;
- data.m_file = file;
- data.m_line = line;
- data.m_func = func;
- data.m_formattedTimeTaken = formattedTime;
- PerformanceTrackingCallback *callback = nullptr;
- for (const std::pair<std::string,
- base::type::PerformanceTrackingCallbackPtr> &h :
- ELPP->m_performanceTrackingCallbacks) {
- callback = h.second.get();
- if (callback != nullptr && callback->enabled()) {
- callback->handle(&data);
- }
- }
- base::utils::DateTime::gettimeofday(&m_lastCheckpointTime);
- m_hasChecked = true;
- m_lastCheckpointId = id;
- }
-#endif // !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED
- ELPP_UNUSED(id);
- ELPP_UNUSED(file);
- ELPP_UNUSED(line);
- ELPP_UNUSED(func);
-}
-
-const base::type::string_t
-PerformanceTracker::getFormattedTimeTaken(struct timeval startTime) const {
- if (ELPP->hasFlag(LoggingFlag::FixedTimeFormat)) {
- base::type::stringstream_t ss;
- ss << base::utils::DateTime::getTimeDifference(m_endTime, startTime,
- m_timestampUnit)
- << " "
- << base::consts::kTimeFormats[static_cast<base::type::EnumType>(
- m_timestampUnit)]
- .unit;
- return ss.str();
- }
- return base::utils::DateTime::formatTime(
- base::utils::DateTime::getTimeDifference(m_endTime, startTime,
- m_timestampUnit),
- m_timestampUnit);
-}
-
-#endif // defined(ELPP_FEATURE_ALL) ||
- // defined(ELPP_FEATURE_PERFORMANCE_TRACKING)
-
-namespace debug {
-#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_CRASH_LOG)
-
-// StackTrace
-
-StackTrace::StackTraceEntry::StackTraceEntry(std::size_t index,
- const std::string &loc,
- const std::string &demang,
- const std::string &hex,
- const std::string &addr)
- : m_index(index), m_location(loc), m_demangled(demang), m_hex(hex),
- m_addr(addr) {}
-
-std::ostream &operator<<(std::ostream &ss,
- const StackTrace::StackTraceEntry &si) {
- ss << "[" << si.m_index << "] " << si.m_location
- << (si.m_hex.empty() ? "" : "+") << si.m_hex << " " << si.m_addr
- << (si.m_demangled.empty() ? "" : ":") << si.m_demangled;
- return ss;
-}
-
-std::ostream &operator<<(std::ostream &os, const StackTrace &st) {
- std::vector<StackTrace::StackTraceEntry>::const_iterator it =
- st.m_stack.begin();
- while (it != st.m_stack.end()) {
- os << " " << *it++ << "\n";
- }
- return os;
-}
-
-void StackTrace::generateNew(void) {
-#ifdef HAVE_EXECINFO
- m_stack.clear();
- void *stack[kMaxStack];
- unsigned int size = backtrace(stack, kMaxStack);
- char **strings = backtrace_symbols(stack, size);
- if (size > kStackStart) { // Skip StackTrace c'tor and generateNew
- for (std::size_t i = kStackStart; i < size; ++i) {
- std::string mangName;
- std::string location;
- std::string hex;
- std::string addr;
-
- // entry: 2 crash.cpp.bin 0x0000000101552be5
- // _ZN2el4base5debug10StackTraceC1Ev + 21
- const std::string line(strings[i]);
- auto p = line.find("_");
- if (p != std::string::npos) {
- mangName = line.substr(p);
- mangName = mangName.substr(0, mangName.find(" +"));
- }
- p = line.find("0x");
- if (p != std::string::npos) {
- addr = line.substr(p);
- addr = addr.substr(0, addr.find("_"));
- }
- // Perform demangling if parsed properly
- if (!mangName.empty()) {
- int status = 0;
- char *demangName = abi::__cxa_demangle(mangName.data(), 0, 0, &status);
- // if demangling is successful, output the demangled function name
- if (status == 0) {
- // Success (see
- // http://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.3/a01696.html)
- StackTraceEntry entry(i - 1, location, demangName, hex, addr);
- m_stack.push_back(entry);
- } else {
- // Not successful - we will use mangled name
- StackTraceEntry entry(i - 1, location, mangName, hex, addr);
- m_stack.push_back(entry);
- }
- free(demangName);
- } else {
- StackTraceEntry entry(i - 1, line);
- m_stack.push_back(entry);
- }
- }
- }
- free(strings);
-#else
- ELPP_INTERNAL_INFO(
- 1, "Stacktrace generation not supported for selected compiler");
-#endif // ELPP_STACKTRACE
-}
-
-// Static helper functions
-
-static std::string crashReason(int sig) {
- std::stringstream ss;
- bool foundReason = false;
- for (int i = 0; i < base::consts::kCrashSignalsCount; ++i) {
- if (base::consts::kCrashSignals[i].numb == sig) {
- ss << "Application has crashed due to ["
- << base::consts::kCrashSignals[i].name << "] signal";
- if (ELPP->hasFlag(el::LoggingFlag::LogDetailedCrashReason)) {
- ss << std::endl
- << " " << base::consts::kCrashSignals[i].brief << std::endl
- << " " << base::consts::kCrashSignals[i].detail;
- }
- foundReason = true;
- }
- }
- if (!foundReason) {
- ss << "Application has crashed due to unknown signal [" << sig << "]";
- }
- return ss.str();
-}
-/// @brief Logs reason of crash from sig
-static void logCrashReason(int sig, bool stackTraceIfAvailable, Level level,
- const char *logger) {
- if (sig == SIGINT && ELPP->hasFlag(el::LoggingFlag::IgnoreSigInt)) {
- return;
- }
- std::stringstream ss;
- ss << "CRASH HANDLED; ";
- ss << crashReason(sig);
-#if ELPP_STACKTRACE
- if (stackTraceIfAvailable) {
- ss << std::endl
- << " ======= Backtrace: =========" << std::endl
- << base::debug::StackTrace();
- }
-#else
- ELPP_UNUSED(stackTraceIfAvailable);
-#endif // ELPP_STACKTRACE
- ELPP_WRITE_LOG(el::base::Writer, level, base::DispatchAction::NormalLog,
- logger)
- << ss.str();
-}
-
-static inline void crashAbort(int sig) {
- base::utils::abort(sig, std::string());
-}
-
-/// @brief Default application crash handler
-///
-/// @detail This function writes log using 'default' logger, prints stack trace
-/// for GCC based compilers and aborts program.
-static inline void defaultCrashHandler(int sig) {
- base::debug::logCrashReason(sig, true, Level::Fatal,
- base::consts::kDefaultLoggerId);
- base::debug::crashAbort(sig);
-}
-
-// CrashHandler
-
-CrashHandler::CrashHandler(bool useDefault) {
- if (useDefault) {
- setHandler(defaultCrashHandler);
- }
-}
-
-void CrashHandler::setHandler(const Handler &cHandler) {
- m_handler = cHandler;
-#if defined(ELPP_HANDLE_SIGABRT)
- int i = 0; // SIGABRT is at base::consts::kCrashSignals[0]
-#else
- int i = 1;
-#endif // defined(ELPP_HANDLE_SIGABRT)
- for (; i < base::consts::kCrashSignalsCount; ++i) {
- m_handler = signal(base::consts::kCrashSignals[i].numb, cHandler);
- }
-}
-
-#endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_CRASH_LOG)
-} // namespace debug
-} // namespace base
-
-// el
-
-// Helpers
-
-#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_CRASH_LOG)
-
-void Helpers::crashAbort(int sig, const char *sourceFile,
- unsigned int long line) {
- std::stringstream ss;
- ss << base::debug::crashReason(sig).c_str();
- ss << " - [Called el::Helpers::crashAbort(" << sig << ")]";
- if (sourceFile != nullptr && strlen(sourceFile) > 0) {
- ss << " - Source: " << sourceFile;
- if (line > 0)
- ss << ":" << line;
- else
- ss << " (line number not specified)";
- }
- base::utils::abort(sig, ss.str());
-}
-
-void Helpers::logCrashReason(int sig, bool stackTraceIfAvailable, Level level,
- const char *logger) {
- el::base::debug::logCrashReason(sig, stackTraceIfAvailable, level, logger);
-}
-
-#endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_CRASH_LOG)
-
-// Loggers
-
-Logger *Loggers::getLogger(const std::string &identity,
- bool registerIfNotAvailable) {
- return ELPP->registeredLoggers()->get(identity, registerIfNotAvailable);
-}
-
-void Loggers::setDefaultLogBuilder(el::LogBuilderPtr &logBuilderPtr) {
- ELPP->registeredLoggers()->setDefaultLogBuilder(logBuilderPtr);
-}
-
-bool Loggers::unregisterLogger(const std::string &identity) {
- return ELPP->registeredLoggers()->remove(identity);
-}
-
-bool Loggers::hasLogger(const std::string &identity) {
- return ELPP->registeredLoggers()->has(identity);
-}
-
-Logger *Loggers::reconfigureLogger(Logger *logger,
- const Configurations &configurations) {
- if (!logger)
- return nullptr;
- logger->configure(configurations);
- return logger;
-}
-
-Logger *Loggers::reconfigureLogger(const std::string &identity,
- const Configurations &configurations) {
- return Loggers::reconfigureLogger(Loggers::getLogger(identity),
- configurations);
-}
-
-Logger *Loggers::reconfigureLogger(const std::string &identity,
- ConfigurationType configurationType,
- const std::string &value) {
- Logger *logger = Loggers::getLogger(identity);
- if (logger == nullptr) {
- return nullptr;
- }
- logger->configurations()->set(Level::Global, configurationType, value);
- logger->reconfigure();
- return logger;
-}
-
-void Loggers::reconfigureAllLoggers(const Configurations &configurations) {
- for (base::RegisteredLoggers::iterator it =
- ELPP->registeredLoggers()->begin();
- it != ELPP->registeredLoggers()->end(); ++it) {
- Loggers::reconfigureLogger(it->second, configurations);
- }
-}
-
-void Loggers::reconfigureAllLoggers(Level level,
- ConfigurationType configurationType,
- const std::string &value) {
- for (base::RegisteredLoggers::iterator it =
- ELPP->registeredLoggers()->begin();
- it != ELPP->registeredLoggers()->end(); ++it) {
- Logger *logger = it->second;
- logger->configurations()->set(level, configurationType, value);
- logger->reconfigure();
- }
-}
-
-void Loggers::setDefaultConfigurations(const Configurations &configurations,
- bool reconfigureExistingLoggers) {
- ELPP->registeredLoggers()->setDefaultConfigurations(configurations);
- if (reconfigureExistingLoggers) {
- Loggers::reconfigureAllLoggers(configurations);
- }
-}
-
-const Configurations *Loggers::defaultConfigurations(void) {
- return ELPP->registeredLoggers()->defaultConfigurations();
-}
-
-const base::LogStreamsReferenceMapPtr Loggers::logStreamsReference(void) {
- return ELPP->registeredLoggers()->logStreamsReference();
-}
-
-base::TypedConfigurations Loggers::defaultTypedConfigurations(void) {
- return base::TypedConfigurations(
- ELPP->registeredLoggers()->defaultConfigurations(),
- ELPP->registeredLoggers()->logStreamsReference());
-}
-
-std::vector<std::string> *
-Loggers::populateAllLoggerIds(std::vector<std::string> *targetList) {
- targetList->clear();
- for (base::RegisteredLoggers::iterator it =
- ELPP->registeredLoggers()->list().begin();
- it != ELPP->registeredLoggers()->list().end(); ++it) {
- targetList->push_back(it->first);
- }
- return targetList;
-}
-
-void Loggers::configureFromGlobal(const char *globalConfigurationFilePath) {
- std::ifstream gcfStream(globalConfigurationFilePath, std::ifstream::in);
- ELPP_ASSERT(gcfStream.is_open(), "Unable to open global configuration file ["
- << globalConfigurationFilePath
- << "] for parsing.");
- std::string line = std::string();
- std::stringstream ss;
- Logger *logger = nullptr;
- auto configure = [&](void) {
- ELPP_INTERNAL_INFO(8, "Configuring logger: '"
- << logger->id() << "' with configurations \n"
- << ss.str() << "\n--------------");
- Configurations c;
- c.parseFromText(ss.str());
- logger->configure(c);
- };
- while (gcfStream.good()) {
- std::getline(gcfStream, line);
- ELPP_INTERNAL_INFO(1, "Parsing line: " << line);
- base::utils::Str::trim(line);
- if (Configurations::Parser::isComment(line))
- continue;
- Configurations::Parser::ignoreComments(&line);
- base::utils::Str::trim(line);
- if (line.size() > 2 &&
- base::utils::Str::startsWith(
- line, std::string(base::consts::kConfigurationLoggerId))) {
- if (!ss.str().empty() && logger != nullptr) {
- configure();
- }
- ss.str(std::string(""));
- line = line.substr(2);
- base::utils::Str::trim(line);
- if (line.size() > 1) {
- ELPP_INTERNAL_INFO(1, "Getting logger: '" << line << "'");
- logger = getLogger(line);
- }
- } else {
- ss << line << "\n";
- }
- }
- if (!ss.str().empty() && logger != nullptr) {
- configure();
- }
-}
-
-bool Loggers::configureFromArg(const char *argKey) {
-#if defined(ELPP_DISABLE_CONFIGURATION_FROM_PROGRAM_ARGS)
- ELPP_UNUSED(argKey);
-#else
- if (!Helpers::commandLineArgs()->hasParamWithValue(argKey)) {
- return false;
- }
- configureFromGlobal(Helpers::commandLineArgs()->getParamValue(argKey));
-#endif // defined(ELPP_DISABLE_CONFIGURATION_FROM_PROGRAM_ARGS)
- return true;
-}
-
-void Loggers::flushAll(void) { ELPP->registeredLoggers()->flushAll(); }
-
-void Loggers::setVerboseLevel(base::type::VerboseLevel level) {
- ELPP->vRegistry()->setLevel(level);
-}
-
-base::type::VerboseLevel Loggers::verboseLevel(void) {
- return ELPP->vRegistry()->level();
-}
-
-void Loggers::setVModules(const char *modules) {
- if (ELPP->vRegistry()->vModulesEnabled()) {
- ELPP->vRegistry()->setModules(modules);
- }
-}
-
-void Loggers::clearVModules(void) { ELPP->vRegistry()->clearModules(); }
-
-// VersionInfo
-
-const std::string VersionInfo::version(void) { return std::string("9.96.7"); }
-/// @brief Release date of current version
-const std::string VersionInfo::releaseDate(void) {
- return std::string("24-11-2018 0728hrs");
-}
-
-} // namespace el