diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 14:53:22 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 14:53:22 +0000 |
commit | 52c021ee0b0c6ad2128ed550c694aad0d11d4c3f (patch) | |
tree | 83cf8627b94336cf4bee7479b9749263bbfd3a06 /src/lib/log/logger_level_impl.cc | |
parent | Initial commit. (diff) | |
download | isc-kea-52c021ee0b0c6ad2128ed550c694aad0d11d4c3f.tar.xz isc-kea-52c021ee0b0c6ad2128ed550c694aad0d11d4c3f.zip |
Adding upstream version 2.5.7.upstream/2.5.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/lib/log/logger_level_impl.cc')
-rw-r--r-- | src/lib/log/logger_level_impl.cc | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/src/lib/log/logger_level_impl.cc b/src/lib/log/logger_level_impl.cc new file mode 100644 index 0000000..a4aba73 --- /dev/null +++ b/src/lib/log/logger_level_impl.cc @@ -0,0 +1,215 @@ +// Copyright (C) 2011-2022 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <algorithm> +#include <string.h> +#include <iostream> +#include <boost/lexical_cast.hpp> + +#include <log4cplus/logger.h> + +#include <log/logger_level.h> +#include <log/logger_level_impl.h> +#include <log/logimpl_messages.h> +#include <log/macros.h> + +using namespace log4cplus; +using namespace std; + +namespace { +isc::log::Logger logger("log"); +} + +namespace isc { +namespace log { + +// Convert Kea level to a log4cplus logging level. +log4cplus::LogLevel +LoggerLevelImpl::convertFromBindLevel(const Level& level) { + + // Kea logging levels are small integers so we can do a table lookup + static const log4cplus::LogLevel log4cplus_levels[] = { + log4cplus::NOT_SET_LOG_LEVEL, + log4cplus::DEBUG_LOG_LEVEL, + log4cplus::INFO_LOG_LEVEL, + log4cplus::WARN_LOG_LEVEL, + log4cplus::ERROR_LOG_LEVEL, + log4cplus::FATAL_LOG_LEVEL, + log4cplus::OFF_LOG_LEVEL + }; + + // ... with compile-time checks to ensure that table indexes are correct. + BOOST_STATIC_ASSERT(static_cast<int>(DEFAULT) == 0); + BOOST_STATIC_ASSERT(static_cast<int>(DEBUG) == 1); + BOOST_STATIC_ASSERT(static_cast<int>(INFO) == 2); + BOOST_STATIC_ASSERT(static_cast<int>(WARN) == 3); + BOOST_STATIC_ASSERT(static_cast<int>(ERROR) == 4); + BOOST_STATIC_ASSERT(static_cast<int>(FATAL) == 5); + BOOST_STATIC_ASSERT(static_cast<int>(NONE) == 6); + + // Do the conversion + if (level.severity == DEBUG) { + + // Debug severity, so the log4cplus level returned depends on the + // debug level. Silently limit the debug level to the range + // MIN_DEBUG_LEVEL to MAX_DEBUG_LEVEL (avoids the hassle of throwing + // and catching exceptions and besides, this is for debug information). + int limited = std::max(MIN_DEBUG_LEVEL, + std::min(level.dbglevel, MAX_DEBUG_LEVEL)); + LogLevel newlevel = static_cast<int>(DEBUG_LOG_LEVEL - + (limited - MIN_DEBUG_LEVEL)); + return (static_cast<log4cplus::LogLevel>(newlevel)); + + } else { + + // Can do a table lookup to speed things up. There is no need to check + // that the index is out of range. That the variable is of type + // isc::log::Severity ensures that it must be one of the Severity enum + // members - conversion of a numeric value to an enum is not permitted. + return (log4cplus_levels[level.severity]); + } +} + +// Convert log4cplus logging level to Kea debug level. It is up to the +// caller to validate that the debug level is valid. +Level +LoggerLevelImpl::convertToBindLevel(const log4cplus::LogLevel loglevel) { + + // Not easy to do a table lookup as the numerical values of log4cplus levels + // are quite high. + if (loglevel <= log4cplus::NOT_SET_LOG_LEVEL) { + return (Level(DEFAULT)); + + } else if (loglevel <= log4cplus::DEBUG_LOG_LEVEL) { + + // Debug severity, so extract the debug level from the numeric value. + // If outside the limits, change the severity to the level above or + // below. + int dbglevel = MIN_DEBUG_LEVEL + + static_cast<int>(log4cplus::DEBUG_LOG_LEVEL) - + static_cast<int>(loglevel); + if (dbglevel > MAX_DEBUG_LEVEL) { + return (Level(DEFAULT)); + } else if (dbglevel < MIN_DEBUG_LEVEL) { + return (Level(INFO)); + } + return (Level(DEBUG, dbglevel)); + + } else if (loglevel <= log4cplus::INFO_LOG_LEVEL) { + return (Level(INFO)); + + } else if (loglevel <= log4cplus::WARN_LOG_LEVEL) { + return (Level(WARN)); + + } else if (loglevel <= log4cplus::ERROR_LOG_LEVEL) { + return (Level(ERROR)); + + } else if (loglevel <= log4cplus::FATAL_LOG_LEVEL) { + return (Level(FATAL)); + + } + + return (Level(NONE)); +} + + +// Convert string to appropriate logging level +log4cplus::LogLevel +LoggerLevelImpl::logLevelFromString(const log4cplus::tstring& level) { + + std::string name = level; // Get to known type + size_t length = name.size(); // Length of the string + + if (length < 5) { + + // String can't possibly start DEBUG so we don't know what it is. + // As per documentation, return NOT_SET level. + return (NOT_SET_LOG_LEVEL); + } else { + if (strncasecmp(name.c_str(), "DEBUG", 5) == 0) { + + // String starts "DEBUG" (or "debug" or any case mixture). The + // rest of the string - if any - should be a number. + if (length == 5) { + + // It is plain "DEBUG". Take this as level 0. + return (DEBUG_LOG_LEVEL); + } else { + + // Try converting the remainder to an integer. The "5" is + // the length of the string "DEBUG". Note that if the number + // is outside the range of debug levels, it is coerced to the + // nearest limit. Thus a level of DEBUG509 will end up as + // if DEBUG99 has been specified. + try { + int dbglevel = boost::lexical_cast<int>(name.substr(5)); + if (dbglevel < MIN_DEBUG_LEVEL) { + LOG_WARN(logger, LOGIMPL_BELOW_MIN_DEBUG).arg(dbglevel) + .arg(MIN_DEBUG_LEVEL); + dbglevel = MIN_DEBUG_LEVEL; + + } else if (dbglevel > MAX_DEBUG_LEVEL) { + LOG_WARN(logger, LOGIMPL_ABOVE_MAX_DEBUG).arg(dbglevel) + .arg(MAX_DEBUG_LEVEL); + dbglevel = MAX_DEBUG_LEVEL; + + } + return convertFromBindLevel(Level(DEBUG, dbglevel)); + } + catch (const boost::bad_lexical_cast&) { + LOG_ERROR(logger, LOGIMPL_BAD_DEBUG_STRING).arg(name); + return (NOT_SET_LOG_LEVEL); + } + } + } else { + + // Unknown string - return default. Log4cplus will call any other + // registered conversion functions to interpret it. + return (NOT_SET_LOG_LEVEL); + } + } +} + +// Convert logging level to string. If the level is a valid debug level, +// return the string DEBUG, else return the empty string. +#if LOG4CPLUS_VERSION < LOG4CPLUS_MAKE_VERSION(2, 0, 0) +LoggerLevelImpl::LogLevelString +#else +const LoggerLevelImpl::LogLevelString& +#endif +LoggerLevelImpl::logLevelToString(log4cplus::LogLevel level) { + Level bindlevel = convertToBindLevel(level); + Severity& severity = bindlevel.severity; + int& dbglevel = bindlevel.dbglevel; + static LoggerLevelImpl::LogLevelString debug_ = tstring("DEBUG"); + static LoggerLevelImpl::LogLevelString empty_ = tstring(); + + if ((severity == DEBUG) && + ((dbglevel >= MIN_DEBUG_LEVEL) && (dbglevel <= MAX_DEBUG_LEVEL))) { + return (debug_); + } + + // Unknown, so return empty string for log4cplus to try other conversion + // functions. + return (empty_); +} + +// Initialization. Register the conversion functions with the LogLevelManager. +void +LoggerLevelImpl::init() { + + // Get the singleton log-level manager. + LogLevelManager& manager = getLogLevelManager(); + + // Register the conversion functions + manager.pushFromStringMethod(LoggerLevelImpl::logLevelFromString); + manager.pushToStringMethod(LoggerLevelImpl::logLevelToString); +} + +} // namespace log +} // namespace isc |