// Copyright 2014 The Android Open Source Project // // This software is licensed under the terms of the GNU General Public // License version 2, as published by the Free Software Foundation, and // may be copied, distributed, and modified under those terms. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. #ifndef ANDROID_BASE_LOG_H #define ANDROID_BASE_LOG_H #include #include #include namespace android { namespace base { // The list of severity levels used for logging. // Note that negative verbosity levels are used. typedef int LogSeverity; const LogSeverity LOG_VERBOSE = -1; const LogSeverity LOG_INFO = 0; const LogSeverity LOG_WARNING = 1; const LogSeverity LOG_ERROR = 2; const LogSeverity LOG_FATAL = 3; const LogSeverity LOG_NUM_SEVERITIES = 4; // LOG_DFATAL will be LOG_ERROR in release builds, and LOG_FATAL in debug // ones. #ifdef NDEBUG const LogSeverity LOG_DFATAL = LOG_ERROR; #else const LogSeverity LOG_DFATAL = LOG_FATAL; #endif // Returns the minimal log level. LogSeverity getMinLogLevel(); // Helper macro used to test if logging for a given log level is // currently enabled. |severity| must be a log level without the LOG_ // prefix, as in: // // if (LOG_IS_ON(INFO)) { // ... do additionnal logging // } // #define LOG_IS_ON(severity) \ ((::android::base::LOG_ ## severity) >= \ ::android::base::getMinLogLevel()) // For performance reasons, it's important to avoid constructing a // LogMessage instance every time a LOG() or CHECK() statement is // encountered at runtime, i.e. these objects should only be constructed // when absolutely necessary, which means: // - For LOG() statements, when the corresponding log level is enabled. // - For CHECK(), when the tested expression doesn't hold. // // At the same time, we really want to use expressions like: // LOG(severity) << some_stuff << some_more_stuff; // // This means LOG(severity) should expand to something that can take // << operators on its right hand side. This is achieved with the // ternary '? :', as implemented by this helper macro. // // Unfortunately, a simple thing like: // // !(condition) ? (void)0 : (expr) // // will not work, because the compiler complains loudly with: // // error: second operand to the conditional operator is of type 'void', // but the third operand is neither a throw-expression nor of type 'void' #define LOG_LAZY_EVAL(condition, expr) \ !(condition) ? (void)0 : ::android::base::LogStreamVoidify() & (expr) // Send a message to the log if |severity| is higher or equal to the current // logging severity level. This macro expands to an expression that acts as // an input stream for strings, ints and floating point values, as well as // LogString instances. Usage example: // // LOG(INFO) << "Starting flux capacitor"; // fluxCapacitor::start(); // LOG(INFO) << "Flux capacitor started"; // // Note that the macro implementation is optimized to avoid doing any work // if the severity level is disabled. // // It's possible to do conditional logging with LOG_IF() #define LOG(severity) \ LOG_LAZY_EVAL(LOG_IS_ON(severity), \ LOG_MESSAGE_STREAM_COMPACT(severity)) // A variant of LOG() that only performs logging if a specific condition // is encountered. Note that |condition| is only evaluated if |severity| // is high enough. Usage example: // // LOG(INFO) << "Starting fuel injector"; // fuelInjector::start(); // LOG(INFO) << "Fuel injection started"; // LOG_IF(INFO, fuelInjector::hasOptimalLevel()) // << "Fuel injection at optimal level"; // #define LOG_IF(severity, condition) \ LOG_LAZY_EVAL(LOG_IS_ON(severity) && (condition), \ LOG_MESSAGE_STREAM_COMPACT(severity)) // A variant of LOG() that also appends the string message corresponding // to the current value of 'errno' just before the macro is called. This // also preserves the value of 'errno' so it can be tested after the // macro call (i.e. any error during log output does not interfere). #define PLOG(severity) \ LOG_LAZY_EVAL(LOG_IS_ON(severity), \ PLOG_MESSAGE_STREAM_COMPACT(severity)) // A variant of LOG_IF() that also appends the string message corresponding // to the current value of 'errno' just before the macro is called. This // also preserves the value of 'errno' so it can be tested after the // macro call (i.e. any error during log output does not interfere). #define PLOG_IF(severity, condition) \ LOG_LAZY_EVAL(LOG_IS_ON(severity) && (condition), \ PLOG_MESSAGE_STREAM_COMPACT(severity)) // Evaluate |condition|, and if it fails, log a fatal message. // This is a better version of assert(), in the future, this will // also break directly into the debugger for debug builds. // // Usage is similar to LOG(FATAL), e.g.: // // CHECK(some_condition) << "Something really bad happened!"; // #define CHECK(condition) \ LOG_IF(FATAL, !(condition)) << "Check failed: " #condition ". " // A variant of CHECK() that also appends the errno message string at // the end of the log message before exiting the process. #define PCHECK(condition) \ PLOG_IF(FATAL, !(condition)) << "Check failed: " #condition ". " // Define ENABLE_DLOG to 1 here if DLOG() statements should be compiled // as normal LOG() ones in the final binary. If 0, the statements will not // be compiled. #ifndef ENABLE_DLOG # if defined(NDEBUG) # define ENABLE_DLOG 0 # else # define ENABLE_DLOG 1 # endif #endif // ENABLE_DCHECK controls how DCHECK() statements are compiled: // 0 - DCHECK() are not compiled in the binary at all. // 1 - DCHECK() are compiled, but are not performed at runtime, unless // the DCHECK level has been increased explicitely. // 2 - DCHECK() are always compiled as CHECK() in the final binary. #ifndef ENABLE_DCHECK # if defined(NDEBUG) # define ENABLE_DCHECK 1 # else # define ENABLE_DCHECK 2 # endif #endif // DLOG_IS_ON(severity) is used to indicate whether DLOG() should print // something for the current level. #if ENABLE_DLOG # define DLOG_IS_ON(severity) LOG_IS_ON(severity) #else // NOTE: The compile-time constant ensures that the DLOG() statements are // not compiled in the final binary. # define DLOG_IS_ON(severity) false #endif // DCHECK_IS_ON() is used to indicate whether DCHECK() should do anything. #if ENABLE_DCHECK == 0 // NOTE: Compile-time constant ensures the DCHECK() statements are // note compiled in the final binary. # define DCHECK_IS_ON() false #elif ENABLE_DCHECK == 1 # define DCHECK_IS_ON() ::android::base::dcheckIsEnabled() #else # define DCHECK_IS_ON() true #endif // A function that returns true iff DCHECK() should actually do any checking. bool dcheckIsEnabled(); // Change the DCHECK() level to either false or true. Should only be called // early, e.g. after parsing command-line arguments. Returns previous value. bool setDcheckLevel(bool enabled); // DLOG() is like LOG() for debug builds, and doesn't do anything for // release one. This is useful to add log messages that you don't want // to see in the final binaries, but are useful during testing. #define DLOG(severity) LOG_IF(severity, DLOG_IS_ON()) // DLOG_IF() is like DLOG() for debug builds, and doesn't do anything for // release one. See DLOG() comments. #define DLOG_IF(severity, condition) \ LOG_IF(severity, DLOG_IS_ON() && (condition)) // DCHECK(condition) is used to perform CHECK() in debug builds, or if // the program called setDcheckLevel(true) previously. Note that it is // also possible to completely remove them from the final binary by // using the compiler flag -DENABLE_DCHECK=0 #define DCHECK(condition) \ LOG_IF(FATAL, DCHECK_IS_ON() && !(condition)) \ << "Check failed: " #condition ". " // Convenience class used hold a formatted string for logging reasons. // Usage example: // // LOG(INFO) << LogString("There are %d items in this set", count); // class LogString { public: LogString(const char* fmt, ...); ~LogString(); const char* string() const { return mString; } private: char* mString; }; // Helper structure used to group the parameters of a LOG() or CHECK() // statement. struct LogParams { LogParams() : file(NULL), lineno(-1), severity(-1) {} LogParams(const char* a_file, int a_lineno, LogSeverity a_severity) : file(a_file), lineno(a_lineno), severity(a_severity) {} const char* file; int lineno; LogSeverity severity; }; // Helper class used to implement an input stream similar to std::istream // where it's possible to inject strings, integers, floats and LogString // instances with the << operator. // // This also takes a source file, line number and severity to avoid // storing these in the stack of the functions were LOG() and CHECK() // statements are called. class LogStream { public: LogStream(const char* file, int lineno, LogSeverity severity); ~LogStream(); inline LogStream& operator<<(const char* str) { append(str); return *this; } inline LogStream& operator<<(const LogString& str) { append(str.string()); return *this; } // Note: this prints the pointer value (address). LogStream& operator<<(const void* v); LogStream& operator<<(char ch); LogStream& operator<<(int v); LogStream& operator<<(unsigned v); LogStream& operator<<(long v); LogStream& operator<<(unsigned long v); //LogStream& operator<<(size_t v); LogStream& operator<<(long long v); LogStream& operator<<(unsigned long long v); LogStream& operator<<(float v); LogStream& operator<<(double v); const char* string() const { return mString ? mString : ""; } size_t size() const { return mSize; } const LogParams& params() const { return mParams; } private: void append(const char* str); void append(const char* str, size_t len); LogParams mParams; char* mString; size_t mSize; size_t mCapacity; }; // Helper class used to avoid compiler errors, see LOG_LAZY_EVAL for // more information. class LogStreamVoidify { public: LogStreamVoidify() { } // This has to be an operator with a precedence lower than << but // higher than ?: void operator&(LogStream&) { } }; // This represents an log message. At creation time, provide the name of // the current file, the source line number and a severity. // You can them stream stuff into it with <<. For example: // // LogMessage(__FILE__, __LINE__, LOG_INFO) << "Hello World!\n"; // // When destroyed, the message sends the final output to the appropriate // log (e.g. stderr by default). class LogMessage { public: LogMessage(const char* file, int line, LogSeverity severity); ~LogMessage(); LogStream& stream() const { return *mStream; } protected: // Avoid that each LOG() statement LogStream* mStream; }; // Helper macros to avoid too much typing. This creates a new LogMessage // instance with the appropriate file source path, file source line and // severity. #define LOG_MESSAGE_COMPACT(severity) \ ::android::base::LogMessage( \ __FILE__, \ __LINE__, \ ::android::base::LOG_ ## severity) #define LOG_MESSAGE_STREAM_COMPACT(severity) \ LOG_MESSAGE_COMPACT(severity).stream() // A variant of LogMessage that saves the errno value on creation, // then restores it on destruction, as well as append a strerror() // error message to the log before sending it for output. Used by // the PLOG() implementation(s). // // This cannot be a sub-class of LogMessage because the destructor needs // to restore the saved errno message after sending the message to the // LogOutput and deleting the stream. class ErrnoLogMessage { public: ErrnoLogMessage(const char* file, int line, LogSeverity severity, int errnoCode); ~ErrnoLogMessage(); LogStream& stream() const { return *mStream; } private: LogStream* mStream; int mErrno; }; // Helper macros to avoid too much typing. #define PLOG_MESSAGE_COMPACT(severity) \ ::android::base::ErrnoLogMessage( \ __FILE__, \ __LINE__, \ ::android::base::LOG_ ## severity, \ errno) #define PLOG_MESSAGE_STREAM_COMPACT(severity) \ PLOG_MESSAGE_COMPACT(severity).stream() namespace testing { // Abstract interface to the output where the log messages are sent. // IMPORTANT: Only use this for unit testing the log facility. class LogOutput { public: LogOutput() {} virtual ~LogOutput() {} // Send a full log message to the output. Not zero terminated, and // Does not have a trailing \n which can be added by the implementation // when writing the message to a file. // Note: if |severity| is LOG_FATAL, this should also terminate the // process. virtual void logMessage(const LogParams& params, const char* message, size_t message_len) = 0; // Set a new log output, and return pointer to the previous // implementation, which will be NULL for the default one. // |newOutput| is either NULL (which means the default), or a // custom instance of LogOutput. static LogOutput* setNewOutput(LogOutput* newOutput); }; } // namespace testing } // namespace base } // namespace android #endif // ANDROID_BASE_LOG_H