Browse Source

[2445] initial working version

needs cleanup and tests
Jelte Jansen 12 years ago
parent
commit
bbefd6bc41

+ 1 - 0
src/lib/log/logger_impl.cc

@@ -60,6 +60,7 @@ LoggerImpl::LoggerImpl(const string& name) :
 // Destructor. (Here because of virtual declaration.)
 
 LoggerImpl::~LoggerImpl() {
+    logger_.shutdown();
     delete sync_;
 }
 

+ 1 - 0
src/lib/log/logger_manager.cc

@@ -96,6 +96,7 @@ void
 LoggerManager::init(const std::string& root, isc::log::Severity severity,
                     int dbglevel, const char* file)
 {
+
     // Load in the messages declared in the program and registered by
     // statically-declared MessageInitializer objects.
     MessageInitializer::loadDictionary();

+ 8 - 2
src/lib/log/logger_manager.h

@@ -59,8 +59,14 @@ public:
     template <typename T>
     void process(T start, T finish) {
         processInit();
-        for (T i = start; i != finish; ++i) {
-            processSpecification(*i);
+        if (start == finish) {
+            // empty iterator; set defaults
+            const LoggerSpecification spec;
+            processSpecification(spec);
+        } else {
+            for (T i = start; i != finish; ++i) {
+                processSpecification(*i);
+            }
         }
         processEnd();
     }

+ 105 - 13
src/lib/log/logger_manager_impl.cc

@@ -23,6 +23,7 @@
 #include <log4cplus/syslogappender.h>
 
 #include <log/logger.h>
+#include <log/logger_support.h>
 #include <log/logger_level_impl.h>
 #include <log/logger_manager.h>
 #include <log/logger_manager_impl.h>
@@ -30,17 +31,76 @@
 #include <log/logger_name.h>
 #include <log/logger_specification.h>
 
+#include <boost/scoped_ptr.hpp>
+
 using namespace std;
 
 namespace isc {
 namespace log {
 
+class LogBuffer {
+public:
+    LogBuffer() {
+        flushed_ = false;
+    }
+
+    ~LogBuffer() {
+        // If there is anything left in the buffer,
+        // it means no reconfig has been done, and
+        // we can assume the logging system was either
+        // never setup, or broke while doing so.
+        // So dump all that is left to stdout
+        flush_stdout();
+    }
+    void add(const log4cplus::spi::InternalLoggingEvent& event) {
+        if (flushed_) {
+            isc_throw(isc::Exception, "BUFFER APPEND AFTER FLUSH");
+        }
+        stored_.push_back(log4cplus::spi::InternalLoggingEvent(event));
+    }
+    void flush_stdout() {
+        // This does not show a bit of information normal log messages
+        // do, so perhaps we should try and setup a new logger here
+        // However, as this is called from a destructor, it may not
+        // be a good idea.
+        for (size_t i = 0; i < stored_.size(); ++i) {
+            std::cout << stored_.at(i).getMessage() << std::endl;
+        }
+        stored_.clear();
+    }
+    //void flush(log4cplus::Logger& logger) {
+    void flush() {
+        for (size_t i = 0; i < stored_.size(); ++i) {
+            const log4cplus::spi::InternalLoggingEvent event(stored_.at(i));
+            //logger.log(event.getLogLevel(), event.getMessage());
+            // Flush to the last defined logger
+            log4cplus::Logger logger = log4cplus::Logger::getInstance(event.getLoggerName());
+
+            logger.log(event.getLogLevel(), event.getMessage());
+        }
+        stored_.clear();
+        flushed_ = true;
+    }
+private:
+    std::vector<log4cplus::spi::InternalLoggingEvent> stored_;
+    bool flushed_;
+};
+
+LogBuffer& getLogBuffer() {
+    static boost::scoped_ptr<LogBuffer> log_buffer(NULL);
+    if (!log_buffer) {
+        log_buffer.reset(new LogBuffer);
+    }
+    return (*log_buffer);
+}
+
+
+
 // Reset hierarchy of loggers back to default settings.  This removes all
 // appenders from loggers, sets their severity to NOT_SET (so that events are
 // passed back to the parent) and resets the root logger to logging
 // informational messages.  (This last is not a log4cplus default, so we have to
 // explicitly reset the logging severity.)
-
 void
 LoggerManagerImpl::processInit() {
     log4cplus::Logger::getDefaultHierarchy().resetConfiguration();
@@ -49,12 +109,16 @@ LoggerManagerImpl::processInit() {
 
 // Process logging specification.  Set up the common states then dispatch to
 // add output specifications.
-
 void
 LoggerManagerImpl::processSpecification(const LoggerSpecification& spec) {
-
-    log4cplus::Logger logger = log4cplus::Logger::getInstance(
+    log4cplus::Logger logger;
+    // If this is an 'empty' specification, just set the root logger
+    if (spec.getName() == "") {
+        logger = log4cplus::Logger::getInstance(getRootLoggerName());
+    } else {
+        logger = log4cplus::Logger::getInstance(
                                    expandLoggerName(spec.getName()));
+    }
 
     // Set severity level according to specification entry.
     logger.setLogLevel(LoggerLevelImpl::convertFromBindLevel(
@@ -95,7 +159,15 @@ LoggerManagerImpl::processSpecification(const LoggerSpecification& spec) {
                           i->destination);
             }
         }
+    } else {
+        // If no output options are given, use a default appender
+        // Yes, so replace all appenders for this logger.
+        logger.removeAllAppenders();
+        OutputOption opt;
+        createConsoleAppender(logger, opt);
     }
+    // Should anything be left in the buffer, this is the time to flush it.
+    getLogBuffer().flush();
 }
 
 // Console appender - log to either stdout or stderr.
@@ -134,7 +206,28 @@ LoggerManagerImpl::createFileAppender(log4cplus::Logger& logger,
     logger.addAppender(fileapp);
 }
 
-// Syslog appender. 
+class BufferAppender : public log4cplus::Appender {
+public:
+    BufferAppender() {}
+
+    virtual void close() {
+        //relog();
+        //log2out();
+    }
+    virtual void append(const log4cplus::spi::InternalLoggingEvent& event) {
+        getLogBuffer().add(event);
+    }
+};
+
+void
+LoggerManagerImpl::createBufferAppender(log4cplus::Logger& logger)
+{
+    log4cplus::SharedAppenderPtr bufferapp(new BufferAppender());
+    bufferapp->setName("buffer");
+    logger.addAppender(bufferapp);
+}
+
+// Syslog appender.
 void
 LoggerManagerImpl::createSyslogAppender(log4cplus::Logger& logger,
                                          const OutputOption& opt)
@@ -147,10 +240,8 @@ LoggerManagerImpl::createSyslogAppender(log4cplus::Logger& logger,
 
 
 // One-time initialization of the log4cplus system
-
 void
 LoggerManagerImpl::init(isc::log::Severity severity, int dbglevel) {
-
     // Set up basic configurator.  This attaches a ConsoleAppender to the
     // root logger with suitable output.  This is used until we we have
     // actually read the logging configuration, in which case the output
@@ -169,7 +260,6 @@ LoggerManagerImpl::init(isc::log::Severity severity, int dbglevel) {
 // It is principally used in testing.
 void
 LoggerManagerImpl::reset(isc::log::Severity severity, int dbglevel) {
-
     // Initialize the root logger
     initRootLogger(severity, dbglevel);
 }
@@ -192,13 +282,15 @@ void LoggerManagerImpl::initRootLogger(isc::log::Severity severity,
                                                     Level(severity, dbglevel)));
 
     // Set the BIND 10 root to use a console logger.
-    OutputOption opt;
-    createConsoleAppender(b10root, opt);
+    //OutputOption opt;
+    //createConsoleAppender(b10root, opt);
+    createBufferAppender(b10root);
+    //if (!buffer_appender_) {
+    //    buffer_appender_ = new BufferAppender(logger);
+    //    b10_root.addAppender(buffer_appender_);
+    //}
 }
 
-// Set the the "console" layout for the given appenders.  This layout includes
-// a date/time and the name of the logger.
-
 void LoggerManagerImpl::setConsoleAppenderLayout(
         log4cplus::SharedAppenderPtr& appender)
 {

+ 5 - 2
src/lib/log/logger_manager_impl.h

@@ -51,8 +51,9 @@ class LoggerManagerImpl {
 public:
 
     /// \brief Constructor
-    LoggerManagerImpl()
-    {}
+    LoggerManagerImpl() {}
+
+    ~LoggerManagerImpl() {}
 
     /// \brief Initialize Processing
     ///
@@ -132,6 +133,8 @@ private:
     static void createSyslogAppender(log4cplus::Logger& logger,
                                      const OutputOption& opt);
 
+    static void createBufferAppender(log4cplus::Logger& logger);
+
     /// \brief Set default layout and severity for root logger
     ///
     /// Initializes the root logger to BIND 10 defaults - console output and

+ 3 - 1
src/lib/python/isc/config/cfgmgr.py

@@ -226,6 +226,8 @@ class ConfigManager:
         if self.log_module_name in config:
             ccsession.default_logconfig_handler(config[self.log_module_name],
                                                 self.log_config_data)
+        else:
+            ccsession.default_logconfig_handler({}, self.log_config_data)
 
     def notify_boss(self):
         """Notifies the Boss module that the Config Manager is running"""
@@ -313,11 +315,11 @@ class ConfigManager:
             self.config = ConfigManagerData.read_from_file(self.data_path,
                                                            self.\
                                                            database_filename)
-            self.check_logging_config(self.config.data);
         except ConfigManagerDataEmpty:
             # ok, just start with an empty config
             self.config = ConfigManagerData(self.data_path,
                                             self.database_filename)
+        self.check_logging_config(self.config.data);
 
     def write_config(self):
         """Write the current configuration to the file specificied at init()"""