Browse Source

[trac899] Basic changes for log4cplus

The code compilers and produces basic output.  Still to be done is
1) Add idea of debug levels.
2) Modify tests to copy with new format output.
Stephen Morris 14 years ago
parent
commit
4fcd0d3125

+ 51 - 0
configure.ac

@@ -447,6 +447,55 @@ AC_LINK_IFELSE(
 CPPFLAGS=$CPPFLAGS_SAVED
 LDFLAGS=$LDFLAGS_SAVED
 
+# Check for log4cplus
+log4cplus_path="yes"
+AC_ARG_WITH([log4cplus],
+  AC_HELP_STRING([--with-log4cplus=PATH],
+    [specify exact directory of log4cplus library and headers]),
+    [log4cplus_path="$withval"])
+if test "${log4cplus_path}" == "no" ; then
+    AC_MSG_ERROR([Need log4cplus])
+elif test "${log4cplus_path}" != "yes" ; then
+  LOG4CPLUS_INCLUDES="-I${log4cplus_path}/include"
+  LOG4CPLUS_LDFLAGS="-L${log4cplus_path}/lib"
+else
+# If not specified, try some common paths.
+	log4cplusdirs="/usr/local /usr/pkg /opt /opt/local"
+	for d in $log4cplusdirs
+	do
+		if test -f $d/include/log4cplus/logger.h; then
+			LOG4CPLUS_INCLUDES="-I$d/include"
+			LOG4CPLUS_LDFLAGS="-L$d/lib"
+			break
+		fi
+	done
+fi
+
+LOG4CPLUS_LDFLAGS="$LOG4CPLUS_LDFLAGS -llog4cplus $MULTITHREADING_FLAG"
+
+AC_SUBST(LOG4CPLUS_LDFLAGS)
+AC_SUBST(LOG4CPLUS_INCLUDES)
+
+CPPFLAGS_SAVED=$CPPFLAGS
+CPPFLAGS="$LOG4CPLUS_INCLUDES $CPPFLAGS"
+LDFLAGS_SAVED="$LDFLAGS"
+LDFLAGS="$LOG4CPLUS_LDFLAGS $LDFLAGS"
+
+AC_CHECK_HEADERS([log4cplus/logger.h],,AC_MSG_ERROR([Missing required header files.]))
+AC_LINK_IFELSE(
+        [AC_LANG_PROGRAM([#include <log4cplus/logger.h>
+                         ],
+                         [using namespace log4cplus;
+                          Logger logger = Logger::getInstance("main");
+                         ])],
+        [AC_MSG_RESULT([checking for log4cplus library... yes])],
+        [AC_MSG_RESULT([checking for log4cplus library... no])
+         AC_MSG_ERROR([Needs log4cplus library])]
+)
+
+CPPFLAGS=$CPPFLAGS_SAVED
+LDFLAGS=$LDFLAGS_SAVED
+
 #
 # Configure Boost header path
 #
@@ -902,6 +951,8 @@ dnl includes too
   Boost:         ${BOOST_INCLUDES}
   Botan:         ${BOTAN_INCLUDES}
                  ${BOTAN_LDFLAGS}
+  Log4cplus:     ${LOG4CPLUS_INCLUDES}
+                 ${LOG4CPLUS_LDFLAGS}
   SQLite:        $SQLITE_CFLAGS
                  $SQLITE_LIBS
 

+ 1 - 3
src/lib/log/Makefile.am

@@ -1,9 +1,7 @@
 SUBDIRS = . compiler tests
 
 AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
-AM_CPPFLAGS += $(BOOST_INCLUDES)
-AM_CPPFLAGS += -I$(top_srcdir)/src/lib/log -I$(top_builddir)/src/lib/log
-AM_CPPFLAGS += -I$(top_srcdir)/src/lib/util -I$(top_builddir)/src/lib/util
+AM_CPPFLAGS += $(BOOST_INCLUDES) $(LOG4CPLUS_INCLUDES)
 
 CLEANFILES = *.gcno *.gcda
 

+ 1 - 3
src/lib/log/compiler/Makefile.am

@@ -1,8 +1,6 @@
 SUBDIRS = .
 
 AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
-AM_CPPFLAGS += -I$(top_srcdir)/src/lib/log -I$(top_builddir)/src/lib/log
-AM_CPPFLAGS += -I$(top_srcdir)/src/lib/util -I$(top_builddir)/src/lib/util
 AM_CPPFLAGS += $(BOOST_INCLUDES)
 
 AM_CXXFLAGS = $(B10_CXXFLAGS)
@@ -17,4 +15,4 @@ noinst_PROGRAMS = message
 message_SOURCES = message.cc
 message_LDADD  = $(top_builddir)/src/lib/log/liblog.la
 message_LDADD += $(top_builddir)/src/lib/util/libutil.la
-
+message_LDADD += $(LOG4CPLUS_LDFLAGS)

+ 18 - 13
src/lib/log/log_formatter.h

@@ -17,6 +17,7 @@
 
 #include <string>
 #include <boost/lexical_cast.hpp>
+#include <log/logger_levels.h>
 
 namespace isc {
 namespace log {
@@ -73,13 +74,18 @@ private:
     ///
     /// If NULL, we are not active and should not produce anything.
     mutable Logger* logger_;
-    /// \brief Prefix (eg. "ERROR", "DEBUG" or like that)
-    const char* prefix_;
+
+    /// \brief Message severity
+    Severity severity_;
+
     /// \brief The messages with %1, %2... placeholders
     std::string* message_;
+
     /// \brief Which will be the next placeholder to replace
     unsigned nextPlaceholder_;
+
     Formatter& operator =(const Formatter& other);
+
 public:
     /// \brief Constructor of "active" formatter
     ///
@@ -89,21 +95,21 @@ public:
     ///
     /// It is not expected to be called by user of logging system directly.
     ///
-    /// \param prefix The severity prefix, like "ERROR" or "DEBUG"
+    /// \param severity The severity of the message (DEBUG, ERROR etc.)
     /// \param message The message with placeholders. We take ownership of
     ///     it and we will modify the string. Must not be NULL unless
     ///     logger is also NULL, but it's not checked.
     /// \param logger The logger where the final output will go, or NULL
     ///     if no output is wanted.
-    Formatter(const char* prefix = NULL, std::string* message = NULL,
+    Formatter(const Severity& severity = NONE, std::string* message = NULL,
               Logger* logger = NULL) :
-        logger_(logger), prefix_(prefix), message_(message),
-        nextPlaceholder_(1)
+        logger_(logger), severity_(severity), message_(message),
+        nextPlaceholder_(0)
     {
     }
 
     Formatter(const Formatter& other) :
-        logger_(other.logger_), prefix_(other.prefix_),
+        logger_(other.logger_), severity_(other.severity_),
         message_(other.message_), nextPlaceholder_(other.nextPlaceholder_)
     {
         other.logger_ = false;
@@ -113,7 +119,7 @@ public:
     /// This is the place where output happens if the formatter is active.
     ~ Formatter() {
         if (logger_) {
-            logger_->output(prefix_, *message_);
+            logger_->output(severity_, *message_);
             delete message_;
         }
     }
@@ -134,11 +140,10 @@ public:
     /// \brief String version of arg.
     Formatter& arg(const std::string& arg) {
         if (logger_) {
-            // FIXME: This logic has a problem. If we had a message like
-            // "%1 %2" and called .arg("%2").arg(42), we would get "42 %2".
-            // But we consider this to be rare enough not to complicate
-            // matters.
-            replacePlaceholder(message_, arg, nextPlaceholder_ ++);
+            // Note that if we had a message like "%1 %2" and called
+            // .arg(42).arg("%1"), we would get "42 %1" (i.e. no recursive
+            // replacements).  This is a limitation but not a problem.
+            replacePlaceholder(message_, arg, ++nextPlaceholder_ );
         }
         return (*this);
     }

+ 7 - 7
src/lib/log/logger.cc

@@ -112,14 +112,14 @@ Logger::isFatalEnabled() {
 // Output methods
 
 void
-Logger::output(const char* sevText, const string& message) {
-    getLoggerPtr()->outputRaw(sevText, message);
+Logger::output(const Severity& severity, const string& message) {
+    getLoggerPtr()->outputRaw(severity, message);
 }
 
 Logger::Formatter
 Logger::debug(int dbglevel, const isc::log::MessageID& ident) {
     if (isDebugEnabled(dbglevel)) {
-        return (Formatter("DEBUG", getLoggerPtr()->lookupMessage(ident),
+        return (Formatter(DEBUG, getLoggerPtr()->lookupMessage(ident),
                           this));
     } else {
         return (Formatter());
@@ -129,7 +129,7 @@ Logger::debug(int dbglevel, const isc::log::MessageID& ident) {
 Logger::Formatter
 Logger::info(const isc::log::MessageID& ident) {
     if (isInfoEnabled()) {
-        return (Formatter("INFO ", getLoggerPtr()->lookupMessage(ident),
+        return (Formatter(INFO, getLoggerPtr()->lookupMessage(ident),
                           this));
     } else {
         return (Formatter());
@@ -139,7 +139,7 @@ Logger::info(const isc::log::MessageID& ident) {
 Logger::Formatter
 Logger::warn(const isc::log::MessageID& ident) {
     if (isWarnEnabled()) {
-        return (Formatter("WARN ", getLoggerPtr()->lookupMessage(ident),
+        return (Formatter(WARN, getLoggerPtr()->lookupMessage(ident),
                           this));
     } else {
         return (Formatter());
@@ -149,7 +149,7 @@ Logger::warn(const isc::log::MessageID& ident) {
 Logger::Formatter
 Logger::error(const isc::log::MessageID& ident) {
     if (isErrorEnabled()) {
-        return (Formatter("ERROR", getLoggerPtr()->lookupMessage(ident),
+        return (Formatter(ERROR, getLoggerPtr()->lookupMessage(ident),
                           this));
     } else {
         return (Formatter());
@@ -159,7 +159,7 @@ Logger::error(const isc::log::MessageID& ident) {
 Logger::Formatter
 Logger::fatal(const isc::log::MessageID& ident) {
     if (isFatalEnabled()) {
-        return (Formatter("FATAL", getLoggerPtr()->lookupMessage(ident),
+        return (Formatter(FATAL, getLoggerPtr()->lookupMessage(ident),
                           this));
     } else {
         return (Formatter());

+ 5 - 15
src/lib/log/logger.h

@@ -95,7 +95,6 @@ public:
     /// \return The full name of the logger (including the root name)
     virtual std::string getName();
 
-
     /// \brief Set Severity Level for Logger
     ///
     /// Sets the level at which this logger will log messages.  If none is set,
@@ -107,14 +106,12 @@ public:
     /// outside these limits is silently coerced to the nearest boundary.
     virtual void setSeverity(isc::log::Severity severity, int dbglevel = 1);
 
-
     /// \brief Get Severity Level for Logger
     ///
     /// \return The current logging level of this logger.  In most cases though,
     /// the effective logging level is what is required.
     virtual isc::log::Severity getSeverity();
 
-
     /// \brief Get Effective Severity Level for Logger
     ///
     /// \return The effective severity level of the logger.  This is the same
@@ -122,14 +119,12 @@ public:
     /// is the severity of the parent.
     virtual isc::log::Severity getEffectiveSeverity();
 
-
     /// \brief Return DEBUG Level
     ///
     /// \return Current setting of debug level.  This is returned regardless of
     /// whether the severity is set to debug.
     virtual int getDebugLevel();
 
-
     /// \brief Returns if Debug Message Should Be Output
     ///
     /// \param dbglevel Level for which debugging is checked.  Debugging is
@@ -137,23 +132,18 @@ public:
     /// checked is less than or equal to the debug level set for the logger.
     virtual bool isDebugEnabled(int dbglevel = MIN_DEBUG_LEVEL);
 
-
     /// \brief Is INFO Enabled?
     virtual bool isInfoEnabled();
 
-
     /// \brief Is WARNING Enabled?
     virtual bool isWarnEnabled();
 
-
     /// \brief Is ERROR Enabled?
     virtual bool isErrorEnabled();
 
-
     /// \brief Is FATAL Enabled?
     virtual bool isFatalEnabled();
 
-
     /// \brief Output Debug Message
     ///
     /// \param dbglevel Debug level, ranging between 0 and 99.  Higher numbers
@@ -161,25 +151,21 @@ public:
     /// \param ident Message identification.
     Formatter debug(int dbglevel, const MessageID& ident);
 
-
     /// \brief Output Informational Message
     ///
     /// \param ident Message identification.
     Formatter info(const MessageID& ident);
 
-
     /// \brief Output Warning Message
     ///
     /// \param ident Message identification.
     Formatter warn(const MessageID& ident);
 
-
     /// \brief Output Error Message
     ///
     /// \param ident Message identification.
     Formatter error(const MessageID& ident);
 
-
     /// \brief Output Fatal Message
     ///
     /// \param ident Message identification.
@@ -203,10 +189,14 @@ protected:
 
 private:
     friend class isc::log::Formatter<Logger>;
+
     /// \brief Raw output function
     ///
     /// This is used by the formatter to output formatted output.
-    void output(const char* sevText, const std::string& message);
+    ///
+    /// \param severity Severity of the message being output.
+    /// \param message Text of the message to be output.
+    void output(const Severity& severity, const std::string& message);
 
     /// \brief Copy Constructor
     ///

+ 120 - 115
src/lib/log/logger_impl.cc

@@ -19,10 +19,14 @@
 #include <stdarg.h>
 #include <stdio.h>
 #include <boost/lexical_cast.hpp>
+#include <boost/static_assert.hpp>
+
+#include <log4cplus/configurator.h>
 
 #include <log/debug_levels.h>
 #include <log/root_logger_name.h>
 #include <log/logger.h>
+#include <log/logger_levels.h>
 #include <log/logger_impl.h>
 #include <log/message_dictionary.h>
 #include <log/message_types.h>
@@ -37,8 +41,6 @@ namespace log {
 
 // Static initializations
 
-LoggerImpl::LoggerInfoMap LoggerImpl::logger_info_;
-LoggerImpl::LoggerInfo LoggerImpl::root_logger_info_(isc::log::INFO, 0);
 
 // Constructor
 LoggerImpl::LoggerImpl(const std::string& name, bool)
@@ -51,6 +53,13 @@ LoggerImpl::LoggerImpl(const std::string& name, bool)
         is_root_ = false;
         name_ = getRootLoggerName() + "." + name;
     }
+    fmt_name_ = std::string("[") + name_ + std::string("] ");
+
+    // Initialize log4cplus if not already done
+    initLog4cplus();
+
+    // Return existing instance of logger, creating it if it does not exist.
+    logger_ = log4cplus::Logger::getInstance(name_);
 }
 
 // Destructor. (Here because of virtual declaration.)
@@ -59,54 +68,22 @@ LoggerImpl::~LoggerImpl() {
 }
 
 // Set the severity for logging.
+// TODO IGNORE DEBUG LEVEL FOR NOW
 
 void
-LoggerImpl::setSeverity(isc::log::Severity severity, int dbglevel) {
+LoggerImpl::setSeverity(isc::log::Severity severity, int /*dbglevel*/) {
 
     // Silently coerce the debug level into the valid range of 0 to 99
 
-    int debug_level = max(MIN_DEBUG_LEVEL, min(MAX_DEBUG_LEVEL, dbglevel));
-    if (is_root_) {
-
-        // Can only set severity for the root logger, you can't disable it.
-        // Any attempt to do so is silently ignored.
-        if (severity != isc::log::DEFAULT) {
-            root_logger_info_ = LoggerInfo(severity, debug_level);
-        }
-
-    } else if (severity == isc::log::DEFAULT) {
-
-        // Want to set to default; this means removing the information
-        // about this logger from the logger_info_ if it is set.
-        LoggerInfoMap::iterator i = logger_info_.find(name_);
-        if (i != logger_info_.end()) {
-            logger_info_.erase(i);
-        }
-
-    } else {
-
-        // Want to set this information
-        logger_info_[name_] = LoggerInfo(severity, debug_level);
-    }
+    //int debug_level = max(MIN_DEBUG_LEVEL, min(MAX_DEBUG_LEVEL, dbglevel));
+    logger_.setLogLevel(convertFromBindSeverity(severity));
 }
 
 // Return severity level
 
 isc::log::Severity
 LoggerImpl::getSeverity() {
-
-    if (is_root_) {
-        return (root_logger_info_.severity);
-    }
-    else {
-        LoggerInfoMap::iterator i = logger_info_.find(name_);
-        if (i != logger_info_.end()) {
-           return ((i->second).severity);
-        }
-        else {
-            return (isc::log::DEFAULT);
-        }
-    }
+    return convertToBindSeverity(logger_.getLogLevel());
 }
 
 // Get effective severity.  Either the current severity or, if not set, the
@@ -114,86 +91,29 @@ LoggerImpl::getSeverity() {
 
 isc::log::Severity
 LoggerImpl::getEffectiveSeverity() {
-
-    if (!is_root_ && !logger_info_.empty()) {
-
-        // Not root logger and there is at least one item in the info map for a
-        // logger.
-        LoggerInfoMap::iterator i = logger_info_.find(name_);
-        if (i != logger_info_.end()) {
-
-            // Found, so return the severity.
-            return ((i->second).severity);
-        }
-    }
-
-    // Must be the root logger, or this logger is defaulting to the root logger
-    // settings.
-    return (root_logger_info_.severity);
+    return convertToBindSeverity(logger_.getChainedLogLevel());
 }
 
+
 // Get the debug level.  This returns 0 unless the severity is DEBUG.
+// TODO: DEBUG LEVEL IGNORED FOR NOW
 
 int
 LoggerImpl::getDebugLevel() {
-
-    if (!is_root_ && !logger_info_.empty()) {
-
-        // Not root logger and there is something in the map, check if there
-        // is a setting for this one.
-        LoggerInfoMap::iterator i = logger_info_.find(name_);
-        if (i != logger_info_.end()) {
-
-            // Found, so return the debug level.
-            if ((i->second).severity == isc::log::DEBUG) {
-                return ((i->second).dbglevel);
-            } else {
-                return (0);
-            }
-        }
-    }
-
-    // Must be the root logger, or this logger is defaulting to the root logger
-    // settings.
-    if (root_logger_info_.severity == isc::log::DEBUG) {
-        return (root_logger_info_.dbglevel);
-    } else {
-        return (0);
-    }
+    return (0);
 }
 
 // The code for isXxxEnabled is quite simple and is in the header.  The only
 // exception is isDebugEnabled() where we have the complication of the debug
 // levels.
+// TODO: DEBUG LEVEL IGNORED FOR NOW
 
 bool
 LoggerImpl::isDebugEnabled(int dbglevel) {
-
-    if (!is_root_ && !logger_info_.empty()) {
-
-        // Not root logger and there is something in the map, check if there
-        // is a setting for this one.
-        LoggerInfoMap::iterator i = logger_info_.find(name_);
-        if (i != logger_info_.end()) {
-
-            // Found, so return the debug level.
-            if ((i->second).severity <= isc::log::DEBUG) {
-                return ((i->second).dbglevel >= dbglevel);
-            } else {
-                return (false); // Nothing lower than debug
-            }
-        }
-    }
-
-    // Must be the root logger, or this logger is defaulting to the root logger
-    // settings.
-    if (root_logger_info_.severity <= isc::log::DEBUG) {
-        return (root_logger_info_.dbglevel >= dbglevel);
-    } else {
-       return (false);
-    }
+    return logger_.isEnabledFor(log4cplus::DEBUG_LOG_LEVEL);
 }
 
+
 // Output a general message
 string*
 LoggerImpl::lookupMessage(const MessageID& ident) {
@@ -202,18 +122,103 @@ LoggerImpl::lookupMessage(const MessageID& ident) {
 }
 
 void
-LoggerImpl::outputRaw(const char* sevText, const string& message) {
-    // Get the time in a struct tm format, and convert to text
-    time_t t_time;
-    time(&t_time);
-    struct tm* tm_time = localtime(&t_time);
-
-    char chr_time[32];
-    (void) strftime(chr_time, sizeof(chr_time), "%Y-%m-%d %H:%M:%S", tm_time);
-
-    // Now output.
-    cout << chr_time << " " << sevText << " [" << getName() << "] " <<
-        message << endl;
+LoggerImpl::outputRaw(const Severity& severity, const string& message) {
+    switch (severity) {
+        case DEBUG:
+            LOG4CPLUS_DEBUG(logger_, fmt_name_ << message);
+            break;
+
+        case INFO:
+            LOG4CPLUS_INFO(logger_, fmt_name_ << message);
+            break;
+
+        case WARN:
+            LOG4CPLUS_WARN(logger_, fmt_name_ << message);
+            break;
+
+        case ERROR:
+            LOG4CPLUS_ERROR(logger_, fmt_name_ << message);
+            break;
+
+        case FATAL:
+            LOG4CPLUS_FATAL(logger_, fmt_name_ << message);
+    }
+}
+
+// Convert levels - from BIND 10 level to log4cplus level.
+// Namespaces explicitly used to clarify what level we are talking about
+log4cplus::LogLevel
+LoggerImpl::convertFromBindSeverity(const isc::log::Severity& inlevel) {
+
+    // BIND 10 logging levels are small integers so we can do a table lookup
+    static const log4cplus::LogLevel level[] = {
+        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>(isc::log::DEFAULT) == 0);
+    BOOST_STATIC_ASSERT(static_cast<int>(isc::log::DEBUG) == 1);
+    BOOST_STATIC_ASSERT(static_cast<int>(isc::log::INFO) == 2);
+    BOOST_STATIC_ASSERT(static_cast<int>(isc::log::WARN) == 3);
+    BOOST_STATIC_ASSERT(static_cast<int>(isc::log::ERROR) == 4);
+    BOOST_STATIC_ASSERT(static_cast<int>(isc::log::FATAL) == 5);
+    BOOST_STATIC_ASSERT(static_cast<int>(isc::log::NONE) == 6);
+
+    // No need to check that the iundex is out of range.  Setting the type of
+    // the argument to 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 (level[inlevel]);
+}
+
+// Convert levels - from log4plus level to BIND 10 level
+// Namespaces explicitly used to clarify what level we are talking about
+isc::log::Severity
+LoggerImpl::convertToBindSeverity(const log4cplus::LogLevel& inlevel) {
+
+    // Not easy to do a table lookup as the numerical values of log4cplus levels
+    // are quite high.
+    switch (inlevel) {
+        case log4cplus::NOT_SET_LOG_LEVEL:
+            return (isc::log::DEFAULT);
+
+        case log4cplus::DEBUG_LOG_LEVEL:
+            return (isc::log::DEBUG);
+
+        case log4cplus::INFO_LOG_LEVEL:
+            return (isc::log::INFO);
+
+        case log4cplus::WARN_LOG_LEVEL:
+            return (isc::log::WARN);
+
+        case log4cplus::ERROR_LOG_LEVEL:
+            return (isc::log::ERROR);
+
+        case log4cplus::FATAL_LOG_LEVEL:
+            return (isc::log::FATAL);
+    }
+
+    return (isc::log::NONE);
+}
+
+// One-time initialization of log4cplus
+
+
+void
+LoggerImpl::initLog4cplus() {
+    static bool not_initialized = true;
+
+    if (not_initialized) {
+        log4cplus::BasicConfigurator config;
+        config.configure();
+        not_initialized = false;
+    }
 }
 
 } // namespace log

+ 45 - 33
src/lib/log/logger_impl.h

@@ -23,6 +23,11 @@
 #include <map>
 #include <utility>
 
+
+// log4cplus logger header file
+#include <log4cplus/logger.h>
+
+// BIND-10 logger files
 #include <log/debug_levels.h>
 #include <log/logger.h>
 #include <log/message_types.h>
@@ -131,47 +136,33 @@ public:
 
     /// \brief Is INFO Enabled?
     virtual bool isInfoEnabled() {
-        return (isEnabled(isc::log::INFO));
+        return (logger_.isEnabledFor(log4cplus::INFO_LOG_LEVEL));
     }
 
     /// \brief Is WARNING Enabled?
     virtual bool isWarnEnabled() {
-        return (isEnabled(isc::log::WARN));
+        return (logger_.isEnabledFor(log4cplus::WARN_LOG_LEVEL));
     }
 
     /// \brief Is ERROR Enabled?
     virtual bool isErrorEnabled() {
-        return (isEnabled(isc::log::ERROR));
+        return (logger_.isEnabledFor(log4cplus::ERROR_LOG_LEVEL));
     }
 
     /// \brief Is FATAL Enabled?
     virtual bool isFatalEnabled() {
-        return (isEnabled(isc::log::FATAL));
-    }
-
-
-    /// \brief Common Severity check
-    ///
-    /// Implements the common severity check.  As an optimisation, this checks
-    /// to see if any logger-specific levels have been set (a quick check as it
-    /// just involves seeing if the collection of logger information is empty).
-    /// if not, it returns the information for the root level; if so, it has
-    /// to take longer and look up the information in the map holding the
-    /// logging details.
-    virtual bool isEnabled(isc::log::Severity severity) {
-        if (logger_info_.empty()) {
-            return (root_logger_info_.severity <= severity);
-        }
-        else {
-            return (getSeverity() <= severity);
-        }
+        return (logger_.isEnabledFor(log4cplus::FATAL_LOG_LEVEL));
     }
 
     /// \brief Raw output
     ///
     /// Writes the message with time into the log. Used by the Formatter
     /// to produce output.
-    void outputRaw(const char* sev_text, const std::string& message);
+    ///
+    /// \param severity Severity of the message. (This controls the prefix
+    ///        label output with the message text.)
+    /// \param message Text of the message.
+    void outputRaw(const Severity& severity, const std::string& message);
 
     /// \brief Look up message text in dictionary
     ///
@@ -194,22 +185,43 @@ public:
     /// Only used for testing, this clears all the logger information and
     /// resets it back to default values.
     static void reset() {
-        root_logger_info_ = LoggerInfo(isc::log::INFO, MIN_DEBUG_LEVEL);
-        logger_info_.clear();
+        //root_logger_info_ = LoggerInfo(isc::log::INFO, MIN_DEBUG_LEVEL);
+        //logger_info_.clear();
     }
 
 
 private:
-    bool                is_root_;           ///< true if a root logger
-    std::string         name_;              ///< Name of this logger
+    /// \brief Convert Log Levels
+    ///
+    /// Converts a BIND 10 log level to a log4cplus log level.
+    ///
+    /// \param inlevel BIND 10 log level.
+    ///
+    /// \return Log4cplus log level.
+    log4cplus::LogLevel convertFromBindSeverity(
+        const isc::log::Severity& inlevel);
+
+    /// \brief Convert Log Levels
+    ///
+    /// Converts a log4cplus log level to a BIND 10 log level.
+    ///
+    /// \param inlevel log4cplus log level.
+    ///
+    /// \return BIND 10 log level.
+    isc::log::Severity convertToBindSeverity(
+        const log4cplus::LogLevel& inlevel);
+
+    /// \brief Initialize log4cplus
+    ///
+    /// Static method to perform one-time initialization of the log4cplus
+    /// system.
+    static void initLog4cplus();
 
-    // Split the status of the root logger from this logger.  If - is will
-    // probably be the usual case - no per-logger setting is enabled, a
-    // quick check of logger_info_.empty() will return true and we can quickly
-    // return the root logger status without a length lookup in the map.
+    bool                is_root_;           ///< Is this BIND 10 root logger?
+    std::string         name_;              ///< Full name of this logger
+    std::string         fmt_name_;          ///< Formatted name
+    log4cplus::Logger   logger_;            ///< Underlying log4cplus logger
 
-    static LoggerInfo       root_logger_info_;  ///< Status of root logger
-    static LoggerInfoMap    logger_info_;       ///< Store of debug levels etc.
 };
 
 } // namespace log

+ 2 - 4
src/lib/log/tests/Makefile.am

@@ -2,8 +2,6 @@ SUBDIRS = .
 
 AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
 AM_CPPFLAGS += $(BOOST_INCLUDES)
-AM_CPPFLAGS += -I$(top_srcdir)/src/lib/log -I$(top_builddir)/src/lib/log
-AM_CPPFLAGS += -I$(top_srcdir)/src/lib/util -I$(top_builddir)/src/lib/util
 AM_CXXFLAGS = $(B10_CXXFLAGS)
 
 if USE_STATIC_LINK
@@ -25,7 +23,7 @@ run_unittests_SOURCES += run_unittests.cc
 run_unittests_SOURCES += log_formatter_unittest.cc
 
 run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
-run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
+run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS) $(LOG4CPLUS_LDFLAGS)
 
 run_unittests_LDADD  = $(GTEST_LDADD)
 run_unittests_LDADD += $(top_builddir)/src/lib/log/liblog.la
@@ -35,7 +33,7 @@ endif
 TESTS += logger_support_test
 logger_support_test_SOURCES = logger_support_test.cc
 logger_support_test_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
-logger_support_test_LDFLAGS = $(AM_LDFLAGS)
+logger_support_test_LDFLAGS = $(AM_LDFLAGS) $(LOG4CPLUS_LDFLAGS)
 logger_support_test_LDADD  = $(top_builddir)/src/lib/log/liblog.la
 logger_support_test_LDADD += $(top_builddir)/src/lib/util/libutil.la
 

+ 19 - 18
src/lib/log/tests/log_formatter_unittest.cc

@@ -14,6 +14,7 @@
 
 #include <gtest/gtest.h>
 #include <log/log_formatter.h>
+#include <log/logger_levels.h>
 
 #include <vector>
 #include <string>
@@ -24,11 +25,11 @@ namespace {
 
 class FormatterTest : public ::testing::Test {
 protected:
-    typedef pair<const char*, string> Output;
+    typedef pair<isc::log::Severity, string> Output;
     typedef isc::log::Formatter<FormatterTest> Formatter;
     vector<Output> outputs;
 public:
-    void output(const char* prefix, const string& message) {
+    void output(const isc::log::Severity& prefix, const string& message) {
         outputs.push_back(Output(prefix, message));
     }
     // Just shortcut for new string
@@ -46,9 +47,9 @@ TEST_F(FormatterTest, inactive) {
 // Create an active formatter and check it produces output. Does no arg
 // substitution yet
 TEST_F(FormatterTest, active) {
-    Formatter("TEST", s("Text of message"), this);
+    Formatter(isc::log::INFO, s("Text of message"), this);
     ASSERT_EQ(1, outputs.size());
-    EXPECT_STREQ("TEST", outputs[0].first);
+    EXPECT_EQ(isc::log::INFO, outputs[0].first);
     EXPECT_EQ("Text of message", outputs[0].second);
 }
 
@@ -62,53 +63,53 @@ TEST_F(FormatterTest, inactiveArg) {
 TEST_F(FormatterTest, stringArg) {
     {
         SCOPED_TRACE("C++ string");
-        Formatter("TEST", s("Hello %1"), this).arg(string("World"));
+        Formatter(isc::log::INFO, s("Hello %1"), this).arg(string("World"));
         ASSERT_EQ(1, outputs.size());
-        EXPECT_STREQ("TEST", outputs[0].first);
+        EXPECT_EQ(isc::log::INFO, outputs[0].first);
         EXPECT_EQ("Hello World", outputs[0].second);
     }
     {
         SCOPED_TRACE("C++ string");
-        Formatter("TEST", s("Hello %1"), this).arg(string("Internet"));
+        Formatter(isc::log::INFO, s("Hello %1"), this).arg(string("Internet"));
         ASSERT_EQ(2, outputs.size());
-        EXPECT_STREQ("TEST", outputs[1].first);
+        EXPECT_EQ(isc::log::INFO, outputs[1].first);
         EXPECT_EQ("Hello Internet", outputs[1].second);
     }
 }
 
 // Can convert to string
 TEST_F(FormatterTest, intArg) {
-    Formatter("TEST", s("The answer is %1"), this).arg(42);
+    Formatter(isc::log::INFO, s("The answer is %1"), this).arg(42);
     ASSERT_EQ(1, outputs.size());
-    EXPECT_STREQ("TEST", outputs[0].first);
+    EXPECT_EQ(isc::log::INFO, outputs[0].first);
     EXPECT_EQ("The answer is 42", outputs[0].second);
 }
 
 // Can use multiple arguments at different places
 TEST_F(FormatterTest, multiArg) {
-    Formatter("TEST", s("The %2 are %1"), this).arg("switched").
+    Formatter(isc::log::INFO, s("The %2 are %1"), this).arg("switched").
         arg("arguments");
     ASSERT_EQ(1, outputs.size());
-    EXPECT_STREQ("TEST", outputs[0].first);
+    EXPECT_EQ(isc::log::INFO, outputs[0].first);
     EXPECT_EQ("The arguments are switched", outputs[0].second);
 }
 
 // Can survive and complains if placeholder is missing
 TEST_F(FormatterTest, missingPlace) {
-    EXPECT_NO_THROW(Formatter("TEST", s("Missing the first %2"), this).
+    EXPECT_NO_THROW(Formatter(isc::log::INFO, s("Missing the first %2"), this).
                     arg("missing").arg("argument"));
     ASSERT_EQ(1, outputs.size());
-    EXPECT_STREQ("TEST", outputs[0].first);
+    EXPECT_EQ(isc::log::INFO, outputs[0].first);
     EXPECT_EQ("Missing the first argument "
               "@@Missing placeholder %1 for 'missing'@@", outputs[0].second);
 }
 
 // Can replace multiple placeholders
 TEST_F(FormatterTest, multiPlaceholder) {
-    Formatter("TEST", s("The %1 is the %1"), this).
+    Formatter(isc::log::INFO, s("The %1 is the %1"), this).
         arg("first rule of tautology club");
     ASSERT_EQ(1, outputs.size());
-    EXPECT_STREQ("TEST", outputs[0].first);
+    EXPECT_EQ(isc::log::INFO, outputs[0].first);
     EXPECT_EQ("The first rule of tautology club is "
               "the first rule of tautology club", outputs[0].second);
 }
@@ -116,9 +117,9 @@ TEST_F(FormatterTest, multiPlaceholder) {
 // Test we can cope with replacement containing the placeholder
 TEST_F(FormatterTest, noRecurse) {
     // If we recurse, this will probably eat all the memory and crash
-    Formatter("TEST", s("%1"), this).arg("%1 %1");
+    Formatter(isc::log::INFO, s("%1"), this).arg("%1 %1");
     ASSERT_EQ(1, outputs.size());
-    EXPECT_STREQ("TEST", outputs[0].first);
+    EXPECT_EQ(isc::log::INFO, outputs[0].first);
     EXPECT_EQ("%1 %1", outputs[0].second);
 }