Apache Singa
A General Distributed Deep Learning Library
logging.h
1 /************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21 
22 // adapted from google::tensorflow::logging
23 
24 #ifndef SINGA_UTILS_LOGGING_H_
25 #define SINGA_UTILS_LOGGING_H_
26 
27 #include <stdlib.h>
28 #include <sstream>
29 #include <string>
30 #ifdef USE_GLOG
31 #include <glog/logging.h>
32 #endif
33 
34 namespace singa {
35 
37 void InitLogging(const char *argv);
39 void LogToStderr();
42 void SetStderrLogging(int severity);
44 void SetLogDestination(int severity, const char* path);
45 
46 using std::string;
47 
48 const int INFO = 0; // base_logging::INFO;
49 const int WARNING = 1; // base_logging::WARNING;
50 const int ERROR = 2; // base_logging::ERROR;
51 const int FATAL = 3; // base_logging::FATAL;
52 const int NUM_SEVERITIES = 4; // base_logging::NUM_SEVERITIES;
53 
54 #ifndef USE_GLOG
55 namespace logging {
56 
57 class LogMessage : public std::basic_ostringstream<char> {
58  public:
59  LogMessage(const char* fname, int line, int severity);
60  ~LogMessage();
61 
62  protected:
63  void GenerateLogMessage();
64  void DoLogging(FILE* file, const struct tm& tm_time);
65 
66  private:
67  const char* fname_;
68  int line_;
69  int severity_;
70 };
71 
72 // LogMessageFatal ensures the process will exit in failure after
73 // logging this message.
74 class LogMessageFatal : public LogMessage {
75  public:
76  LogMessageFatal(const char* file, int line);
77  ~LogMessageFatal();
78 };
79 
80 #define _SINGA_LOG_INFO \
81  ::singa::logging::LogMessage(__FILE__, __LINE__, singa::INFO)
82 #define _SINGA_LOG_WARNING \
83  ::singa::logging::LogMessage(__FILE__, __LINE__, singa::WARNING)
84 #define _SINGA_LOG_ERROR \
85  ::singa::logging::LogMessage(__FILE__, __LINE__, singa::ERROR)
86 #define _SINGA_LOG_FATAL \
87  ::singa::logging::LogMessageFatal(__FILE__, __LINE__)
88 
89 #define LOG(severity) _SINGA_LOG_##severity
90 
95 #define CHECK(condition) \
96  if (!(condition)) \
97  LOG(FATAL) << "Check failed: " #condition " "
98 
99 // Function is overloaded for integral types to allow static const
100 // integrals declared in classes and not defined to be used as arguments to
101 // CHECK* macros. It's not encouraged though.
102 template <typename T>
103  inline const T& GetReferenceableValue(const T& t) {
104  return t;
105  }
106 inline char GetReferenceableValue(char t) { return t; }
107 inline unsigned char GetReferenceableValue(unsigned char t) { return t; }
108 inline signed char GetReferenceableValue(signed char t) { return t; }
109 inline short GetReferenceableValue(short t) { return t; }
110 inline unsigned short GetReferenceableValue(unsigned short t) { return t; }
111 inline int GetReferenceableValue(int t) { return t; }
112 inline unsigned int GetReferenceableValue(unsigned int t) { return t; }
113 inline long GetReferenceableValue(long t) { return t; }
114 inline unsigned long GetReferenceableValue(unsigned long t) { return t; }
115 inline long long GetReferenceableValue(long long t) { return t; }
116 inline unsigned long long GetReferenceableValue(unsigned long long t) {
117  return t;
118 }
119 
120 // This formats a value for a failing CHECK_XX statement. Ordinarily,
121 // it uses the definition for operator<<, with a few special cases below.
122 template <typename T>
123 inline void MakeCheckOpValueString(std::ostream* os, const T& v) {
124  (*os) << v;
125 }
126 
127 // Overrides for char types provide readable values for unprintable
128 // characters.
129 template <>
130 void MakeCheckOpValueString(std::ostream* os, const char& v);
131 template <>
132 void MakeCheckOpValueString(std::ostream* os, const signed char& v);
133 template <>
134 void MakeCheckOpValueString(std::ostream* os, const unsigned char& v);
135 
136 // We need an explicit specialization for std::nullptr_t.
137 template <>
138 void MakeCheckOpValueString(std::ostream* os, const std::nullptr_t& p);
139 
140 // A container for a string pointer which can be evaluated to a bool -
141 // true iff the pointer is non-NULL.
143  CheckOpString(string* str) : str_(str) {}
144  // No destructor: if str_ is non-NULL, we're about to LOG(FATAL),
145  // so there's no point in cleaning up str_.
146  operator bool() const { return str_ != NULL; }
147  string* str_;
148 };
149 
150 // Build the error message string. Specify no inlining for code size.
151 template <typename T1, typename T2>
152 string* MakeCheckOpString(const T1& v1, const T2& v2,
153  const char* exprtext);
154 
155 // A helper class for formatting "expr (V1 vs. V2)" in a CHECK_XX
156 // statement. See MakeCheckOpString for sample usage. Other
157 // approaches were considered: use of a template method (e.g.,
158 // base::BuildCheckOpString(exprtext, base::Print<T1>, &v1,
159 // base::Print<T2>, &v2), however this approach has complications
160 // related to volatile arguments and function-pointer arguments).
162  public:
163  // Inserts "exprtext" and " (" to the stream.
164  explicit CheckOpMessageBuilder(const char* exprtext);
165  // Deletes "stream_".
167  // For inserting the first variable.
168  std::ostream* ForVar1() { return stream_; }
169  // For inserting the second variable (adds an intermediate " vs. ").
170  std::ostream* ForVar2();
171  // Get the result (inserts the closing ")").
172  string* NewString();
173 
174  private:
175  std::ostringstream* stream_;
176 };
177 
178 template <typename T1, typename T2>
179 string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext) {
180  CheckOpMessageBuilder comb(exprtext);
181  MakeCheckOpValueString(comb.ForVar1(), v1);
182  MakeCheckOpValueString(comb.ForVar2(), v2);
183  return comb.NewString();
184 }
185 
186 // Helper functions for CHECK_OP macro.
187 // The (int, int) specialization works around the issue that the compiler
188 // will not instantiate the template version of the function on values of
189 // unnamed enum type - see comment below.
190 #define SINGA_DEFINE_CHECK_OP_IMPL(name, op) \
191  template <typename T1, typename T2> \
192  inline string* name##Impl(const T1& v1, const T2& v2, \
193  const char* exprtext) { \
194  if (v1 op v2) \
195  return NULL; \
196  else \
197  return ::singa::logging::MakeCheckOpString(v1, v2, exprtext); \
198  } \
199  inline string* name##Impl(int v1, int v2, const char* exprtext) { \
200  return name##Impl<int, int>(v1, v2, exprtext); \
201  }
202 
203 // We use the full name Check_EQ, Check_NE, etc. in case the file including
204 // base/logging.h provides its own #defines for the simpler names EQ, NE, etc.
205 // This happens if, for example, those are used as token names in a
206 // yacc grammar.
207 SINGA_DEFINE_CHECK_OP_IMPL(Check_EQ,
208  == ) // Compilation error with CHECK_EQ(NULL, x)?
209 SINGA_DEFINE_CHECK_OP_IMPL(Check_NE, != ) // Use CHECK(x == NULL) instead.
210 SINGA_DEFINE_CHECK_OP_IMPL(Check_LE, <= )
211 SINGA_DEFINE_CHECK_OP_IMPL(Check_LT, < )
212 SINGA_DEFINE_CHECK_OP_IMPL(Check_GE, >= )
213 SINGA_DEFINE_CHECK_OP_IMPL(Check_GT, > )
214 #undef SINGA_DEFINE_CHECK_OP_IMPL
215 
216 // In optimized mode, use CheckOpString to hint to compiler that
217 // the while condition is unlikely.
218 #define CHECK_OP_LOG(name, op, val1, val2) \
219  while (::singa::logging::CheckOpString _result = \
220  ::singa::logging::name##Impl( \
221  ::singa::logging::GetReferenceableValue(val1), \
222  ::singa::logging::GetReferenceableValue(val2), \
223  #val1 " " #op " " #val2)) \
224  ::singa::logging::LogMessageFatal(__FILE__, __LINE__) << *(_result.str_)
225 
226 #define CHECK_OP(name, op, val1, val2) CHECK_OP_LOG(name, op, val1, val2)
227 
228 // CHECK_EQ/NE/...
229 #define CHECK_EQ(val1, val2) CHECK_OP(Check_EQ, ==, val1, val2)
230 #define CHECK_NE(val1, val2) CHECK_OP(Check_NE, !=, val1, val2)
231 #define CHECK_LE(val1, val2) CHECK_OP(Check_LE, <=, val1, val2)
232 #define CHECK_LT(val1, val2) CHECK_OP(Check_LT, <, val1, val2)
233 #define CHECK_GE(val1, val2) CHECK_OP(Check_GE, >=, val1, val2)
234 #define CHECK_GT(val1, val2) CHECK_OP(Check_GT, >, val1, val2)
235 #define CHECK_NOTNULL(val) \
236  ::singa::logging::CheckNotNull(__FILE__, __LINE__, \
237  "'" #val "' Must be non NULL", (val))
238 
239 #ifndef NDEBUG
240 // DCHECK_EQ/NE/...
241 #define DCHECK(condition) CHECK(condition)
242 #define DCHECK_EQ(val1, val2) CHECK_EQ(val1, val2)
243 #define DCHECK_NE(val1, val2) CHECK_NE(val1, val2)
244 #define DCHECK_LE(val1, val2) CHECK_LE(val1, val2)
245 #define DCHECK_LT(val1, val2) CHECK_LT(val1, val2)
246 #define DCHECK_GE(val1, val2) CHECK_GE(val1, val2)
247 #define DCHECK_GT(val1, val2) CHECK_GT(val1, val2)
248 
249 #else
250 
251 #define DCHECK(condition) \
252  while (false && (condition)) LOG(FATAL)
253 
254 // NDEBUG is defined, so DCHECK_EQ(x, y) and so on do nothing.
255 // However, we still want the compiler to parse x and y, because
256 // we don't want to lose potentially useful errors and warnings.
257 // _DCHECK_NOP is a helper, and should not be used outside of this file.
258 #define _SINGA_DCHECK_NOP(x, y) \
259  while (false && ((void)(x), (void)(y), 0)) LOG(FATAL)
260 
261 #define DCHECK_EQ(x, y) _SINGA_DCHECK_NOP(x, y)
262 #define DCHECK_NE(x, y) _SINGA_DCHECK_NOP(x, y)
263 #define DCHECK_LE(x, y) _SINGA_DCHECK_NOP(x, y)
264 #define DCHECK_LT(x, y) _SINGA_DCHECK_NOP(x, y)
265 #define DCHECK_GE(x, y) _SINGA_DCHECK_NOP(x, y)
266 #define DCHECK_GT(x, y) _SINGA_DCHECK_NOP(x, y)
267 
268 #endif
269 
270 // These are for when you don't want a CHECK failure to print a verbose
271 // stack trace. The implementation of CHECK* in this file already doesn't.
272 #define QCHECK(condition) CHECK(condition)
273 #define QCHECK_EQ(x, y) CHECK_EQ(x, y)
274 #define QCHECK_NE(x, y) CHECK_NE(x, y)
275 #define QCHECK_LE(x, y) CHECK_LE(x, y)
276 #define QCHECK_LT(x, y) CHECK_LT(x, y)
277 #define QCHECK_GE(x, y) CHECK_GE(x, y)
278 #define QCHECK_GT(x, y) CHECK_GT(x, y)
279 
280 template <typename T>
281 T&& CheckNotNull(const char* file, int line, const char* exprtext, T&& t) {
282  if (t == nullptr) {
283  LogMessageFatal(file, line) << string(exprtext);
284  }
285  return std::forward<T>(t);
286 }
287 
288 } // namespace logging
289 #endif
290 
291 } // namespace singa
292 
293 #endif // SINGA_UTILS_LOGGING_H_
void LogToStderr()
Make it so that all log messages go only to stderr.
Definition: logging.h:57
Definition: logging.h:74
void InitLogging(const char *argv)
Global functions for both glog and built-in log.
Definition: logging.h:161
Definition: logging.h:142
void SetStderrLogging(int severity)
Make it so that all log messages of at least a particular severity are logged to stderr (in addtion t...
Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements...
Definition: common.h:48
void SetLogDestination(int severity, const char *path)
Set the file name for logging (and disable logging to stderr)