// Copyright (C) 2011-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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // Note: as log4cplus and the Kea logger have many concepts in common, and // thus many similar names, to disambiguate types we don't "use" the log4cplus // namespace: instead, all log4cplus types are explicitly qualified. using namespace std; namespace isc { namespace log { /// @brief detects whether file locking is enabled or disabled /// /// The lockfile is enabled by default. The only way to disable it is to /// set KEA_LOCKFILE_DIR variable to 'none'. /// @return true if lockfile is enabled, false otherwise bool lockfileEnabled() { const char* const env = getenv("KEA_LOCKFILE_DIR"); if (env && boost::iequals(string(env), string("none"))) { return (false); } return (true); } // Constructor. The setting of logger_ must be done when the variable is // constructed (instead of being left to the body of the function); at least // one compiler requires that all member variables be constructed before the // constructor is run, but log4cplus::Logger (the type of logger_) has no // default constructor. LoggerImpl::LoggerImpl(const string& name) : name_(expandLoggerName(name)), logger_(log4cplus::Logger::getInstance(name_)) { if (lockfileEnabled()) { sync_ = new interprocess::InterprocessSyncFile("logger"); } else { sync_ = new interprocess::InterprocessSyncNull("logger"); } } // Destructor. (Here because of virtual declaration.) LoggerImpl::~LoggerImpl() { delete sync_; } /// \brief Version std::string LoggerImpl::getVersion() { std::ostringstream ver; ver << "log4cplus "; ver << log4cplus::versionStr; return (ver.str()); } // Set the severity for logging. void LoggerImpl::setSeverity(isc::log::Severity severity, int dbglevel) { Level level(severity, dbglevel); logger_.setLogLevel(LoggerLevelImpl::convertFromBindLevel(level)); } // Return severity level isc::log::Severity LoggerImpl::getSeverity() { Level level = LoggerLevelImpl::convertToBindLevel(logger_.getLogLevel()); return level.severity; } // Return current debug level (only valid if current severity level is DEBUG). int LoggerImpl::getDebugLevel() { Level level = LoggerLevelImpl::convertToBindLevel(logger_.getLogLevel()); return level.dbglevel; } // Get effective severity. Either the current severity or, if not set, the // severity of the root level. isc::log::Severity LoggerImpl::getEffectiveSeverity() { Level level = LoggerLevelImpl::convertToBindLevel(logger_.getChainedLogLevel()); return level.severity; } // Return effective debug level (only valid if current effective severity level // is DEBUG). int LoggerImpl::getEffectiveDebugLevel() { Level level = LoggerLevelImpl::convertToBindLevel(logger_.getChainedLogLevel()); return level.dbglevel; } // Output a general message boost::shared_ptr LoggerImpl::lookupMessage(const MessageID& ident) { return (boost::make_shared(string(ident) + " " + MessageDictionary::globalDictionary()->getText(ident))); } // Replace the interprocess synchronization object void LoggerImpl::setInterprocessSync(interprocess::InterprocessSync* sync) { if (sync == NULL) { isc_throw(BadInterprocessSync, "NULL was passed to setInterprocessSync()"); } delete sync_; sync_ = sync; } void LoggerImpl::outputRaw(const Severity& severity, const string& message) { // Use a mutex locker for mutual exclusion from other threads in // this process. std::lock_guard mutex_locker(LoggerManager::getMutex()); // Use an interprocess sync locker for mutual exclusion from other // processes to avoid log messages getting interspersed. interprocess::InterprocessSyncLocker locker(*sync_); if (!locker.lock()) { LOG4CPLUS_ERROR(logger_, "Unable to lock logger lockfile"); } switch (severity) { case DEBUG: LOG4CPLUS_DEBUG(logger_, message); break; case INFO: LOG4CPLUS_INFO(logger_, message); break; case WARN: LOG4CPLUS_WARN(logger_, message); break; case ERROR: LOG4CPLUS_ERROR(logger_, message); break; case FATAL: LOG4CPLUS_FATAL(logger_, message); break; case NONE: break; default: LOG4CPLUS_ERROR(logger_, "Unsupported severity in LoggerImpl::outputRaw(): " << severity); } if (!locker.unlock()) { LOG4CPLUS_ERROR(logger_, "Unable to unlock logger lockfile"); } } bool LoggerImpl::hasAppender(OutputOption::Destination const destination) { // Get the appender for the name under which this logger is registered. log4cplus::SharedAppenderPtrList appenders( log4cplus::Logger::getInstance(name_).getAllAppenders()); // If there are no appenders, they might be under the root name. if (appenders.size() == 0) { appenders = log4cplus::Logger::getInstance(getRootLoggerName()).getAllAppenders(); } for (log4cplus::helpers::SharedObjectPtr logger : appenders) { if (destination == OutputOption::DEST_CONSOLE && dynamic_cast(logger.get())) { return true; } else if (destination == OutputOption::DEST_FILE && dynamic_cast(logger.get())) { return true; } else if (destination == OutputOption::DEST_SYSLOG && dynamic_cast(logger.get())) { return true; } } return false; } } // namespace log } // namespace isc