mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-30 21:45:37 +00:00
[3427] Logging configuration implemented.
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
#include <d2/d_controller.h>
|
||||
#include <exceptions/exceptions.h>
|
||||
#include <log/logger_support.h>
|
||||
#include <dhcpsrv/configuration.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
@@ -217,6 +218,28 @@ DControllerBase::configFromFile() {
|
||||
isc::data::ConstElementPtr whole_config =
|
||||
isc::data::Element::fromJSONFile(config_file, true);
|
||||
|
||||
// Let's configure logging before applying the configuration,
|
||||
// so we can log things during configuration process.
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// Extract derivation-specific portion of the configuration.
|
||||
module_config = whole_config->get(getAppName());
|
||||
if (!module_config) {
|
||||
|
@@ -17,6 +17,7 @@
|
||||
#include <dhcp4/json_config_parser.h>
|
||||
#include <dhcp4/ctrl_dhcp4_srv.h>
|
||||
#include <dhcp4/dhcp4_log.h>
|
||||
#include <dhcpsrv/cfgmgr.h>
|
||||
#include <exceptions/exceptions.h>
|
||||
|
||||
#include <string>
|
||||
@@ -42,6 +43,7 @@ void configure(const std::string& file_name) {
|
||||
|
||||
isc::data::ConstElementPtr json;
|
||||
isc::data::ConstElementPtr dhcp4;
|
||||
isc::data::ConstElementPtr logger;
|
||||
isc::data::ConstElementPtr result;
|
||||
|
||||
// Basic sanity check: file name must not be empty.
|
||||
@@ -62,6 +64,23 @@ void configure(const std::string& file_name) {
|
||||
" file: " << 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());
|
||||
}
|
||||
|
||||
// Get Dhcp4 component from the config
|
||||
dhcp4 = json->get("Dhcp4");
|
||||
|
||||
|
@@ -47,6 +47,7 @@ void configure(const std::string& file_name) {
|
||||
|
||||
isc::data::ConstElementPtr json;
|
||||
isc::data::ConstElementPtr dhcp6;
|
||||
isc::data::ConstElementPtr logger;
|
||||
isc::data::ConstElementPtr result;
|
||||
|
||||
// Basic sanity check: file name must not be empty.
|
||||
@@ -67,6 +68,22 @@ void configure(const std::string& file_name) {
|
||||
+ 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());
|
||||
}
|
||||
|
||||
// Get Dhcp6 component from the config
|
||||
dhcp6 = json->get("Dhcp6");
|
||||
|
||||
|
@@ -59,6 +59,8 @@ libkea_dhcpsrv_la_SOURCES += key_from_key.h
|
||||
libkea_dhcpsrv_la_SOURCES += lease.cc lease.h
|
||||
libkea_dhcpsrv_la_SOURCES += lease_mgr.cc lease_mgr.h
|
||||
libkea_dhcpsrv_la_SOURCES += lease_mgr_factory.cc lease_mgr_factory.h
|
||||
libkea_dhcpsrv_la_SOURCES += logging.cc logging.h
|
||||
libkea_dhcpsrv_la_SOURCES += configuration.h
|
||||
libkea_dhcpsrv_la_SOURCES += memfile_lease_mgr.cc memfile_lease_mgr.h
|
||||
|
||||
if HAVE_MYSQL
|
||||
|
@@ -437,10 +437,15 @@ CfgMgr::getD2ClientMgr() {
|
||||
return (d2_client_mgr_);
|
||||
}
|
||||
|
||||
ConfigurationPtr
|
||||
CfgMgr::getConfiguration() {
|
||||
return (configuration_);
|
||||
}
|
||||
|
||||
CfgMgr::CfgMgr()
|
||||
: datadir_(DHCP_DATA_DIR),
|
||||
all_ifaces_active_(false), echo_v4_client_id_(true),
|
||||
d2_client_mgr_() {
|
||||
d2_client_mgr_(), configuration_(new Configuration()) {
|
||||
// DHCP_DATA_DIR must be set set with -DDHCP_DATA_DIR="..." in Makefile.am
|
||||
// Note: the definition of DHCP_DATA_DIR needs to include quotation marks
|
||||
// See AM_CPPFLAGS definition in Makefile.am
|
||||
|
@@ -24,6 +24,7 @@
|
||||
#include <dhcpsrv/option_space_container.h>
|
||||
#include <dhcpsrv/pool.h>
|
||||
#include <dhcpsrv/subnet.h>
|
||||
#include <dhcpsrv/configuration.h>
|
||||
#include <util/buffer.h>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
@@ -420,6 +421,12 @@ public:
|
||||
/// @return a reference to the DHCP-DDNS manager.
|
||||
D2ClientMgr& getD2ClientMgr();
|
||||
|
||||
|
||||
/// @brief Returns the current configuration.
|
||||
///
|
||||
/// @return a pointer to the current configuration.
|
||||
ConfigurationPtr getConfiguration();
|
||||
|
||||
protected:
|
||||
|
||||
/// @brief Protected constructor.
|
||||
@@ -516,6 +523,14 @@ private:
|
||||
|
||||
/// @brief Manages the DHCP-DDNS client and its configuration.
|
||||
D2ClientMgr d2_client_mgr_;
|
||||
|
||||
/// @brief Configuration
|
||||
///
|
||||
/// This is a structure that will hold all configuration.
|
||||
/// @todo: migrate all other parameters to that structure.
|
||||
/// @todo: maybe this should be a vector<Configuration>, so we could keep
|
||||
/// previous configurations and do a rollback if needed?
|
||||
ConfigurationPtr configuration_;
|
||||
};
|
||||
|
||||
} // namespace isc::dhcp
|
||||
|
94
src/lib/dhcpsrv/configuration.h
Normal file
94
src/lib/dhcpsrv/configuration.h
Normal file
@@ -0,0 +1,94 @@
|
||||
// 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
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#ifndef DHCPSRV_CONFIG_H
|
||||
#define DHCPSRV_CONFIG_H
|
||||
|
||||
#include <log/logger_level.h>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
|
||||
|
||||
/// @brief Defines single logging destination
|
||||
///
|
||||
/// This structure is used to keep log4cplus configuration parameters.
|
||||
struct LoggingDestination {
|
||||
|
||||
/// @brief defines logging destination output
|
||||
///
|
||||
/// Values accepted are: stdout, stderr, syslog, syslog:name.
|
||||
/// Any other destination will be considered a file name.
|
||||
std::string output_;
|
||||
|
||||
/// @brief Maximum number of log files in rotation
|
||||
int maxver_;
|
||||
|
||||
/// @brief Maximum log file size
|
||||
uint64_t maxsize_;
|
||||
};
|
||||
|
||||
/// @brief structure that describes one logging entry
|
||||
///
|
||||
/// This is a structure that conveys one logger entry configuration.
|
||||
/// The structure in JSON form has the following syntax:
|
||||
/// {
|
||||
/// "name": "*",
|
||||
/// "output_options": [
|
||||
/// {
|
||||
/// "output": "/path/to/the/logfile.log",
|
||||
/// "maxver": 8,
|
||||
/// "maxsize": 204800
|
||||
/// }
|
||||
/// ],
|
||||
/// "severity": "WARN",
|
||||
/// "debuglevel": 99
|
||||
/// },
|
||||
struct LoggingInfo {
|
||||
|
||||
/// @brief logging name
|
||||
std::string name_;
|
||||
|
||||
/// @brief describes logging severity
|
||||
isc::log::Severity severity_;
|
||||
|
||||
/// @brief debuglevel (used when severity_ == DEBUG)
|
||||
///
|
||||
/// We use range 0(least verbose)..99(most verbose)
|
||||
int debuglevel_;
|
||||
|
||||
/// @brief specific logging destinations
|
||||
std::vector<LoggingDestination> destinations_;
|
||||
};
|
||||
|
||||
/// @brief storage for logging information in log4cplus format
|
||||
typedef std::vector<isc::dhcp::LoggingInfo> LoggingInfoStorage;
|
||||
|
||||
/// @brief Specifies current DHCP configuration
|
||||
///
|
||||
/// @todo Migrate all other configuration parameters from cfgmgr.h here
|
||||
struct Configuration {
|
||||
|
||||
/// @brief logging specific information
|
||||
LoggingInfoStorage logging_info_;
|
||||
};
|
||||
|
||||
/// @brief pointer to the configuration
|
||||
typedef boost::shared_ptr<Configuration> ConfigurationPtr;
|
||||
|
||||
} // namespace isc::dhcp
|
||||
} // namespace isc
|
||||
|
||||
#endif
|
@@ -15,11 +15,13 @@
|
||||
#include <config.h>
|
||||
#include <dhcpsrv/daemon.h>
|
||||
#include <exceptions/exceptions.h>
|
||||
#include <cc/data.h>
|
||||
#include <boost/bind.hpp>
|
||||
#include <logging.h>
|
||||
#include <errno.h>
|
||||
|
||||
/// @brief provides default implementation for basic daemon operations
|
||||
///
|
||||
///
|
||||
/// This file provides stub implementations that are expected to be redefined
|
||||
/// in derived classes (e.g. ControlledDhcpv6Srv)
|
||||
namespace isc {
|
||||
@@ -53,6 +55,41 @@ void Daemon::handleSignal() {
|
||||
}
|
||||
}
|
||||
|
||||
void Daemon::configureLogger(isc::data::ConstElementPtr log_config,
|
||||
const ConfigurationPtr& storage) {
|
||||
|
||||
// This is utility class that translates JSON structures into formats
|
||||
// understandable by log4cplus.
|
||||
LogConfigParser parser(storage);
|
||||
|
||||
if (!log_config) {
|
||||
// There was no logger configuration. Let's clear any config
|
||||
// and revert to the default.
|
||||
|
||||
parser.defaultLogging(); // Set up default logging
|
||||
return;
|
||||
}
|
||||
|
||||
isc::data::ConstElementPtr loggers;
|
||||
loggers = log_config->get("loggers");
|
||||
if (!loggers) {
|
||||
// There is Logging structure, but it doesn't have loggers
|
||||
// array in it. Let's clear any old logging configuration
|
||||
// we may have and revert to the default.
|
||||
|
||||
parser.defaultLogging(); // Set up default logging
|
||||
return;
|
||||
}
|
||||
|
||||
// Translate JSON structures into log4cplus formats
|
||||
parser.parseConfiguration(loggers);
|
||||
|
||||
// Apply the configuration
|
||||
|
||||
/// @todo: Once configuration unrolling is implemented,
|
||||
/// this call will be moved to a separate method.
|
||||
parser.applyConfiguration();
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
@@ -12,12 +12,16 @@
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#ifndef DAEMON_H
|
||||
#define DAEMON_H
|
||||
|
||||
#include <config.h>
|
||||
#include <cc/data.h>
|
||||
#include <dhcpsrv/configuration.h>
|
||||
#include <util/signal_set.h>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
|
||||
@@ -105,7 +109,7 @@ public:
|
||||
return (config_file_);
|
||||
}
|
||||
|
||||
/// Initializes logger
|
||||
/// @brief Initializes logger
|
||||
///
|
||||
/// This method initializes logger. Currently its implementation is specific
|
||||
/// to each configuration backend.
|
||||
@@ -114,6 +118,19 @@ public:
|
||||
/// @param verbose verbose mode (true usually enables DEBUG messages)
|
||||
static void loggerInit(const char* log_name, bool verbose);
|
||||
|
||||
/// @brief Configures logger
|
||||
///
|
||||
/// Applies configuration stored in "Logging" structure in the
|
||||
/// configuration file. This structure has a "loggers" array that
|
||||
/// contains 0 or more entries, each configuring one logging source
|
||||
/// (name, severity, debuglevel), each with zero or more outputs (file,
|
||||
/// maxsize, maximum number of files).
|
||||
///
|
||||
/// @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);
|
||||
|
||||
protected:
|
||||
|
||||
/// @brief Invokes handler for the next received signal.
|
||||
@@ -150,3 +167,5 @@ private:
|
||||
|
||||
}; // end of isc::dhcp namespace
|
||||
}; // end of isc namespace
|
||||
|
||||
#endif
|
||||
|
220
src/lib/dhcpsrv/logging.cc
Normal file
220
src/lib/dhcpsrv/logging.cc
Normal file
@@ -0,0 +1,220 @@
|
||||
// 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
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include <cc/data.h>
|
||||
#include <dhcpsrv/logging.h>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <log/logger_specification.h>
|
||||
#include <log/logger_manager.h>
|
||||
|
||||
using namespace isc::data;
|
||||
using namespace isc::log;
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
|
||||
static const char* DEFAULT_SYSLOG_NAME = "kea";
|
||||
|
||||
LogConfigParser::LogConfigParser(const ConfigurationPtr& storage)
|
||||
:config_(storage) {
|
||||
if (!storage) {
|
||||
isc_throw(InvalidOperation, "LogConfigParser needs a pointer to the "
|
||||
"configuration, so parsed data can be stored there");
|
||||
}
|
||||
}
|
||||
|
||||
void LogConfigParser::parseConfiguration(isc::data::ConstElementPtr loggers) {
|
||||
|
||||
// Iterate over all entries in "Logging/loggers" list
|
||||
BOOST_FOREACH(ConstElementPtr logger, loggers->listValue()) {
|
||||
parseConfigEntry(logger);
|
||||
}
|
||||
}
|
||||
|
||||
void LogConfigParser::parseConfigEntry(isc::data::ConstElementPtr entry) {
|
||||
if (!entry) {
|
||||
// This should not happen, but let's be on the safe side and check
|
||||
return;
|
||||
}
|
||||
|
||||
if (!config_) {
|
||||
isc_throw(BadValue, "configuration storage not set, can't parse logger config.");
|
||||
}
|
||||
|
||||
LoggingInfo info;
|
||||
|
||||
// Get a name
|
||||
isc::data::ConstElementPtr name_ptr = entry->get("name");
|
||||
if (!name_ptr) {
|
||||
isc_throw(BadValue, "loggers entry does not have a mandatory 'name' "
|
||||
"element (" << entry->getPosition() << ")");
|
||||
}
|
||||
info.name_ = name_ptr->stringValue();
|
||||
|
||||
// Get severity
|
||||
isc::data::ConstElementPtr severity_ptr = entry->get("severity");
|
||||
if (!name_ptr) {
|
||||
isc_throw(BadValue, "loggers entry does not have a mandatory "
|
||||
"'severity' element (" << entry->getPosition() << ")");
|
||||
}
|
||||
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()
|
||||
<< ")");
|
||||
}
|
||||
|
||||
// Get debug logging level
|
||||
info.debuglevel_ = 0;
|
||||
isc::data::ConstElementPtr debuglevel_ptr = entry->get("debuglevel");
|
||||
|
||||
// It's ok to not have debuglevel, we'll just assume its least verbose
|
||||
// (0) level.
|
||||
if (debuglevel_ptr) {
|
||||
try {
|
||||
info.debuglevel_ = boost::lexical_cast<int>(debuglevel_ptr->str());
|
||||
if ( (info.debuglevel_ < 0) || (info.debuglevel_ > 99) ) {
|
||||
// Comment doesn't matter, it is caught several lines below
|
||||
isc_throw(BadValue, "");
|
||||
}
|
||||
} catch (...) {
|
||||
isc_throw(BadValue, "Unable to convert '" << debuglevel_ptr->stringValue()
|
||||
<< "' into allowed debuglevel range (0-99) ("
|
||||
<< debuglevel_ptr->getPosition() << ")");
|
||||
}
|
||||
}
|
||||
|
||||
isc::data::ConstElementPtr output_options = entry->get("output_options");
|
||||
|
||||
if (output_options) {
|
||||
parseOutputOptions(info.destinations_, output_options);
|
||||
}
|
||||
|
||||
config_->logging_info_.push_back(info);
|
||||
}
|
||||
|
||||
void LogConfigParser::parseOutputOptions(std::vector<LoggingDestination>& destination,
|
||||
isc::data::ConstElementPtr output_options) {
|
||||
if (!output_options) {
|
||||
isc_throw(BadValue, "Missing 'output_options' structure in 'loggers'");
|
||||
}
|
||||
BOOST_FOREACH(ConstElementPtr output_option, output_options->listValue()) {
|
||||
|
||||
LoggingDestination dest;
|
||||
|
||||
isc::data::ConstElementPtr output = output_option->get("output");
|
||||
if (!output) {
|
||||
isc_throw(BadValue, "output_options entry does not have a mandatory 'output' "
|
||||
"element (" << output_option->getPosition() << ")");
|
||||
}
|
||||
dest.output_ = output->stringValue();
|
||||
|
||||
isc::data::ConstElementPtr maxver_ptr = output_option->get("maxver");
|
||||
if (maxver_ptr) {
|
||||
dest.maxver_ = boost::lexical_cast<int>(maxver_ptr->str());
|
||||
}
|
||||
|
||||
isc::data::ConstElementPtr maxsize_ptr = output_option->get("maxsize");
|
||||
if (maxsize_ptr) {
|
||||
dest.maxsize_ = boost::lexical_cast<uint64_t>(maxsize_ptr->str());
|
||||
}
|
||||
|
||||
destination.push_back(dest);
|
||||
}
|
||||
}
|
||||
|
||||
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";
|
||||
static const std::string SYSLOG_COLON = "syslog:";
|
||||
|
||||
// Set locking directory to /tmp
|
||||
setenv("B10_LOCKFILE_DIR_FROM_BUILD", "/tmp", 1);
|
||||
|
||||
// Now iterate through all specified loggers
|
||||
for (LoggingInfoStorage::const_iterator it = config_->logging_info_.begin();
|
||||
it != config_->logging_info_.end(); ++it) {
|
||||
|
||||
// Prepare the objects to define the logging specification
|
||||
LoggerSpecification spec(it->name_,
|
||||
it->severity_,
|
||||
it->debuglevel_);
|
||||
OutputOption option;
|
||||
|
||||
for (std::vector<LoggingDestination>::const_iterator dest = it->destinations_.begin();
|
||||
dest != it->destinations_.end(); ++dest) {
|
||||
|
||||
// Set up output option according to destination specification
|
||||
if (dest->output_ == STDOUT) {
|
||||
option.destination = OutputOption::DEST_CONSOLE;
|
||||
option.stream = OutputOption::STR_STDOUT;
|
||||
|
||||
} else if (dest->output_ == STDERR) {
|
||||
option.destination = OutputOption::DEST_CONSOLE;
|
||||
option.stream = OutputOption::STR_STDERR;
|
||||
|
||||
} else if (dest->output_ == SYSLOG) {
|
||||
option.destination = OutputOption::DEST_SYSLOG;
|
||||
// Use default specified in OutputOption constructor for the
|
||||
// syslog destination
|
||||
|
||||
} else if (dest->output_.find(SYSLOG_COLON) == 0) {
|
||||
option.destination = OutputOption::DEST_SYSLOG;
|
||||
// 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;
|
||||
|
||||
} else {
|
||||
// Everything else in the string is the facility name
|
||||
option.facility = dest->output_.substr(SYSLOG_COLON.size());
|
||||
}
|
||||
|
||||
} else {
|
||||
// Not a recognised destination, assume a file.
|
||||
option.destination = OutputOption::DEST_FILE;
|
||||
option.filename = dest->output_;
|
||||
}
|
||||
|
||||
// ... and set the destination
|
||||
spec.addOutputOption(option);
|
||||
}
|
||||
|
||||
LoggerManager manager;
|
||||
manager.process(spec);
|
||||
}
|
||||
}
|
||||
|
||||
void LogConfigParser::defaultLogging() {
|
||||
LoggerSpecification spec("kea", isc::log::INFO, 0);
|
||||
|
||||
OutputOption option;
|
||||
option.destination = OutputOption::DEST_CONSOLE;
|
||||
option.stream = OutputOption::STR_STDOUT;
|
||||
|
||||
spec.addOutputOption(option);
|
||||
|
||||
LoggerManager manager;
|
||||
manager.process(spec);
|
||||
}
|
||||
|
||||
} // namespace isc::dhcp
|
||||
} // namespace isc
|
92
src/lib/dhcpsrv/logging.h
Normal file
92
src/lib/dhcpsrv/logging.h
Normal file
@@ -0,0 +1,92 @@
|
||||
// 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
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#ifndef DHCPSRV_LOGGING_H
|
||||
#define DHCPSRV_LOGGING_H
|
||||
|
||||
#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
|
||||
///
|
||||
/// This parser iterates over provided JSON structures and translates them
|
||||
/// into values applicable to log4cplus.
|
||||
///
|
||||
/// This class uses Configuration structure to store logging configuration.
|
||||
class LogConfigParser {
|
||||
public:
|
||||
|
||||
/// @brief Constructor
|
||||
///
|
||||
/// @param storage parsed logging configuration will be stored here
|
||||
LogConfigParser(const ConfigurationPtr& storage);
|
||||
|
||||
/// @brief Parses specified configuration
|
||||
///
|
||||
/// Walks over specified logging configuration JSON structures and store
|
||||
/// parsed information in config_->logging_info_.
|
||||
///
|
||||
/// @param log_config JSON structures to be parsed
|
||||
void parseConfiguration(isc::data::ConstElementPtr log_config);
|
||||
|
||||
/// @brief Applies stored configuration
|
||||
void applyConfiguration();
|
||||
|
||||
/// @brief Configures default logging
|
||||
static void defaultLogging();
|
||||
|
||||
protected:
|
||||
|
||||
/// @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
|
||||
///
|
||||
/// @param destination parsed parameters will be stored here
|
||||
/// @param output_options element to be parsed
|
||||
void parseOutputOptions(std::vector<LoggingDestination>& destination,
|
||||
isc::data::ConstElementPtr output_options);
|
||||
|
||||
/// @brief Configuration is stored here
|
||||
///
|
||||
/// LogConfigParser class uses only config_->logging_info_ field.
|
||||
ConfigurationPtr config_;
|
||||
};
|
||||
|
||||
} // namespace isc::dhcp
|
||||
} // namespace isc
|
||||
|
||||
#endif // CFGMGR_H
|
Reference in New Issue
Block a user