1/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.
2
3Licensed under the Apache License, Version 2.0 (the "License");
4you may not use this file except in compliance with the License.
5You may obtain a copy of the License at
6
7    http://www.apache.org/licenses/LICENSE-2.0
8
9Unless required by applicable law or agreed to in writing, software
10distributed under the License is distributed on an "AS IS" BASIS,
11WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12See the License for the specific language governing permissions and
13limitations under the License.
14==============================================================================*/
15
16#ifndef TENSORFLOW_PLATFORM_DEFAULT_LOGGING_H_
17#define TENSORFLOW_PLATFORM_DEFAULT_LOGGING_H_
18
19// IWYU pragma: private, include "third_party/tensorflow/core/platform/logging.h"
20// IWYU pragma: friend third_party/tensorflow/core/platform/logging.h
21
22#include <limits>
23#include <sstream>
24#include "tensorflow/core/platform/macros.h"
25#include "tensorflow/core/platform/types.h"
26
27// TODO(mrry): Prevent this Windows.h #define from leaking out of our headers.
28#undef ERROR
29
30namespace tensorflow {
31const int INFO = 0;            // base_logging::INFO;
32const int WARNING = 1;         // base_logging::WARNING;
33const int ERROR = 2;           // base_logging::ERROR;
34const int FATAL = 3;           // base_logging::FATAL;
35const int NUM_SEVERITIES = 4;  // base_logging::NUM_SEVERITIES;
36
37namespace internal {
38
39class LogMessage : public std::basic_ostringstream<char> {
40 public:
41  LogMessage(const char* fname, int line, int severity);
42  ~LogMessage();
43
44  // Returns the minimum log level for VLOG statements.
45  // E.g., if MinVLogLevel() is 2, then VLOG(2) statements will produce output,
46  // but VLOG(3) will not. Defaults to 0.
47  static int64 MinVLogLevel();
48
49 protected:
50  void GenerateLogMessage();
51
52 private:
53  const char* fname_;
54  int line_;
55  int severity_;
56};
57
58// LogMessageFatal ensures the process will exit in failure after
59// logging this message.
60class LogMessageFatal : public LogMessage {
61 public:
62  LogMessageFatal(const char* file, int line) TF_ATTRIBUTE_COLD;
63  TF_ATTRIBUTE_NORETURN ~LogMessageFatal();
64};
65
66#define _TF_LOG_INFO \
67  ::tensorflow::internal::LogMessage(__FILE__, __LINE__, tensorflow::INFO)
68#define _TF_LOG_WARNING \
69  ::tensorflow::internal::LogMessage(__FILE__, __LINE__, tensorflow::WARNING)
70#define _TF_LOG_ERROR \
71  ::tensorflow::internal::LogMessage(__FILE__, __LINE__, tensorflow::ERROR)
72#define _TF_LOG_FATAL \
73  ::tensorflow::internal::LogMessageFatal(__FILE__, __LINE__)
74
75#define _TF_LOG_QFATAL _TF_LOG_FATAL
76
77#define LOG(severity) _TF_LOG_##severity
78
79#ifdef IS_MOBILE_PLATFORM
80// Turn VLOG off when under mobile devices for considerations of binary size.
81#define VLOG_IS_ON(lvl) ((lvl) <= 0)
82#else
83// Otherwise, Set TF_CPP_MIN_VLOG_LEVEL environment to update minimum log level
84// of VLOG
85#define VLOG_IS_ON(lvl) \
86  ((lvl) <= ::tensorflow::internal::LogMessage::MinVLogLevel())
87#endif
88
89#define VLOG(lvl)                        \
90  if (TF_PREDICT_FALSE(VLOG_IS_ON(lvl))) \
91  ::tensorflow::internal::LogMessage(__FILE__, __LINE__, tensorflow::INFO)
92
93// CHECK dies with a fatal error if condition is not true.  It is *not*
94// controlled by NDEBUG, so the check will be executed regardless of
95// compilation mode.  Therefore, it is safe to do things like:
96//    CHECK(fp->Write(x) == 4)
97#define CHECK(condition)              \
98  if (TF_PREDICT_FALSE(!(condition))) \
99  LOG(FATAL) << "Check failed: " #condition " "
100
101// Function is overloaded for integral types to allow static const
102// integrals declared in classes and not defined to be used as arguments to
103// CHECK* macros. It's not encouraged though.
104template <typename T>
105inline const T& GetReferenceableValue(const T& t) {
106  return t;
107}
108inline char GetReferenceableValue(char t) { return t; }
109inline unsigned char GetReferenceableValue(unsigned char t) { return t; }
110inline signed char GetReferenceableValue(signed char t) { return t; }
111inline short GetReferenceableValue(short t) { return t; }
112inline unsigned short GetReferenceableValue(unsigned short t) { return t; }
113inline int GetReferenceableValue(int t) { return t; }
114inline unsigned int GetReferenceableValue(unsigned int t) { return t; }
115inline long GetReferenceableValue(long t) { return t; }
116inline unsigned long GetReferenceableValue(unsigned long t) { return t; }
117inline long long GetReferenceableValue(long long t) { return t; }
118inline unsigned long long GetReferenceableValue(unsigned long long t) {
119  return t;
120}
121
122// This formats a value for a failing CHECK_XX statement.  Ordinarily,
123// it uses the definition for operator<<, with a few special cases below.
124template <typename T>
125inline void MakeCheckOpValueString(std::ostream* os, const T& v) {
126  (*os) << v;
127}
128
129// Overrides for char types provide readable values for unprintable
130// characters.
131template <>
132void MakeCheckOpValueString(std::ostream* os, const char& v);
133template <>
134void MakeCheckOpValueString(std::ostream* os, const signed char& v);
135template <>
136void MakeCheckOpValueString(std::ostream* os, const unsigned char& v);
137
138#if LANG_CXX11
139// We need an explicit specialization for std::nullptr_t.
140template <>
141void MakeCheckOpValueString(std::ostream* os, const std::nullptr_t& p);
142#endif
143
144// A container for a string pointer which can be evaluated to a bool -
145// true iff the pointer is non-NULL.
146struct CheckOpString {
147  CheckOpString(string* str) : str_(str) {}
148  // No destructor: if str_ is non-NULL, we're about to LOG(FATAL),
149  // so there's no point in cleaning up str_.
150  operator bool() const { return TF_PREDICT_FALSE(str_ != NULL); }
151  string* str_;
152};
153
154// Build the error message string. Specify no inlining for code size.
155template <typename T1, typename T2>
156string* MakeCheckOpString(const T1& v1, const T2& v2,
157                          const char* exprtext) TF_ATTRIBUTE_NOINLINE;
158
159// A helper class for formatting "expr (V1 vs. V2)" in a CHECK_XX
160// statement.  See MakeCheckOpString for sample usage.  Other
161// approaches were considered: use of a template method (e.g.,
162// base::BuildCheckOpString(exprtext, base::Print<T1>, &v1,
163// base::Print<T2>, &v2), however this approach has complications
164// related to volatile arguments and function-pointer arguments).
165class CheckOpMessageBuilder {
166 public:
167  // Inserts "exprtext" and " (" to the stream.
168  explicit CheckOpMessageBuilder(const char* exprtext);
169  // Deletes "stream_".
170  ~CheckOpMessageBuilder();
171  // For inserting the first variable.
172  std::ostream* ForVar1() { return stream_; }
173  // For inserting the second variable (adds an intermediate " vs. ").
174  std::ostream* ForVar2();
175  // Get the result (inserts the closing ")").
176  string* NewString();
177
178 private:
179  std::ostringstream* stream_;
180};
181
182template <typename T1, typename T2>
183string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext) {
184  CheckOpMessageBuilder comb(exprtext);
185  MakeCheckOpValueString(comb.ForVar1(), v1);
186  MakeCheckOpValueString(comb.ForVar2(), v2);
187  return comb.NewString();
188}
189
190// Helper functions for CHECK_OP macro.
191// The (int, int) specialization works around the issue that the compiler
192// will not instantiate the template version of the function on values of
193// unnamed enum type - see comment below.
194// The (size_t, int) and (int, size_t) specialization are to handle unsigned
195// comparison errors while still being thorough with the comparison.
196#define TF_DEFINE_CHECK_OP_IMPL(name, op)                                 \
197  template <typename T1, typename T2>                                     \
198  inline string* name##Impl(const T1& v1, const T2& v2,                   \
199                            const char* exprtext) {                       \
200    if (TF_PREDICT_TRUE(v1 op v2))                                        \
201      return NULL;                                                        \
202    else                                                                  \
203      return ::tensorflow::internal::MakeCheckOpString(v1, v2, exprtext); \
204  }                                                                       \
205  inline string* name##Impl(int v1, int v2, const char* exprtext) {       \
206    return name##Impl<int, int>(v1, v2, exprtext);                        \
207  }                                                                       \
208  inline string* name##Impl(const size_t v1, const int v2,                \
209                            const char* exprtext) {                       \
210    if (TF_PREDICT_FALSE(v2 < 0)) {                                       \
211      return ::tensorflow::internal::MakeCheckOpString(v1, v2, exprtext); \
212    }                                                                     \
213    const size_t uval = (size_t)((unsigned)v1);                           \
214    return name##Impl<size_t, size_t>(uval, v2, exprtext);                \
215  }                                                                       \
216  inline string* name##Impl(const int v1, const size_t v2,                \
217                            const char* exprtext) {                       \
218    if (TF_PREDICT_FALSE(v2 >= std::numeric_limits<int>::max())) {        \
219      return ::tensorflow::internal::MakeCheckOpString(v1, v2, exprtext); \
220    }                                                                     \
221    const size_t uval = (size_t)((unsigned)v2);                           \
222    return name##Impl<size_t, size_t>(v1, uval, exprtext);                \
223  }
224
225// We use the full name Check_EQ, Check_NE, etc. in case the file including
226// base/logging.h provides its own #defines for the simpler names EQ, NE, etc.
227// This happens if, for example, those are used as token names in a
228// yacc grammar.
229TF_DEFINE_CHECK_OP_IMPL(Check_EQ,
230                        ==)  // Compilation error with CHECK_EQ(NULL, x)?
231TF_DEFINE_CHECK_OP_IMPL(Check_NE, !=)  // Use CHECK(x == NULL) instead.
232TF_DEFINE_CHECK_OP_IMPL(Check_LE, <=)
233TF_DEFINE_CHECK_OP_IMPL(Check_LT, <)
234TF_DEFINE_CHECK_OP_IMPL(Check_GE, >=)
235TF_DEFINE_CHECK_OP_IMPL(Check_GT, >)
236#undef TF_DEFINE_CHECK_OP_IMPL
237
238// In optimized mode, use CheckOpString to hint to compiler that
239// the while condition is unlikely.
240#define CHECK_OP_LOG(name, op, val1, val2)                            \
241  while (::tensorflow::internal::CheckOpString _result =              \
242             ::tensorflow::internal::name##Impl(                      \
243                 ::tensorflow::internal::GetReferenceableValue(val1), \
244                 ::tensorflow::internal::GetReferenceableValue(val2), \
245                 #val1 " " #op " " #val2))                            \
246  ::tensorflow::internal::LogMessageFatal(__FILE__, __LINE__) << *(_result.str_)
247
248#define CHECK_OP(name, op, val1, val2) CHECK_OP_LOG(name, op, val1, val2)
249
250// CHECK_EQ/NE/...
251#define CHECK_EQ(val1, val2) CHECK_OP(Check_EQ, ==, val1, val2)
252#define CHECK_NE(val1, val2) CHECK_OP(Check_NE, !=, val1, val2)
253#define CHECK_LE(val1, val2) CHECK_OP(Check_LE, <=, val1, val2)
254#define CHECK_LT(val1, val2) CHECK_OP(Check_LT, <, val1, val2)
255#define CHECK_GE(val1, val2) CHECK_OP(Check_GE, >=, val1, val2)
256#define CHECK_GT(val1, val2) CHECK_OP(Check_GT, >, val1, val2)
257#define CHECK_NOTNULL(val)                                 \
258  ::tensorflow::internal::CheckNotNull(__FILE__, __LINE__, \
259                                       "'" #val "' Must be non NULL", (val))
260
261#ifndef NDEBUG
262// DCHECK_EQ/NE/...
263#define DCHECK(condition) CHECK(condition)
264#define DCHECK_EQ(val1, val2) CHECK_EQ(val1, val2)
265#define DCHECK_NE(val1, val2) CHECK_NE(val1, val2)
266#define DCHECK_LE(val1, val2) CHECK_LE(val1, val2)
267#define DCHECK_LT(val1, val2) CHECK_LT(val1, val2)
268#define DCHECK_GE(val1, val2) CHECK_GE(val1, val2)
269#define DCHECK_GT(val1, val2) CHECK_GT(val1, val2)
270
271#else
272
273#define DCHECK(condition) \
274  while (false && (condition)) LOG(FATAL)
275
276// NDEBUG is defined, so DCHECK_EQ(x, y) and so on do nothing.
277// However, we still want the compiler to parse x and y, because
278// we don't want to lose potentially useful errors and warnings.
279// _DCHECK_NOP is a helper, and should not be used outside of this file.
280#define _TF_DCHECK_NOP(x, y) \
281  while (false && ((void)(x), (void)(y), 0)) LOG(FATAL)
282
283#define DCHECK_EQ(x, y) _TF_DCHECK_NOP(x, y)
284#define DCHECK_NE(x, y) _TF_DCHECK_NOP(x, y)
285#define DCHECK_LE(x, y) _TF_DCHECK_NOP(x, y)
286#define DCHECK_LT(x, y) _TF_DCHECK_NOP(x, y)
287#define DCHECK_GE(x, y) _TF_DCHECK_NOP(x, y)
288#define DCHECK_GT(x, y) _TF_DCHECK_NOP(x, y)
289
290#endif
291
292// These are for when you don't want a CHECK failure to print a verbose
293// stack trace.  The implementation of CHECK* in this file already doesn't.
294#define QCHECK(condition) CHECK(condition)
295#define QCHECK_EQ(x, y) CHECK_EQ(x, y)
296#define QCHECK_NE(x, y) CHECK_NE(x, y)
297#define QCHECK_LE(x, y) CHECK_LE(x, y)
298#define QCHECK_LT(x, y) CHECK_LT(x, y)
299#define QCHECK_GE(x, y) CHECK_GE(x, y)
300#define QCHECK_GT(x, y) CHECK_GT(x, y)
301
302template <typename T>
303T&& CheckNotNull(const char* file, int line, const char* exprtext, T&& t) {
304  if (t == nullptr) {
305    LogMessageFatal(file, line) << string(exprtext);
306  }
307  return std::forward<T>(t);
308}
309
310int64 MinLogLevelFromEnv();
311
312int64 MinVLogLevelFromEnv();
313
314}  // namespace internal
315}  // namespace tensorflow
316
317#endif  // TENSORFLOW_PLATFORM_DEFAULT_LOGGING_H_
318