Caffe2 - C++ API
A deep learning, cross platform ML framework
logging.h
1 #ifndef CAFFE2_CORE_LOGGING_H_
2 #define CAFFE2_CORE_LOGGING_H_
3 
4 #include <climits>
5 #include <exception>
6 #include <functional>
7 #include <limits>
8 #include <sstream>
9 
10 #include "caffe2/core/flags.h"
11 #include "caffe2/proto/caffe2.pb.h"
12 
13 // CAFFE2_LOG_THRESHOLD is a compile time flag that would allow us to turn off
14 // logging at compile time so no logging message below that level is produced
15 // at all. The value should be between INT_MIN and CAFFE_FATAL.
16 #ifndef CAFFE2_LOG_THRESHOLD
17 // If we have not defined the compile time log threshold, we keep all the
18 // log cases.
19 #define CAFFE2_LOG_THRESHOLD INT_MIN
20 #endif // CAFFE2_LOG_THRESHOLD
21 
22 // Below are different implementations for glog and non-glog cases.
23 #ifdef CAFFE2_USE_GOOGLE_GLOG
24 #include "caffe2/core/logging_is_google_glog.h"
25 #else // !CAFFE2_USE_GOOGLE_GLOG
26 #include "caffe2/core/logging_is_not_google_glog.h"
27 #endif // CAFFE2_USE_GOOGLE_GLOG
28 
29 CAFFE2_DECLARE_int(caffe2_log_level);
30 CAFFE2_DECLARE_bool(caffe2_use_fatal_for_enforce);
31 
32 namespace caffe2 {
33 // Functions that we use for initialization.
34 bool InitCaffeLogging(int* argc, char** argv);
35 
36 constexpr bool IsUsingGoogleLogging() {
37 #ifdef CAFFE2_USE_GOOGLE_GLOG
38  return true;
39 #else
40  return false;
41 #endif
42 }
43 
52 void ShowLogInfoToStderr();
53 
54 inline void MakeStringInternal(std::stringstream& /*ss*/) {}
55 
56 template <typename T>
57 inline void MakeStringInternal(std::stringstream& ss, const T& t) {
58  ss << t;
59 }
60 
61 template <typename T, typename... Args>
62 inline void
63 MakeStringInternal(std::stringstream& ss, const T& t, const Args&... args) {
64  MakeStringInternal(ss, t);
65  MakeStringInternal(ss, args...);
66 }
67 
68 template <typename... Args>
69 string MakeString(const Args&... args) {
70  std::stringstream ss;
71  MakeStringInternal(ss, args...);
72  return string(ss.str());
73 }
74 
75 // Specializations for already-a-string types.
76 template <>
77 inline string MakeString(const string& str) {
78  return str;
79 }
80 inline string MakeString(const char* c_str) {
81  return string(c_str);
82 }
83 
84 template <class Container>
85 inline string Join(const string& delimiter, const Container& v) {
86  std::stringstream s;
87  int cnt = static_cast<int64_t>(v.size()) - 1;
88  for (auto i = v.begin(); i != v.end(); ++i, --cnt) {
89  s << (*i) << (cnt ? delimiter : "");
90  }
91  return s.str();
92 }
93 
94 // Obtains the base name from a full path.
95 string StripBasename(const std::string& full_path);
96 
97 // Replace all occurrences of "from" substring to "to" string.
98 // Returns number of replacements
99 size_t ReplaceAll(string& s, const char* from, const char* to);
100 
101 void SetStackTraceFetcher(std::function<string(void)> fetcher);
102 
103 void SetOperatorLogger(std::function<void(const OperatorDef&)> tracer);
104 std::function<void(const OperatorDef&)> GetOperatorLogger();
105 
106 class EnforceNotMet : public std::exception {
107  public:
109  const char* file,
110  const int line,
111  const char* condition,
112  const string& msg,
113  const void* caller=nullptr);
114  void AppendMessage(const string& msg);
115  string msg() const;
116  inline const vector<string>& msg_stack() const {
117  return msg_stack_;
118  }
119 
120  const char* what() const noexcept override;
121 
122  const void* caller() const noexcept;
123 
124  private:
125  vector<string> msg_stack_;
126  string full_msg_;
127  string stack_trace_;
128  const void* caller_;
129 };
130 
131 #define CAFFE_ENFORCE(condition, ...) \
132  do { \
133  if (!(condition)) { \
134  throw ::caffe2::EnforceNotMet( \
135  __FILE__, __LINE__, #condition, ::caffe2::MakeString(__VA_ARGS__)); \
136  } \
137  } while (false)
138 
139 #define CAFFE_ENFORCE_WITH_CALLER(condition, ...) \
140  do { \
141  if (!(condition)) { \
142  throw ::caffe2::EnforceNotMet( \
143  __FILE__, __LINE__, #condition, ::caffe2::MakeString(__VA_ARGS__), this); \
144  } \
145  } while (false)
146 
147 #define CAFFE_THROW(...) \
148  throw ::caffe2::EnforceNotMet( \
149  __FILE__, __LINE__, "", ::caffe2::MakeString(__VA_ARGS__))
150 
178 namespace enforce_detail {
179 
180 struct EnforceOK {};
181 
183  public:
184 #ifdef _MSC_VER
185  // MSVC + NVCC ignores constexpr and will issue a warning if included.
186  /* implicit */ EnforceFailMessage(EnforceOK) : msg_(nullptr) {}
187 #else
188  constexpr /* implicit */ EnforceFailMessage(EnforceOK) : msg_(nullptr) {}
189 #endif
190  EnforceFailMessage(EnforceFailMessage&&) = default;
191  EnforceFailMessage(const EnforceFailMessage&) = delete;
192  EnforceFailMessage& operator=(EnforceFailMessage&&) = delete;
193  EnforceFailMessage& operator=(const EnforceFailMessage&) = delete;
194 
195  // Catch all wrong usages like CAFFE_ENFORCE_THAT(x < y)
196  template <class... Args>
197  /* implicit */ EnforceFailMessage(Args...) {
198  static_assert(
199  // This stands for an "impossible" condition. Plain `false` doesn't
200  // trick compiler enough.
201  sizeof...(Args) == std::numeric_limits<std::size_t>::max(),
202  "CAFFE_ENFORCE_THAT has to be used with one of special check functions "
203  "like `Equals`. Use CAFFE_ENFORCE for simple boolean checks.");
204  }
205 
206  /* implicit */ EnforceFailMessage(std::string&& msg) {
207  msg_ = new std::string(std::move(msg));
208  }
209  inline bool bad() const {
210  return msg_ != nullptr;
211  }
212  std::string get_message_and_free(std::string&& extra) const {
213  std::string r;
214  if (extra.empty()) {
215  r = std::move(*msg_);
216  } else {
217  r = ::caffe2::MakeString(std::move(*msg_), ". ", std::move(extra));
218  }
219  delete msg_;
220  return r;
221  }
222 
223  private:
224  std::string* msg_;
225 };
226 
227 #define BINARY_COMP_HELPER(name, op) \
228  template <typename T1, typename T2> \
229  inline EnforceFailMessage name(const T1& x, const T2& y) { \
230  if (x op y) { \
231  return EnforceOK(); \
232  } \
233  return MakeString(x, " vs ", y); \
234  }
235 BINARY_COMP_HELPER(Equals, ==)
236 BINARY_COMP_HELPER(NotEquals, !=)
237 BINARY_COMP_HELPER(Greater, >)
238 BINARY_COMP_HELPER(GreaterEquals, >=)
239 BINARY_COMP_HELPER(Less, <)
240 BINARY_COMP_HELPER(LessEquals, <=)
241 #undef BINARY_COMP_HELPER
242 
243 #define CAFFE_ENFORCE_THAT_IMPL(condition, expr, ...) \
244  do { \
245  using namespace ::caffe2::enforce_detail; \
246  const EnforceFailMessage& CAFFE_ENFORCE_THAT_IMPL_r_ = (condition); \
247  if (CAFFE_ENFORCE_THAT_IMPL_r_.bad()) { \
248  throw ::caffe2::EnforceNotMet( \
249  __FILE__, \
250  __LINE__, \
251  expr, \
252  CAFFE_ENFORCE_THAT_IMPL_r_.get_message_and_free( \
253  ::caffe2::MakeString(__VA_ARGS__))); \
254  } \
255  } while (false)
256 
257 #define CAFFE_ENFORCE_THAT_IMPL_WITH_CALLER(condition, expr, ...) \
258  do { \
259  using namespace ::caffe2::enforce_detail; \
260  const EnforceFailMessage& CAFFE_ENFORCE_THAT_IMPL_WITH_CALLER_r_ = \
261  (condition); \
262  if (CAFFE_ENFORCE_THAT_IMPL_WITH_CALLER_r_.bad()) { \
263  throw ::caffe2::EnforceNotMet( \
264  __FILE__, \
265  __LINE__, \
266  expr, \
267  CAFFE_ENFORCE_THAT_IMPL_WITH_CALLER_r_.get_message_and_free( \
268  ::caffe2::MakeString(__VA_ARGS__)), \
269  this); \
270  } \
271  } while (false)
272 }
273 
274 #define CAFFE_ENFORCE_THAT(condition, ...) \
275  CAFFE_ENFORCE_THAT_IMPL((condition), #condition, __VA_ARGS__)
276 
277 #define CAFFE_ENFORCE_EQ(x, y, ...) \
278  CAFFE_ENFORCE_THAT_IMPL(Equals((x), (y)), #x " == " #y, __VA_ARGS__)
279 #define CAFFE_ENFORCE_NE(x, y, ...) \
280  CAFFE_ENFORCE_THAT_IMPL(NotEquals((x), (y)), #x " != " #y, __VA_ARGS__)
281 #define CAFFE_ENFORCE_LE(x, y, ...) \
282  CAFFE_ENFORCE_THAT_IMPL(LessEquals((x), (y)), #x " <= " #y, __VA_ARGS__)
283 #define CAFFE_ENFORCE_LT(x, y, ...) \
284  CAFFE_ENFORCE_THAT_IMPL(Less((x), (y)), #x " < " #y, __VA_ARGS__)
285 #define CAFFE_ENFORCE_GE(x, y, ...) \
286  CAFFE_ENFORCE_THAT_IMPL(GreaterEquals((x), (y)), #x " >= " #y, __VA_ARGS__)
287 #define CAFFE_ENFORCE_GT(x, y, ...) \
288  CAFFE_ENFORCE_THAT_IMPL(Greater((x), (y)), #x " > " #y, __VA_ARGS__)
289 #define CAFFE_ENFORCE_EQ_WITH_CALLER(x, y, ...) \
290  CAFFE_ENFORCE_THAT_IMPL_WITH_CALLER(Equals((x), (y)), #x " == " #y, __VA_ARGS__)
291 #define CAFFE_ENFORCE_NE_WITH_CALLER(x, y, ...) \
292  CAFFE_ENFORCE_THAT_IMPL_WITH_CALLER(NotEquals((x), (y)), #x " != " #y, __VA_ARGS__)
293 #define CAFFE_ENFORCE_LE_WITH_CALLER(x, y, ...) \
294  CAFFE_ENFORCE_THAT_IMPL_WITH_CALLER(LessEquals((x), (y)), #x " <= " #y, __VA_ARGS__)
295 #define CAFFE_ENFORCE_LT_WITH_CALLER(x, y, ...) \
296  CAFFE_ENFORCE_THAT_IMPL_WITH_CALLER(Less((x), (y)), #x " < " #y, __VA_ARGS__)
297 #define CAFFE_ENFORCE_GE_WITH_CALLER(x, y, ...) \
298  CAFFE_ENFORCE_THAT_IMPL_WITH_CALLER(GreaterEquals((x), (y)), #x " >= " #y, __VA_ARGS__)
299 #define CAFFE_ENFORCE_GT_WITH_CALLER(x, y, ...) \
300  CAFFE_ENFORCE_THAT_IMPL_WITH_CALLER(Greater((x), (y)), #x " > " #y, __VA_ARGS__)
301 } // namespace caffe2
302 
303 #endif // CAFFE2_CORE_LOGGING_H_
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...
void ShowLogInfoToStderr()
A utility to allow one to show log info to stderr after the program starts.
Definition: logging.cc:196
Commandline flags support for Caffe2.