Commit 58ec390c authored by Stephen Morris's avatar Stephen Morris
Browse files

[trac555] Checkpoint

Checkpoint of work at end of 23 May (so that code is copied down to
the BIND 10 server).  Work is in progress on the logger manager
implementation class.
parent 34ebe17e
......@@ -14,6 +14,7 @@ liblog_la_SOURCES += logger_impl.cc logger_impl.h
liblog_la_SOURCES += logger_level.h
liblog_la_SOURCES += logger_level.h
liblog_la_SOURCES += logger_level_impl.cc logger_level_impl.h
liblog_la_SOURCES += logger_manager.cc logger_manager.h
liblog_la_SOURCES += logger_specification.h
liblog_la_SOURCES += logger_support.cc logger_support.h
liblog_la_SOURCES += macros.h
......
// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <log/logger_manager_impl.h>
#include <log/logger_manager.h>
// Constructor - create the implementation class.
LoggerManager::LoggerManager() {
impl_ = new LoggerManagerImpl();
}
// Destructor - get rid of the implementation class
LoggerManager::~LoggerManager() {
delete impl_;
}
// Initialize processing
void
LoggerManager::processInit() {
impl_->processInit();
}
// Process loggging specification
void
LoggerManager::processSpecification(const LoggerSpecification& spec) {
impl_->processSpecification(spec);
}
// End Processing
void
LoggerManager::processEnd() {
impl_->processEnd();
}
// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#ifndef __LOGGER_MANAGER_H
#define __LOGGER_MANAGER_H
#include </log/logger_specification.h>
namespace isc {
namespace log {
class LoggerManagerImpl;
/// \brief Logger Manager
///
/// The logger manager class exists to process the set of logger specifications
/// and use them to set up the logging in the program appropriately.
///
/// To isolate the underlying implementation from basic processing, the
/// LoggerManager is implemented using the "pimpl" idiom.
class LoggerManager {
public:
/// \brief Constructor
LoggerManager();
/// \brief Destructor
~LoggerManager();
/// \brief Process Specifications
///
/// Given a list of logger specifications, disables all current logging
/// and resets the properties of each logger to that given.
///
/// \param start Iterator pointing to the start of the collection of
/// logging specifications.
/// \param finish Iterator pointing to the end of the collection of
/// logging specification.
template <typename T>
void process(T start, T finish) {
processInit();
for (T i = start; i != finish; ++i) {
processSpecification(*i);
}
processEnd();
}
private:
/// \brief Initialize Processing
///
/// Initializes the processing of a list of specifications by resetting all
/// loggers to their defaults. Note that loggers aren't removed as unless
/// a previously-enabled logger is re-enabled, it becomes inactive.
void processInit();
/// \brief Process Logging Specification
///
/// Processes the given specification. It is assumed at this point that
/// either the logger does not exist or has been made inactive.
void processSpecification(const LoggerSpecification& spec);
/// \brief End Processing
///
/// Place holder for finish processing.
/// TODO: Check that the root logger has something enabled
void processEnd();
// Members
LoggerManagerImpl* impl_; ///< Pointer to implementation
};
} // namespace log
} // namespace isc
#endif // __LOGGER_MANAGER_H
// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#ifndef __LOGGER_MANAGER_IMPL_H
#define __LOGGER_MANAGER_IMPL_H
#include <log/logger_specification.h>
namespace isc {
namespace log {
/// \brief Logger Manager Implementation
///
/// This is the implementation of the logger manager for the log4cplus
/// underlying logger.
///
/// As noted in logger_manager.h, the logger manager class exists to set up the
/// logging given a set of specifications. This class handles the processing
/// of those specifications.
class LoggerManagerImpl {
public:
/// \brief Constructor
LoggerManagerImpl()
{}
/// \brief Initialize Processing
///
/// This resets the hierachy of loggers back to their defaults. This means
/// that all non-root loggers (if they exist) are set to NOT_SET, and the
/// root logger reset to logging informational messages.
void processInit();
/// \brief Process Specification
///
/// Processes the specification for a single logger.
///
/// \param spec Logging specification for this logger
void process(const LoggerSpecification& spec);
/// \brief End Processing
///
/// Terminates the processing of the logging specifications.
void processEnd();
};
} // namespace log
} // namespace isc
#endif // __LOGGER_MANAGER_IMPL_H
......@@ -17,6 +17,7 @@ run_unittests_SOURCES = run_unittests.cc
run_unittests_SOURCES += log_formatter_unittest.cc
run_unittests_SOURCES += logger_level_impl_unittest.cc
run_unittests_SOURCES += logger_level_unittest.cc
run_unittests_SOURCES += logger_manager_unittest.cc
run_unittests_SOURCES += logger_unittest.cc
run_unittests_SOURCES += logger_specification_unittest.cc
run_unittests_SOURCES += message_dictionary_unittest.cc
......
// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <stdio.h>
#include <unistd.h>
#include <fstream>
#include <iostream>
#include <string>
#include <gtest/gtest.h>
#include <log/macros.h>
#include <log/messagedef.h>
#include <log/logger.h>
#include <log/logger_level.h>
#include <log/logger_manager.h>
#include <log/logger_specification.h>
#include <log/output_option.h>
using namespace isc::log;
using namespace std;
/// \brief Derived logger
///
/// Only exists to make the protected static methods in Logger public for
/// test purposes.
class DerivedLogger : public isc::log::Logger {
public:
DerivedLogger(std::string name) : isc::log::Logger(name)
{}
virtual ~DerivedLogger()
{}
static void reset() {
isc::log::Logger::reset();
}
};
/// \brief LoggerManager Test
class LoggerManagerTest : public ::testing::Test {
public:
LoggerManagerTest()
{}
~LoggerManagerTest()
{
DerivedLogger::reset();
}
};
// Convenience class to create the specification for the logger "filelogger",
// which, as the name suggests, logs to a file. It remembers the file name and
// deletes the file when instance of the class is destroyed.
class SpecificationForFileLogger {
public:
// Constructor - allocate file and create the specification object
SpecificationForFileLogger() : spec_(), name_(""), logname_("filelogger") {
OutputOption option;
option.destination = OutputOption::DEST_FILE;
name_ = option.filename = std::string(tmpnam(NULL));
spec_.setName(logname_);
spec_.addOutputOption(option);
}
// Destructor, remove the file. This is only a test, so ignore failures
~SpecificationForFileLogger() {
if (! name_.empty()) {
(void) unlink(name_.c_str());
}
}
// Return reference to the logging specification for this loggger
LoggerSpecification& getSpecification() {
return spec_;
}
// Return name of the logger
string getLoggerName() const {
return logname_;
}
// Return name of the file
string getFileName() const {
return name_;
}
private:
LoggerSpecification spec_; // Specification for this file logger
string name_; // Name of the output file
string logname_; // Name of this logger
};
// Convenience function to read an output log file and check that each line
// contains the expected message ID
//
// \param filename Name of the file to check
// \param start Iterator pointing to first expected message ID
// \param finish Iterator pointing to last expected message ID
template <typename T>
void checkFileContents(const std::string& filename, T start, T finish) {
// Access the file for input
ifstream infile(filename.c_str());
if (! infile.good()) {
FAIL() << "Unable to open the logging file " << filename;
}
// Iterate round the expected message IDs and check that they appear in
// the string.
string line; // Line read from the file
T i = start; // Iterator
getline(infile, line);
int lineno = 1;
while ((i != finish) && (infile.good())) {
// Check that the message ID appears in the line.
EXPECT_TRUE(line.find(string(*i)) != string::npos)
<< "Expected to find " << string(*i) << " on line " << lineno
<< " of logging file " << filename;
// Go for the next line
++i;
getline(infile, line);
++lineno;
}
// Why did the loop end?
EXPECT_TRUE(i == finish) << "Did not reach the end of the message ID list";
EXPECT_TRUE(infile.eof()) << "Did not reach the end of the logging file";
// File will close when the instream is deleted at the end of this
// function.
}
// Check that the logger correctly creates something logging to a file.
TEST_F(LoggerManagerTest, FileLogger) {
// Create a specification for the file logger and use the manager to
// connect the "filelogger" logger to it.
SpecificationForFileLogger file_spec;
vector<LoggerSpecification> specVector(1, file_spec.getSpecification());
LoggerManager manager;
manager.process(specVector.begin(), specVector.end());
// Try logging to the file. Local scope is set to ensure that the logger
// is destroyed before we reset the global logging. We record what we
// put in the file for a later comparison.
vector<MessageID> ids;
{
Logger logger(file_spec.getLoggerName());
LOG_FATAL(logger, MSG_DUPMSGID).arg("test");
ids.push_back(MSG_DUPMSGID);
LOG_FATAL(logger, MSG_DUPLNS).arg("test");
ids.push_back(MSG_DUPLNS);
}
DerivedLogger::reset();
// At this point, the output file should contain two lines with messages
// LOGTEST_TEST1 and LOGTEST_TEST2 messages - test this.
checkFileContents(file_spec.getFileName(), ids.begin(), ids.end());
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment