mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-31 14:05:33 +00:00
[#2537] add inheritance of output_options
Unlike severity and debug level that have inheritance support embedded in log4cplus, output_options do not. This commit adds support for this inheritance by storing a copy of the root logger's specification and using it on child loggers if they don't have a specification themselves.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2011-2021 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2011-2022 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
@@ -62,8 +62,10 @@ LoggerManagerImpl::processEnd() {
|
||||
// add output specifications.
|
||||
void
|
||||
LoggerManagerImpl::processSpecification(const LoggerSpecification& spec) {
|
||||
log4cplus::Logger logger = log4cplus::Logger::getInstance(
|
||||
expandLoggerName(spec.getName()));
|
||||
string const& name(spec.getName());
|
||||
string const& root_logger_name(getRootLoggerName());
|
||||
|
||||
log4cplus::Logger logger = log4cplus::Logger::getInstance(expandLoggerName(name));
|
||||
|
||||
// Set severity level according to specification entry.
|
||||
logger.setLogLevel(LoggerLevelImpl::convertFromBindLevel(
|
||||
@@ -72,36 +74,48 @@ LoggerManagerImpl::processSpecification(const LoggerSpecification& spec) {
|
||||
// Set the additive flag.
|
||||
logger.setAdditivity(spec.getAdditive());
|
||||
|
||||
// Replace all appenders for this logger.
|
||||
logger.removeAllAppenders();
|
||||
|
||||
if (name == root_logger_name) {
|
||||
// Store a copy of the root specification. It might be required later.
|
||||
root_spec_ = spec;
|
||||
}
|
||||
|
||||
// Output options given?
|
||||
if (spec.optionCount() > 0) {
|
||||
// Replace all appenders for this logger.
|
||||
logger.removeAllAppenders();
|
||||
// If there are output options provided, continue with the given spec.
|
||||
appenderFactory(logger, spec);
|
||||
} else {
|
||||
// If there are no output options, inherit them from the root logger.
|
||||
appenderFactory(logger, root_spec_);
|
||||
}
|
||||
}
|
||||
|
||||
// Now process output specifications.
|
||||
for (LoggerSpecification::const_iterator i = spec.begin();
|
||||
i != spec.end(); ++i) {
|
||||
switch (i->destination) {
|
||||
case OutputOption::DEST_CONSOLE:
|
||||
createConsoleAppender(logger, *i);
|
||||
break;
|
||||
void
|
||||
LoggerManagerImpl::appenderFactory(log4cplus::Logger& logger,
|
||||
LoggerSpecification const& spec) {
|
||||
for (OutputOption const& i : spec) {
|
||||
switch (i.destination) {
|
||||
case OutputOption::DEST_CONSOLE:
|
||||
createConsoleAppender(logger, i);
|
||||
break;
|
||||
|
||||
case OutputOption::DEST_FILE:
|
||||
createFileAppender(logger, *i);
|
||||
break;
|
||||
case OutputOption::DEST_FILE:
|
||||
createFileAppender(logger, i);
|
||||
break;
|
||||
|
||||
case OutputOption::DEST_SYSLOG:
|
||||
createSyslogAppender(logger, *i);
|
||||
break;
|
||||
case OutputOption::DEST_SYSLOG:
|
||||
createSyslogAppender(logger, i);
|
||||
break;
|
||||
|
||||
default:
|
||||
// Not a valid destination. As we are in the middle of updating
|
||||
// logging destinations, we could be in the situation where
|
||||
// there are no valid appenders. For this reason, throw an
|
||||
// exception.
|
||||
isc_throw(UnknownLoggingDestination,
|
||||
"Unknown logging destination, code = " <<
|
||||
i->destination);
|
||||
}
|
||||
default:
|
||||
// Not a valid destination. As we are in the middle of updating
|
||||
// logging destinations, we could be in the situation where
|
||||
// there are no valid appenders. For this reason, throw an
|
||||
// exception.
|
||||
isc_throw(UnknownLoggingDestination,
|
||||
"Unknown logging destination, code = " << i.destination);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2011-2019 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2011-2022 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <log4cplus/appender.h>
|
||||
#include <log/logger_level.h>
|
||||
#include <log/logger_specification.h>
|
||||
|
||||
// Forward declaration to avoid need to include log4cplus header file here.
|
||||
namespace log4cplus {
|
||||
@@ -22,7 +23,6 @@ namespace isc {
|
||||
namespace log {
|
||||
|
||||
// Forward declarations
|
||||
class LoggerSpecification;
|
||||
struct OutputOption;
|
||||
|
||||
/// \brief Logger Manager Implementation
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
/// Processes the specification for a single logger.
|
||||
///
|
||||
/// \param spec Logging specification for this logger
|
||||
static void processSpecification(const LoggerSpecification& spec);
|
||||
void processSpecification(const LoggerSpecification& spec);
|
||||
|
||||
/// \brief End Processing
|
||||
///
|
||||
@@ -94,6 +94,16 @@ public:
|
||||
int dbglevel = 0);
|
||||
|
||||
private:
|
||||
/// @brief Decides what appender to create.
|
||||
///
|
||||
/// Delegates to the other functions that create appenders based on what's
|
||||
/// in spec.
|
||||
///
|
||||
/// @param logger log4cplus logger to which the appender must be attached
|
||||
/// @param spec the configured specification consisting of output options
|
||||
static void appenderFactory(log4cplus::Logger& logger,
|
||||
LoggerSpecification const& spec);
|
||||
|
||||
/// \brief Create console appender
|
||||
///
|
||||
/// Creates an object that, when attached to a logger, will log to one
|
||||
@@ -171,10 +181,14 @@ private:
|
||||
/// \c storeBufferAppenders(), and clears it
|
||||
void flushBufferAppenders();
|
||||
|
||||
/// Only used between processInit() and processEnd(), to temporarily
|
||||
/// @brief Only used between processInit() and processEnd(), to temporarily
|
||||
/// store the buffer appenders in order to flush them after
|
||||
/// processSpecification() calls have been completed
|
||||
std::vector<log4cplus::SharedAppenderPtr> buffer_appender_store_;
|
||||
|
||||
/// @brief A hard copy of the specification for the root logger used for
|
||||
/// inheritance by child loggers.
|
||||
LoggerSpecification root_spec_;
|
||||
};
|
||||
|
||||
} // namespace log
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2011-2021 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2011-2022 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <log/logger.h>
|
||||
#include <log/logger_level.h>
|
||||
#include <log/logger_manager.h>
|
||||
#include <log/logger_name.h>
|
||||
#include <log/logger_specification.h>
|
||||
#include <log/message_initializer.h>
|
||||
#include <log/output_option.h>
|
||||
@@ -444,3 +445,67 @@ TEST_F(LoggerManagerTest, logDuplicatedMessages) {
|
||||
LoggerManager::logDuplicatedMessages();
|
||||
ASSERT_EQ(0, MessageInitializer::getDuplicates().size());
|
||||
}
|
||||
|
||||
// Check that output options can be inherited.
|
||||
TEST_F(LoggerManagerTest, outputOptionsInheritance) {
|
||||
LoggerManager manager;
|
||||
SpecificationForFileLogger file_spec;
|
||||
vector<LoggerSpecification> specs;
|
||||
|
||||
// Create the root logger configuration with a file output option.
|
||||
string root_name(getRootLoggerName());
|
||||
LoggerSpecification root_spec(root_name);
|
||||
OutputOption root_option;
|
||||
root_option.destination = OutputOption::DEST_FILE;
|
||||
root_option.filename = file_spec.getFileName();
|
||||
root_option.pattern = "%p %m\n";
|
||||
root_spec.addOutputOption(root_option);
|
||||
specs.push_back(root_spec);
|
||||
|
||||
// Create a child logger configuration without any output options.
|
||||
// It should inherit the output option from the root logger.
|
||||
string foo_name(root_name + ".foo");
|
||||
LoggerSpecification foo_spec(foo_name);
|
||||
specs.push_back(foo_spec);
|
||||
|
||||
// Create another child logger configuration with a console output option.
|
||||
string bar_name(root_name + ".bar");
|
||||
LoggerSpecification bar_spec(bar_name);
|
||||
OutputOption bar_option;
|
||||
bar_option.destination = OutputOption::DEST_CONSOLE;
|
||||
bar_option.pattern = "%p %m\n";
|
||||
bar_spec.addOutputOption(bar_option);
|
||||
specs.push_back(bar_spec);
|
||||
|
||||
// Check the number of output options for each specification.
|
||||
EXPECT_EQ(root_spec.optionCount(), 1);
|
||||
EXPECT_EQ(foo_spec.optionCount(), 0);
|
||||
EXPECT_EQ(bar_spec.optionCount(), 1);
|
||||
|
||||
// Process all the specifications.
|
||||
manager.process(specs.begin(), specs.end());
|
||||
|
||||
// Log two messages each.
|
||||
Logger root_logger(root_name.c_str());
|
||||
Logger foo_logger(foo_name.c_str());
|
||||
Logger bar_logger(bar_name.c_str());
|
||||
LOG_INFO(root_logger, "from root logger 1");
|
||||
LOG_INFO(foo_logger, "from foo logger 1");
|
||||
LOG_INFO(bar_logger, "from bar logger 1");
|
||||
LOG_INFO(root_logger, "from root logger 2");
|
||||
LOG_INFO(foo_logger, "from foo logger 2");
|
||||
LOG_INFO(bar_logger, "from bar logger 2");
|
||||
|
||||
// Check that root and foo were logged to file and that bar which
|
||||
// had an explicit console configuration did not.
|
||||
std::ifstream ifs(file_spec.getFileName());
|
||||
std::stringstream s;
|
||||
s << ifs.rdbuf();
|
||||
std::string const result(s.str());
|
||||
EXPECT_NE(result.find("INFO from root logger 1"), string::npos);
|
||||
EXPECT_NE(result.find("INFO from foo logger 1"), string::npos);
|
||||
EXPECT_EQ(result.find("INFO from bar logger 1"), string::npos);
|
||||
EXPECT_NE(result.find("INFO from root logger 2"), string::npos);
|
||||
EXPECT_NE(result.find("INFO from foo logger 2"), string::npos);
|
||||
EXPECT_EQ(result.find("INFO from bar logger 2"), string::npos);
|
||||
}
|
||||
|
Reference in New Issue
Block a user