1 // Copyright 2011 Google Inc. All Rights Reserved.
2 // Author: settinger@google.com (Scott Ettinger)
3
4 // Simplified Google3 style logging with Android support.
5 // Supported macros are : LOG(INFO), LOG(WARNING), LOG(ERROR), LOG(FATAL),
6 // and VLOG(n).
7 //
8 // Portions of this code are taken from the GLOG package. This code
9 // is only a small subset of the GLOG functionality. And like GLOG,
10 // higher levels are more verbose.
11 //
12 // Notable differences from GLOG :
13 //
14 // 1. lack of support for displaying unprintable characters and lack
15 // of stack trace information upon failure of the CHECK macros.
16 // 2. All output is tagged with the string "native".
17 // 3. While there is no runtime flag filtering logs (-v, -vmodule), the
18 // compile time define MAX_LOG_LEVEL can be used to silence any
19 // logging above the given level.
20 //
21 // -------------------------------- Usage ------------------------------------
22 // Basic usage :
23 // LOG(<severity level>) acts as a c++ stream to the Android logcat output.
24 // e.g. LOG(INFO) << "Value of counter = " << counter;
25 //
26 // Valid severity levels include INFO, WARNING, ERROR, FATAL.
27 // The various severity levels are routed to the corresponding Android logcat
28 // output.
29 // LOG(FATAL) outputs to the log and then terminates.
30 //
31 // VLOG(<severity level>) can also be used.
32 // VLOG(n) output is directed to the Android logcat levels as follows :
33 // >=2 - Verbose
34 // 1 - Debug
35 // 0 - Info
36 // -1 - Warning
37 // -2 - Error
38 // <=-3 - Fatal
39 // Note that VLOG(FATAL) will terminate the program.
40 //
41 // CHECK macros are defined to test for conditions within code. Any CHECK
42 // that fails will log the failure and terminate the application.
43 // e.g. CHECK_GE(3, 2) will pass while CHECK_GE(3, 4) will fail after logging
44 // "Check failed 3 >= 4".
45 // The following CHECK macros are defined :
46 //
47 // CHECK(condition) - fails if condition is false and logs condition.
48 // CHECK_NOTNULL(variable) - fails if the variable is NULL.
49 //
50 // The following binary check macros are also defined :
51 // Macro operator applied
52 // ------------------------------------------
53 // CHECK_EQ(val1, val2) val1 == val2
54 // CHECK_NE(val1, val2) val1 != val2
55 // CHECK_GT(val1, val2) val1 > val2
56 // CHECK_GE(val1, val2) val1 >= val2
57 // CHECK_LT(val1, val2) val1 < val2
58 // CHECK_LE(val1, val2) val1 <= val2
59 //
60 // Debug only versions of all of the check macros are also defined. These
61 // macros generate no code in a release build, but avoid unused variable
62 // warnings / errors.
63 // To use the debug only versions, Prepend a D to the normal check macros.
64 // e.g. DCHECK_EQ(a, b);
65
66 #ifndef MOBILE_BASE_LOGGING_H_
67 #define MOBILE_BASE_LOGGING_H_
68
69 // Definitions for building on an Android system.
70 #include <android/log.h>
71 #include <time.h>
72
73 #include <algorithm>
74 #include <iostream>
75 #include <string>
76 #include <fstream>
77 #include <set>
78 #include <sstream>
79 #include <vector>
80
81 // Log severity level constants.
82 const int FATAL = -3;
83 const int ERROR = -2;
84 const int WARNING = -1;
85 const int INFO = 0;
86
87 // ------------------------- Glog compatibility ------------------------------
88
89 namespace google {
90
91 typedef int LogSeverity;
92 const int INFO = ::INFO;
93 const int WARNING = ::WARNING;
94 const int ERROR = ::ERROR;
95 const int FATAL = ::FATAL;
96
97 #ifdef ENABLE_LOG_SINKS
98
99 // Sink class used for integration with mock and test functions.
100 // If sinks are added, all log output is also sent to each sink through
101 // the send function. In this implementation, WaitTillSent() is called
102 // immediately after the send.
103 // This implementation is not thread safe.
104 class LogSink {
105 public:
~LogSink()106 virtual ~LogSink() {}
107 virtual void send(LogSeverity severity, const char* full_filename,
108 const char* base_filename, int line,
109 const struct tm* tm_time,
110 const char* message, size_t message_len) = 0;
111 virtual void WaitTillSent() = 0;
112 };
113
114 // Global set of log sinks.
115 // TODO(settinger): Move this into a .cc file.
116 static std::set<LogSink *> log_sinks_global;
117
118 // Note: the Log sink functions are not thread safe.
AddLogSink(LogSink * sink)119 inline void AddLogSink(LogSink *sink) {
120 // TODO(settinger): Add locks for thread safety.
121 log_sinks_global.insert(sink);
122 }
RemoveLogSink(LogSink * sink)123 inline void RemoveLogSink(LogSink *sink) {
124 log_sinks_global.erase(sink);
125 }
126
127 #endif // #ifdef ENABLE_LOG_SINKS
128
InitGoogleLogging(char * argv)129 inline void InitGoogleLogging(char *argv) {}
130
131 } // namespace google
132
133 // ---------------------------- Logger Class --------------------------------
134
135 // Class created for each use of the logging macros.
136 // The logger acts as a stream and routes the final stream contents to the
137 // Android logcat output at the proper filter level. This class should not
138 // be directly instantiated in code, rather it should be invoked through the
139 // use of the log macros LOG, or VLOG.
140 class MessageLogger {
141 public:
MessageLogger(const char * file,int line,const char * tag,int severity)142 MessageLogger(const char *file, int line, const char *tag, int severity)
143 : file_(file), line_(line), tag_(tag), severity_(severity) {
144 // Pre-pend the stream with the file and line number.
145 StripBasename(std::string(file), &filename_only_);
146 stream_ << filename_only_ << ":" << line << " ";
147 }
148
149 // Output the contents of the stream to the proper channel on destruction.
~MessageLogger()150 ~MessageLogger() {
151 #ifdef MAX_LOG_LEVEL
152 if (severity_ > MAX_LOG_LEVEL && severity_ > FATAL) {
153 return;
154 }
155 #endif
156 stream_ << "\n";
157 static const int android_log_levels[] = {
158 ANDROID_LOG_FATAL, // LOG(FATAL)
159 ANDROID_LOG_ERROR, // LOG(ERROR)
160 ANDROID_LOG_WARN, // LOG(WARNING)
161 ANDROID_LOG_INFO, // LOG(INFO), VLOG(0)
162 ANDROID_LOG_DEBUG, // VLOG(1)
163 ANDROID_LOG_VERBOSE, // VLOG(2) .. VLOG(N)
164 };
165
166 // Bound the logging level.
167 const int kMaxVerboseLevel = 2;
168 int android_level_index = std::min(std::max(FATAL, severity_),
169 kMaxVerboseLevel) - FATAL;
170 int android_log_level = android_log_levels[android_level_index];
171
172 // Output the log string the Android log at the appropriate level.
173 __android_log_write(android_log_level, tag_.c_str(), stream_.str().c_str());
174
175 // Indicate termination if needed.
176 if (severity_ == FATAL) {
177 __android_log_write(ANDROID_LOG_FATAL,
178 tag_.c_str(),
179 "terminating.\n");
180 }
181
182 #ifdef ENABLE_LOG_SINKS
183
184 LogToSinks(severity_);
185 WaitForSinks();
186
187 #endif // #ifdef ENABLE_LOG_SINKS
188
189 // Android logging at level FATAL does not terminate execution, so abort()
190 // is still required to stop the program.
191 if (severity_ == FATAL) {
192 abort();
193 }
194 }
195
196 // Return the stream associated with the logger object.
stream()197 std::stringstream &stream() { return stream_; }
198
199 private:
200 #ifdef ENABLE_LOG_SINKS
201
LogToSinks(int severity)202 void LogToSinks(int severity) {
203 time_t rawtime;
204 struct tm * timeinfo;
205
206 time ( &rawtime );
207 timeinfo = localtime ( &rawtime );
208 std::set<google::LogSink *>::iterator iter;
209 // Send the log message to all sinks.
210 for (iter = google::log_sinks_global.begin();
211 iter != google::log_sinks_global.end(); ++iter)
212 (*iter)->send(severity, file_.c_str(), filename_only_.c_str(), line_,
213 timeinfo, stream_.str().c_str(), stream_.str().size());
214 }
215
WaitForSinks()216 void WaitForSinks() {
217 // TODO(settinger): add locks for thread safety.
218 std::set<google::LogSink *>::iterator iter;
219 // Call WaitTillSent() for all sinks.
220 for (iter = google::log_sinks_global.begin();
221 iter != google::log_sinks_global.end(); ++iter)
222 (*iter)->WaitTillSent();
223 }
224
225 #endif // #ifdef ENABLE_LOG_SINKS
226
StripBasename(const std::string & full_path,std::string * filename)227 void StripBasename(const std::string &full_path, std::string *filename) {
228 // TODO(settinger): add support for OS with different path separators.
229 const char kSeparator = '/';
230 size_t pos = full_path.rfind(kSeparator);
231 if (pos != std::string::npos)
232 *filename = full_path.substr(pos + 1, std::string::npos);
233 else
234 *filename = full_path;
235 }
236
237 std::string file_;
238 std::string filename_only_;
239 int line_;
240 std::string tag_;
241 std::stringstream stream_;
242 int severity_;
243 };
244
245 // ---------------------- Logging Macro definitions --------------------------
246
247 // This class is used to explicitly ignore values in the conditional
248 // logging macros. This avoids compiler warnings like "value computed
249 // is not used" and "statement has no effect".
250 class LoggerVoidify {
251 public:
LoggerVoidify()252 LoggerVoidify() { }
253 // This has to be an operator with a precedence lower than << but
254 // higher than ?:
255 void operator&(const std::ostream &s) { }
256 };
257
258 // Log only if condition is met. Otherwise evaluates to void.
259 #define LOG_IF(severity, condition) \
260 !(condition) ? (void) 0 : LoggerVoidify() & \
261 MessageLogger((char *)__FILE__, __LINE__, "native", severity).stream()
262
263 // Log only if condition is NOT met. Otherwise evaluates to void.
264 #define LOG_IF_FALSE(severity, condition) LOG_IF(severity, !(condition))
265
266 // LG is a convenient shortcut for LOG(INFO). Its use is in new
267 // google3 code is discouraged and the following shortcut exists for
268 // backward compatibility with existing code.
269 #ifdef MAX_LOG_LEVEL
270 #define LOG(n) LOG_IF(n, n <= MAX_LOG_LEVEL)
271 #define VLOG(n) LOG_IF(n, n <= MAX_LOG_LEVEL)
272 #define LG LOG_IF(INFO, INFO <= MAX_LOG_LEVEL)
273 #else
274 #define LOG(n) MessageLogger((char *)__FILE__, __LINE__, "native", n).stream()
275 #define VLOG(n) MessageLogger((char *)__FILE__, __LINE__, "native", n).stream()
276 #define LG MessageLogger((char *)__FILE__, __LINE__, "native", INFO).stream()
277 #endif
278
279 // Currently, VLOG is always on for levels below MAX_LOG_LEVEL.
280 #ifndef MAX_LOG_LEVEL
281 #define VLOG_IS_ON(x) (1)
282 #else
283 #define VLOG_IS_ON(x) (x <= MAX_LOG_LEVEL)
284 #endif
285
286 #ifndef NDEBUG
287 #define DLOG LOG
288 #else
289 #define DLOG(severity) true ? (void) 0 : LoggerVoidify() & \
290 MessageLogger((char *)__FILE__, __LINE__, "native", severity).stream()
291 #endif
292
293 // ---------------------------- CHECK helpers --------------------------------
294
295 // Log a message and terminate.
296 template<class T>
LogMessageFatal(const char * file,int line,const T & message)297 void LogMessageFatal(const char *file, int line, const T &message) {
298 MessageLogger((char *)__FILE__, __LINE__, "native", FATAL).stream()
299 << message;
300 }
301
302 // ---------------------------- CHECK macros ---------------------------------
303
304 // Check for a given boolean condition.
305 #define CHECK(condition) LOG_IF_FALSE(FATAL, condition) \
306 << "Check failed: " #condition " "
307
308 #ifndef NDEBUG
309 // Debug only version of CHECK
310 #define DCHECK(condition) LOG_IF_FALSE(FATAL, condition) \
311 << "Check failed: " #condition " "
312 #else
313 // Optimized version - generates no code.
314 #define DCHECK(condition) if (false) LOG_IF_FALSE(FATAL, condition) \
315 << "Check failed: " #condition " "
316 #endif // NDEBUG
317
318 // ------------------------- CHECK_OP macros ---------------------------------
319
320 // Generic binary operator check macro. This should not be directly invoked,
321 // instead use the binary comparison macros defined below.
322 #define CHECK_OP(val1, val2, op) LOG_IF_FALSE(FATAL, (val1 op val2)) \
323 << "Check failed: " #val1 " " #op " " #val2 " "
324
325 // Check_op macro definitions
326 #define CHECK_EQ(val1, val2) CHECK_OP(val1, val2, ==)
327 #define CHECK_NE(val1, val2) CHECK_OP(val1, val2, !=)
328 #define CHECK_LE(val1, val2) CHECK_OP(val1, val2, <=)
329 #define CHECK_LT(val1, val2) CHECK_OP(val1, val2, <)
330 #define CHECK_GE(val1, val2) CHECK_OP(val1, val2, >=)
331 #define CHECK_GT(val1, val2) CHECK_OP(val1, val2, >)
332
333 #ifndef NDEBUG
334 // Debug only versions of CHECK_OP macros.
335 #define DCHECK_EQ(val1, val2) CHECK_OP(val1, val2, ==)
336 #define DCHECK_NE(val1, val2) CHECK_OP(val1, val2, !=)
337 #define DCHECK_LE(val1, val2) CHECK_OP(val1, val2, <=)
338 #define DCHECK_LT(val1, val2) CHECK_OP(val1, val2, <)
339 #define DCHECK_GE(val1, val2) CHECK_OP(val1, val2, >=)
340 #define DCHECK_GT(val1, val2) CHECK_OP(val1, val2, >)
341 #else
342 // These versions generate no code in optimized mode.
343 #define DCHECK_EQ(val1, val2) if (false) CHECK_OP(val1, val2, ==)
344 #define DCHECK_NE(val1, val2) if (false) CHECK_OP(val1, val2, !=)
345 #define DCHECK_LE(val1, val2) if (false) CHECK_OP(val1, val2, <=)
346 #define DCHECK_LT(val1, val2) if (false) CHECK_OP(val1, val2, <)
347 #define DCHECK_GE(val1, val2) if (false) CHECK_OP(val1, val2, >=)
348 #define DCHECK_GT(val1, val2) if (false) CHECK_OP(val1, val2, >)
349 #endif // NDEBUG
350
351 // ---------------------------CHECK_NOTNULL macros ---------------------------
352
353 // Helpers for CHECK_NOTNULL(). Two are necessary to support both raw pointers
354 // and smart pointers.
355 template <typename T>
CheckNotNullCommon(const char * file,int line,const char * names,T & t)356 T& CheckNotNullCommon(const char *file, int line, const char *names, T& t) {
357 if (t == NULL) {
358 LogMessageFatal(file, line, std::string(names));
359 }
360 return t;
361 }
362
363 template <typename T>
CheckNotNull(const char * file,int line,const char * names,T * t)364 T* CheckNotNull(const char *file, int line, const char *names, T* t) {
365 return CheckNotNullCommon(file, line, names, t);
366 }
367
368 template <typename T>
CheckNotNull(const char * file,int line,const char * names,T & t)369 T& CheckNotNull(const char *file, int line, const char *names, T& t) {
370 return CheckNotNullCommon(file, line, names, t);
371 }
372
373 // Check that a pointer is not null.
374 #define CHECK_NOTNULL(val) \
375 CheckNotNull(__FILE__, __LINE__, "'" #val "' Must be non NULL", (val))
376
377 #ifndef NDEBUG
378 // Debug only version of CHECK_NOTNULL
379 #define DCHECK_NOTNULL(val) \
380 CheckNotNull(__FILE__, __LINE__, "'" #val "' Must be non NULL", (val))
381 #else
382 // Optimized version - generates no code.
383 #define DCHECK_NOTNULL(val) if (false)\
384 CheckNotNull(__FILE__, __LINE__, "'" #val "' Must be non NULL", (val))
385 #endif // NDEBUG
386
PrintAndroid(const char * msg)387 inline void PrintAndroid(const char *msg) {
388 __android_log_write(ANDROID_LOG_VERBOSE, "native", msg);
389 }
390
391 #endif // MOBILE_BASE_LOGGING_H_
392