Kea  2.3.4-git
logger_impl.cc
Go to the documentation of this file.
1 // Copyright (C) 2011-2022 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #include <config.h>
8 
9 
10 #include <algorithm>
11 #include <cstring>
12 #include <iomanip>
13 #include <iostream>
14 #include <stdarg.h>
15 #include <stdio.h>
16 #include <sstream>
17 
18 #include <boost/make_shared.hpp>
19 #include <boost/lexical_cast.hpp>
20 #include <boost/static_assert.hpp>
21 #include <boost/algorithm/string.hpp>
22 
23 #include <log4cplus/configurator.h>
24 #include <log4cplus/consoleappender.h>
25 #include <log4cplus/fileappender.h>
26 #include <log4cplus/loggingmacros.h>
27 #include <log4cplus/syslogappender.h>
28 #include <log4cplus/version.h>
29 
30 #include <log/logger.h>
31 #include <log/logger_impl.h>
32 #include <log/logger_level.h>
33 #include <log/logger_level_impl.h>
34 #include <log/logger_name.h>
35 #include <log/logger_manager.h>
36 #include <log/message_dictionary.h>
37 #include <log/message_types.h>
40 
41 #include <util/strutil.h>
42 
43 // Note: as log4cplus and the Kea logger have many concepts in common, and
44 // thus many similar names, to disambiguate types we don't "use" the log4cplus
45 // namespace: instead, all log4cplus types are explicitly qualified.
46 
47 using namespace std;
48 
49 namespace isc {
50 namespace log {
51 
58  const char* const env = getenv("KEA_LOCKFILE_DIR");
59  if (env && boost::iequals(string(env), string("none"))) {
60  return (false);
61  }
62 
63  return (true);
64 }
65 
66 // Constructor. The setting of logger_ must be done when the variable is
67 // constructed (instead of being left to the body of the function); at least
68 // one compiler requires that all member variables be constructed before the
69 // constructor is run, but log4cplus::Logger (the type of logger_) has no
70 // default constructor.
71 LoggerImpl::LoggerImpl(const string& name) :
72  name_(expandLoggerName(name)),
73  logger_(log4cplus::Logger::getInstance(name_))
74 {
75  if (lockfileEnabled()) {
76  sync_ = new interprocess::InterprocessSyncFile("logger");
77  } else {
78  sync_ = new interprocess::InterprocessSyncNull("logger");
79  }
80 }
81 
82 // Destructor. (Here because of virtual declaration.)
83 
85  delete sync_;
86 }
87 
89 std::string
91  std::ostringstream ver;
92  ver << "log4cplus ";
93  ver << log4cplus::versionStr;
94  return (ver.str());
95 }
96 
97 // Set the severity for logging.
98 void
100  Level level(severity, dbglevel);
101  logger_.setLogLevel(LoggerLevelImpl::convertFromBindLevel(level));
102 }
103 
104 // Return severity level
107  Level level = LoggerLevelImpl::convertToBindLevel(logger_.getLogLevel());
108  return level.severity;
109 }
110 
111 // Return current debug level (only valid if current severity level is DEBUG).
112 int
114  Level level = LoggerLevelImpl::convertToBindLevel(logger_.getLogLevel());
115  return level.dbglevel;
116 }
117 
118 // Get effective severity. Either the current severity or, if not set, the
119 // severity of the root level.
122  Level level = LoggerLevelImpl::convertToBindLevel(logger_.getChainedLogLevel());
123  return level.severity;
124 }
125 
126 // Return effective debug level (only valid if current effective severity level
127 // is DEBUG).
128 int
130  Level level = LoggerLevelImpl::convertToBindLevel(logger_.getChainedLogLevel());
131  return level.dbglevel;
132 }
133 
134 
135 // Output a general message
136 boost::shared_ptr<string>
138  return (boost::make_shared<string>(string(ident) + " " +
139  MessageDictionary::globalDictionary()->getText(ident)));
140 }
141 
142 // Replace the interprocess synchronization object
143 
144 void
146  if (sync == NULL) {
148  "NULL was passed to setInterprocessSync()");
149  }
150 
151  delete sync_;
152  sync_ = sync;
153 }
154 
155 void
156 LoggerImpl::outputRaw(const Severity& severity, const string& message) {
157  // Use a mutex locker for mutual exclusion from other threads in
158  // this process.
159  std::lock_guard<std::mutex> mutex_locker(LoggerManager::getMutex());
160 
161  // Use an interprocess sync locker for mutual exclusion from other
162  // processes to avoid log messages getting interspersed.
164 
165  if (!locker.lock()) {
166  LOG4CPLUS_ERROR(logger_, "Unable to lock logger lockfile");
167  }
168 
169  switch (severity) {
170  case DEBUG:
171  LOG4CPLUS_DEBUG(logger_, message);
172  break;
173 
174  case INFO:
175  LOG4CPLUS_INFO(logger_, message);
176  break;
177 
178  case WARN:
179  LOG4CPLUS_WARN(logger_, message);
180  break;
181 
182  case ERROR:
183  LOG4CPLUS_ERROR(logger_, message);
184  break;
185 
186  case FATAL:
187  LOG4CPLUS_FATAL(logger_, message);
188  break;
189 
190  case NONE:
191  break;
192 
193  default:
194  LOG4CPLUS_ERROR(logger_,
195  "Unsupported severity in LoggerImpl::outputRaw(): "
196  << severity);
197  }
198 
199  if (!locker.unlock()) {
200  LOG4CPLUS_ERROR(logger_, "Unable to unlock logger lockfile");
201  }
202 }
203 
204 bool
206  // Get the appender for the name under which this logger is registered.
207  log4cplus::SharedAppenderPtrList appenders(
208  log4cplus::Logger::getInstance(name_).getAllAppenders());
209 
210  // If there are no appenders, they might be under the root name.
211  if (appenders.size() == 0) {
212  appenders = log4cplus::Logger::getInstance(getRootLoggerName()).getAllAppenders();
213  }
214 
215  for (log4cplus::helpers::SharedObjectPtr<log4cplus::Appender> logger : appenders) {
216  if (destination == OutputOption::DEST_CONSOLE &&
217  dynamic_cast<log4cplus::ConsoleAppender*>(logger.get())) {
218  return true;
219  } else if (destination == OutputOption::DEST_FILE &&
220  dynamic_cast<log4cplus::FileAppender*>(logger.get())) {
221  return true;
222  } else if (destination == OutputOption::DEST_SYSLOG &&
223  dynamic_cast<log4cplus::SysLogAppender*>(logger.get())) {
224  return true;
225  }
226  }
227  return false;
228 }
229 
230 } // namespace log
231 } // namespace isc
const std::string & getRootLoggerName()
Get root logger name.
Definition: logger_name.cc:33
Logger Class.
Definition: log/logger.h:142
static const MessageDictionaryPtr & globalDictionary()
Return Global Dictionary.
virtual Severity getEffectiveSeverity()
Get Effective Severity Level for Logger.
Definition: logger_impl.cc:121
Severity severity
Logging severity.
Definition: logger_level.h:43
Bad Interprocess Sync.
Definition: log/logger.h:92
STL namespace.
static log4cplus::LogLevel convertFromBindLevel(const isc::log::Level &level)
Convert Kea level to log4cplus logging level.
static std::mutex & getMutex()
Return a process-global mutex that&#39;s used for mutual exclusion among threads of a single process duri...
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
virtual ~LoggerImpl()
Destructor.
Definition: logger_impl.cc:84
Destination
Destinations.
Definition: output_option.h:48
int dbglevel
Debug level.
Definition: logger_level.h:44
Severity
Severity Levels.
Definition: logger_level.h:23
void setInterprocessSync(isc::log::interprocess::InterprocessSync *sync)
Replace the interprocess synchronization object.
Definition: logger_impl.cc:145
boost::shared_ptr< std::string > lookupMessage(const MessageID &id)
Look up message text in dictionary.
Definition: logger_impl.cc:137
static isc::log::Level convertToBindLevel(const log4cplus::LogLevel loglevel)
Convert log4cplus logging level to Kea logging level.
bool hasAppender(OutputOption::Destination const destination)
Check if this logger has an appender of the given type.
Definition: logger_impl.cc:205
std::string expandLoggerName(const std::string &name)
Expand logger name.
Definition: logger_name.cc:42
Defines the logger used by the top-level component of kea-lfc.
isc::log::Logger logger("asiodns")
Use the ASIO logger.
Log level structure.
Definition: logger_level.h:42
File-based Interprocess Sync Class.
bool lockfileEnabled()
detects whether file locking is enabled or disabled
Definition: logger_impl.cc:57
const Name & name_
Definition: dns/message.cc:693
static std::string getVersion()
Version.
Definition: logger_impl.cc:90
virtual int getDebugLevel()
Return debug level.
Definition: logger_impl.cc:113
virtual void setSeverity(Severity severity, int dbglevel=1)
Set Severity Level for Logger.
Definition: logger_impl.cc:99
void outputRaw(const Severity &severity, const std::string &message)
Raw output.
Definition: logger_impl.cc:156
const char * MessageID
Definition: message_types.h:15
virtual Severity getSeverity()
Get Severity Level for Logger.
Definition: logger_impl.cc:106
bool lock()
Acquire the lock (blocks if something else has acquired a lock on the same task name) ...
virtual int getEffectiveDebugLevel()
Return effective debug level.
Definition: logger_impl.cc:129