1 | // Licensed to the Apache Software Foundation (ASF) under one |
2 | // or more contributor license agreements. See the NOTICE file |
3 | // distributed with this work for additional information |
4 | // regarding copyright ownership. The ASF licenses this file |
5 | // to you under the Apache License, Version 2.0 (the |
6 | // "License"); you may not use this file except in compliance |
7 | // with the License. You may obtain a copy of the License at |
8 | // |
9 | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | // |
11 | // Unless required by applicable law or agreed to in writing, |
12 | // software distributed under the License is distributed on an |
13 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | // KIND, either express or implied. See the License for the |
15 | // specific language governing permissions and limitations |
16 | // under the License. |
17 | |
18 | #ifndef ARROW_UTIL_LOGGING_H |
19 | #define ARROW_UTIL_LOGGING_H |
20 | |
21 | #ifdef GANDIVA_IR |
22 | |
23 | // The LLVM IR code doesn't have an NDEBUG mode. And, it shouldn't include references to |
24 | // streams or stdc++. So, making the DCHECK calls void in that case. |
25 | |
26 | #define ARROW_IGNORE_EXPR(expr) ((void)(expr)) |
27 | |
28 | #define DCHECK(condition) ARROW_IGNORE_EXPR(condition) |
29 | #define DCHECK_OK(status) ARROW_IGNORE_EXPR(status) |
30 | #define DCHECK_EQ(val1, val2) ARROW_IGNORE_EXPR(val1) |
31 | #define DCHECK_NE(val1, val2) ARROW_IGNORE_EXPR(val1) |
32 | #define DCHECK_LE(val1, val2) ARROW_IGNORE_EXPR(val1) |
33 | #define DCHECK_LT(val1, val2) ARROW_IGNORE_EXPR(val1) |
34 | #define DCHECK_GE(val1, val2) ARROW_IGNORE_EXPR(val1) |
35 | #define DCHECK_GT(val1, val2) ARROW_IGNORE_EXPR(val1) |
36 | |
37 | #else // !GANDIVA_IR |
38 | |
39 | #include <iostream> |
40 | #include <memory> |
41 | #include <string> |
42 | |
43 | #include "arrow/util/macros.h" |
44 | #include "arrow/util/visibility.h" |
45 | |
46 | namespace arrow { |
47 | namespace util { |
48 | |
49 | enum class ArrowLogLevel : int { |
50 | ARROW_DEBUG = -1, |
51 | ARROW_INFO = 0, |
52 | ARROW_WARNING = 1, |
53 | ARROW_ERROR = 2, |
54 | ARROW_FATAL = 3 |
55 | }; |
56 | |
57 | #define ARROW_LOG_INTERNAL(level) ::arrow::util::ArrowLog(__FILE__, __LINE__, level) |
58 | #define ARROW_LOG(level) ARROW_LOG_INTERNAL(::arrow::util::ArrowLogLevel::ARROW_##level) |
59 | #define ARROW_IGNORE_EXPR(expr) ((void)(expr)) |
60 | |
61 | #define ARROW_CHECK(condition) \ |
62 | (condition) ? ARROW_IGNORE_EXPR(0) \ |
63 | : ::arrow::util::Voidify() & \ |
64 | ::arrow::util::ArrowLog(__FILE__, __LINE__, \ |
65 | ::arrow::util::ArrowLogLevel::ARROW_FATAL) \ |
66 | << " Check failed: " #condition " " |
67 | |
68 | // If 'to_call' returns a bad status, CHECK immediately with a logged message |
69 | // of 'msg' followed by the status. |
70 | #define ARROW_CHECK_OK_PREPEND(to_call, msg) \ |
71 | do { \ |
72 | ::arrow::Status _s = (to_call); \ |
73 | ARROW_CHECK(_s.ok()) << (msg) << ": " << _s.ToString(); \ |
74 | } while (false) |
75 | |
76 | // If the status is bad, CHECK immediately, appending the status to the |
77 | // logged message. |
78 | #define ARROW_CHECK_OK(s) ARROW_CHECK_OK_PREPEND(s, "Bad status") |
79 | |
80 | #ifdef NDEBUG |
81 | #define ARROW_DFATAL ::arrow::util::ArrowLogLevel::ARROW_WARNING |
82 | |
83 | #define DCHECK(condition) \ |
84 | ARROW_IGNORE_EXPR(condition); \ |
85 | while (false) ::arrow::util::ArrowLogBase() |
86 | #define DCHECK_OK(status) \ |
87 | ARROW_IGNORE_EXPR(status); \ |
88 | while (false) ::arrow::util::ArrowLogBase() |
89 | #define DCHECK_EQ(val1, val2) \ |
90 | ARROW_IGNORE_EXPR(val1); \ |
91 | while (false) ::arrow::util::ArrowLogBase() |
92 | #define DCHECK_NE(val1, val2) \ |
93 | ARROW_IGNORE_EXPR(val1); \ |
94 | while (false) ::arrow::util::ArrowLogBase() |
95 | #define DCHECK_LE(val1, val2) \ |
96 | ARROW_IGNORE_EXPR(val1); \ |
97 | while (false) ::arrow::util::ArrowLogBase() |
98 | #define DCHECK_LT(val1, val2) \ |
99 | ARROW_IGNORE_EXPR(val1); \ |
100 | while (false) ::arrow::util::ArrowLogBase() |
101 | #define DCHECK_GE(val1, val2) \ |
102 | ARROW_IGNORE_EXPR(val1); \ |
103 | while (false) ::arrow::util::ArrowLogBase() |
104 | #define DCHECK_GT(val1, val2) \ |
105 | ARROW_IGNORE_EXPR(val1); \ |
106 | while (false) ::arrow::util::ArrowLogBase() |
107 | |
108 | #else |
109 | #define ARROW_DFATAL ::arrow::util::ArrowLogLevel::ARROW_FATAL |
110 | |
111 | #define DCHECK(condition) ARROW_CHECK(condition) |
112 | #define DCHECK_OK(status) (ARROW_CHECK((status).ok()) << (status).message()) |
113 | #define DCHECK_EQ(val1, val2) ARROW_CHECK((val1) == (val2)) |
114 | #define DCHECK_NE(val1, val2) ARROW_CHECK((val1) != (val2)) |
115 | #define DCHECK_LE(val1, val2) ARROW_CHECK((val1) <= (val2)) |
116 | #define DCHECK_LT(val1, val2) ARROW_CHECK((val1) < (val2)) |
117 | #define DCHECK_GE(val1, val2) ARROW_CHECK((val1) >= (val2)) |
118 | #define DCHECK_GT(val1, val2) ARROW_CHECK((val1) > (val2)) |
119 | |
120 | #endif // NDEBUG |
121 | |
122 | // This code is adapted from |
123 | // https://github.com/ray-project/ray/blob/master/src/ray/util/logging.h. |
124 | |
125 | // To make the logging lib plugable with other logging libs and make |
126 | // the implementation unawared by the user, ArrowLog is only a declaration |
127 | // which hide the implementation into logging.cc file. |
128 | // In logging.cc, we can choose different log libs using different macros. |
129 | |
130 | // This is also a null log which does not output anything. |
131 | class ARROW_EXPORT ArrowLogBase { |
132 | public: |
133 | virtual ~ArrowLogBase() {} |
134 | |
135 | virtual bool IsEnabled() const { return false; } |
136 | |
137 | template <typename T> |
138 | ArrowLogBase& operator<<(const T& t) { |
139 | if (IsEnabled()) { |
140 | Stream() << t; |
141 | } |
142 | return *this; |
143 | } |
144 | |
145 | protected: |
146 | virtual std::ostream& Stream() { return std::cerr; } |
147 | }; |
148 | |
149 | class ARROW_EXPORT ArrowLog : public ArrowLogBase { |
150 | public: |
151 | ArrowLog(const char* file_name, int line_number, ArrowLogLevel severity); |
152 | |
153 | virtual ~ArrowLog(); |
154 | |
155 | /// Return whether or not current logging instance is enabled. |
156 | /// |
157 | /// \return True if logging is enabled and false otherwise. |
158 | virtual bool IsEnabled() const; |
159 | |
160 | /// The init function of arrow log for a program which should be called only once. |
161 | /// |
162 | /// \param appName The app name which starts the log. |
163 | /// \param severity_threshold Logging threshold for the program. |
164 | /// \param logDir Logging output file name. If empty, the log won't output to file. |
165 | static void StartArrowLog(const std::string& appName, |
166 | ArrowLogLevel severity_threshold = ArrowLogLevel::ARROW_INFO, |
167 | const std::string& logDir = "" ); |
168 | |
169 | /// The shutdown function of arrow log, it should be used with StartArrowLog as a pair. |
170 | static void ShutDownArrowLog(); |
171 | |
172 | /// Install the failure signal handler to output call stack when crash. |
173 | /// If glog is not installed, this function won't do anything. |
174 | static void InstallFailureSignalHandler(); |
175 | |
176 | private: |
177 | ARROW_DISALLOW_COPY_AND_ASSIGN(ArrowLog); |
178 | |
179 | // Hide the implementation of log provider by void *. |
180 | // Otherwise, lib user may define the same macro to use the correct header file. |
181 | void* logging_provider_; |
182 | /// True if log messages should be logged and false if they should be ignored. |
183 | bool is_enabled_; |
184 | |
185 | static ArrowLogLevel severity_threshold_; |
186 | // In InitGoogleLogging, it simply keeps the pointer. |
187 | // We need to make sure the app name passed to InitGoogleLogging exist. |
188 | static std::unique_ptr<std::string> app_name_; |
189 | |
190 | protected: |
191 | virtual std::ostream& Stream(); |
192 | }; |
193 | |
194 | // This class make ARROW_CHECK compilation pass to change the << operator to void. |
195 | // This class is copied from glog. |
196 | class ARROW_EXPORT Voidify { |
197 | public: |
198 | Voidify() {} |
199 | // This has to be an operator with a precedence lower than << but |
200 | // higher than ?: |
201 | void operator&(ArrowLogBase&) {} |
202 | }; |
203 | |
204 | } // namespace util |
205 | } // namespace arrow |
206 | #endif // GANDIVA_IR |
207 | |
208 | #endif // ARROW_UTIL_LOGGING_H |
209 | |