Mitsuba Renderer  0.5.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
logger.h
Go to the documentation of this file.
1 /*
2  This file is part of Mitsuba, a physically based rendering system.
3 
4  Copyright (c) 2007-2014 by Wenzel Jakob and others.
5 
6  Mitsuba is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License Version 3
8  as published by the Free Software Foundation.
9 
10  Mitsuba is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #pragma once
20 #if !defined(__MITSUBA_CORE_LOGGER_H_)
21 #define __MITSUBA_CORE_LOGGER_H_
22 
23 #include <mitsuba/core/formatter.h>
24 
25 // -----------------------------------------------------------------------
26 // Logging
27 // -----------------------------------------------------------------------
28 
30 
31 /*! \addtogroup libcore */
32 /*! @{ */
33 
34 /// Write a Log message to the console (to be used within subclasses of <tt>Object</tt>)
35 #define Log(level, fmt, ...) do { \
36  mitsuba::Thread *thread = mitsuba::Thread::getThread(); \
37  if (EXPECT_NOT_TAKEN(thread == NULL)) \
38  throw std::runtime_error("Null thread pointer"); \
39  mitsuba::Logger *logger = thread->getLogger(); \
40  if (logger != NULL && level >= logger->getLogLevel()) \
41  logger->log(level, m_theClass, \
42  __FILE__, __LINE__, fmt, ## __VA_ARGS__); \
43  } while (0)
44 
45 /**
46  * \brief Write a Log message to the console (static version - to be used
47  * outside of classes that derive from Object)
48  */
49 #define SLog(level, fmt, ...) do { \
50  mitsuba::Thread *thread = mitsuba::Thread::getThread(); \
51  if (EXPECT_NOT_TAKEN(thread == NULL)) \
52  throw std::runtime_error("Null thread pointer"); \
53  mitsuba::Logger *logger = thread->getLogger(); \
54  if (logger != NULL && level >= logger->getLogLevel()) \
55  logger->log(level, NULL, \
56  __FILE__, __LINE__, fmt, ## __VA_ARGS__); \
57  } while (0)
58 
59 /*! @} */
60 
61 #ifdef MTS_NDEBUG
62 #define Assert(cond) ((void) 0)
63 #define AssertEx(cond, explanation) ((void) 0)
64 #define SAssert(cond) ((void) 0)
65 #define SAssertEx(cond, explanation) ((void) 0)
66 #else
67 
68 /* Assertions */
69 /*! \addtogroup libcore */
70 /*! @{ */
71 
72 /// Assert that a condition is true (to be used \a inside of classes that derive from \ref Object)
73 #define Assert(cond) do { \
74  if (!(cond)) Log(EError, "Assertion \"%s\" failed in %s:%i", \
75  #cond, __FILE__, __LINE__); \
76  } while (0)
77 
78 /// ``Static'' assertion (to be used \a outside of classes that derive from \ref Object)
79 #define SAssert(cond) do { \
80  if (!(cond)) SLog(EError, "Assertion \"%s\" failed in %s:%i", \
81  #cond, __FILE__, __LINE__); \
82  } while (0)
83 
84 /// Assertion with a customizable error explanation
85 #define AssertEx(cond, explanation) do { \
86  if (!(cond)) Log(EError, "Assertion \"%s\" failed in %s:%i (" explanation ")", \
87  #cond, __FILE__, __LINE__); \
88  } while (0)
89 
90 /// Static assertion with a customizable error explanation (see \ref SLog)
91 #define SAssertEx(cond, explanation) do { \
92  if (!(cond)) SLog(EError, "Assertion \"%s\" failed in %s:%i (" explanation ")", \
93  #cond, __FILE__, __LINE__); \
94  } while (0)
95 #endif
96 
97 /// Throw an exception reporting that the given function is not implemented
98 #define NotImplementedError(funcName) \
99  throw std::runtime_error(formatString("%s::" funcName "(): Not implemented!", \
100  getClass()->getName().c_str()));
101 
102 /*! @} */
103 
104 /**
105  * \headerfile mitsuba/core/logger.h mitsuba/mitsuba.h
106  * \brief Responsible for processing log messages
107  *
108  * Upon receiving a log message, the Logger class invokes
109  * a Formatter to convert it into a human-readable form.
110  * Following that, it sends this information to every
111  * registered Appender.
112  *
113  * \ingroup libcore
114  * \ingroup libpython
115  */
116 class MTS_EXPORT_CORE Logger : public Object {
117  friend class Statistics;
118 public:
119  /// Construct a new logger with the given minimum log level
120  Logger(ELogLevel logLevel = EDebug);
121 
122  /**
123  * \brief Process a log message
124  * \param level Log level of the message
125  * \param theClass Class descriptor of the message creator
126  * \param fileName Source file of the message creator
127  * \param lineNumber Source line number of the message creator
128  * \param fmt printf-style string formatter
129  * \note This function is not exposed in the Python bindings.
130  * Instead, please use \cc mitsuba.core.Log
131  */
132  void log(ELogLevel level, const Class *theClass,
133  const char *fileName, int lineNumber,
134  const char *fmt, ...);
135 
136  /**
137  * \brief Process a progress message
138  * \param progress Percentage value in [0,100]
139  * \param name Title of the progress message
140  * \param formatted Formatted string representation of the message
141  * \param eta Estimated time until 100% is reached.
142  * \param ptr Custom pointer payload. This is used to express the
143  * context of a progress message. When rendering a scene, it
144  * will usually contain a pointer to the associated \c RenderJob.
145  * \remark The \c ptr argument is missing in the Python bindings
146  */
147  void logProgress(Float progress, const std::string &name,
148  const std::string &formatted, const std::string &eta,
149  const void *ptr);
150 
151  /// Set the log level (everything below will be ignored)
152  void setLogLevel(ELogLevel level);
153 
154  /**
155  * \brief Set the error log level (this level and anything
156  * above will throw exceptions).
157  *
158  * The value provided here can be used for instance to turn
159  * warnings into errors. But \a level must always be
160  * less than \ref EError, i.e. it isn't possible to
161  * cause errors not to throw an exception.
162  */
163  void setErrorLevel(ELogLevel level);
164 
165  /// Return the current log level
166  inline ELogLevel getLogLevel() const { return m_logLevel; }
167 
168  /// Return the current error level
169  inline ELogLevel getErrorLevel() const { return m_errorLevel; }
170 
171  /// Add an appender to this logger
172  void addAppender(Appender *appender);
173 
174  /// Remove an appender from this logger
175  void removeAppender(Appender *appender);
176 
177  /// Remove all appenders from this logger
178  void clearAppenders();
179 
180  /// Return the number of registered appenders
181  inline size_t getAppenderCount() const { return m_appenders.size(); }
182 
183  /// Return one of the appenders
184  inline Appender *getAppender(size_t index) { return m_appenders[index]; }
185 
186  /// Return one of the appenders
187  inline const Appender *getAppender(size_t index) const { return m_appenders[index]; }
188 
189  /// Set the logger's formatter implementation
190  void setFormatter(Formatter *formatter);
191 
192  /// Return the logger's formatter implementation
193  inline Formatter *getFormatter() { return m_formatter; }
194 
195  /**
196  * \brief Return the contents of the log file as a string (if it exists)
197  *
198  * \return \c true upon success
199  */
200  bool readLog(std::string &target);
201 
202  /// Return the number of warnings reported so far
203  inline size_t getWarningCount() const { return m_warningCount; }
204 
205  /// Initialize logging
206  static void staticInitialization();
207 
208  /// Shutdown logging
209  static void staticShutdown();
210 
212 protected:
213  /// Virtual destructor
214  virtual ~Logger();
215 private:
216  ELogLevel m_logLevel;
217  ELogLevel m_errorLevel;
218  ref<Formatter> m_formatter;
219  ref<Mutex> m_mutex;
220  std::vector<Appender *> m_appenders;
221  size_t m_warningCount;
222 };
223 
225 
226 #endif /* __MITSUBA_CORE_LOGGER_H_ */
Abstract interface for converting log information into a human-readable format.
Definition: formatter.h:42
Formatter * getFormatter()
Return the logger&#39;s formatter implementation.
Definition: logger.h:193
const Appender * getAppender(size_t index) const
Return one of the appenders.
Definition: logger.h:187
Collects various rendering statistics and presents them in a human-readable form. ...
Definition: statistics.h:339
static void staticInitialization()
Initializes the built-in reference count debugger (if enabled)
ELogLevel getErrorLevel() const
Return the current error level.
Definition: logger.h:169
#define MTS_EXPORT_CORE
Definition: getopt.h:29
Debug message, usually turned off.
Definition: formatter.h:30
#define MTS_NAMESPACE_BEGIN
Definition: platform.h:137
Appender * getAppender(size_t index)
Return one of the appenders.
Definition: logger.h:184
#define MTS_DECLARE_CLASS()
This macro must be used in the initial definition in classes that derive from Object.
Definition: class.h:158
Reference counting helper.
Definition: ref.h:40
Stores meta-information about Object instances.
Definition: class.h:43
This class defines an abstract destination for logging-relevant information.
Definition: appender.h:33
ELogLevel
Available Log message types.
Definition: formatter.h:28
Responsible for processing log messages.
Definition: logger.h:116
Parent of all Mitsuba classes.
Definition: object.h:38
static void staticShutdown()
Free the memory taken by staticInitialization()
#define MTS_NAMESPACE_END
Definition: platform.h:138
size_t getWarningCount() const
Return the number of warnings reported so far.
Definition: logger.h:203
Thin wrapper around the recursive boost thread lock.
Definition: lock.h:34
ELogLevel getLogLevel() const
Return the current log level.
Definition: logger.h:166
size_t getAppenderCount() const
Return the number of registered appenders.
Definition: logger.h:181