mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-30 13:37:55 +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:
@@ -55,13 +55,14 @@
|
||||
<title>name (string)</title>
|
||||
|
||||
<para>
|
||||
Each logger in the system has a name, the name being that
|
||||
of the component using it to log messages. For instance,
|
||||
if you want to configure logging for the Dhcp4 module,
|
||||
you add an entry for a logger named <quote>Dhcp4</quote>. This
|
||||
configuration will then be used by the loggers in the
|
||||
Dhcp4 module, and all the libraries used by it.
|
||||
</para>
|
||||
Each logger in the system has a name, the name being that
|
||||
of the component using it to log messages. For instance,
|
||||
if you want to configure logging for the Dhcp4 module,
|
||||
you add an entry for a logger named <quote>Dhcp4</quote>. This
|
||||
configuration will then be used by the loggers in the
|
||||
Dhcp4 module, and all the libraries used by it (unless
|
||||
a library defines its own logger).
|
||||
</para>
|
||||
|
||||
<!-- 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
|
||||
there is no entry in Logging for a particular library,
|
||||
it will use the configuration given for the module.
|
||||
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@@ -138,6 +138,24 @@ Right now you can only see what their names are if they are running
|
||||
|
||||
</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>
|
||||
|
@@ -224,21 +224,9 @@ DControllerBase::configFromFile() {
|
||||
// Temporary storage for logging configuration
|
||||
isc::dhcp::ConfigurationPtr storage(new isc::dhcp::Configuration());
|
||||
|
||||
// Get 'Logging' element from the config
|
||||
isc::data::ConstElementPtr logger = whole_config->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, 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);
|
||||
}
|
||||
// Get 'Logging' element from the config and use it to set up
|
||||
// logging. If there's no such element, we'll just pass NULL.
|
||||
Daemon::configureLogger(whole_config->get("Logging"), storage, verbose_);
|
||||
|
||||
// Extract derivation-specific portion of the configuration.
|
||||
module_config = whole_config->get(getAppName());
|
||||
|
@@ -25,6 +25,20 @@ CONFIG="{
|
||||
\"tsig_keys\": [],
|
||||
\"forward_ddns\" : {},
|
||||
\"reverse_ddns\" : {}
|
||||
},
|
||||
\"Logging\":
|
||||
{
|
||||
\"loggers\": [
|
||||
{
|
||||
\"name\": \"kea-dhcp-ddns\",
|
||||
\"output_options\": [
|
||||
{
|
||||
\"output\": \"$LOG_FILE\"
|
||||
}
|
||||
],
|
||||
\"severity\": \"DEBUG\"
|
||||
}
|
||||
]
|
||||
}
|
||||
}"
|
||||
|
||||
@@ -38,6 +52,20 @@ CONFIG_INVALID="{
|
||||
\"tsig_keys\": [],
|
||||
\"forward_ddns\" : {},
|
||||
\"reverse_ddns\" : {}
|
||||
},
|
||||
\"Logging\":
|
||||
{
|
||||
\"loggers\": [
|
||||
{
|
||||
\"name\": \"kea-dhcp-ddns\",
|
||||
\"output_options\": [
|
||||
{
|
||||
\"output\": \"$LOG_FILE\"
|
||||
}
|
||||
],
|
||||
\"severity\": \"INFO\"
|
||||
}
|
||||
]
|
||||
}
|
||||
}"
|
||||
|
||||
|
@@ -66,20 +66,12 @@ void configure(const std::string& file_name) {
|
||||
|
||||
// Let's configure logging before applying the configuration,
|
||||
// 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());
|
||||
} 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());
|
||||
}
|
||||
// If there's no logging element, we'll just pass NULL pointer,
|
||||
// which will be handled by configureLogger().
|
||||
Daemon::configureLogger(json->get("Logging"),
|
||||
CfgMgr::instance().getConfiguration(),
|
||||
ControlledDhcpv4Srv::getInstance()->getVerbose());
|
||||
|
||||
// Get Dhcp4 component from the config
|
||||
dhcp4 = json->get("Dhcp4");
|
||||
|
@@ -111,6 +111,9 @@ main(int argc, char* argv[]) {
|
||||
// Create the server instance.
|
||||
ControlledDhcpv4Srv server(port_number);
|
||||
|
||||
// Remember verbose-mode
|
||||
server.setVerbose(verbose_mode);
|
||||
|
||||
try {
|
||||
// Initialize the server.
|
||||
server.init(config_file);
|
||||
|
@@ -34,6 +34,21 @@ CONFIG="{
|
||||
\"subnet\": \"10.0.0.0/8\",
|
||||
\"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
|
||||
@@ -55,6 +70,21 @@ CONFIG_INVALID="{
|
||||
\"subnet\": \"10.0.0.0/8\",
|
||||
\"pool\": [ \"10.0.0.10-10.0.0.100\" ]
|
||||
} ]
|
||||
},
|
||||
|
||||
\"Logging\":
|
||||
{
|
||||
\"loggers\": [
|
||||
{
|
||||
\"name\": \"kea\",
|
||||
\"output_options\": [
|
||||
{
|
||||
\"output\": \"$LOG_FILE\"
|
||||
}
|
||||
],
|
||||
\"severity\": \"INFO\"
|
||||
}
|
||||
]
|
||||
}
|
||||
}"
|
||||
|
||||
|
@@ -70,19 +70,11 @@ void configure(const std::string& file_name) {
|
||||
|
||||
// Let's configure logging before applying the configuration,
|
||||
// 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());
|
||||
} 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());
|
||||
}
|
||||
// If there's no logging element, we'll just pass NULL pointer,
|
||||
// which will be handled by configureLogger().
|
||||
Daemon::configureLogger(json->get("Logging"),
|
||||
CfgMgr::instance().getConfiguration(),
|
||||
ControlledDhcpv6Srv::getInstance()->getVerbose());
|
||||
|
||||
// Get Dhcp6 component from the config
|
||||
dhcp6 = json->get("Dhcp6");
|
||||
|
@@ -111,6 +111,9 @@ main(int argc, char* argv[]) {
|
||||
// Create the server instance.
|
||||
ControlledDhcpv6Srv server(port_number);
|
||||
|
||||
// Remember verbose-mode
|
||||
server.setVerbose(verbose_mode);
|
||||
|
||||
try {
|
||||
// Initialize the server, i.e. establish control session
|
||||
// if BIND10 backend is used or read a configuration file
|
||||
|
@@ -35,6 +35,21 @@ CONFIG="{
|
||||
\"subnet\": \"2001:db8:1::/64\",
|
||||
\"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
|
||||
@@ -57,6 +72,21 @@ CONFIG_INVALID="{
|
||||
\"subnet\": \"2001:db8:1::/64\",
|
||||
\"pool\": [ \"2001:db8:1::10-2001:db8:1::100\" ]
|
||||
} ]
|
||||
},
|
||||
|
||||
\"Logging\":
|
||||
{
|
||||
\"loggers\": [
|
||||
{
|
||||
\"name\": \"kea\",
|
||||
\"output_options\": [
|
||||
{
|
||||
\"output\": \"$LOG_FILE\"
|
||||
}
|
||||
],
|
||||
\"severity\": \"INFO\"
|
||||
}
|
||||
]
|
||||
}
|
||||
}"
|
||||
|
||||
|
@@ -65,6 +65,25 @@
|
||||
"tsig_keys": [],
|
||||
"forward_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
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -12,8 +12,8 @@
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#ifndef DHCPSRV_CONFIG_H
|
||||
#define DHCPSRV_CONFIG_H
|
||||
#ifndef DHCPSRV_CONFIGURATION_H
|
||||
#define DHCPSRV_CONFIGURATION_H
|
||||
|
||||
#include <log/logger_level.h>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
@@ -23,7 +23,6 @@
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
|
||||
|
||||
/// @brief Defines single logging destination
|
||||
///
|
||||
/// This structure is used to keep log4cplus configuration parameters.
|
||||
@@ -93,4 +92,4 @@ typedef boost::shared_ptr<Configuration> ConfigurationPtr;
|
||||
} // namespace isc::dhcp
|
||||
} // namespace isc
|
||||
|
||||
#endif
|
||||
#endif // DHCPSRV_CONFIGURATION_H
|
||||
|
@@ -31,7 +31,7 @@ namespace dhcp {
|
||||
std::string Daemon::config_file_ = "";
|
||||
|
||||
Daemon::Daemon()
|
||||
: signal_set_(), signal_handler_() {
|
||||
: signal_set_(), signal_handler_(), verbose_(false) {
|
||||
}
|
||||
|
||||
Daemon::~Daemon() {
|
||||
@@ -55,8 +55,9 @@ void Daemon::handleSignal() {
|
||||
}
|
||||
}
|
||||
|
||||
void Daemon::configureLogger(isc::data::ConstElementPtr log_config,
|
||||
const ConfigurationPtr& storage) {
|
||||
void Daemon::configureLogger(const isc::data::ConstElementPtr& log_config,
|
||||
const ConfigurationPtr& storage,
|
||||
bool verbose) {
|
||||
|
||||
// This is utility class that translates JSON structures into formats
|
||||
// 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
|
||||
// and revert to the default.
|
||||
|
||||
parser.defaultLogging(); // Set up default logging
|
||||
parser.applyDefaultConfiguration(verbose); // Set up default logging
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -77,12 +78,12 @@ void Daemon::configureLogger(isc::data::ConstElementPtr log_config,
|
||||
// array in it. Let's clear any old logging configuration
|
||||
// we may have and revert to the default.
|
||||
|
||||
parser.defaultLogging(); // Set up default logging
|
||||
parser.applyDefaultConfiguration(verbose); // Set up default logging
|
||||
return;
|
||||
}
|
||||
|
||||
// Translate JSON structures into log4cplus formats
|
||||
parser.parseConfiguration(loggers);
|
||||
parser.parseConfiguration(loggers, verbose);
|
||||
|
||||
// Apply the configuration
|
||||
|
||||
|
@@ -128,8 +128,26 @@ public:
|
||||
///
|
||||
/// @param log_config JSON structures that describe logging
|
||||
/// @param storage configuration will be stored here
|
||||
static void configureLogger(isc::data::ConstElementPtr log_config,
|
||||
const isc::dhcp::ConfigurationPtr& storage);
|
||||
/// @param verbose specifies if verbose mode should be enabled
|
||||
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:
|
||||
|
||||
@@ -163,6 +181,9 @@ private:
|
||||
|
||||
/// @brief Config file name or empty if config file not used.
|
||||
static std::string config_file_;
|
||||
|
||||
/// @brief Verbose mode
|
||||
bool verbose_;
|
||||
};
|
||||
|
||||
}; // end of isc::dhcp namespace
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <log/logger_specification.h>
|
||||
#include <log/logger_manager.h>
|
||||
#include <log/logger_name.h>
|
||||
|
||||
using namespace isc::data;
|
||||
using namespace isc::log;
|
||||
@@ -25,17 +26,17 @@ using namespace isc::log;
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
|
||||
static const char* DEFAULT_SYSLOG_NAME = "kea";
|
||||
|
||||
LogConfigParser::LogConfigParser(const ConfigurationPtr& storage)
|
||||
:config_(storage) {
|
||||
:config_(storage), verbose_(false) {
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
BOOST_FOREACH(ConstElementPtr logger, loggers->listValue()) {
|
||||
@@ -72,9 +73,9 @@ void LogConfigParser::parseConfigEntry(isc::data::ConstElementPtr entry) {
|
||||
try {
|
||||
info.severity_ = isc::log::getSeverity(severity_ptr->stringValue().c_str());
|
||||
} catch (const std::exception& ex) {
|
||||
isc_throw(BadValue, "Unable to convert '" << severity_ptr->stringValue()
|
||||
<< "' into allowed severity (" << severity_ptr->getPosition()
|
||||
<< ")");
|
||||
isc_throw(BadValue, "Unsupported severity value '"
|
||||
<< severity_ptr->stringValue() << "' ("
|
||||
<< severity_ptr->getPosition() << ")");
|
||||
}
|
||||
|
||||
// Get debug logging level
|
||||
@@ -91,12 +92,21 @@ void LogConfigParser::parseConfigEntry(isc::data::ConstElementPtr entry) {
|
||||
isc_throw(BadValue, "");
|
||||
}
|
||||
} catch (...) {
|
||||
isc_throw(BadValue, "Unable to convert '" << debuglevel_ptr->stringValue()
|
||||
<< "' into allowed debuglevel range (0-99) ("
|
||||
isc_throw(BadValue, "Unsupported debuglevel value '"
|
||||
<< debuglevel_ptr->stringValue()
|
||||
<< "', expected 0-99 ("
|
||||
<< 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");
|
||||
|
||||
if (output_options) {
|
||||
@@ -138,8 +148,6 @@ void LogConfigParser::parseOutputOptions(std::vector<LoggingDestination>& destin
|
||||
|
||||
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 STDERR = "stderr";
|
||||
static const std::string SYSLOG = "syslog";
|
||||
@@ -180,8 +188,8 @@ void LogConfigParser::applyConfiguration() {
|
||||
// Must take account of the string actually being "syslog:"
|
||||
if (dest->output_ == SYSLOG_COLON) {
|
||||
// The expected syntax is syslog:facility. User skipped
|
||||
// the logging name, so we'll just use DEFAULT_SYSLOG_NAME.
|
||||
option.facility = DEFAULT_SYSLOG_NAME;
|
||||
// the logging name, so we'll just use the default ("kea")
|
||||
option.facility = isc::log::getDefaultRootLoggerName();
|
||||
|
||||
} else {
|
||||
// Everything else in the string is the facility name
|
||||
@@ -203,8 +211,9 @@ void LogConfigParser::applyConfiguration() {
|
||||
}
|
||||
}
|
||||
|
||||
void LogConfigParser::defaultLogging() {
|
||||
LoggerSpecification spec("kea", isc::log::INFO, 0);
|
||||
void LogConfigParser::applyDefaultConfiguration(bool verbose) {
|
||||
LoggerSpecification spec("kea", (verbose?isc::log::DEBUG : isc::log::INFO),
|
||||
(verbose?99:0));
|
||||
|
||||
OutputOption option;
|
||||
option.destination = OutputOption::DEST_CONSOLE;
|
||||
|
@@ -17,18 +17,34 @@
|
||||
|
||||
#include <cc/data.h>
|
||||
#include <dhcpsrv/configuration.h>
|
||||
#include <dhcpsrv/cfgmgr.h>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
namespace isc {
|
||||
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.
|
||||
///
|
||||
/// 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.
|
||||
class LogConfigParser {
|
||||
public:
|
||||
@@ -44,37 +60,39 @@ public:
|
||||
/// parsed information in config_->logging_info_.
|
||||
///
|
||||
/// @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
|
||||
void applyConfiguration();
|
||||
|
||||
/// @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
|
||||
///
|
||||
/// 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
|
||||
/// @brief parses one structure in Logging/loggers.
|
||||
void parseConfigEntry(isc::data::ConstElementPtr entry);
|
||||
|
||||
/// @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 output_options element to be parsed
|
||||
void parseOutputOptions(std::vector<LoggingDestination>& destination,
|
||||
@@ -84,9 +102,15 @@ protected:
|
||||
///
|
||||
/// LogConfigParser class uses only config_->logging_info_ field.
|
||||
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
|
||||
|
||||
#endif // CFGMGR_H
|
||||
#endif // DHCPSRV_LOGGING_H
|
||||
|
@@ -778,4 +778,4 @@ typedef std::vector<Subnet6Ptr> Subnet6Collection;
|
||||
} // end of isc::dhcp namespace
|
||||
} // end of isc namespace
|
||||
|
||||
#endif // SUBNET_T
|
||||
#endif // SUBNET_H
|
||||
|
@@ -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
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
|
@@ -25,9 +25,14 @@ using namespace isc::data;
|
||||
|
||||
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) {
|
||||
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.
|
||||
@@ -55,7 +60,7 @@ TEST(DaemonTest, parsingConsoleOutput) {
|
||||
|
||||
// Spawn a daemon and tell it to configure logger
|
||||
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
|
||||
// stored in configuration storage.
|
||||
|
@@ -27,8 +27,8 @@ namespace {
|
||||
// Checks that contructor is able to process specified storage properly
|
||||
TEST(LoggingTest, constructor) {
|
||||
|
||||
ConfigurationPtr nullPtr;
|
||||
EXPECT_THROW(LogConfigParser parser(nullPtr), InvalidOperation);
|
||||
ConfigurationPtr null_ptr;
|
||||
EXPECT_THROW(LogConfigParser parser(null_ptr), BadValue);
|
||||
|
||||
ConfigurationPtr nonnull(new Configuration());
|
||||
|
||||
@@ -116,11 +116,109 @@ TEST(LoggingTest, parsingFile) {
|
||||
EXPECT_EQ("logfile.txt" , storage->logging_info_[0].destinations_[0].output_);
|
||||
}
|
||||
|
||||
// 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.
|
||||
// Checks if the LogConfigParser class is able to transform data structures
|
||||
// into Configuration usable by log4cplus. This test checks that more than
|
||||
// one logger can be configured.
|
||||
TEST(LoggingTest, multipleLoggers) {
|
||||
|
||||
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.
|
||||
|
||||
};
|
||||
|
@@ -51,7 +51,7 @@ int& initDebugLevel() {
|
||||
}
|
||||
|
||||
std::string& initRootName() {
|
||||
static std::string root("bind10");
|
||||
static std::string root(isc::log::getDefaultRootLoggerName());
|
||||
return (root);
|
||||
}
|
||||
|
||||
|
@@ -40,6 +40,11 @@ const std::string& getRootLoggerName() {
|
||||
return (getRootLoggerNameInternal());
|
||||
}
|
||||
|
||||
const std::string& getDefaultRootLoggerName() {
|
||||
static std::string root_name("kea");
|
||||
return (root_name);
|
||||
}
|
||||
|
||||
std::string expandLoggerName(const std::string& name) {
|
||||
|
||||
// Are we the root logger, or does the logger name start with
|
||||
|
@@ -40,6 +40,12 @@ void setRootLoggerName(const std::string& name);
|
||||
/// \return Name of the root logger.
|
||||
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
|
||||
///
|
||||
/// Given a logger name, returns the fully-expanded logger name. If the name
|
||||
|
@@ -150,11 +150,10 @@ resetUnitTestRootLogger() {
|
||||
void initLogger(isc::log::Severity severity, int dbglevel) {
|
||||
|
||||
// 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");
|
||||
if (! root) {
|
||||
root = DEFAULT_ROOT;
|
||||
// If not present, the name is "kea".
|
||||
root = isc::log::getDefaultRootLoggerName().c_str();
|
||||
}
|
||||
|
||||
// Set the local message file
|
||||
|
@@ -34,7 +34,7 @@ namespace log {
|
||||
/// environment variables. These are:
|
||||
///
|
||||
/// - 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
|
||||
/// Severity of messages that will be logged. This must be one of the strings
|
||||
|
@@ -37,13 +37,13 @@ echo "1. Checking that B10_LOGGER_SEVERITY/B10_LOGGER_DBGLEVEL work"
|
||||
|
||||
echo -n " - severity=DEBUG, dbglevel=99: "
|
||||
cat > $tempfile << .
|
||||
DEBUG [bind10.log] LOG_BAD_DESTINATION unrecognized log destination: debug-0
|
||||
DEBUG [bind10.log] LOG_BAD_DESTINATION unrecognized log destination: debug-50
|
||||
DEBUG [bind10.log] LOG_BAD_DESTINATION unrecognized log destination: debug-99
|
||||
INFO [bind10.log] LOG_BAD_SEVERITY unrecognized log severity: info
|
||||
WARN [bind10.log] LOG_BAD_STREAM bad log console output stream: warn
|
||||
ERROR [bind10.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
|
||||
DEBUG [kea.log] LOG_BAD_DESTINATION unrecognized log destination: debug-0
|
||||
DEBUG [kea.log] LOG_BAD_DESTINATION unrecognized log destination: debug-50
|
||||
DEBUG [kea.log] LOG_BAD_DESTINATION unrecognized log destination: debug-99
|
||||
INFO [kea.log] LOG_BAD_SEVERITY unrecognized log severity: info
|
||||
WARN [kea.log] LOG_BAD_STREAM bad log console output stream: warn
|
||||
ERROR [kea.log] LOG_DUPLICATE_MESSAGE_ID duplicate message ID (error) in compiled code
|
||||
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 | \
|
||||
sed -e 's/\[\([a-z0-9\.]\{1,\}\)\/\([0-9]\{1,\}\)\]/[\1]/' | \
|
||||
@@ -52,12 +52,12 @@ passfail $?
|
||||
|
||||
echo -n " - severity=DEBUG, dbglevel=50: "
|
||||
cat > $tempfile << .
|
||||
DEBUG [bind10.log] LOG_BAD_DESTINATION unrecognized log destination: debug-0
|
||||
DEBUG [bind10.log] LOG_BAD_DESTINATION unrecognized log destination: debug-50
|
||||
INFO [bind10.log] LOG_BAD_SEVERITY unrecognized log severity: info
|
||||
WARN [bind10.log] LOG_BAD_STREAM bad log console output stream: warn
|
||||
ERROR [bind10.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
|
||||
DEBUG [kea.log] LOG_BAD_DESTINATION unrecognized log destination: debug-0
|
||||
DEBUG [kea.log] LOG_BAD_DESTINATION unrecognized log destination: debug-50
|
||||
INFO [kea.log] LOG_BAD_SEVERITY unrecognized log severity: info
|
||||
WARN [kea.log] LOG_BAD_STREAM bad log console output stream: warn
|
||||
ERROR [kea.log] LOG_DUPLICATE_MESSAGE_ID duplicate message ID (error) in compiled code
|
||||
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 | \
|
||||
sed -e 's/\[\([a-z0-9\.]\{1,\}\)\/\([0-9]\{1,\}\)\]/[\1]/' | \
|
||||
@@ -66,9 +66,9 @@ passfail $?
|
||||
|
||||
echo -n " - severity=WARN: "
|
||||
cat > $tempfile << .
|
||||
WARN [bind10.log] LOG_BAD_STREAM bad log console output stream: warn
|
||||
ERROR [bind10.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
|
||||
WARN [kea.log] LOG_BAD_STREAM bad log console output stream: warn
|
||||
ERROR [kea.log] LOG_DUPLICATE_MESSAGE_ID duplicate message ID (error) in compiled code
|
||||
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 | \
|
||||
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: "
|
||||
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
|
||||
B10_LOGGER_SEVERITY=FATAL B10_LOGGER_DESTINATION=stdout ./init_logger_test 1> $destfile_tmp
|
||||
|
@@ -33,7 +33,7 @@ echo -n "Testing that logger acquires and releases locks correctly:"
|
||||
cat > $tempfile << .
|
||||
LOGGER_LOCK_TEST: MUTEXLOCK
|
||||
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
|
||||
.
|
||||
rm -f $destfile
|
||||
|
@@ -114,7 +114,7 @@ public:
|
||||
//
|
||||
// \return Temporary file name
|
||||
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
|
||||
boost::scoped_array<char> tname(new char[filename.size() + 1]);
|
||||
|
@@ -75,3 +75,8 @@ TEST_F(LoggerNameTest, ExpandLoggerName) {
|
||||
EXPECT_EQ(FULL_NAME, expandLoggerName(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());
|
||||
}
|
||||
|
Reference in New Issue
Block a user