treelite
logging.h
Go to the documentation of this file.
1 
7 #ifndef TREELITE_LOGGING_H_
8 #define TREELITE_LOGGING_H_
9 
10 #include <treelite/error.h>
11 #include <treelite/thread_local.h>
12 
13 #include <cstdio>
14 #include <ctime>
15 #include <functional>
16 #include <iostream>
17 #include <memory>
18 #include <sstream>
19 #include <string>
20 
21 namespace treelite {
22 
23 template <typename X, typename Y>
24 std::unique_ptr<std::string> LogCheckFormat(X const& x, Y const& y) {
25  std::ostringstream os;
26  os << " (" << x << " vs. " << y << ") ";
27  /* CHECK_XX(x, y) requires x and y can be serialized to string. Use CHECK(x OP y) otherwise. */
28  return std::make_unique<std::string>(os.str());
29 }
30 
31 #if defined(__GNUC__) || defined(__clang__)
32 #define TREELITE_ALWAYS_INLINE inline __attribute__((__always_inline__))
33 #elif defined(_MSC_VER)
34 #define TREELITE_ALWAYS_INLINE __forceinline
35 #else
36 #define TREELITE_ALWAYS_INLINE inline
37 #endif
38 
39 #define DEFINE_CHECK_FUNC(name, op) \
40  template <typename X, typename Y> \
41  TREELITE_ALWAYS_INLINE std::unique_ptr<std::string> LogCheck##name(const X& x, const Y& y) { \
42  if (x op y) \
43  return nullptr; \
44  return LogCheckFormat(x, y); \
45  } \
46  TREELITE_ALWAYS_INLINE std::unique_ptr<std::string> LogCheck##name(int x, int y) { \
47  return LogCheck##name<int, int>(x, y); \
48  }
49 
50 #ifdef __GNUC__
51 #pragma GCC diagnostic push
52 #pragma GCC diagnostic ignored "-Wsign-compare"
53 #endif // __GNUC__
54 
55 DEFINE_CHECK_FUNC(_LT, <)
56 DEFINE_CHECK_FUNC(_GT, >)
57 DEFINE_CHECK_FUNC(_LE, <=)
58 DEFINE_CHECK_FUNC(_GE, >=)
59 DEFINE_CHECK_FUNC(_EQ, ==)
60 DEFINE_CHECK_FUNC(_NE, !=)
61 
62 #ifdef __GNUC__
63 #pragma GCC diagnostic pop
64 #endif // __GNUC__
65 
66 #define TREELITE_CHECK_BINARY_OP(name, op, x, y) \
67  if (auto __treelite__log__err = ::treelite::LogCheck##name(x, y)) \
68  ::treelite::LogMessageFatal(__FILE__, __LINE__).stream() \
69  << "Check failed: " << #x " " #op " " #y << *__treelite__log__err << ": "
70 #define TREELITE_CHECK(x) \
71  if (!(x)) \
72  ::treelite::LogMessageFatal(__FILE__, __LINE__).stream() << "Check failed: " #x << ": "
73 #define TREELITE_CHECK_LT(x, y) TREELITE_CHECK_BINARY_OP(_LT, <, x, y)
74 #define TREELITE_CHECK_GT(x, y) TREELITE_CHECK_BINARY_OP(_GT, >, x, y)
75 #define TREELITE_CHECK_LE(x, y) TREELITE_CHECK_BINARY_OP(_LE, <=, x, y)
76 #define TREELITE_CHECK_GE(x, y) TREELITE_CHECK_BINARY_OP(_GE, >=, x, y)
77 #define TREELITE_CHECK_EQ(x, y) TREELITE_CHECK_BINARY_OP(_EQ, ==, x, y)
78 #define TREELITE_CHECK_NE(x, y) TREELITE_CHECK_BINARY_OP(_NE, !=, x, y)
79 
80 #define TREELITE_LOG_INFO ::treelite::LogMessage(__FILE__, __LINE__)
81 #define TREELITE_LOG_ERROR TREELITE_LOG_INFO
82 #define TREELITE_LOG_WARNING ::treelite::LogMessageWarning(__FILE__, __LINE__)
83 #define TREELITE_LOG_FATAL ::treelite::LogMessageFatal(__FILE__, __LINE__)
84 #define TREELITE_LOG(severity) TREELITE_LOG_##severity.stream()
85 
86 class DateLogger {
87  public:
89 #if defined(_MSC_VER)
90  _tzset();
91 #endif // defined(_MSC_VER)
92  }
93  char const* HumanDate() {
94 #if defined(_MSC_VER)
95  _strtime_s(buffer_, sizeof(buffer_));
96 #else // defined(_MSC_VER)
97  time_t time_value = std::time(nullptr);
98  struct tm* pnow;
99 #if !defined(_WIN32)
100  struct tm now;
101  pnow = localtime_r(&time_value, &now);
102 #else // !defined(_WIN32)
103  pnow = std::localtime(&time_value); // NOLINT(*)
104 #endif // !defined(_WIN32)
105  std::snprintf(
106  buffer_, sizeof(buffer_), "%02d:%02d:%02d", pnow->tm_hour, pnow->tm_min, pnow->tm_sec);
107 #endif // defined(_MSC_VER)
108  return buffer_;
109  }
110 
111  private:
112  char buffer_[9];
113 };
114 
116  public:
117  LogMessageFatal(char const* file, int line) {
118  log_stream_ << "[" << pretty_date_.HumanDate() << "] " << file << ":" << line << ": ";
119  }
121  void operator=(LogMessageFatal const&) = delete;
122 
123  std::ostringstream& stream() {
124  return log_stream_;
125  }
126  ~LogMessageFatal() noexcept(false) {
127  throw Error(log_stream_.str());
128  }
129 
130  private:
131  std::ostringstream log_stream_;
132  DateLogger pretty_date_;
133 };
134 
135 class LogMessage {
136  public:
137  LogMessage(char const* file, int line) {
138  log_stream_ << "[" << DateLogger().HumanDate() << "] " << file << ":" << line << ": ";
139  }
141  Log(log_stream_.str());
142  }
143  std::ostream& stream() {
144  return log_stream_;
145  }
146  static void Log(std::string const& msg);
147 
148  private:
149  std::ostringstream log_stream_;
150 };
151 
153  public:
154  LogMessageWarning(char const* file, int line) {
155  log_stream_ << "[" << DateLogger().HumanDate() << "] " << file << ":" << line << ": ";
156  }
158  Log(log_stream_.str());
159  }
160  std::ostream& stream() {
161  return log_stream_;
162  }
163  static void Log(std::string const& msg);
164 
165  private:
166  std::ostringstream log_stream_;
167 };
168 
170  public:
171  using Callback = void (*)(char const*);
173  : log_callback_info_([](char const* msg) { std::cerr << msg << std::endl; }),
174  log_callback_warn_([](char const* msg) { std::cerr << msg << std::endl; }) {}
175  inline void RegisterCallBackLogInfo(Callback log_callback) {
176  this->log_callback_info_ = log_callback;
177  }
178  inline Callback GetCallbackLogInfo() const {
179  return log_callback_info_;
180  }
181  inline void RegisterCallBackLogWarning(Callback log_callback) {
182  this->log_callback_warn_ = log_callback;
183  }
185  return log_callback_warn_;
186  }
187 
188  private:
189  Callback log_callback_info_;
190  Callback log_callback_warn_;
191 };
192 
194 
195 } // namespace treelite
196 
197 #endif // TREELITE_LOGGING_H_
Definition: logging.h:86
char const * HumanDate()
Definition: logging.h:93
DateLogger()
Definition: logging.h:88
Definition: logging.h:169
LogCallbackRegistry()
Definition: logging.h:172
void RegisterCallBackLogInfo(Callback log_callback)
Definition: logging.h:175
void RegisterCallBackLogWarning(Callback log_callback)
Definition: logging.h:181
Callback GetCallbackLogInfo() const
Definition: logging.h:178
void(*)(char const *) Callback
Definition: logging.h:171
Callback GetCallbackLogWarning() const
Definition: logging.h:184
Definition: logging.h:115
void operator=(LogMessageFatal const &)=delete
LogMessageFatal(char const *file, int line)
Definition: logging.h:117
~LogMessageFatal() noexcept(false)
Definition: logging.h:126
LogMessageFatal(LogMessageFatal const &)=delete
std::ostringstream & stream()
Definition: logging.h:123
Definition: logging.h:152
std::ostream & stream()
Definition: logging.h:160
LogMessageWarning(char const *file, int line)
Definition: logging.h:154
static void Log(std::string const &msg)
~LogMessageWarning()
Definition: logging.h:157
Definition: logging.h:135
LogMessage(char const *file, int line)
Definition: logging.h:137
~LogMessage()
Definition: logging.h:140
static void Log(std::string const &msg)
std::ostream & stream()
Definition: logging.h:143
A thread-local storage.
Definition: thread_local.h:17
Exception class used throughout the Treelite codebase.
#define DEFINE_CHECK_FUNC(name, op)
Definition: logging.h:39
Definition: contiguous_array.h:14
std::unique_ptr< std::string > LogCheckFormat(X const &x, Y const &y)
Definition: logging.h:24
Exception class that will be thrown by Treelite.
Definition: error.h:18
Helper class for thread-local storage.