SMTK  @SMTK_VERSION@
Simulation Modeling Tool Kit
Logger.h
Go to the documentation of this file.
1 //=========================================================================
2 // Copyright (c) Kitware, Inc.
3 // All rights reserved.
4 // See LICENSE.txt for details.
5 //
6 // This software is distributed WITHOUT ANY WARRANTY; without even
7 // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
8 // PURPOSE. See the above copyright notice for more information.
9 //=========================================================================
10 #ifndef smtk_io_Logger_h
11 #define smtk_io_Logger_h
12 
14 #include "smtk/CoreExports.h"
15 #include "smtk/SystemConfig.h"
16 #include "smtk/common/Deprecation.h"
17 #include <functional>
18 #include <iosfwd>
19 #include <mutex>
20 #include <sstream>
21 #include <string>
22 #include <vector>
23 #ifdef DEBUG
24 #undef DEBUG // Some libraries publicly export this define when built in debug mode
25 // That messes up the DEBUG enumeration in Severity.
26 #endif
27 #ifdef ERROR // Same
28 #undef ERROR
29 #endif
30 #ifdef WARNING // Same
31 #undef WARNING
32 #endif
33 
38 #define smtkErrorMacro(logger, x) \
39  do \
40  { \
41  std::stringstream s1; \
42  s1 << x; /* NOLINT(bugprone-macro-parentheses) */ \
43  (logger).addRecord(smtk::io::Logger::Error, s1.str(), __FILE__, __LINE__); \
44  } while (0)
45 
50 #define smtkWarningMacro(logger, x) \
51  do \
52  { \
53  std::stringstream s1; \
54  s1 << x; /* NOLINT(bugprone-macro-parentheses) */ \
55  (logger).addRecord(smtk::io::Logger::Warning, s1.str(), __FILE__, __LINE__); \
56  } while (0)
57 
62 #define smtkDebugMacro(logger, x) \
63  do \
64  { \
65  std::stringstream s1; \
66  s1 << x; /* NOLINT(bugprone-macro-parentheses) */ \
67  (logger).addRecord(smtk::io::Logger::Debug, s1.str(), __FILE__, __LINE__); \
68  } while (0)
69 
77 #define smtkInfoMacro(logger, x) \
78  do \
79  { \
80  std::stringstream s1; \
81  s1 << x; /* NOLINT(bugprone-macro-parentheses) */ \
82  (logger).addRecord(smtk::io::Logger::Info, s1.str()); \
83  } while (0)
84 
85 namespace smtk
86 {
87 namespace io
88 {
89 
95 class SMTKCORE_EXPORT Logger
96 {
97 public:
98  static Logger& instance();
99 
100  enum Severity
101  {
102  Debug,
103  Info,
104  Warning,
105  Error,
106  Fatal,
107 
108 #ifdef _MSC_VER
109  /*
110  * MSVC doesn't have a way to deprecate enum variants other than through
111  * `#pragma`. Just let other platforms handle it.
112  */
113  DEBUG = Debug,
114  INFO = Info,
115  WARNING = Warning,
116  ERROR = Error,
117  FATAL = Fatal
118 #else
119  DEBUG SMTK_DEPRECATED_IN_22_02("Use `Debug`") = Debug,
120  INFO SMTK_DEPRECATED_IN_22_02("Use `Info`") = Info,
121  WARNING SMTK_DEPRECATED_IN_22_02("Use `Warning`") = Warning,
122  ERROR SMTK_DEPRECATED_IN_22_02("Use `Error`") = Error,
123  FATAL SMTK_DEPRECATED_IN_22_02("Use `Fatal`") = Fatal
124 #endif
125  };
126 
127  struct Record
128  {
129  Severity severity{ Info };
130  std::string message;
131  std::string fileName;
132  unsigned int lineNumber{ 0 };
133  Record(Severity s, const std::string& m, const std::string& f = "", unsigned int l = 0)
134  : severity(s)
135  , message(m)
136  , fileName(f)
137  , lineNumber(l)
138  {
139  }
140  Record() = default;
141  };
142 
143  Logger() = default;
144 
145  Logger(const Logger& logger)
146  : m_hasErrors(logger.m_hasErrors)
147  , m_records(logger.m_records)
148  {
149  }
150 
151  virtual ~Logger();
152 
153  Logger& operator=(const Logger& logger);
154  std::size_t numberOfRecords() const { return m_records.size(); }
155 
156  bool hasErrors() const { return m_hasErrors; }
157  void clearErrors() { m_hasErrors = false; }
158 
159  void
160  addRecord(Severity s, const std::string& m, const std::string& fname = "", unsigned int line = 0);
161 
166  std::vector<Record> records() const;
168  Record record(std::size_t i) const;
169 
170  static std::string toString(const Record& record, bool includeSourceLoc = false);
171  std::string toString(std::size_t i, bool includeSourceLoc = false) const;
172  std::string toString(std::size_t i, std::size_t j, bool includeSourceLoc = false) const;
173 
174  std::string toHTML(std::size_t i, std::size_t j, bool includeSourceLoc) const;
175 
176  // Convert all the messages into a single string
177  std::string convertToString(bool includeSourceLoc = false) const;
178  std::string convertToHTML(bool includeSourceLoc = false) const;
179  void reset();
180 
181  void append(const Logger& l);
182 
183  static std::string severityAsString(Severity s);
184 
185  void setFlushToStream(std::ostream* output, bool ownFile, bool includePast);
186  bool setFlushToFile(std::string filename, bool includePast);
187  void setFlushToStdout(bool includePast);
188  void setFlushToStderr(bool includePast);
189 
190  void setCallback(std::function<void()> fn);
191 
192 protected:
193  void flushRecordsToStream(std::size_t beginRec, std::size_t endRec);
194  std::string toStringInternal(std::size_t i, std::size_t j, bool includeSourceLoc = false) const;
195 
196  bool m_hasErrors{ false };
197  std::vector<Record> m_records;
198  std::ostream* m_stream{ nullptr };
199  bool m_ownStream{ false };
200  std::function<void()> m_callback;
201 
202 private:
203  static Logger m_instance;
204  mutable std::mutex m_mutex;
205 };
206 
207 template<typename J>
208 void to_json(J& json, const Logger::Record& rec)
209 {
210  json = { { "severity", rec.severity },
211  { "message", rec.message },
212  { "file", rec.fileName },
213  { "line", rec.lineNumber } };
214 }
215 } // namespace io
216 } // namespace smtk
217 
218 #endif /* smtk_io_Logger_h */
smtk
The main namespace for the Simulation Modeling Tool Kit (SMTK).
Definition: doc.h:33
smtk::io::Logger
Log messages for later presentation to a user or a file.
Definition: Logger.h:95
smtk::io::Logger::Record
Definition: Logger.h:127