|
@@ -35,6 +35,10 @@
|
|
|
#include <config/config_log.h>
|
|
|
#include <config/ccsession.h>
|
|
|
|
|
|
+#include <log/logger_support.h>
|
|
|
+#include <log/logger_specification.h>
|
|
|
+#include <log/logger_manager.h>
|
|
|
+
|
|
|
using namespace std;
|
|
|
|
|
|
using isc::data::Element;
|
|
@@ -151,6 +155,115 @@ parseCommand(ConstElementPtr& arg, ConstElementPtr command) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+namespace {
|
|
|
+// Temporary workaround functions for missing functionality in
|
|
|
+// getValue() (main problem described in ticket #993)
|
|
|
+// This returns either the value set for the given relative id,
|
|
|
+// or its default value
|
|
|
+// (intentially defined here so this interface does not get
|
|
|
+// included in ConfigData as it is)
|
|
|
+ConstElementPtr getValueOrDefault(ConstElementPtr config_part,
|
|
|
+ const std::string& relative_id,
|
|
|
+ const ConfigData& config_data,
|
|
|
+ const std::string& full_id) {
|
|
|
+ if (config_part->contains(relative_id)) {
|
|
|
+ return config_part->get(relative_id);
|
|
|
+ } else {
|
|
|
+ return config_data.getDefaultValue(full_id);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// Reads a output_option subelement of a logger configuration,
|
|
|
+// and sets the values thereing to the given OutputOption struct,
|
|
|
+// or defaults values if they are not provided (from config_data).
|
|
|
+void
|
|
|
+readOutputOptionConf(isc::log::OutputOption& output_option,
|
|
|
+ ConstElementPtr output_option_el,
|
|
|
+ const ConfigData& config_data)
|
|
|
+{
|
|
|
+ ConstElementPtr destination_el = getValueOrDefault(output_option_el,
|
|
|
+ "destination", config_data,
|
|
|
+ "loggers/output_options/destination");
|
|
|
+ output_option.destination = isc::log::getDestination(destination_el->stringValue());
|
|
|
+ ConstElementPtr output_el = getValueOrDefault(output_option_el,
|
|
|
+ "output", config_data,
|
|
|
+ "loggers/output_options/output");
|
|
|
+ if (output_option.destination == isc::log::OutputOption::DEST_CONSOLE) {
|
|
|
+ output_option.stream = isc::log::getStream(output_el->stringValue());
|
|
|
+ } else if (output_option.destination == isc::log::OutputOption::DEST_FILE) {
|
|
|
+ output_option.filename = output_el->stringValue();
|
|
|
+ } else if (output_option.destination == isc::log::OutputOption::DEST_SYSLOG) {
|
|
|
+ output_option.facility = output_el->stringValue();
|
|
|
+ }
|
|
|
+ output_option.flush = getValueOrDefault(output_option_el,
|
|
|
+ "flush", config_data,
|
|
|
+ "loggers/output_options/flush")->boolValue();
|
|
|
+ output_option.maxsize = getValueOrDefault(output_option_el,
|
|
|
+ "maxsize", config_data,
|
|
|
+ "loggers/output_options/maxsize")->intValue();
|
|
|
+ output_option.maxver = getValueOrDefault(output_option_el,
|
|
|
+ "maxver", config_data,
|
|
|
+ "loggers/output_options/maxver")->intValue();
|
|
|
+}
|
|
|
+
|
|
|
+// Reads a full 'loggers' configuration, and adds the loggers therein
|
|
|
+// to the given vector, fills in blanks with defaults from config_data
|
|
|
+void
|
|
|
+readLoggersConf(std::vector<isc::log::LoggerSpecification>& specs,
|
|
|
+ ConstElementPtr logger,
|
|
|
+ const ConfigData& config_data)
|
|
|
+{
|
|
|
+ const std::string lname = logger->get("name")->stringValue();
|
|
|
+ ConstElementPtr severity_el = getValueOrDefault(logger,
|
|
|
+ "severity", config_data,
|
|
|
+ "loggers/severity");
|
|
|
+ isc::log::Severity severity = isc::log::getSeverity(
|
|
|
+ severity_el->stringValue());
|
|
|
+ int dbg_level = getValueOrDefault(logger, "debuglevel",
|
|
|
+ config_data,
|
|
|
+ "loggers/debuglevel")->intValue();
|
|
|
+ bool additive = getValueOrDefault(logger, "additive", config_data,
|
|
|
+ "loggers/additive")->boolValue();
|
|
|
+
|
|
|
+ isc::log::LoggerSpecification logger_spec(
|
|
|
+ lname, severity, dbg_level, additive
|
|
|
+ );
|
|
|
+
|
|
|
+ if (logger->contains("output_options")) {
|
|
|
+ BOOST_FOREACH(ConstElementPtr output_option_el,
|
|
|
+ logger->get("output_options")->listValue()) {
|
|
|
+ // create outputoptions
|
|
|
+ isc::log::OutputOption output_option;
|
|
|
+ readOutputOptionConf(output_option,
|
|
|
+ output_option_el,
|
|
|
+ config_data);
|
|
|
+ logger_spec.addOutputOption(output_option);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ specs.push_back(logger_spec);
|
|
|
+}
|
|
|
+
|
|
|
+} // end anonymous namespace
|
|
|
+
|
|
|
+void
|
|
|
+my_logconfig_handler(const std::string&n, ConstElementPtr new_config, const ConfigData& config_data) {
|
|
|
+ config_data.getModuleSpec().validateConfig(new_config, true);
|
|
|
+
|
|
|
+ std::vector<isc::log::LoggerSpecification> specs;
|
|
|
+
|
|
|
+ if (new_config->contains("loggers")) {
|
|
|
+ BOOST_FOREACH(ConstElementPtr logger,
|
|
|
+ new_config->get("loggers")->listValue()) {
|
|
|
+ readLoggersConf(specs, logger, config_data);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ isc::log::LoggerManager logger_manager;
|
|
|
+ logger_manager.process(specs.begin(), specs.end());
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
ModuleSpec
|
|
|
ModuleCCSession::readModuleSpecification(const std::string& filename) {
|
|
|
std::ifstream file;
|
|
@@ -193,7 +306,8 @@ ModuleCCSession::ModuleCCSession(
|
|
|
isc::data::ConstElementPtr new_config),
|
|
|
isc::data::ConstElementPtr(*command_handler)(
|
|
|
const std::string& command, isc::data::ConstElementPtr args),
|
|
|
- bool start_immediately
|
|
|
+ bool start_immediately,
|
|
|
+ bool handle_logging
|
|
|
) :
|
|
|
started_(false),
|
|
|
session_(session)
|
|
@@ -207,10 +321,8 @@ ModuleCCSession::ModuleCCSession(
|
|
|
|
|
|
session_.establish(NULL);
|
|
|
session_.subscribe(module_name_, "*");
|
|
|
- //session_.subscribe("Boss", "*");
|
|
|
- //session_.subscribe("statistics", "*");
|
|
|
- // send the data specification
|
|
|
|
|
|
+ // send the data specification
|
|
|
ConstElementPtr spec_msg = createCommand("module_spec",
|
|
|
module_specification_.getFullSpec());
|
|
|
unsigned int seq = session_.group_sendmsg(spec_msg, "ConfigManager");
|
|
@@ -239,9 +351,15 @@ ModuleCCSession::ModuleCCSession(
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // Keep track of logging settings automatically
|
|
|
+ if (handle_logging) {
|
|
|
+ addRemoteConfig("Logging", my_logconfig_handler, false);
|
|
|
+ }
|
|
|
+
|
|
|
if (start_immediately) {
|
|
|
start();
|
|
|
}
|
|
|
+
|
|
|
}
|
|
|
|
|
|
void
|
|
@@ -361,6 +479,11 @@ ModuleCCSession::checkCommand() {
|
|
|
}
|
|
|
} catch (const CCSessionError& re) {
|
|
|
LOG_ERROR(config_logger, CONFIG_CCSESSION_MSG).arg(re.what());
|
|
|
+ } catch (const std::exception& stde) {
|
|
|
+ // No matter what unexpected error happens, we do not want
|
|
|
+ // to crash because of an incoming event, so we log the
|
|
|
+ // exception and continue to run
|
|
|
+ LOG_ERROR(config_logger, CONFIG_CCSESSION_MSG_INTERNAL).arg(stde.what());
|
|
|
}
|
|
|
if (!isNull(answer)) {
|
|
|
session_.reply(routing, answer);
|
|
@@ -382,9 +505,7 @@ ModuleCCSession::fetchRemoteSpec(const std::string& module, bool is_filename) {
|
|
|
ConstElementPtr cmd(createCommand("get_module_spec",
|
|
|
Element::fromJSON("{\"module_name\": \"" + module +
|
|
|
"\"}")));
|
|
|
- const unsigned int seq = session_.group_sendmsg(cmd, "ConfigManager");
|
|
|
-
|
|
|
- // Wait for the answer
|
|
|
+ unsigned int seq = session_.group_sendmsg(cmd, "ConfigManager");
|
|
|
ConstElementPtr env, answer;
|
|
|
session_.group_recvmsg(env, answer, false, seq);
|
|
|
int rcode;
|
|
@@ -407,7 +528,8 @@ ModuleCCSession::fetchRemoteSpec(const std::string& module, bool is_filename) {
|
|
|
std::string
|
|
|
ModuleCCSession::addRemoteConfig(const std::string& spec_name,
|
|
|
void (*handler)(const std::string& module,
|
|
|
- ConstElementPtr),
|
|
|
+ ConstElementPtr,
|
|
|
+ const ConfigData&),
|
|
|
bool spec_is_filename)
|
|
|
{
|
|
|
// First get the module name, specification and default config
|
|
@@ -439,7 +561,7 @@ ModuleCCSession::addRemoteConfig(const std::string& spec_name,
|
|
|
remote_module_configs_[module_name] = rmod_config;
|
|
|
if (handler) {
|
|
|
remote_module_handlers_[module_name] = handler;
|
|
|
- handler(module_name, local_config);
|
|
|
+ handler(module_name, local_config, rmod_config);
|
|
|
}
|
|
|
|
|
|
// Make sure we get updates in future
|
|
@@ -487,7 +609,7 @@ ModuleCCSession::updateRemoteConfig(const std::string& module_name,
|
|
|
std::map<std::string, RemoteHandler>::iterator hit =
|
|
|
remote_module_handlers_.find(module_name);
|
|
|
if (hit != remote_module_handlers_.end()) {
|
|
|
- hit->second(module_name, new_config);
|
|
|
+ hit->second(module_name, new_config, it->second);
|
|
|
}
|
|
|
}
|
|
|
}
|