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. 82const int FATAL = -3; 83const int ERROR = -2; 84const int WARNING = -1; 85const int INFO = 0; 86 87// ------------------------- Glog compatibility ------------------------------ 88 89namespace google { 90 91typedef int LogSeverity; 92const int INFO = ::INFO; 93const int WARNING = ::WARNING; 94const int ERROR = ::ERROR; 95const 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. 104class LogSink { 105 public: 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. 116static std::set<LogSink *> log_sinks_global; 117 118// Note: the Log sink functions are not thread safe. 119inline void AddLogSink(LogSink *sink) { 120 // TODO(settinger): Add locks for thread safety. 121 log_sinks_global.insert(sink); 122} 123inline void RemoveLogSink(LogSink *sink) { 124 log_sinks_global.erase(sink); 125} 126 127#endif // #ifdef ENABLE_LOG_SINKS 128 129inline 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. 140class MessageLogger { 141 public: 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. 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. 197 std::stringstream &stream() { return stream_; } 198 199 private: 200#ifdef ENABLE_LOG_SINKS 201 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 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 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". 250class LoggerVoidify { 251 public: 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. 296template<class T> 297void 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. 355template <typename T> 356T& 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 363template <typename T> 364T* CheckNotNull(const char *file, int line, const char *names, T* t) { 365 return CheckNotNullCommon(file, line, names, t); 366} 367 368template <typename T> 369T& 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 387inline void PrintAndroid(const char *msg) { 388 __android_log_write(ANDROID_LOG_VERBOSE, "native", msg); 389} 390 391#endif // MOBILE_BASE_LOGGING_H_ 392