summaryrefslogtreecommitdiffstats
path: root/src/lib/log/logger_impl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/log/logger_impl.cc')
-rw-r--r--src/lib/log/logger_impl.cc231
1 files changed, 231 insertions, 0 deletions
diff --git a/src/lib/log/logger_impl.cc b/src/lib/log/logger_impl.cc
new file mode 100644
index 0000000..f0e5298
--- /dev/null
+++ b/src/lib/log/logger_impl.cc
@@ -0,0 +1,231 @@
+// 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 <config.h>
+
+
+#include <algorithm>
+#include <cstring>
+#include <iomanip>
+#include <iostream>
+#include <stdarg.h>
+#include <stdio.h>
+#include <sstream>
+
+#include <boost/make_shared.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/algorithm/string.hpp>
+
+#include <log4cplus/configurator.h>
+#include <log4cplus/consoleappender.h>
+#include <log4cplus/fileappender.h>
+#include <log4cplus/loggingmacros.h>
+#include <log4cplus/syslogappender.h>
+#include <log4cplus/version.h>
+
+#include <log/logger.h>
+#include <log/logger_impl.h>
+#include <log/logger_level.h>
+#include <log/logger_level_impl.h>
+#include <log/logger_name.h>
+#include <log/logger_manager.h>
+#include <log/message_dictionary.h>
+#include <log/message_types.h>
+#include <log/interprocess/interprocess_sync_file.h>
+#include <log/interprocess/interprocess_sync_null.h>
+
+#include <util/strutil.h>
+
+// 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<string>
+LoggerImpl::lookupMessage(const MessageID& ident) {
+ return (boost::make_shared<string>(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<std::mutex> 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<log4cplus::Appender> logger : appenders) {
+ if (destination == OutputOption::DEST_CONSOLE &&
+ dynamic_cast<log4cplus::ConsoleAppender*>(logger.get())) {
+ return true;
+ } else if (destination == OutputOption::DEST_FILE &&
+ dynamic_cast<log4cplus::FileAppender*>(logger.get())) {
+ return true;
+ } else if (destination == OutputOption::DEST_SYSLOG &&
+ dynamic_cast<log4cplus::SysLogAppender*>(logger.get())) {
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace log
+} // namespace isc