blob: d1ef3d38dde51556526bcdbd7cecac501cc6b4fe [file] [log] [blame]
// 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