| // 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 <errno.h> |
| #include <stdarg.h> |
| #include <stddef.h> |
| |
| 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 |