Commit 92113f50 authored by Stephen Morris's avatar Stephen Morris
Browse files

[trac976] Ignore log4cplus root logger

Create BIND 10 root logger as child of the (unused) log4cplus
root logger and create other loggers as children of that.  This
simplifies the inclusion of logger name in output messages.
Also, enhance documentation.
parent 7855203e
......@@ -25,26 +25,67 @@
namespace isc {
namespace log {
/// \brief Logging API
///
/// This module forms the interface into the logging subsystem. Features of the
/// system and its implementation are:
///
/// # Multiple logging objects can be created, each given a name; those with the
/// same name share characteristics (like destination, level being logged
/// etc.)
/// # Messages can be logged at severity levels of FATAL, ERROR, WARN, INFO or
/// DEBUG. The DEBUG level has further sub-levels numbered 0 (least
/// informative) to 99 (most informative).
/// # Each logger has a severity level set associated with it. When a message
/// is logged, it is output only if it is logged at a level equal to the
/// logger severity level or greater, e.g. if the logger's severity is WARN,
/// only messages logged at WARN, ERROR or FATAL will be output.
/// # Messages are identified by message identifiers, which are keys into a
/// message dictionary.
/// \page LoggingApi Logging API
/// \section LoggingApiOverview Overview
/// BIND 10 logging uses the concepts of the widely-used Java logging
/// package log4j (http://logging.apache.log/log4j), albeit implemented
/// in C++ using an open-source port. Features of the system are:
///
/// - Within the code objects - known as loggers - can be created and
/// used to log messages. These loggers have names; those with the
/// same name share characteristics (such as output destination).
/// - Loggers have a hierarchical relationship, with each logger being
/// the child of another logger, except for the top of the hierarchy, the
/// root logger. If a logger does not log a message, it is passed to the
/// parent logger.
/// - Messages can be logged at severity levels of FATAL, ERROR, WARN, INFO
/// or DEBUG. The DEBUG level has further sub-levels numbered 0 (least
/// informative) to 99 (most informative).
/// - Each logger has a severity level set associated with it. When a
/// message is logged, it is output only if it is logged at a level equal
/// to the logger severity level or greater, e.g. if the logger's severity
/// is WARN, only messages logged at WARN, ERROR or FATAL will be output.
///
/// \section LoggingApiLoggerNames BIND 10 Logger Names
/// Within BIND 10, the root logger root logger is given the name of the
/// program (via the stand-along function setRootLoggerName()). Other loggers
/// are children of the root logger and are named "<program>.<sublogger>".
/// This name appears in logging output, allowing users to identify both
/// the BIND 10 program and the component within the program that generated
/// the message.
///
/// When creating a logger, the abbreviated name "<sublogger>" can be used;
/// the program name will be prepended to it when the logger is created.
/// In this way, individual libraries can have their own loggers without
/// worrying about the program in which they are used, but:
/// - The origin of the message will be clearly identified.
/// - The same component can have different options (e.g. logging severity)
/// in different programs at the same time.
///
/// \section LoggingApiLoggingMessages Logging Messages
/// Instead of embedding the text of messages within the code, each message
/// is referred to using a symbolic name. The logging code uses this name as
/// a key in a dictionary from which the message text is obtained. Such a
/// system allows for the optional replacement of message text at run time.
/// More details about the message disction (and the compiler used to create
/// the symbol definitions) can be found in other modules in the src/lib/log
/// directory.
class LoggerImpl; // Forward declaration of the implementation class
/// \brief Logger Class
///
/// This class is the main class used for logging. Use comprises:
///
/// 1. Constructing a logger by instantiating it with a specific name. As
/// well as instantiating it when needed, the logger can also be declared
/// outside a program using.
///
/// 2. Using the error(), info() etc. methods to log an error. (Although it is
/// recommended to use the LOG_ERROR, LOG_INFO etc. macros defined in macros.h.
/// These will avoid the potentially-expensive evaluation of arguments if the
/// severity is such that the message will be suppressed.)
class Logger {
public:
......
......@@ -42,26 +42,14 @@ using namespace std;
namespace isc {
namespace log {
// Constructor. Although it may be immediately reset, logger_ is initialized to
// the log4cplus root logger; at least one compiler requires that all member
// variables be constructed before the constructor is run, but log4cplus::Logger
// (the type of logger_) has no default constructor.
LoggerImpl::LoggerImpl(const string& name) :
logger_(log4cplus::Logger::getRoot())
// Constructor. The setting of logger_ must be done when the variable is
// constructed (instead of being left to the body of the function); at least
// one compiler requires that all member variables be constructed before the
// constructor is run, but log4cplus::Logger (the type of logger_) has no
// default constructor.
LoggerImpl::LoggerImpl(const string& name) : name_(expandLoggerName(name)),
logger_(log4cplus::Logger::getInstance(name_))
{
// Are we the root logger, or does the logger name start with
// the string "<root_logger_name>.". If so, use a logger
// whose name is the one given.
if ((name == getRootLoggerName()) ||
(name.find(getRootLoggerName() + string(".")) == 0)) {
name_ = name;
} else {
// Anything else is assumed to be a sub-logger of the
// root logger.
name_ = getRootLoggerName() + "." + name;
}
logger_ = log4cplus::Logger::getInstance(name);
}
// Destructor. (Here because of virtual declaration.)
......
......@@ -50,21 +50,14 @@ namespace log {
/// documentation, but actually unnamed) and all loggers created are subloggers
/// if it.
///
/// In this implementation, the name of the logger is checked. If it is the
/// name of the program (as set in the call to isc::log::setRootLoggerName),
/// the log4cplus root logger is used. Otherwise the name passed is used as
/// the name of a logger when a log4cplus logger is created.
/// In this implementation, the log4cplus root logger is unused. Instead, the
/// BIND 10 root logger is created as a child of the log4cplus root logger,
/// and all other loggers used in the program are created as sub-loggers of
/// that. In this way, the logging system can just include the name of the
/// logger in each message without the need to specially consider if the
/// message is the root logger or not.
///
/// To clarify: if the program is "b10auth" (and that is used to set the BIND 10
/// root logger name via a call to isc::log::setRootLoggerName()), the BIND 10
/// logger "b10auth" corresponds to the log4cplus root logger instance (returned
/// by a call to log4cplus::Logger::getRoot()). The BIND 10 sub-logger "cache"
/// corresponds to the log4cplus logger "cache", created by a call to
/// log4cplus::Logger::getInstance("cache"). The distinction is, however,
/// invisible to users as the logger reported in messages is always
/// "programm.sublogger".
///
/// b) The idea of debug levels is implemented. Seee logger_level.h and
/// b) The idea of debug levels is implemented. See logger_level.h and
/// logger_level_impl.h for more details on this.
class LoggerImpl {
......
......@@ -52,9 +52,8 @@ LoggerManagerImpl::processInit() {
void
LoggerManagerImpl::processSpecification(const LoggerSpecification& spec) {
log4cplus::Logger logger = (spec.getName() == getRootLoggerName()) ?
log4cplus::Logger::getRoot() :
log4cplus::Logger::getInstance(spec.getName());
log4cplus::Logger logger = log4cplus::Logger::getInstance(
expandLoggerName(spec.getName()));
// Set severity level according to specification entry.
logger.setLogLevel(LoggerLevelImpl::convertFromBindLevel(
......@@ -180,14 +179,20 @@ void LoggerManagerImpl::initRootLogger(isc::log::Severity severity,
{
log4cplus::Logger::getDefaultHierarchy().resetConfiguration();
// Set the severity for the root logger
log4cplus::Logger::getRoot().setLogLevel(
LoggerLevelImpl::convertFromBindLevel(Level(severity, dbglevel)));
// Set the log4cplus root to not output anything - effectively we are
// ignoring it.
log4cplus::Logger::getRoot().setLogLevel(log4cplus::OFF_LOG_LEVEL);
// Set the root to use a console logger.
// Set the level for the BIND 10 root logger to the given severity and
// debug level.
log4cplus::Logger b10root = log4cplus::Logger::getInstance(
getRootLoggerName());
b10root.setLogLevel(LoggerLevelImpl::convertFromBindLevel(
Level(severity, dbglevel)));
// Set the BIND 10 root to use a console logger.
OutputOption opt;
log4cplus::Logger root = log4cplus::Logger::getRoot();
createConsoleAppender(root, opt);
createConsoleAppender(b10root, opt);
}
// Set the the "console" layout for the given appenders. This layout includes
......@@ -197,8 +202,7 @@ void LoggerManagerImpl::setConsoleAppenderLayout(
log4cplus::SharedAppenderPtr& appender)
{
// Create the pattern we want for the output - local time.
string pattern = "%D{%Y-%m-%d %H:%M:%S.%q} %-5p [";
pattern += getRootLoggerName() + string(".%c] %m\n");
string pattern = "%D{%Y-%m-%d %H:%M:%S.%q} %-5p [%c] %m\n";
// Finally the text of the message
auto_ptr<log4cplus::Layout> layout(new log4cplus::PatternLayout(pattern));
......@@ -213,7 +217,7 @@ void LoggerManagerImpl::setSysLogAppenderLayout(
log4cplus::SharedAppenderPtr& appender)
{
// Create the pattern we want for the output - local time.
string pattern = "%-5p [" + getRootLoggerName() + string(".%c] %m\n");
string pattern = "%-5p [%c] %m\n";
// Finally the text of the message
auto_ptr<log4cplus::Layout> layout(new log4cplus::PatternLayout(pattern));
......
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