diff options
Diffstat (limited to 'src/lib/process/log_parser.cc')
-rw-r--r-- | src/lib/process/log_parser.cc | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/src/lib/process/log_parser.cc b/src/lib/process/log_parser.cc new file mode 100644 index 0000000..258aa4e --- /dev/null +++ b/src/lib/process/log_parser.cc @@ -0,0 +1,158 @@ +// Copyright (C) 2014-2022 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> +#include <cc/data.h> +#include <process/log_parser.h> +#include <boost/foreach.hpp> +#include <boost/lexical_cast.hpp> +#include <log/logger_specification.h> +#include <log/logger_support.h> +#include <log/logger_manager.h> +#include <log/logger_name.h> + +using namespace isc::data; +using namespace isc::log; + +namespace isc { +namespace process { + +LogConfigParser::LogConfigParser(const ConfigPtr& storage) + :config_(storage), verbose_(false) { + if (!storage) { + isc_throw(BadValue, "LogConfigParser needs a pointer to the " + "configuration, so parsed data can be stored there"); + } +} + +void LogConfigParser::parseConfiguration(const isc::data::ConstElementPtr& loggers, + bool verbose) { + verbose_ = verbose; + + // Iterate over all entries in "Server/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; + // Remove default destinations as we are going to replace them. + info.clearDestinations(); + + // Get user context + isc::data::ConstElementPtr user_context = entry->get("user-context"); + if (user_context) { + info.setContext(user_context); + } + + // 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 the severity. + // If not configured, set it to DEFAULT to inherit it from the root logger later. + isc::data::ConstElementPtr severity_ptr = entry->get("severity"); + if (severity_ptr) { + info.severity_ = getSeverity(severity_ptr->stringValue()); + } else { + info.severity_ = DEFAULT; + } + + // 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, "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) { + parseOutputOptions(info.destinations_, output_options); + } + + config_->addLoggingInfo(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()); + } + + isc::data::ConstElementPtr flush_ptr = output_option->get("flush"); + if (flush_ptr) { + dest.flush_ = flush_ptr->boolValue(); + } + + isc::data::ConstElementPtr pattern = output_option->get("pattern"); + if (pattern) { + dest.pattern_ = pattern->stringValue(); + } + + destination.push_back(dest); + } +} + +} // namespace isc::dhcp +} // namespace isc |