// Copyright (C) 2014-2024 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 #include #include #include using namespace isc::log; using namespace isc::data; namespace isc { namespace process { 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:"; bool LoggingDestination::equals(const LoggingDestination& other) const { return (output_ == other.output_ && maxver_ == other.maxver_ && maxsize_ == other.maxsize_ && flush_ == other.flush_ && pattern_ == other.pattern_); } ElementPtr LoggingDestination::toElement() const { ElementPtr result = Element::createMap(); // Set output result->set("output", Element::create(output_)); // Set flush result->set("flush", Element::create(flush_)); // Set pattern result->set("pattern", Element::create(pattern_)); if ((output_ != STDOUT) && (output_ != STDERR) && (output_ != SYSLOG) && (output_.find(SYSLOG_COLON) == std::string::npos)) { // Set maxver result->set("maxver", Element::create(maxver_)); // Set maxsize result->set("maxsize", Element::create(static_cast(maxsize_))); } return (result); } LoggingInfo::LoggingInfo() : name_("kea"), severity_(isc::log::INFO), debuglevel_(0) { // If configuration Manager is in the verbose mode, we need to modify the // default settings. if (Daemon::getVerbose()) { severity_ = isc::log::DEBUG; debuglevel_ = 99; } // If the process has set the non-empty name for the default logger, // let's use this name. std::string default_logger = Daemon::getDefaultLoggerName(); if (!default_logger.empty()) { name_ = default_logger; } // Add a default logging destination in case use hasn't provided a // logger specification. LoggingDestination dest; dest.output_ = "stdout"; destinations_.push_back(dest); } bool LoggingInfo::equals(const LoggingInfo& other) const { // If number of destinations aren't equal, the objects are not equal. if (destinations_.size() != other.destinations_.size()) { return (false); } // If there is the same number of logging destinations verify that the // destinations are equal. The order doesn't matter to we don't expect // that they are at the same index of the vectors. for (auto const& dest : destinations_) { bool match = false; for (auto const& dest_other : other.destinations_) { if (dest.equals(dest_other)) { match = true; break; } } if (!match) { return (false); } } // Logging destinations are equal. Check the rest of the parameters for // equality. return (name_ == other.name_ && severity_ == other.severity_ && debuglevel_ == other.debuglevel_); } LoggerSpecification LoggingInfo::toSpec() const { LoggerSpecification spec(name_, severity_, debuglevel_); // Go over logger destinations and create output options accordingly. for (auto const& dest : destinations_) { OutputOption option; // 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 the default ("kea") option.facility = isc::log::getDefaultRootLoggerName(); } else { // Everything else in the string is the facility name option.facility = dest.output_.substr(SYSLOG_COLON.size()); } } else { // Not a recognized destination, assume a file. option.destination = OutputOption::DEST_FILE; option.filename = dest.output_; option.maxsize = dest.maxsize_; option.maxver = dest.maxver_; } // Copy the immediate flush flag option.flush = dest.flush_; // Copy the pattern option.pattern = dest.pattern_; // ... and set the destination spec.addOutputOption(option); } return (spec); } ElementPtr LoggingInfo::toElement() const { ElementPtr result = Element::createMap(); // Set user context contextToElement(result); // Set name result->set("name", Element::create(name_)); // Set output-options if not empty if (!destinations_.empty()) { ElementPtr options = Element::createList(); for (auto const& dest : destinations_) { options->add(dest.toElement()); } result->set("output-options", options); } // Set severity std::string severity; switch (severity_) { case isc::log::DEBUG: severity = "DEBUG"; break; case isc::log::INFO: severity = "INFO"; break; case isc::log::WARN: severity = "WARN"; break; case isc::log::ERROR: severity = "ERROR"; break; case isc::log::FATAL: severity = "FATAL"; break; case isc::log::NONE: severity = "NONE"; break; default: isc_throw(ToElementError, "illegal severity: " << severity_); break; } result->set("severity", Element::create(severity)); // Set debug level result->set("debuglevel", Element::create(debuglevel_)); return (result); } } // end of namespace isc::dhcp } // end of namespace isc