HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
logging.h
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2012-2018 DreamWorks Animation LLC
4 //
5 // All rights reserved. This software is distributed under the
6 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
7 //
8 // Redistributions of source code must retain the above copyright
9 // and license notice and the following restrictions and disclaimer.
10 //
11 // * Neither the name of DreamWorks Animation nor the names of
12 // its contributors may be used to endorse or promote products derived
13 // from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
20 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 // IN NO EVENT SHALL THE COPYRIGHT HOLDERS' AND CONTRIBUTORS' AGGREGATE
27 // LIABILITY FOR ALL CLAIMS REGARDLESS OF THEIR BASIS EXCEED US$250.00.
28 //
29 ///////////////////////////////////////////////////////////////////////////
30 
31 #ifndef OPENVDB_UTIL_LOGGING_HAS_BEEN_INCLUDED
32 #define OPENVDB_UTIL_LOGGING_HAS_BEEN_INCLUDED
33 
34 #include <openvdb/version.h>
35 
36 #ifdef OPENVDB_USE_LOG4CPLUS
37 
38 #include <log4cplus/appender.h>
39 #include <log4cplus/configurator.h>
40 #include <log4cplus/consoleappender.h>
41 #include <log4cplus/layout.h>
42 #include <log4cplus/logger.h>
43 #include <log4cplus/spi/loggingevent.h>
44 #include <algorithm> // for std::remove()
45 #include <cstring> // for ::strrchr()
46 #include <memory>
47 #include <sstream>
48 #include <string>
49 #include <vector>
50 
51 
52 namespace openvdb {
54 namespace OPENVDB_VERSION_NAME {
55 namespace logging {
56 
57 /// @brief Message severity level
58 enum class Level {
59  Debug = log4cplus::DEBUG_LOG_LEVEL,
60  Info = log4cplus::INFO_LOG_LEVEL,
61  Warn = log4cplus::WARN_LOG_LEVEL,
62  Error = log4cplus::ERROR_LOG_LEVEL,
63  Fatal = log4cplus::FATAL_LOG_LEVEL
64 };
65 
66 
67 namespace internal {
68 
69 /// @brief log4cplus layout that outputs text in different colors
70 /// for different log levels, using ANSI escape codes
71 class ColoredPatternLayout: public log4cplus::PatternLayout
72 {
73 public:
74  explicit ColoredPatternLayout(const std::string& progName_, bool useColor = true)
75  : log4cplus::PatternLayout(
76  progName_.empty() ? std::string{"%5p: %m%n"} : (progName_ + " %5p: %m%n"))
77  , mUseColor(useColor)
78  , mProgName(progName_)
79  {
80  }
81 
82  ~ColoredPatternLayout() override {}
83 
84  const std::string& progName() const { return mProgName; }
85 
86  void formatAndAppend(log4cplus::tostream& strm,
87  const log4cplus::spi::InternalLoggingEvent& event) override
88  {
89  if (!mUseColor) {
90  log4cplus::PatternLayout::formatAndAppend(strm, event);
91  return;
92  }
93  log4cplus::tostringstream s;
94  switch (event.getLogLevel()) {
95  case log4cplus::DEBUG_LOG_LEVEL: s << "\033[32m"; break; // green
96  case log4cplus::ERROR_LOG_LEVEL:
97  case log4cplus::FATAL_LOG_LEVEL: s << "\033[31m"; break; // red
98  case log4cplus::INFO_LOG_LEVEL: s << "\033[36m"; break; // cyan
99  case log4cplus::WARN_LOG_LEVEL: s << "\033[35m"; break; // magenta
100  }
101  log4cplus::PatternLayout::formatAndAppend(s, event);
102  strm << s.str() << "\033[0m" << std::flush;
103  }
104 
105 // Disable deprecation warnings for std::auto_ptr.
106 #if defined(__ICC)
107  #pragma warning push
108  #pragma warning disable:1478
109 #elif defined(__clang__)
110  #pragma clang diagnostic push
111  #pragma clang diagnostic ignored "-Wdeprecated-declarations"
112 #elif defined(__GNUC__)
113  #pragma GCC diagnostic push
114  #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
115 #endif
116 
117 #if defined(LOG4CPLUS_VERSION) && defined(LOG4CPLUS_MAKE_VERSION)
118  #if LOG4CPLUS_VERSION >= LOG4CPLUS_MAKE_VERSION(2, 0, 0)
119  // In log4cplus 2.0.0, std::auto_ptr was replaced with std::unique_ptr.
120  using Ptr = std::unique_ptr<log4cplus::Layout>;
121  #else
122  using Ptr = std::auto_ptr<log4cplus::Layout>;
123  #endif
124 #else
125  using Ptr = std::auto_ptr<log4cplus::Layout>;
126 #endif
127 
128  static Ptr create(const std::string& progName_, bool useColor = true)
129  {
130  return Ptr{new ColoredPatternLayout{progName_, useColor}};
131  }
132 
133 #if defined(__ICC)
134  #pragma warning pop
135 #elif defined(__clang__)
136  #pragma clang diagnostic pop
137 #elif defined(__GNUC__)
138  #pragma GCC diagnostic pop
139 #endif
140 
141 private:
142  bool mUseColor = true;
143  std::string mProgName;
144 }; // class ColoredPatternLayout
145 
146 
147 inline log4cplus::Logger
148 getLogger()
149 {
150  return log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("openvdb"));
151 }
152 
153 
154 inline log4cplus::SharedAppenderPtr
155 getAppender()
156 {
157  return getLogger().getAppender(LOG4CPLUS_TEXT("OPENVDB"));
158 }
159 
160 } // namespace internal
161 
162 
163 /// @brief Return the current logging level.
164 inline Level
165 getLevel()
166 {
167  switch (internal::getLogger().getLogLevel()) {
168  case log4cplus::DEBUG_LOG_LEVEL: return Level::Debug;
169  case log4cplus::INFO_LOG_LEVEL: return Level::Info;
170  case log4cplus::WARN_LOG_LEVEL: return Level::Warn;
171  case log4cplus::ERROR_LOG_LEVEL: return Level::Error;
172  case log4cplus::FATAL_LOG_LEVEL: break;
173  }
174  return Level::Fatal;
175 }
176 
177 
178 /// @brief Set the logging level. (Lower-level messages will be suppressed.)
179 inline void
180 setLevel(Level lvl)
181 {
182  internal::getLogger().setLogLevel(static_cast<log4cplus::LogLevel>(lvl));
183 }
184 
185 
186 /// @brief If "-debug", "-info", "-warn", "-error" or "-fatal" is found
187 /// in the given array of command-line arguments, set the logging level
188 /// appropriately and remove the relevant argument(s) from the array.
189 inline void
190 setLevel(int& argc, char* argv[])
191 {
192  for (int i = 1; i < argc; ++i) { // note: skip argv[0]
193  const std::string arg{argv[i]};
194  bool remove = true;
195  if (arg == "-debug") { setLevel(Level::Debug); }
196  else if (arg == "-error") { setLevel(Level::Error); }
197  else if (arg == "-fatal") { setLevel(Level::Fatal); }
198  else if (arg == "-info") { setLevel(Level::Info); }
199  else if (arg == "-warn") { setLevel(Level::Warn); }
200  else { remove = false; }
201  if (remove) argv[i] = nullptr;
202  }
203  auto end = std::remove(argv + 1, argv + argc, nullptr);
204  argc = static_cast<int>(end - argv);
205 }
206 
207 
208 /// @brief Specify a program name to be displayed in log messages.
209 inline void
210 setProgramName(const std::string& progName, bool useColor = true)
211 {
212  // Change the layout of the OpenVDB appender to use colored text
213  // and to incorporate the supplied program name.
214  if (auto appender = internal::getAppender()) {
215  appender->setLayout(internal::ColoredPatternLayout::create(progName, useColor));
216  }
217 }
218 
219 
220 /// @brief Initialize the logging system if it is not already initialized.
221 inline void
222 initialize(bool useColor = true)
223 {
225 
226  if (internal::getAppender()) return; // already initialized
227 
228  // Create the OpenVDB logger if it doesn't already exist.
229  auto logger = internal::getLogger();
230 
231  // Disable "additivity", so that OpenVDB-related messages are directed
232  // to the OpenVDB logger only and are not forwarded up the logger tree.
233  logger.setAdditivity(false);
234 
235  // Attach a console appender to the OpenVDB logger.
236  if (auto appender = log4cplus::SharedAppenderPtr{new log4cplus::ConsoleAppender}) {
237  appender->setName(LOG4CPLUS_TEXT("OPENVDB"));
238  logger.addAppender(appender);
239  }
240 
242  setProgramName("", useColor);
243 }
244 
245 
246 /// @brief Initialize the logging system from command-line arguments.
247 /// @details If "-debug", "-info", "-warn", "-error" or "-fatal" is found
248 /// in the given array of command-line arguments, set the logging level
249 /// appropriately and remove the relevant argument(s) from the array.
250 inline void
251 initialize(int& argc, char* argv[], bool useColor = true)
252 {
253  initialize();
254 
255  setLevel(argc, argv);
256 
257  auto progName = (argc > 0 ? argv[0] : "");
258  if (const char* ptr = ::strrchr(progName, '/')) progName = ptr + 1;
259  setProgramName(progName, useColor);
260 }
261 
262 } // namespace logging
263 } // namespace OPENVDB_VERSION_NAME
264 } // namespace openvdb
265 
266 
267 #define OPENVDB_LOG(level, message) \
268  do { \
269  auto _log = openvdb::logging::internal::getLogger(); \
270  if (_log.isEnabledFor(log4cplus::level##_LOG_LEVEL)) { \
271  std::ostringstream _buf; \
272  _buf << message; \
273  _log.forcedLog(log4cplus::level##_LOG_LEVEL, _buf.str(), __FILE__, __LINE__); \
274  } \
275  } while (0);
276 
277 /// Log an info message of the form '<TT>someVar << "some text" << ...</TT>'.
278 #define OPENVDB_LOG_INFO(message) OPENVDB_LOG(INFO, message)
279 /// Log a warning message of the form '<TT>someVar << "some text" << ...</TT>'.
280 #define OPENVDB_LOG_WARN(message) OPENVDB_LOG(WARN, message)
281 /// Log an error message of the form '<TT>someVar << "some text" << ...</TT>'.
282 #define OPENVDB_LOG_ERROR(message) OPENVDB_LOG(ERROR, message)
283 /// Log a fatal error message of the form '<TT>someVar << "some text" << ...</TT>'.
284 #define OPENVDB_LOG_FATAL(message) OPENVDB_LOG(FATAL, message)
285 #ifdef DEBUG
286 /// In debug builds only, log a debugging message of the form '<TT>someVar << "text" << ...</TT>'.
287 #define OPENVDB_LOG_DEBUG(message) OPENVDB_LOG(DEBUG, message)
288 #else
289 /// In debug builds only, log a debugging message of the form '<TT>someVar << "text" << ...</TT>'.
290 #define OPENVDB_LOG_DEBUG(message)
291 #endif
292 /// @brief Log a debugging message in both debug and optimized builds.
293 /// @warning Don't use this in performance-critical code.
294 #define OPENVDB_LOG_DEBUG_RUNTIME(message) OPENVDB_LOG(DEBUG, message)
295 
296 #else // ifdef OPENVDB_USE_LOG4CPLUS
297 
298 #include <iostream>
299 
300 #define OPENVDB_LOG_INFO(mesg)
301 #define OPENVDB_LOG_WARN(mesg) do { std::cerr << "WARNING: " << mesg << std::endl; } while (0);
302 #define OPENVDB_LOG_ERROR(mesg) do { std::cerr << "ERROR: " << mesg << std::endl; } while (0);
303 #define OPENVDB_LOG_FATAL(mesg) do { std::cerr << "FATAL: " << mesg << std::endl; } while (0);
304 #define OPENVDB_LOG_DEBUG(mesg)
305 #define OPENVDB_LOG_DEBUG_RUNTIME(mesg)
306 
307 namespace openvdb {
309 namespace OPENVDB_VERSION_NAME {
310 namespace logging {
311 
312 enum class Level { Debug, Info, Warn, Error, Fatal };
313 
314 inline Level getLevel() { return Level::Warn; }
315 inline void setLevel(Level) {}
316 inline void setLevel(int&, char*[]) {}
317 inline void setProgramName(const std::string&, bool = true) {}
318 inline void initialize() {}
319 inline void initialize(int&, char*[], bool = true) {}
320 
321 } // namespace logging
322 } // namespace OPENVDB_VERSION_NAME
323 } // namespace openvdb
324 
325 #endif // OPENVDB_USE_LOG4CPLUS
326 
327 
328 namespace openvdb {
330 namespace OPENVDB_VERSION_NAME {
331 namespace logging {
332 
333 /// @brief A LevelScope object sets the logging level to a given level
334 /// and restores it to the current level when the object goes out of scope.
336 {
338  explicit LevelScope(Level newLevel): level(getLevel()) { setLevel(newLevel); }
340 };
341 
342 } // namespace logging
343 } // namespace OPENVDB_VERSION_NAME
344 } // namespace openvdb
345 
346 #endif // OPENVDB_UTIL_LOGGING_HAS_BEEN_INCLUDED
347 
348 // Copyright (c) 2012-2018 DreamWorks Animation LLC
349 // All rights reserved. This software is distributed under the
350 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
GLsizei const GLchar *const * string
Definition: glcorearb.h:813
png_voidp ptr
Definition: png.h:2145
GLint level
Definition: glcorearb.h:107
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:189
A LevelScope object sets the logging level to a given level and restores it to the current level when...
Definition: logging.h:335
png_uint_32 i
Definition: png.h:2877
void initialize(int &, char *[], bool=true)
Definition: logging.h:319
struct _cl_event * event
Definition: glcorearb.h:2960
GLuint GLuint end
Definition: glcorearb.h:474
void setProgramName(const std::string &, bool=true)
Definition: logging.h:317
void initialize()
Global registration of basic types.
Definition: logging.h:318
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:135