HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
logging.h
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2012-2017 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 #ifdef OPENVDB_USE_LOG4CPLUS
35 
36 #include <log4cplus/appender.h>
37 #include <log4cplus/configurator.h>
38 #include <log4cplus/consoleappender.h>
39 #include <log4cplus/layout.h>
40 #include <log4cplus/logger.h>
41 #include <log4cplus/spi/loggingevent.h>
42 #include <algorithm> // for std::remove()
43 #include <cstring> // for ::strrchr()
44 #include <memory>
45 #include <sstream>
46 #include <string>
47 #include <vector>
48 
49 
50 namespace openvdb {
52 namespace OPENVDB_VERSION_NAME {
53 namespace logging {
54 
55 /// @brief Message severity level
56 enum class Level {
57  Debug = log4cplus::DEBUG_LOG_LEVEL,
58  Info = log4cplus::INFO_LOG_LEVEL,
59  Warn = log4cplus::WARN_LOG_LEVEL,
60  Error = log4cplus::ERROR_LOG_LEVEL,
61  Fatal = log4cplus::FATAL_LOG_LEVEL
62 };
63 
64 
65 namespace internal {
66 
67 /// @brief log4cplus layout that outputs text in different colors
68 /// for different log levels, using ANSI escape codes
69 class ColoredPatternLayout: public log4cplus::PatternLayout
70 {
71 public:
72  explicit ColoredPatternLayout(const std::string& progName_, bool useColor = true)
73  : log4cplus::PatternLayout(
74  progName_.empty() ? std::string{"%5p: %m%n"} : (progName_ + " %5p: %m%n"))
75  , mUseColor(useColor)
76  , mProgName(progName_)
77  {
78  }
79 
80  ~ColoredPatternLayout() override {}
81 
82  const std::string& progName() const { return mProgName; }
83 
84  void formatAndAppend(log4cplus::tostream& strm,
85  const log4cplus::spi::InternalLoggingEvent& event) override
86  {
87  if (!mUseColor) {
88  log4cplus::PatternLayout::formatAndAppend(strm, event);
89  return;
90  }
91  log4cplus::tostringstream s;
92  switch (event.getLogLevel()) {
93  case log4cplus::DEBUG_LOG_LEVEL: s << "\033[32m"; break; // green
94  case log4cplus::ERROR_LOG_LEVEL:
95  case log4cplus::FATAL_LOG_LEVEL: s << "\033[31m"; break; // red
96  case log4cplus::INFO_LOG_LEVEL: s << "\033[36m"; break; // cyan
97  case log4cplus::WARN_LOG_LEVEL: s << "\033[35m"; break; // magenta
98  }
99  log4cplus::PatternLayout::formatAndAppend(s, event);
100  strm << s.str() << "\033[0m" << std::flush;
101  }
102 
103 // Disable deprecation warnings for std::auto_ptr.
104 #if defined(__ICC)
105  #pragma warning push
106  #pragma warning disable:1478
107 #elif defined(__clang__)
108  #pragma clang diagnostic push
109  #pragma clang diagnostic ignored "-Wdeprecated-declarations"
110 #elif defined(__GNUC__)
111  #pragma GCC diagnostic push
112  #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
113 #endif
114 
115 #if defined(LOG4CPLUS_VERSION) && defined(LOG4CPLUS_MAKE_VERSION)
116  #if LOG4CPLUS_VERSION >= LOG4CPLUS_MAKE_VERSION(2, 0, 0)
117  // In log4cplus 2.0.0, std::auto_ptr was replaced with std::unique_ptr.
118  using Ptr = std::unique_ptr<log4cplus::Layout>;
119  #else
120  using Ptr = std::auto_ptr<log4cplus::Layout>;
121  #endif
122 #else
123  using Ptr = std::auto_ptr<log4cplus::Layout>;
124 #endif
125 
126  static Ptr create(const std::string& progName_, bool useColor = true)
127  {
128  return Ptr{new ColoredPatternLayout{progName_, useColor}};
129  }
130 
131 #if defined(__ICC)
132  #pragma warning pop
133 #elif defined(__clang__)
134  #pragma clang diagnostic pop
135 #elif defined(__GNUC__)
136  #pragma GCC diagnostic pop
137 #endif
138 
139 private:
140  bool mUseColor = true;
141  std::string mProgName;
142 }; // class ColoredPatternLayout
143 
144 
145 inline log4cplus::Logger
146 getLogger()
147 {
148  return log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("openvdb"));
149 }
150 
151 
152 inline log4cplus::SharedAppenderPtr
153 getAppender()
154 {
155  return getLogger().getAppender(LOG4CPLUS_TEXT("OPENVDB"));
156 }
157 
158 } // namespace internal
159 
160 
161 /// @brief Return the current logging level.
162 inline Level
163 getLevel()
164 {
165  switch (internal::getLogger().getLogLevel()) {
166  case log4cplus::DEBUG_LOG_LEVEL: return Level::Debug;
167  case log4cplus::INFO_LOG_LEVEL: return Level::Info;
168  case log4cplus::WARN_LOG_LEVEL: return Level::Warn;
169  case log4cplus::ERROR_LOG_LEVEL: return Level::Error;
170  case log4cplus::FATAL_LOG_LEVEL: break;
171  }
172  return Level::Fatal;
173 }
174 
175 
176 /// @brief Set the logging level. (Lower-level messages will be suppressed.)
177 inline void
178 setLevel(Level lvl)
179 {
180  internal::getLogger().setLogLevel(static_cast<log4cplus::LogLevel>(lvl));
181 }
182 
183 
184 /// @brief If "-debug", "-info", "-warn", "-error" or "-fatal" is found
185 /// in the given array of command-line arguments, set the logging level
186 /// appropriately and remove the relevant argument(s) from the array.
187 inline void
188 setLevel(int& argc, char* argv[])
189 {
190  for (int i = 1; i < argc; ++i) { // note: skip argv[0]
191  const std::string arg{argv[i]};
192  bool remove = true;
193  if (arg == "-debug") { setLevel(Level::Debug); }
194  else if (arg == "-error") { setLevel(Level::Error); }
195  else if (arg == "-fatal") { setLevel(Level::Fatal); }
196  else if (arg == "-info") { setLevel(Level::Info); }
197  else if (arg == "-warn") { setLevel(Level::Warn); }
198  else { remove = false; }
199  if (remove) argv[i] = nullptr;
200  }
201  auto end = std::remove(argv + 1, argv + argc, nullptr);
202  argc = static_cast<int>(end - argv);
203 }
204 
205 
206 /// @brief Specify a program name to be displayed in log messages.
207 inline void
208 setProgramName(const std::string& progName, bool useColor = true)
209 {
210  // Change the layout of the OpenVDB appender to use colored text
211  // and to incorporate the supplied program name.
212  if (auto appender = internal::getAppender()) {
213  appender->setLayout(internal::ColoredPatternLayout::create(progName, useColor));
214  }
215 }
216 
217 
218 /// @brief Initialize the logging system if it is not already initialized.
219 inline void
220 initialize(bool useColor = true)
221 {
223 
224  if (internal::getAppender()) return; // already initialized
225 
226  // Create the OpenVDB logger if it doesn't already exist.
227  auto logger = internal::getLogger();
228 
229  // Disable "additivity", so that OpenVDB-related messages are directed
230  // to the OpenVDB logger only and are not forwarded up the logger tree.
231  logger.setAdditivity(false);
232 
233  // Attach a console appender to the OpenVDB logger.
234  if (auto appender = log4cplus::SharedAppenderPtr{new log4cplus::ConsoleAppender}) {
235  appender->setName(LOG4CPLUS_TEXT("OPENVDB"));
236  logger.addAppender(appender);
237  }
238 
240  setProgramName("", useColor);
241 }
242 
243 
244 /// @brief Initialize the logging system from command-line arguments.
245 /// @details If "-debug", "-info", "-warn", "-error" or "-fatal" is found
246 /// in the given array of command-line arguments, set the logging level
247 /// appropriately and remove the relevant argument(s) from the array.
248 inline void
249 initialize(int& argc, char* argv[], bool useColor = true)
250 {
251  initialize();
252 
253  setLevel(argc, argv);
254 
255  auto progName = (argc > 0 ? argv[0] : "");
256  if (const char* ptr = ::strrchr(progName, '/')) progName = ptr + 1;
257  setProgramName(progName, useColor);
258 }
259 
260 } // namespace logging
261 } // namespace OPENVDB_VERSION_NAME
262 } // namespace openvdb
263 
264 
265 #define OPENVDB_LOG(level, message) \
266  do { \
267  auto _log = openvdb::logging::internal::getLogger(); \
268  if (_log.isEnabledFor(log4cplus::level##_LOG_LEVEL)) { \
269  std::ostringstream _buf; \
270  _buf << message; \
271  _log.forcedLog(log4cplus::level##_LOG_LEVEL, _buf.str(), __FILE__, __LINE__); \
272  } \
273  } while (0);
274 
275 /// Log an info message of the form '<TT>someVar << "some text" << ...</TT>'.
276 #define OPENVDB_LOG_INFO(message) OPENVDB_LOG(INFO, message)
277 /// Log a warning message of the form '<TT>someVar << "some text" << ...</TT>'.
278 #define OPENVDB_LOG_WARN(message) OPENVDB_LOG(WARN, message)
279 /// Log an error message of the form '<TT>someVar << "some text" << ...</TT>'.
280 #define OPENVDB_LOG_ERROR(message) OPENVDB_LOG(ERROR, message)
281 /// Log a fatal error message of the form '<TT>someVar << "some text" << ...</TT>'.
282 #define OPENVDB_LOG_FATAL(message) OPENVDB_LOG(FATAL, message)
283 #ifdef DEBUG
284 /// In debug builds only, log a debugging message of the form '<TT>someVar << "text" << ...</TT>'.
285 #define OPENVDB_LOG_DEBUG(message) OPENVDB_LOG(DEBUG, message)
286 #else
287 /// In debug builds only, log a debugging message of the form '<TT>someVar << "text" << ...</TT>'.
288 #define OPENVDB_LOG_DEBUG(message)
289 #endif
290 /// @brief Log a debugging message in both debug and optimized builds.
291 /// @warning Don't use this in performance-critical code.
292 #define OPENVDB_LOG_DEBUG_RUNTIME(message) OPENVDB_LOG(DEBUG, message)
293 
294 #else // ifdef OPENVDB_USE_LOG4CPLUS
295 
296 #include <iostream>
297 
298 #define OPENVDB_LOG_INFO(mesg)
299 #define OPENVDB_LOG_WARN(mesg) do { std::cerr << "WARNING: " << mesg << std::endl; } while (0);
300 #define OPENVDB_LOG_ERROR(mesg) do { std::cerr << "ERROR: " << mesg << std::endl; } while (0);
301 #define OPENVDB_LOG_FATAL(mesg) do { std::cerr << "FATAL: " << mesg << std::endl; } while (0);
302 #define OPENVDB_LOG_DEBUG(mesg)
303 #define OPENVDB_LOG_DEBUG_RUNTIME(mesg)
304 
305 namespace openvdb {
307 namespace OPENVDB_VERSION_NAME {
308 namespace logging {
309 
310 enum class Level { Debug, Info, Warn, Error, Fatal };
311 
312 inline Level getLevel() { return Level::Warn; }
313 inline void setLevel(Level) {}
314 inline void setLevel(int&, char*[]) {}
315 inline void setProgramName(const std::string&, bool = true) {}
316 inline void initialize() {}
317 inline void initialize(int&, char*[], bool = true) {}
318 
319 } // namespace logging
320 } // namespace OPENVDB_VERSION_NAME
321 } // namespace openvdb
322 
323 #endif // OPENVDB_USE_LOG4CPLUS
324 
325 
326 namespace openvdb {
328 namespace OPENVDB_VERSION_NAME {
329 namespace logging {
330 
331 /// @brief A LevelScope object sets the logging level to a given level
332 /// and restores it to the current level when the object goes out of scope.
334 {
336  explicit LevelScope(Level newLevel): level(getLevel()) { setLevel(newLevel); }
338 };
339 
340 } // namespace logging
341 } // namespace OPENVDB_VERSION_NAME
342 } // namespace openvdb
343 
344 #endif // OPENVDB_UTIL_LOGGING_HAS_BEEN_INCLUDED
345 
346 // Copyright (c) 2012-2017 DreamWorks Animation LLC
347 // All rights reserved. This software is distributed under the
348 // 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
A LevelScope object sets the logging level to a given level and restores it to the current level when...
Definition: logging.h:333
png_uint_32 i
Definition: png.h:2877
void initialize(int &, char *[], bool=true)
Definition: logging.h:317
struct _cl_event * event
Definition: glcorearb.h:2960
#define OPENVDB_VERSION_NAME
Definition: version.h:43
GLuint GLuint end
Definition: glcorearb.h:474
void setProgramName(const std::string &, bool=true)
Definition: logging.h:315
void initialize()
Global registration of basic types.
Definition: logging.h:316
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71