OpenVDB: logging.h Source File

OpenVDB 7.0.0

logging.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3
4 #ifndef OPENVDB_UTIL_LOGGING_HAS_BEEN_INCLUDED
5 #define OPENVDB_UTIL_LOGGING_HAS_BEEN_INCLUDED
6
7 #include <openvdb/version.h>
8
9 #ifdef OPENVDB_USE_LOG4CPLUS
10
11 #include <log4cplus/appender.h>
12 #include <log4cplus/configurator.h>
13 #include <log4cplus/consoleappender.h>
14 #include <log4cplus/layout.h>
15 #include <log4cplus/logger.h>
16 #include <log4cplus/spi/loggingevent.h>
17 #include <algorithm> // for std::remove()
18 #include <cstring> // for ::strrchr()
19 #include <memory>
20 #include <sstream>
21 #include <string>
22 #include <vector>
23
24
25 namespace openvdb {
26 OPENVDB_USE_VERSION_NAMESPACE
27 namespace OPENVDB_VERSION_NAME {
28 namespace logging {
29
31 enum class Level {
32 Debug = log4cplus::DEBUG_LOG_LEVEL,
33 Info = log4cplus::INFO_LOG_LEVEL,
34 Warn = log4cplus::WARN_LOG_LEVEL,
35 Error = log4cplus::ERROR_LOG_LEVEL,
36 Fatal = log4cplus::FATAL_LOG_LEVEL
37 };
38
39
40 namespace internal {
41
44 class ColoredPatternLayout: public log4cplus::PatternLayout
45 {
46 public:
47 explicit ColoredPatternLayout(const std::string& progName_, bool useColor = true)
48 : log4cplus::PatternLayout(
49 progName_.empty() ? std::string{"%5p: %m%n"} : (progName_ + " %5p: %m%n"))
50 , mUseColor(useColor)
51 , mProgName(progName_)
52 {
53 }
54
55 ~ColoredPatternLayout() override {}
56
57 const std::string& progName() const { return mProgName; }
58
59 void formatAndAppend(log4cplus::tostream& strm,
60 const log4cplus::spi::InternalLoggingEvent& event) override
61 {
62 if (!mUseColor) {
63 log4cplus::PatternLayout::formatAndAppend(strm, event);
64 return;
65 }
66 log4cplus::tostringstream s;
67 switch (event.getLogLevel()) {
68 case log4cplus::DEBUG_LOG_LEVEL: s << "\033[32m"; break; // green
69 case log4cplus::ERROR_LOG_LEVEL:
70 case log4cplus::FATAL_LOG_LEVEL: s << "\033[31m"; break; // red
71 case log4cplus::INFO_LOG_LEVEL: s << "\033[36m"; break; // cyan
72 case log4cplus::WARN_LOG_LEVEL: s << "\033[35m"; break; // magenta
73 }
74 log4cplus::PatternLayout::formatAndAppend(s, event);
75 strm << s.str() << "\033[0m" << std::flush;
76 }
77
78 // Disable deprecation warnings for std::auto_ptr.
79 #if defined(__ICC)
80 #pragma warning push
81 #pragma warning disable:1478
82 #elif defined(__clang__)
83 #pragma clang diagnostic push
84 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
85 #elif defined(__GNUC__)
86 #pragma GCC diagnostic push
87 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
88 #endif
89
90 #if defined(LOG4CPLUS_VERSION) && defined(LOG4CPLUS_MAKE_VERSION)
91 #if LOG4CPLUS_VERSION >= LOG4CPLUS_MAKE_VERSION(2, 0, 0)
92 // In log4cplus 2.0.0, std::auto_ptr was replaced with std::unique_ptr.
93 using Ptr = std::unique_ptr<log4cplus::Layout>;
94 #else
95 using Ptr = std::auto_ptr<log4cplus::Layout>;
96 #endif
97 #else
98 using Ptr = std::auto_ptr<log4cplus::Layout>;
99 #endif
100
101 static Ptr create(const std::string& progName_, bool useColor = true)
102 {
103 return Ptr{new ColoredPatternLayout{progName_, useColor}};
104 }
105
106 #if defined(__ICC)
107 #pragma warning pop
108 #elif defined(__clang__)
109 #pragma clang diagnostic pop
110 #elif defined(__GNUC__)
111 #pragma GCC diagnostic pop
112 #endif
113
114 private:
115 bool mUseColor = true;
116 std::string mProgName;
117 }; // class ColoredPatternLayout
118
119
120 inline log4cplus::Logger
121 getLogger()
122 {
123 return log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("openvdb"));
124 }
125
126
127 inline log4cplus::SharedAppenderPtr
128 getAppender()
129 {
130 return getLogger().getAppender(LOG4CPLUS_TEXT("OPENVDB"));
131 }
132
133 } // namespace internal
134
135
137 inline Level
138 getLevel()
139 {
140 switch (internal::getLogger().getLogLevel()) {
141 case log4cplus::DEBUG_LOG_LEVEL: return Level::Debug;
142 case log4cplus::INFO_LOG_LEVEL: return Level::Info;
143 case log4cplus::WARN_LOG_LEVEL: return Level::Warn;
144 case log4cplus::ERROR_LOG_LEVEL: return Level::Error;
145 case log4cplus::FATAL_LOG_LEVEL: break;
146 }
147 return Level::Fatal;
148 }
149
150
152 inline void
153 setLevel(Level lvl)
154 {
155 internal::getLogger().setLogLevel(static_cast<log4cplus::LogLevel>(lvl));
156 }
157
158
162 inline void
163 setLevel(int& argc, char* argv[])
164 {
165 for (int i = 1; i < argc; ++i) { // note: skip argv[0]
166 const std::string arg{argv[i]};
167 bool remove = true;
168 if (arg == "-debug") { setLevel(Level::Debug); }
169 else if (arg == "-error") { setLevel(Level::Error); }
170 else if (arg == "-fatal") { setLevel(Level::Fatal); }
171 else if (arg == "-info") { setLevel(Level::Info); }
172 else if (arg == "-warn") { setLevel(Level::Warn); }
173 else { remove = false; }
174 if (remove) argv[i] = nullptr;
175 }
176 auto end = std::remove(argv + 1, argv + argc, nullptr);
177 argc = static_cast<int>(end - argv);
178 }
179
180
182 inline void
183 setProgramName(const std::string& progName, bool useColor = true)
184 {
185 // Change the layout of the OpenVDB appender to use colored text
186 // and to incorporate the supplied program name.
187 if (auto appender = internal::getAppender()) {
188 appender->setLayout(internal::ColoredPatternLayout::create(progName, useColor));
189 }
190 }
191
192
194 inline void
195 initialize(bool useColor = true)
196 {
197 log4cplus::initialize();
198
199 if (internal::getAppender()) return; // already initialized
200
201 // Create the OpenVDB logger if it doesn't already exist.
202 auto logger = internal::getLogger();
203
204 // Disable "additivity", so that OpenVDB-related messages are directed
205 // to the OpenVDB logger only and are not forwarded up the logger tree.
206 logger.setAdditivity(false);
207
208 // Attach a console appender to the OpenVDB logger.
209 if (auto appender = log4cplus::SharedAppenderPtr{new log4cplus::ConsoleAppender}) {
210 appender->setName(LOG4CPLUS_TEXT("OPENVDB"));
211 logger.addAppender(appender);
212 }
213
214 setLevel(Level::Warn);
215 setProgramName("", useColor);
216 }
217
218
223 inline void
224 initialize(int& argc, char* argv[], bool useColor = true)
225 {
226 initialize();
227
228 setLevel(argc, argv);
229
230 auto progName = (argc > 0 ? argv[0] : "");
231 if (const char* ptr = ::strrchr(progName, '/')) progName = ptr + 1;
232 setProgramName(progName, useColor);
233 }
234
235 } // namespace logging
236 } // namespace OPENVDB_VERSION_NAME
237 } // namespace openvdb
238
239
240 #define OPENVDB_LOG(level, message) \
241 do { \
242 auto _log = openvdb::logging::internal::getLogger(); \
243 if (_log.isEnabledFor(log4cplus::level##_LOG_LEVEL)) { \
244 std::ostringstream _buf; \
245 _buf << message; \
246 _log.forcedLog(log4cplus::level##_LOG_LEVEL, _buf.str(), __FILE__, __LINE__); \
247 } \
248 } while (0);
249
251 #define OPENVDB_LOG_INFO(message) OPENVDB_LOG(INFO, message)
252 #define OPENVDB_LOG_WARN(message) OPENVDB_LOG(WARN, message)
254 #define OPENVDB_LOG_ERROR(message) OPENVDB_LOG(ERROR, message)
256 #define OPENVDB_LOG_FATAL(message) OPENVDB_LOG(FATAL, message)
258 #ifdef DEBUG
259 #define OPENVDB_LOG_DEBUG(message) OPENVDB_LOG(DEBUG, message)
261 #else
262 #define OPENVDB_LOG_DEBUG(message)
264 #endif
265 #define OPENVDB_LOG_DEBUG_RUNTIME(message) OPENVDB_LOG(DEBUG, message)
268
269 #else // ifdef OPENVDB_USE_LOG4CPLUS
270
271 #include <iostream>
272
273 #define OPENVDB_LOG_INFO(mesg)
274 #define OPENVDB_LOG_WARN(mesg) do { std::cerr << "WARNING: " << mesg << std::endl; } while (0);
275 #define OPENVDB_LOG_ERROR(mesg) do { std::cerr << "ERROR: " << mesg << std::endl; } while (0);
276 #define OPENVDB_LOG_FATAL(mesg) do { std::cerr << "FATAL: " << mesg << std::endl; } while (0);
277 #define OPENVDB_LOG_DEBUG(mesg)
278 #define OPENVDB_LOG_DEBUG_RUNTIME(mesg)
279
280 namespace openvdb {
281 OPENVDB_USE_VERSION_NAMESPACE
282 namespace OPENVDB_VERSION_NAME {
283 namespace logging {
284
285 enum class Level { Debug, Info, Warn, Error, Fatal };
286
287 inline Level getLevel() { return Level::Warn; }
288 inline void setLevel(Level) {}
289 inline void setLevel(int&, char*[]) {}
290 inline void setProgramName(const std::string&, bool = true) {}
291 inline void initialize() {}
292 inline void initialize(int&, char*[], bool = true) {}
293
294 } // namespace logging
295 } // namespace OPENVDB_VERSION_NAME
296 } // namespace openvdb
297
298 #endif // OPENVDB_USE_LOG4CPLUS
299
300
301 namespace openvdb {
302 OPENVDB_USE_VERSION_NAMESPACE
303 namespace OPENVDB_VERSION_NAME {
304 namespace logging {
305
308 struct LevelScope
309 {
310 Level level;
311 explicit LevelScope(Level newLevel): level(getLevel()) { setLevel(newLevel); }
312 ~LevelScope() { setLevel(level); }
313 };
314
315 } // namespace logging
316 } // namespace OPENVDB_VERSION_NAME
317 } // namespace openvdb
318
319 #endif // OPENVDB_UTIL_LOGGING_HAS_BEEN_INCLUDED
openvdb::v7_0::logging::Level::Fatal
@ Fatal
openvdb::v7_0::logging::internal::ColoredPatternLayout
log4cplus layout that outputs text in different colors for different log levels, using ANSI escape co...
Definition: logging.h:45
version.h
Library and file format version numbers.
openvdb::v7_0::logging::setProgramName
void setProgramName(const std::string &progName, bool useColor=true)
Specify a program name to be displayed in log messages.
Definition: logging.h:183
openvdb::v7_0::logging::LevelScope::LevelScope
LevelScope(Level newLevel)
Definition: logging.h:311
openvdb::v7_0::logging::initialize
void initialize(int &argc, char *argv[], bool useColor=true)
Initialize the logging system from command-line arguments.
Definition: logging.h:224
openvdb::v7_0::logging::Level::Info
@ Info
openvdb::v7_0::logging::Level::Warn
@ Warn
openvdb::v7_0::logging::internal::getLogger
log4cplus::Logger getLogger()
Definition: logging.h:121
openvdb::v7_0::logging::internal::ColoredPatternLayout::formatAndAppend
void formatAndAppend(log4cplus::tostream &strm, const log4cplus::spi::InternalLoggingEvent &event) override
Definition: logging.h:59
openvdb::v7_0::logging::Level::Debug
@ Debug
openvdb::v7_0::logging::internal::ColoredPatternLayout::progName
const std::string & progName() const
Definition: logging.h:57
openvdb::v7_0::logging::LevelScope::~LevelScope
~LevelScope()
Definition: logging.h:312
openvdb::v7_0::logging::Level
Level
Message severity level.
Definition: logging.h:31
openvdb::v7_0::logging::LevelScope::level
Level level
Definition: logging.h:310
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:154
openvdb::v7_0::logging::internal::getAppender
log4cplus::SharedAppenderPtr getAppender()
Definition: logging.h:128
openvdb::v7_0::logging::getLevel
Level getLevel()
Return the current logging level.
Definition: logging.h:138
openvdb::v7_0::logging::internal::ColoredPatternLayout::ColoredPatternLayout
ColoredPatternLayout(const std::string &progName_, bool useColor=true)
Definition: logging.h:47
openvdb::v7_0::logging::Level::Error
@ Error
openvdb::v7_0::logging::LevelScope
A LevelScope object sets the logging level to a given level and restores it to the current level when...
Definition: logging.h:309
std
Definition: Coord.h:587
openvdb::v7_0::logging::internal::ColoredPatternLayout::Ptr
std::auto_ptr< log4cplus::Layout > Ptr
Definition: logging.h:98
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:102
openvdb
Definition: Exceptions.h:13
openvdb::v7_0::logging::setLevel
void setLevel(int &argc, char *argv[])
If "-debug", "-info", "-warn", "-error" or "-fatal" is found in the given array of command-line argum...
Definition: logging.h:163
openvdb::v7_0::logging::internal::ColoredPatternLayout::create
static Ptr create(const std::string &progName_, bool useColor=true)
Definition: logging.h:101
openvdb::v7_0::logging::internal::ColoredPatternLayout::~ColoredPatternLayout
~ColoredPatternLayout() override
Definition: logging.h:55