Kea 3.0.3-git
logger_level_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#include <algorithm>
10#include <string.h>
11#include <iostream>
12#include <boost/lexical_cast.hpp>
13#include <boost/static_assert.hpp>
14
15#include <log4cplus/logger.h>
16
17#include <log/logger_level.h>
20#include <log/macros.h>
21
22using namespace log4cplus;
23using namespace std;
24
25namespace {
27}
28
29namespace isc {
30namespace log {
31
32// Convert Kea level to a log4cplus logging level.
33log4cplus::LogLevel
35
36 // Kea logging levels are small integers so we can do a table lookup
37 static const log4cplus::LogLevel log4cplus_levels[] = {
38 log4cplus::NOT_SET_LOG_LEVEL,
39 log4cplus::DEBUG_LOG_LEVEL,
40 log4cplus::INFO_LOG_LEVEL,
41 log4cplus::WARN_LOG_LEVEL,
42 log4cplus::ERROR_LOG_LEVEL,
43 log4cplus::FATAL_LOG_LEVEL,
44 log4cplus::OFF_LOG_LEVEL
45 };
46
47 // ... with compile-time checks to ensure that table indexes are correct.
48 static_assert(static_cast<int>(DEFAULT) == 0,
49 "static_cast<int>(DEFAULT) == 0");
50 static_assert(static_cast<int>(DEBUG) == 1,
51 "static_cast<int>(DEBUG) == 1");
52 static_assert(static_cast<int>(INFO) == 2,
53 "static_cast<int>(INFO) == 2");
54 static_assert(static_cast<int>(WARN) == 3,
55 "static_cast<int>(WARN) == 3");
56 static_assert(static_cast<int>(ERROR) == 4,
57 "static_cast<int>(ERROR) == 4");
58 static_assert(static_cast<int>(FATAL) == 5,
59 "static_cast<int>(FATAL) == 5");
60 static_assert(static_cast<int>(NONE) == 6,
61 "static_cast<int>(NONE) == 6");
62
63 // Do the conversion
64 if (level.severity == DEBUG) {
65
66 // Debug severity, so the log4cplus level returned depends on the
67 // debug level. Silently limit the debug level to the range
68 // MIN_DEBUG_LEVEL to MAX_DEBUG_LEVEL (avoids the hassle of throwing
69 // and catching exceptions and besides, this is for debug information).
70 int limited = std::max(MIN_DEBUG_LEVEL,
71 std::min(level.dbglevel, MAX_DEBUG_LEVEL));
72 LogLevel newlevel = static_cast<int>(DEBUG_LOG_LEVEL -
73 (limited - MIN_DEBUG_LEVEL));
74 return (static_cast<log4cplus::LogLevel>(newlevel));
75
76 } else {
77
78 // Can do a table lookup to speed things up. There is no need to check
79 // that the index is out of range. That the variable is of type
80 // isc::log::Severity ensures that it must be one of the Severity enum
81 // members - conversion of a numeric value to an enum is not permitted.
82 return (log4cplus_levels[level.severity]);
83 }
84}
85
86// Convert log4cplus logging level to Kea debug level. It is up to the
87// caller to validate that the debug level is valid.
89LoggerLevelImpl::convertToBindLevel(const log4cplus::LogLevel loglevel) {
90
91 // Not easy to do a table lookup as the numerical values of log4cplus levels
92 // are quite high.
93 if (loglevel <= log4cplus::NOT_SET_LOG_LEVEL) {
94 return (Level(DEFAULT));
95
96 } else if (loglevel <= log4cplus::DEBUG_LOG_LEVEL) {
97
98 // Debug severity, so extract the debug level from the numeric value.
99 // If outside the limits, change the severity to the level above or
100 // below.
101 int dbglevel = MIN_DEBUG_LEVEL +
102 static_cast<int>(log4cplus::DEBUG_LOG_LEVEL) -
103 static_cast<int>(loglevel);
104 if (dbglevel > MAX_DEBUG_LEVEL) {
105 return (Level(DEFAULT));
106 } else if (dbglevel < MIN_DEBUG_LEVEL) {
107 return (Level(INFO));
108 }
109 return (Level(DEBUG, dbglevel));
110
111 } else if (loglevel <= log4cplus::INFO_LOG_LEVEL) {
112 return (Level(INFO));
113
114 } else if (loglevel <= log4cplus::WARN_LOG_LEVEL) {
115 return (Level(WARN));
116
117 } else if (loglevel <= log4cplus::ERROR_LOG_LEVEL) {
118 return (Level(ERROR));
119
120 } else if (loglevel <= log4cplus::FATAL_LOG_LEVEL) {
121 return (Level(FATAL));
122
123 }
124
125 return (Level(NONE));
126}
127
128
129// Convert string to appropriate logging level
130log4cplus::LogLevel
131LoggerLevelImpl::logLevelFromString(const log4cplus::tstring& level) {
132
133 std::string name = level; // Get to known type
134 size_t length = name.size(); // Length of the string
135
136 if (length < 5) {
137
138 // String can't possibly start DEBUG so we don't know what it is.
139 // As per documentation, return NOT_SET level.
140 return (NOT_SET_LOG_LEVEL);
141 } else {
142 if (strncasecmp(name.c_str(), "DEBUG", 5) == 0) {
143
144 // String starts "DEBUG" (or "debug" or any case mixture). The
145 // rest of the string - if any - should be a number.
146 if (length == 5) {
147
148 // It is plain "DEBUG". Take this as level 0.
149 return (DEBUG_LOG_LEVEL);
150 } else {
151
152 // Try converting the remainder to an integer. The "5" is
153 // the length of the string "DEBUG". Note that if the number
154 // is outside the range of debug levels, it is coerced to the
155 // nearest limit. Thus a level of DEBUG509 will end up as
156 // if DEBUG99 has been specified.
157 try {
158 int dbglevel = boost::lexical_cast<int>(name.substr(5));
159 if (dbglevel < MIN_DEBUG_LEVEL) {
160 LOG_WARN(logger, LOGIMPL_BELOW_MIN_DEBUG).arg(dbglevel)
161 .arg(MIN_DEBUG_LEVEL);
162 dbglevel = MIN_DEBUG_LEVEL;
163
164 } else if (dbglevel > MAX_DEBUG_LEVEL) {
165 LOG_WARN(logger, LOGIMPL_ABOVE_MAX_DEBUG).arg(dbglevel)
166 .arg(MAX_DEBUG_LEVEL);
167 dbglevel = MAX_DEBUG_LEVEL;
168
169 }
170 return convertFromBindLevel(Level(DEBUG, dbglevel));
171 }
172 catch (const boost::bad_lexical_cast&) {
173 LOG_ERROR(logger, LOGIMPL_BAD_DEBUG_STRING).arg(name);
174 return (NOT_SET_LOG_LEVEL);
175 }
176 }
177 } else {
178
179 // Unknown string - return default. Log4cplus will call any other
180 // registered conversion functions to interpret it.
181 return (NOT_SET_LOG_LEVEL);
182 }
183 }
184}
185
186// Convert logging level to string. If the level is a valid debug level,
187// return the string DEBUG, else return the empty string.
188#if LOG4CPLUS_VERSION < LOG4CPLUS_MAKE_VERSION(2, 0, 0)
190#else
192#endif
193LoggerLevelImpl::logLevelToString(log4cplus::LogLevel level) {
194 Level bindlevel = convertToBindLevel(level);
195 Severity& severity = bindlevel.severity;
196 int& dbglevel = bindlevel.dbglevel;
197 static LoggerLevelImpl::LogLevelString debug_ = tstring("DEBUG");
198 static LoggerLevelImpl::LogLevelString empty_ = tstring();
199
200 if ((severity == DEBUG) &&
201 ((dbglevel >= MIN_DEBUG_LEVEL) && (dbglevel <= MAX_DEBUG_LEVEL))) {
202 return (debug_);
203 }
204
205 // Unknown, so return empty string for log4cplus to try other conversion
206 // functions.
207 return (empty_);
208}
209
210// Initialization. Register the conversion functions with the LogLevelManager.
211void
213
214 // Get the singleton log-level manager.
215 LogLevelManager& manager = getLogLevelManager();
216
217 // Register the conversion functions
218 manager.pushFromStringMethod(LoggerLevelImpl::logLevelFromString);
219 manager.pushToStringMethod(LoggerLevelImpl::logLevelToString);
220}
221
222} // namespace log
223} // namespace isc
static log4cplus::LogLevel convertFromBindLevel(const isc::log::Level &level)
Convert Kea level to log4cplus logging level.
static const LogLevelString & logLevelToString(log4cplus::LogLevel level)
Convert log level to string.
static log4cplus::LogLevel logLevelFromString(const log4cplus::tstring &level)
Convert string to log4cplus logging level.
log4cplus::tstring LogLevelString
static isc::log::Level convertToBindLevel(const log4cplus::LogLevel loglevel)
Convert log4cplus logging level to Kea logging level.
static void init()
Initialize extended logging levels.
Logger Class.
Definition log/logger.h:142
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition macros.h:32
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
Definition macros.h:26
isc::log::Logger logger("asiodns")
Use the ASIO logger.
const isc::log::MessageID LOGIMPL_BAD_DEBUG_STRING
const isc::log::MessageID LOGIMPL_BELOW_MIN_DEBUG
const isc::log::MessageID LOGIMPL_ABOVE_MAX_DEBUG
const int MAX_DEBUG_LEVEL
const int MIN_DEBUG_LEVEL
Minimum/maximum debug levels.
Severity
Severity Levels.
Defines the logger used by the top-level component of kea-lfc.
Log level structure.
int dbglevel
Debug level.
Severity severity
Logging severity.