2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-31 05:55:28 +00:00

[3427] Changes after review:

- Kea ARM updated
 - shell tests for Kea4,Kea6 and D2 are now passing
 - kea.conf updated with logging info
 - Various improvements in Daemon and LogConfigParser
 - DEFAULT_SYSLOG_NAME removed
 - Copyright years fixed
 - Couple additional tests written
This commit is contained in:
Tomek Mrugalski
2014-07-18 21:11:42 +02:00
parent 9c707375d2
commit d26a494520
28 changed files with 413 additions and 138 deletions

View File

@@ -55,13 +55,14 @@
<title>name (string)</title> <title>name (string)</title>
<para> <para>
Each logger in the system has a name, the name being that Each logger in the system has a name, the name being that
of the component using it to log messages. For instance, of the component using it to log messages. For instance,
if you want to configure logging for the Dhcp4 module, if you want to configure logging for the Dhcp4 module,
you add an entry for a logger named <quote>Dhcp4</quote>. This you add an entry for a logger named <quote>Dhcp4</quote>. This
configuration will then be used by the loggers in the configuration will then be used by the loggers in the
Dhcp4 module, and all the libraries used by it. Dhcp4 module, and all the libraries used by it (unless
</para> a library defines its own logger).
</para>
<!-- TODO: later we will have a way to know names of all modules <!-- TODO: later we will have a way to know names of all modules
@@ -78,7 +79,6 @@ Right now you can only see what their names are if they are running
has the full name of <quote>Dhcp4.dhcpsrv</quote>. If has the full name of <quote>Dhcp4.dhcpsrv</quote>. If
there is no entry in Logging for a particular library, there is no entry in Logging for a particular library,
it will use the configuration given for the module. it will use the configuration given for the module.
</para> </para>
<para> <para>
@@ -138,6 +138,24 @@ Right now you can only see what their names are if they are running
</para> </para>
<para>
Currently defined loggers are:
</para>
<itemizedlist>
<listitem>
<simpara>kea.dhcp4</simpara>
</listitem>
<listitem>
<simpara>kea.dhcp6</simpara>
</listitem>
<listitem>
<simpara>kea-dhcp-ddns.dhcpddns</simpara>
</listitem>
<listitem>
<simpara>kea.dhcpsrv</simpara>
</listitem>
</itemizedlist>
</section> </section>
<section> <section>

View File

@@ -224,21 +224,9 @@ DControllerBase::configFromFile() {
// Temporary storage for logging configuration // Temporary storage for logging configuration
isc::dhcp::ConfigurationPtr storage(new isc::dhcp::Configuration()); isc::dhcp::ConfigurationPtr storage(new isc::dhcp::Configuration());
// Get 'Logging' element from the config // Get 'Logging' element from the config and use it to set up
isc::data::ConstElementPtr logger = whole_config->get("Logging"); // logging. If there's no such element, we'll just pass NULL.
if (logger) { Daemon::configureLogger(whole_config->get("Logging"), storage, verbose_);
// Configure logger first, so it can be applied to DHCPv6
// configuration. If we don't have a logger, just pass
// empty configuration.
Daemon::configureLogger(logger, storage);
} else {
// There was no Logging element defined in the config file.
// Let's pass an empty pointer that will remove any current
// configuration.
Daemon::configureLogger(isc::data::ConstElementPtr(),
storage);
}
// Extract derivation-specific portion of the configuration. // Extract derivation-specific portion of the configuration.
module_config = whole_config->get(getAppName()); module_config = whole_config->get(getAppName());

View File

@@ -25,6 +25,20 @@ CONFIG="{
\"tsig_keys\": [], \"tsig_keys\": [],
\"forward_ddns\" : {}, \"forward_ddns\" : {},
\"reverse_ddns\" : {} \"reverse_ddns\" : {}
},
\"Logging\":
{
\"loggers\": [
{
\"name\": \"kea-dhcp-ddns\",
\"output_options\": [
{
\"output\": \"$LOG_FILE\"
}
],
\"severity\": \"DEBUG\"
}
]
} }
}" }"
@@ -38,6 +52,20 @@ CONFIG_INVALID="{
\"tsig_keys\": [], \"tsig_keys\": [],
\"forward_ddns\" : {}, \"forward_ddns\" : {},
\"reverse_ddns\" : {} \"reverse_ddns\" : {}
},
\"Logging\":
{
\"loggers\": [
{
\"name\": \"kea-dhcp-ddns\",
\"output_options\": [
{
\"output\": \"$LOG_FILE\"
}
],
\"severity\": \"INFO\"
}
]
} }
}" }"

View File

@@ -66,20 +66,12 @@ void configure(const std::string& file_name) {
// Let's configure logging before applying the configuration, // Let's configure logging before applying the configuration,
// so we can log things during configuration process. // so we can log things during configuration process.
logger = json->get("Logging");
if (logger) {
// Configure logger first, so it can be applied to DHCPv6
// configuration. If we don't have a logger, just pass
// empty configuration.
Daemon::configureLogger(logger, CfgMgr::instance().getConfiguration()); // If there's no logging element, we'll just pass NULL pointer,
} else { // which will be handled by configureLogger().
// There was no Logging element defined in the config file. Daemon::configureLogger(json->get("Logging"),
// Let's pass an empty pointer that will remove any current CfgMgr::instance().getConfiguration(),
// configuration. ControlledDhcpv4Srv::getInstance()->getVerbose());
Daemon::configureLogger(isc::data::ConstElementPtr(),
CfgMgr::instance().getConfiguration());
}
// Get Dhcp4 component from the config // Get Dhcp4 component from the config
dhcp4 = json->get("Dhcp4"); dhcp4 = json->get("Dhcp4");

View File

@@ -111,6 +111,9 @@ main(int argc, char* argv[]) {
// Create the server instance. // Create the server instance.
ControlledDhcpv4Srv server(port_number); ControlledDhcpv4Srv server(port_number);
// Remember verbose-mode
server.setVerbose(verbose_mode);
try { try {
// Initialize the server. // Initialize the server.
server.init(config_file); server.init(config_file);

View File

@@ -34,6 +34,21 @@ CONFIG="{
\"subnet\": \"10.0.0.0/8\", \"subnet\": \"10.0.0.0/8\",
\"pool\": [ \"10.0.0.10-10.0.0.100\" ] \"pool\": [ \"10.0.0.10-10.0.0.100\" ]
} ] } ]
},
\"Logging\":
{
\"loggers\": [
{
\"name\": \"kea\",
\"output_options\": [
{
\"output\": \"$LOG_FILE\"
}
],
\"severity\": \"INFO\"
}
]
} }
}" }"
# Invalid configuration (negative valid-lifetime) to check that Kea # Invalid configuration (negative valid-lifetime) to check that Kea
@@ -55,6 +70,21 @@ CONFIG_INVALID="{
\"subnet\": \"10.0.0.0/8\", \"subnet\": \"10.0.0.0/8\",
\"pool\": [ \"10.0.0.10-10.0.0.100\" ] \"pool\": [ \"10.0.0.10-10.0.0.100\" ]
} ] } ]
},
\"Logging\":
{
\"loggers\": [
{
\"name\": \"kea\",
\"output_options\": [
{
\"output\": \"$LOG_FILE\"
}
],
\"severity\": \"INFO\"
}
]
} }
}" }"

View File

@@ -70,19 +70,11 @@ void configure(const std::string& file_name) {
// Let's configure logging before applying the configuration, // Let's configure logging before applying the configuration,
// so we can log things during configuration process. // so we can log things during configuration process.
logger = json->get("Logging"); // If there's no logging element, we'll just pass NULL pointer,
if (logger) { // which will be handled by configureLogger().
// Configure logger first, so it can be applied to DHCPv6 Daemon::configureLogger(json->get("Logging"),
// configuration. If we don't have a logger, just pass CfgMgr::instance().getConfiguration(),
// empty configuration. ControlledDhcpv6Srv::getInstance()->getVerbose());
Daemon::configureLogger(logger, CfgMgr::instance().getConfiguration());
} else {
// There was no Logging element defined in the config file.
// Let's pass an empty pointer that will remove any current
// configuration.
Daemon::configureLogger(isc::data::ConstElementPtr(),
CfgMgr::instance().getConfiguration());
}
// Get Dhcp6 component from the config // Get Dhcp6 component from the config
dhcp6 = json->get("Dhcp6"); dhcp6 = json->get("Dhcp6");

View File

@@ -111,6 +111,9 @@ main(int argc, char* argv[]) {
// Create the server instance. // Create the server instance.
ControlledDhcpv6Srv server(port_number); ControlledDhcpv6Srv server(port_number);
// Remember verbose-mode
server.setVerbose(verbose_mode);
try { try {
// Initialize the server, i.e. establish control session // Initialize the server, i.e. establish control session
// if BIND10 backend is used or read a configuration file // if BIND10 backend is used or read a configuration file

View File

@@ -35,6 +35,21 @@ CONFIG="{
\"subnet\": \"2001:db8:1::/64\", \"subnet\": \"2001:db8:1::/64\",
\"pool\": [ \"2001:db8:1::10-2001:db8:1::100\" ] \"pool\": [ \"2001:db8:1::10-2001:db8:1::100\" ]
} ] } ]
},
\"Logging\":
{
\"loggers\": [
{
\"name\": \"kea\",
\"output_options\": [
{
\"output\": \"$LOG_FILE\"
}
],
\"severity\": \"INFO\"
}
]
} }
}" }"
# Invalid configuration (negative preferred-lifetime) to check that Kea # Invalid configuration (negative preferred-lifetime) to check that Kea
@@ -57,6 +72,21 @@ CONFIG_INVALID="{
\"subnet\": \"2001:db8:1::/64\", \"subnet\": \"2001:db8:1::/64\",
\"pool\": [ \"2001:db8:1::10-2001:db8:1::100\" ] \"pool\": [ \"2001:db8:1::10-2001:db8:1::100\" ]
} ] } ]
},
\"Logging\":
{
\"loggers\": [
{
\"name\": \"kea\",
\"output_options\": [
{
\"output\": \"$LOG_FILE\"
}
],
\"severity\": \"INFO\"
}
]
} }
}" }"

View File

@@ -65,6 +65,25 @@
"tsig_keys": [], "tsig_keys": [],
"forward_ddns" : {}, "forward_ddns" : {},
"reverse_ddns" : {} "reverse_ddns" : {}
},
# Logging configuration starts here. It tells Kea servers to store
# all log messages (on severity INFO or more) in a file.
# debuglevel variable is used on DEBUG level only.
"Logging":
{
"loggers": [
{
"name": "kea",
"output_options": [
{
"output": "@localstatedir@/log/kea.log"
}
],
"severity": "INFO",
"debuglevel": 0
}
]
} }
} }

View File

@@ -12,8 +12,8 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE. // PERFORMANCE OF THIS SOFTWARE.
#ifndef DHCPSRV_CONFIG_H #ifndef DHCPSRV_CONFIGURATION_H
#define DHCPSRV_CONFIG_H #define DHCPSRV_CONFIGURATION_H
#include <log/logger_level.h> #include <log/logger_level.h>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
@@ -23,7 +23,6 @@
namespace isc { namespace isc {
namespace dhcp { namespace dhcp {
/// @brief Defines single logging destination /// @brief Defines single logging destination
/// ///
/// This structure is used to keep log4cplus configuration parameters. /// This structure is used to keep log4cplus configuration parameters.
@@ -93,4 +92,4 @@ typedef boost::shared_ptr<Configuration> ConfigurationPtr;
} // namespace isc::dhcp } // namespace isc::dhcp
} // namespace isc } // namespace isc
#endif #endif // DHCPSRV_CONFIGURATION_H

View File

@@ -31,7 +31,7 @@ namespace dhcp {
std::string Daemon::config_file_ = ""; std::string Daemon::config_file_ = "";
Daemon::Daemon() Daemon::Daemon()
: signal_set_(), signal_handler_() { : signal_set_(), signal_handler_(), verbose_(false) {
} }
Daemon::~Daemon() { Daemon::~Daemon() {
@@ -55,8 +55,9 @@ void Daemon::handleSignal() {
} }
} }
void Daemon::configureLogger(isc::data::ConstElementPtr log_config, void Daemon::configureLogger(const isc::data::ConstElementPtr& log_config,
const ConfigurationPtr& storage) { const ConfigurationPtr& storage,
bool verbose) {
// This is utility class that translates JSON structures into formats // This is utility class that translates JSON structures into formats
// understandable by log4cplus. // understandable by log4cplus.
@@ -66,7 +67,7 @@ void Daemon::configureLogger(isc::data::ConstElementPtr log_config,
// There was no logger configuration. Let's clear any config // There was no logger configuration. Let's clear any config
// and revert to the default. // and revert to the default.
parser.defaultLogging(); // Set up default logging parser.applyDefaultConfiguration(verbose); // Set up default logging
return; return;
} }
@@ -77,12 +78,12 @@ void Daemon::configureLogger(isc::data::ConstElementPtr log_config,
// array in it. Let's clear any old logging configuration // array in it. Let's clear any old logging configuration
// we may have and revert to the default. // we may have and revert to the default.
parser.defaultLogging(); // Set up default logging parser.applyDefaultConfiguration(verbose); // Set up default logging
return; return;
} }
// Translate JSON structures into log4cplus formats // Translate JSON structures into log4cplus formats
parser.parseConfiguration(loggers); parser.parseConfiguration(loggers, verbose);
// Apply the configuration // Apply the configuration

View File

@@ -128,8 +128,26 @@ public:
/// ///
/// @param log_config JSON structures that describe logging /// @param log_config JSON structures that describe logging
/// @param storage configuration will be stored here /// @param storage configuration will be stored here
static void configureLogger(isc::data::ConstElementPtr log_config, /// @param verbose specifies if verbose mode should be enabled
const isc::dhcp::ConfigurationPtr& storage); static void configureLogger(const isc::data::ConstElementPtr& log_config,
const isc::dhcp::ConfigurationPtr& storage,
bool verbose);
/// @brief Sets or clears verbose mode
///
/// Verbose mode (-v in command-line) triggers loggers to log everythin
/// (sets severity to DEBUG and debuglevel to 99). Values specified in the
/// config file are ignored.
void setVerbose(bool verbose) {
verbose_ = verbose;
}
/// @brief Returns if running in verbose mode
///
/// @return verbose mode
bool getVerbose() {
return (verbose_);
}
protected: protected:
@@ -163,6 +181,9 @@ private:
/// @brief Config file name or empty if config file not used. /// @brief Config file name or empty if config file not used.
static std::string config_file_; static std::string config_file_;
/// @brief Verbose mode
bool verbose_;
}; };
}; // end of isc::dhcp namespace }; // end of isc::dhcp namespace

View File

@@ -18,6 +18,7 @@
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <log/logger_specification.h> #include <log/logger_specification.h>
#include <log/logger_manager.h> #include <log/logger_manager.h>
#include <log/logger_name.h>
using namespace isc::data; using namespace isc::data;
using namespace isc::log; using namespace isc::log;
@@ -25,17 +26,17 @@ using namespace isc::log;
namespace isc { namespace isc {
namespace dhcp { namespace dhcp {
static const char* DEFAULT_SYSLOG_NAME = "kea";
LogConfigParser::LogConfigParser(const ConfigurationPtr& storage) LogConfigParser::LogConfigParser(const ConfigurationPtr& storage)
:config_(storage) { :config_(storage), verbose_(false) {
if (!storage) { if (!storage) {
isc_throw(InvalidOperation, "LogConfigParser needs a pointer to the " isc_throw(BadValue, "LogConfigParser needs a pointer to the "
"configuration, so parsed data can be stored there"); "configuration, so parsed data can be stored there");
} }
} }
void LogConfigParser::parseConfiguration(isc::data::ConstElementPtr loggers) { void LogConfigParser::parseConfiguration(isc::data::ConstElementPtr loggers,
bool verbose) {
verbose_ = verbose;
// Iterate over all entries in "Logging/loggers" list // Iterate over all entries in "Logging/loggers" list
BOOST_FOREACH(ConstElementPtr logger, loggers->listValue()) { BOOST_FOREACH(ConstElementPtr logger, loggers->listValue()) {
@@ -72,9 +73,9 @@ void LogConfigParser::parseConfigEntry(isc::data::ConstElementPtr entry) {
try { try {
info.severity_ = isc::log::getSeverity(severity_ptr->stringValue().c_str()); info.severity_ = isc::log::getSeverity(severity_ptr->stringValue().c_str());
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
isc_throw(BadValue, "Unable to convert '" << severity_ptr->stringValue() isc_throw(BadValue, "Unsupported severity value '"
<< "' into allowed severity (" << severity_ptr->getPosition() << severity_ptr->stringValue() << "' ("
<< ")"); << severity_ptr->getPosition() << ")");
} }
// Get debug logging level // Get debug logging level
@@ -91,12 +92,21 @@ void LogConfigParser::parseConfigEntry(isc::data::ConstElementPtr entry) {
isc_throw(BadValue, ""); isc_throw(BadValue, "");
} }
} catch (...) { } catch (...) {
isc_throw(BadValue, "Unable to convert '" << debuglevel_ptr->stringValue() isc_throw(BadValue, "Unsupported debuglevel value '"
<< "' into allowed debuglevel range (0-99) (" << debuglevel_ptr->stringValue()
<< "', expected 0-99 ("
<< debuglevel_ptr->getPosition() << ")"); << debuglevel_ptr->getPosition() << ")");
} }
} }
// We want to follow the normal path, so it could catch parsing errors even
// when verbose mode is enabled. If it is, just override whatever was parsed
// in the config file.
if (verbose_) {
info.severity_ = isc::log::DEBUG;
info.debuglevel_ = 99;
}
isc::data::ConstElementPtr output_options = entry->get("output_options"); isc::data::ConstElementPtr output_options = entry->get("output_options");
if (output_options) { if (output_options) {
@@ -138,8 +148,6 @@ void LogConfigParser::parseOutputOptions(std::vector<LoggingDestination>& destin
void LogConfigParser::applyConfiguration() { void LogConfigParser::applyConfiguration() {
// Constants: not declared static as this is function is expected to be
// called once only
static const std::string STDOUT = "stdout"; static const std::string STDOUT = "stdout";
static const std::string STDERR = "stderr"; static const std::string STDERR = "stderr";
static const std::string SYSLOG = "syslog"; static const std::string SYSLOG = "syslog";
@@ -180,8 +188,8 @@ void LogConfigParser::applyConfiguration() {
// Must take account of the string actually being "syslog:" // Must take account of the string actually being "syslog:"
if (dest->output_ == SYSLOG_COLON) { if (dest->output_ == SYSLOG_COLON) {
// The expected syntax is syslog:facility. User skipped // The expected syntax is syslog:facility. User skipped
// the logging name, so we'll just use DEFAULT_SYSLOG_NAME. // the logging name, so we'll just use the default ("kea")
option.facility = DEFAULT_SYSLOG_NAME; option.facility = isc::log::getDefaultRootLoggerName();
} else { } else {
// Everything else in the string is the facility name // Everything else in the string is the facility name
@@ -203,8 +211,9 @@ void LogConfigParser::applyConfiguration() {
} }
} }
void LogConfigParser::defaultLogging() { void LogConfigParser::applyDefaultConfiguration(bool verbose) {
LoggerSpecification spec("kea", isc::log::INFO, 0); LoggerSpecification spec("kea", (verbose?isc::log::DEBUG : isc::log::INFO),
(verbose?99:0));
OutputOption option; OutputOption option;
option.destination = OutputOption::DEST_CONSOLE; option.destination = OutputOption::DEST_CONSOLE;

View File

@@ -17,18 +17,34 @@
#include <cc/data.h> #include <cc/data.h>
#include <dhcpsrv/configuration.h> #include <dhcpsrv/configuration.h>
#include <dhcpsrv/cfgmgr.h>
#include <stdint.h>
#include <vector> #include <vector>
namespace isc { namespace isc {
namespace dhcp { namespace dhcp {
/// @brief Interprets JSON structures and translates them to log4cplus /// @brief Configures log4cplus by translating Kea configuration structures
/// ///
/// This parser iterates over provided JSON structures and translates them /// This parser iterates over provided data elements and translates them
/// into values applicable to log4cplus. /// into values applicable to log4cplus.
/// ///
/// The data structures converted to JSON format have the following syntax:
/// {
/// "name": "kea",
/// "output_options": [
/// {
/// "output": "/home/thomson/kea-inst/kea-warn.log",
/// "maxver": 8,
/// "maxsize": 204800
/// }
/// ],
/// "severity": "WARN"
/// }
///
/// This is only an example and actual values may be different.
///
/// The data structures don't have to originate from JSON. JSON is just a
/// convenient presentation syntax.
///
/// This class uses Configuration structure to store logging configuration. /// This class uses Configuration structure to store logging configuration.
class LogConfigParser { class LogConfigParser {
public: public:
@@ -44,37 +60,39 @@ public:
/// parsed information in config_->logging_info_. /// parsed information in config_->logging_info_.
/// ///
/// @param log_config JSON structures to be parsed (loggers list) /// @param log_config JSON structures to be parsed (loggers list)
void parseConfiguration(isc::data::ConstElementPtr log_config); /// @param verbose specifies verbose mode (true forces DEBUG, debuglevel = 99)
void parseConfiguration(isc::data::ConstElementPtr log_config,
bool verbose = false);
/// @brief Applies stored configuration /// @brief Applies stored configuration
void applyConfiguration(); void applyConfiguration();
/// @brief Configures default logging /// @brief Configures default logging
static void defaultLogging(); ///
/// This method is static,
///
/// @param verbose specifies verbose mode (true forces DEBUG, debuglevel = 99)
void applyDefaultConfiguration(bool verbose = false);
protected: private:
/// @brief Parses one JSON structure in Logging/loggers" array /// @brief Parses one JSON structure in Logging/loggers" array
/// ///
/// The structure has the following syntax:
/// {
/// "name": "*",
/// "output_options": [
/// {
/// "output": "/home/thomson/kea-inst/kea-warn.log",
/// "maxver": 8,
/// "maxsize": 204800
/// }
/// ],
/// "severity": "WARN"
/// }
///
/// @param entry JSON structure to be parsed /// @param entry JSON structure to be parsed
/// @brief parses one structure in Logging/loggers. /// @brief parses one structure in Logging/loggers.
void parseConfigEntry(isc::data::ConstElementPtr entry); void parseConfigEntry(isc::data::ConstElementPtr entry);
/// @brief Parses output_options structure /// @brief Parses output_options structure
/// ///
/// An example data structure that holds output_options in JSON format
/// looks like this:
/// "output_options": [
/// {
/// "output": "/var/log/kea-warn.log",
/// "maxver": 8,
/// "maxsize": 204800
/// }
/// ],
/// @param destination parsed parameters will be stored here /// @param destination parsed parameters will be stored here
/// @param output_options element to be parsed /// @param output_options element to be parsed
void parseOutputOptions(std::vector<LoggingDestination>& destination, void parseOutputOptions(std::vector<LoggingDestination>& destination,
@@ -84,9 +102,15 @@ protected:
/// ///
/// LogConfigParser class uses only config_->logging_info_ field. /// LogConfigParser class uses only config_->logging_info_ field.
ConfigurationPtr config_; ConfigurationPtr config_;
/// @brief Verbose mode
///
/// When verbose mode is enabled, logging severity is overridden to DEBUG,
/// and debuglevel is always 99.
bool verbose_;
}; };
} // namespace isc::dhcp } // namespace isc::dhcp
} // namespace isc } // namespace isc
#endif // CFGMGR_H #endif // DHCPSRV_LOGGING_H

View File

@@ -778,4 +778,4 @@ typedef std::vector<Subnet6Ptr> Subnet6Collection;
} // end of isc::dhcp namespace } // end of isc::dhcp namespace
} // end of isc namespace } // end of isc namespace
#endif // SUBNET_T #endif // SUBNET_H

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2012-2014 Internet Systems Consortium, Inc. ("ISC") // Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
// //
// Permission to use, copy, modify, and/or distribute this software for any // Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above // purpose with or without fee is hereby granted, provided that the above

View File

@@ -25,9 +25,14 @@ using namespace isc::data;
namespace { namespace {
// Very simple test. Checks whether Daemon can be instantiated. // Very simple test. Checks whether Daemon can be instantiated and its
// default parameters are sane
TEST(DaemonTest, noop) { TEST(DaemonTest, noop) {
EXPECT_NO_THROW(Daemon x); EXPECT_NO_THROW(Daemon x);
// Check that the verbose mode is not set by default.
Daemon y;
EXPECT_FALSE(y.getVerbose());
} }
// Checks that configureLogger method is behaving properly. // Checks that configureLogger method is behaving properly.
@@ -55,7 +60,7 @@ TEST(DaemonTest, parsingConsoleOutput) {
// Spawn a daemon and tell it to configure logger // Spawn a daemon and tell it to configure logger
Daemon x; Daemon x;
EXPECT_NO_THROW(x.configureLogger(config, storage)); EXPECT_NO_THROW(x.configureLogger(config, storage, false));
// The parsed configuration should be processed by the daemon and // The parsed configuration should be processed by the daemon and
// stored in configuration storage. // stored in configuration storage.

View File

@@ -27,8 +27,8 @@ namespace {
// Checks that contructor is able to process specified storage properly // Checks that contructor is able to process specified storage properly
TEST(LoggingTest, constructor) { TEST(LoggingTest, constructor) {
ConfigurationPtr nullPtr; ConfigurationPtr null_ptr;
EXPECT_THROW(LogConfigParser parser(nullPtr), InvalidOperation); EXPECT_THROW(LogConfigParser parser(null_ptr), BadValue);
ConfigurationPtr nonnull(new Configuration()); ConfigurationPtr nonnull(new Configuration());
@@ -116,11 +116,109 @@ TEST(LoggingTest, parsingFile) {
EXPECT_EQ("logfile.txt" , storage->logging_info_[0].destinations_[0].output_); EXPECT_EQ("logfile.txt" , storage->logging_info_[0].destinations_[0].output_);
} }
// There is no easy way to test applyConfiguration() and defaultLogging(). // Checks if the LogConfigParser class is able to transform data structures
// To test them, it would require instrumenting log4cplus to actually fake // into Configuration usable by log4cplus. This test checks that more than
// the logging set up. Alternatively, we could develop set of test suites // one logger can be configured.
// that check each logging destination spearately (e.g. configure log file, then TEST(LoggingTest, multipleLoggers) {
// check if the file is indeed created or configure stdout destination, then
// swap console file descriptors and check that messages are really logged. const char* config_txt =
"{ \"loggers\": ["
" {"
" \"name\": \"kea\","
" \"output_options\": ["
" {"
" \"output\": \"logfile.txt\""
" }"
" ],"
" \"severity\": \"INFO\""
" },"
" {"
" \"name\": \"wombat\","
" \"output_options\": ["
" {"
" \"output\": \"logfile2.txt\""
" }"
" ],"
" \"severity\": \"DEBUG\","
" \"debuglevel\": 99"
" }"
"]}";
ConfigurationPtr storage(new Configuration());
LogConfigParser parser(storage);
// We need to parse properly formed JSON and then extract
// "loggers" element from it. For some reason fromJSON is
// throwing at opening square bracket
ConstElementPtr config = Element::fromJSON(config_txt);
config = config->get("loggers");
EXPECT_NO_THROW(parser.parseConfiguration(config));
ASSERT_EQ(2, storage->logging_info_.size());
EXPECT_EQ("kea", storage->logging_info_[0].name_);
EXPECT_EQ(0, storage->logging_info_[0].debuglevel_);
EXPECT_EQ(isc::log::INFO, storage->logging_info_[0].severity_);
ASSERT_EQ(1, storage->logging_info_[0].destinations_.size());
EXPECT_EQ("logfile.txt" , storage->logging_info_[0].destinations_[0].output_);
EXPECT_EQ("wombat", storage->logging_info_[1].name_);
EXPECT_EQ(99, storage->logging_info_[1].debuglevel_);
EXPECT_EQ(isc::log::DEBUG, storage->logging_info_[1].severity_);
ASSERT_EQ(1, storage->logging_info_[1].destinations_.size());
EXPECT_EQ("logfile2.txt" , storage->logging_info_[1].destinations_[0].output_);
}
// Checks if the LogConfigParser class is able to transform data structures
// into Configuration usable by log4cplus. This test checks that more than
// one logging destination can be configured.
TEST(LoggingTest, multipleLoggingDestinations) {
const char* config_txt =
"{ \"loggers\": ["
" {"
" \"name\": \"kea\","
" \"output_options\": ["
" {"
" \"output\": \"logfile.txt\""
" },"
" {"
" \"output\": \"stdout\""
" }"
" ],"
" \"severity\": \"INFO\""
" }"
"]}";
ConfigurationPtr storage(new Configuration());
LogConfigParser parser(storage);
// We need to parse properly formed JSON and then extract
// "loggers" element from it. For some reason fromJSON is
// throwing at opening square bracket
ConstElementPtr config = Element::fromJSON(config_txt);
config = config->get("loggers");
EXPECT_NO_THROW(parser.parseConfiguration(config));
ASSERT_EQ(1, storage->logging_info_.size());
EXPECT_EQ("kea", storage->logging_info_[0].name_);
EXPECT_EQ(0, storage->logging_info_[0].debuglevel_);
EXPECT_EQ(isc::log::INFO, storage->logging_info_[0].severity_);
ASSERT_EQ(2, storage->logging_info_[0].destinations_.size());
EXPECT_EQ("logfile.txt" , storage->logging_info_[0].destinations_[0].output_);
EXPECT_EQ("stdout" , storage->logging_info_[0].destinations_[1].output_);
}
/// @todo There is no easy way to test applyConfiguration() and defaultLogging().
/// To test them, it would require instrumenting log4cplus to actually fake
/// the logging set up. Alternatively, we could develop set of test suites
/// that check each logging destination spearately (e.g. configure log file, then
/// check if the file is indeed created or configure stdout destination, then
/// swap console file descriptors and check that messages are really logged.
}; };

View File

@@ -51,7 +51,7 @@ int& initDebugLevel() {
} }
std::string& initRootName() { std::string& initRootName() {
static std::string root("bind10"); static std::string root(isc::log::getDefaultRootLoggerName());
return (root); return (root);
} }

View File

@@ -40,6 +40,11 @@ const std::string& getRootLoggerName() {
return (getRootLoggerNameInternal()); return (getRootLoggerNameInternal());
} }
const std::string& getDefaultRootLoggerName() {
static std::string root_name("kea");
return (root_name);
}
std::string expandLoggerName(const std::string& name) { std::string expandLoggerName(const std::string& name) {
// Are we the root logger, or does the logger name start with // Are we the root logger, or does the logger name start with

View File

@@ -40,6 +40,12 @@ void setRootLoggerName(const std::string& name);
/// \return Name of the root logger. /// \return Name of the root logger.
const std::string& getRootLoggerName(); const std::string& getRootLoggerName();
/// @brief Returns the default ('kea') root logger name
///
/// @return The default name of root logger.
const std::string& getDefaultRootLoggerName();
/// \brief Expand logger name /// \brief Expand logger name
/// ///
/// Given a logger name, returns the fully-expanded logger name. If the name /// Given a logger name, returns the fully-expanded logger name. If the name

View File

@@ -150,11 +150,10 @@ resetUnitTestRootLogger() {
void initLogger(isc::log::Severity severity, int dbglevel) { void initLogger(isc::log::Severity severity, int dbglevel) {
// Root logger name is defined by the environment variable B10_LOGGER_ROOT. // Root logger name is defined by the environment variable B10_LOGGER_ROOT.
// If not present, the name is "bind10".
const char* DEFAULT_ROOT = "bind10";
const char* root = getenv("B10_LOGGER_ROOT"); const char* root = getenv("B10_LOGGER_ROOT");
if (! root) { if (! root) {
root = DEFAULT_ROOT; // If not present, the name is "kea".
root = isc::log::getDefaultRootLoggerName().c_str();
} }
// Set the local message file // Set the local message file

View File

@@ -34,7 +34,7 @@ namespace log {
/// environment variables. These are: /// environment variables. These are:
/// ///
/// - B10_LOGGER_ROOT\n /// - B10_LOGGER_ROOT\n
/// Name of the root logger. If not given, the string "bind10" will be used. /// Name of the root logger. If not given, the string "kea" will be used.
/// ///
/// - B10_LOGGER_SEVERITY\n /// - B10_LOGGER_SEVERITY\n
/// Severity of messages that will be logged. This must be one of the strings /// Severity of messages that will be logged. This must be one of the strings

View File

@@ -37,13 +37,13 @@ echo "1. Checking that B10_LOGGER_SEVERITY/B10_LOGGER_DBGLEVEL work"
echo -n " - severity=DEBUG, dbglevel=99: " echo -n " - severity=DEBUG, dbglevel=99: "
cat > $tempfile << . cat > $tempfile << .
DEBUG [bind10.log] LOG_BAD_DESTINATION unrecognized log destination: debug-0 DEBUG [kea.log] LOG_BAD_DESTINATION unrecognized log destination: debug-0
DEBUG [bind10.log] LOG_BAD_DESTINATION unrecognized log destination: debug-50 DEBUG [kea.log] LOG_BAD_DESTINATION unrecognized log destination: debug-50
DEBUG [bind10.log] LOG_BAD_DESTINATION unrecognized log destination: debug-99 DEBUG [kea.log] LOG_BAD_DESTINATION unrecognized log destination: debug-99
INFO [bind10.log] LOG_BAD_SEVERITY unrecognized log severity: info INFO [kea.log] LOG_BAD_SEVERITY unrecognized log severity: info
WARN [bind10.log] LOG_BAD_STREAM bad log console output stream: warn WARN [kea.log] LOG_BAD_STREAM bad log console output stream: warn
ERROR [bind10.log] LOG_DUPLICATE_MESSAGE_ID duplicate message ID (error) in compiled code ERROR [kea.log] LOG_DUPLICATE_MESSAGE_ID duplicate message ID (error) in compiled code
FATAL [bind10.log] LOG_NO_MESSAGE_ID line fatal: message definition line found without a message ID FATAL [kea.log] LOG_NO_MESSAGE_ID line fatal: message definition line found without a message ID
. .
B10_LOGGER_DESTINATION=stdout B10_LOGGER_SEVERITY=DEBUG B10_LOGGER_DBGLEVEL=99 ./init_logger_test | \ B10_LOGGER_DESTINATION=stdout B10_LOGGER_SEVERITY=DEBUG B10_LOGGER_DBGLEVEL=99 ./init_logger_test | \
sed -e 's/\[\([a-z0-9\.]\{1,\}\)\/\([0-9]\{1,\}\)\]/[\1]/' | \ sed -e 's/\[\([a-z0-9\.]\{1,\}\)\/\([0-9]\{1,\}\)\]/[\1]/' | \
@@ -52,12 +52,12 @@ passfail $?
echo -n " - severity=DEBUG, dbglevel=50: " echo -n " - severity=DEBUG, dbglevel=50: "
cat > $tempfile << . cat > $tempfile << .
DEBUG [bind10.log] LOG_BAD_DESTINATION unrecognized log destination: debug-0 DEBUG [kea.log] LOG_BAD_DESTINATION unrecognized log destination: debug-0
DEBUG [bind10.log] LOG_BAD_DESTINATION unrecognized log destination: debug-50 DEBUG [kea.log] LOG_BAD_DESTINATION unrecognized log destination: debug-50
INFO [bind10.log] LOG_BAD_SEVERITY unrecognized log severity: info INFO [kea.log] LOG_BAD_SEVERITY unrecognized log severity: info
WARN [bind10.log] LOG_BAD_STREAM bad log console output stream: warn WARN [kea.log] LOG_BAD_STREAM bad log console output stream: warn
ERROR [bind10.log] LOG_DUPLICATE_MESSAGE_ID duplicate message ID (error) in compiled code ERROR [kea.log] LOG_DUPLICATE_MESSAGE_ID duplicate message ID (error) in compiled code
FATAL [bind10.log] LOG_NO_MESSAGE_ID line fatal: message definition line found without a message ID FATAL [kea.log] LOG_NO_MESSAGE_ID line fatal: message definition line found without a message ID
. .
B10_LOGGER_DESTINATION=stdout B10_LOGGER_SEVERITY=DEBUG B10_LOGGER_DBGLEVEL=50 ./init_logger_test | \ B10_LOGGER_DESTINATION=stdout B10_LOGGER_SEVERITY=DEBUG B10_LOGGER_DBGLEVEL=50 ./init_logger_test | \
sed -e 's/\[\([a-z0-9\.]\{1,\}\)\/\([0-9]\{1,\}\)\]/[\1]/' | \ sed -e 's/\[\([a-z0-9\.]\{1,\}\)\/\([0-9]\{1,\}\)\]/[\1]/' | \
@@ -66,9 +66,9 @@ passfail $?
echo -n " - severity=WARN: " echo -n " - severity=WARN: "
cat > $tempfile << . cat > $tempfile << .
WARN [bind10.log] LOG_BAD_STREAM bad log console output stream: warn WARN [kea.log] LOG_BAD_STREAM bad log console output stream: warn
ERROR [bind10.log] LOG_DUPLICATE_MESSAGE_ID duplicate message ID (error) in compiled code ERROR [kea.log] LOG_DUPLICATE_MESSAGE_ID duplicate message ID (error) in compiled code
FATAL [bind10.log] LOG_NO_MESSAGE_ID line fatal: message definition line found without a message ID FATAL [kea.log] LOG_NO_MESSAGE_ID line fatal: message definition line found without a message ID
. .
B10_LOGGER_DESTINATION=stdout B10_LOGGER_SEVERITY=WARN ./init_logger_test | \ B10_LOGGER_DESTINATION=stdout B10_LOGGER_SEVERITY=WARN ./init_logger_test | \
sed -e 's/\[\([a-z0-9\.]\{1,\}\)\/\([0-9]\{1,\}\)\]/[\1]/' | \ sed -e 's/\[\([a-z0-9\.]\{1,\}\)\/\([0-9]\{1,\}\)\]/[\1]/' | \
@@ -79,7 +79,7 @@ echo "2. Checking that B10_LOGGER_DESTINATION works"
echo -n " - stdout: " echo -n " - stdout: "
cat > $tempfile << . cat > $tempfile << .
FATAL [bind10.log] LOG_NO_MESSAGE_ID line fatal: message definition line found without a message ID FATAL [kea.log] LOG_NO_MESSAGE_ID line fatal: message definition line found without a message ID
. .
rm -f $destfile_tmp $destfile rm -f $destfile_tmp $destfile
B10_LOGGER_SEVERITY=FATAL B10_LOGGER_DESTINATION=stdout ./init_logger_test 1> $destfile_tmp B10_LOGGER_SEVERITY=FATAL B10_LOGGER_DESTINATION=stdout ./init_logger_test 1> $destfile_tmp

View File

@@ -33,7 +33,7 @@ echo -n "Testing that logger acquires and releases locks correctly:"
cat > $tempfile << . cat > $tempfile << .
LOGGER_LOCK_TEST: MUTEXLOCK LOGGER_LOCK_TEST: MUTEXLOCK
LOGGER_LOCK_TEST: LOCK LOGGER_LOCK_TEST: LOCK
INFO [bind10.log] LOG_LOCK_TEST_MESSAGE this is a test message. INFO [kea.log] LOG_LOCK_TEST_MESSAGE this is a test message.
LOGGER_LOCK_TEST: UNLOCK LOGGER_LOCK_TEST: UNLOCK
. .
rm -f $destfile rm -f $destfile

View File

@@ -114,7 +114,7 @@ public:
// //
// \return Temporary file name // \return Temporary file name
std::string createTempFilename() { std::string createTempFilename() {
string filename = TEMP_DIR + "/bind10_logger_manager_test_XXXXXX"; string filename = TEMP_DIR + "/kea_logger_manager_test_XXXXXX";
// Copy into writeable storage for the call to mkstemp // Copy into writeable storage for the call to mkstemp
boost::scoped_array<char> tname(new char[filename.size() + 1]); boost::scoped_array<char> tname(new char[filename.size() + 1]);

View File

@@ -75,3 +75,8 @@ TEST_F(LoggerNameTest, ExpandLoggerName) {
EXPECT_EQ(FULL_NAME, expandLoggerName(NAME)); EXPECT_EQ(FULL_NAME, expandLoggerName(NAME));
EXPECT_EQ(FULL_NAME, expandLoggerName(FULL_NAME)); EXPECT_EQ(FULL_NAME, expandLoggerName(FULL_NAME));
} }
// Checks that the default logger name is returned properly.
TEST_F(LoggerNameTest, default) {
EXPECT_EQ("kea", getDefaultRootLoggerName());
}