From bbefd6bc4137c3345845d09e86be68b81770718f Mon Sep 17 00:00:00 2001 From: Jelte Jansen Date: Wed, 28 Nov 2012 18:06:31 +0100 Subject: [PATCH] [2445] initial working version needs cleanup and tests --- src/lib/log/logger_impl.cc | 1 + src/lib/log/logger_manager.cc | 1 + src/lib/log/logger_manager.h | 10 ++- src/lib/log/logger_manager_impl.cc | 118 +++++++++++++++++++++++++--- src/lib/log/logger_manager_impl.h | 7 +- src/lib/python/isc/config/cfgmgr.py | 4 +- 6 files changed, 123 insertions(+), 18 deletions(-) diff --git a/src/lib/log/logger_impl.cc b/src/lib/log/logger_impl.cc index 689795d537..1f441b7726 100644 --- a/src/lib/log/logger_impl.cc +++ b/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_; } diff --git a/src/lib/log/logger_manager.cc b/src/lib/log/logger_manager.cc index 8431c2ea53..6f93a4ff94 100644 --- a/src/lib/log/logger_manager.cc +++ b/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(); diff --git a/src/lib/log/logger_manager.h b/src/lib/log/logger_manager.h index 63699c99e4..154b82aafb 100644 --- a/src/lib/log/logger_manager.h +++ b/src/lib/log/logger_manager.h @@ -59,8 +59,14 @@ public: template 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(); } diff --git a/src/lib/log/logger_manager_impl.cc b/src/lib/log/logger_manager_impl.cc index 6357e1feeb..e7506de1ee 100644 --- a/src/lib/log/logger_manager_impl.cc +++ b/src/lib/log/logger_manager_impl.cc @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -30,17 +31,76 @@ #include #include +#include + 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 stored_; + bool flushed_; +}; + +LogBuffer& getLogBuffer() { + static boost::scoped_ptr 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) { diff --git a/src/lib/log/logger_manager_impl.h b/src/lib/log/logger_manager_impl.h index 2bce655bb7..1e58be512d 100644 --- a/src/lib/log/logger_manager_impl.h +++ b/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 diff --git a/src/lib/python/isc/config/cfgmgr.py b/src/lib/python/isc/config/cfgmgr.py index aa0547b25c..1cb0271fa8 100644 --- a/src/lib/python/isc/config/cfgmgr.py +++ b/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()"""