diff options
Diffstat (limited to 'base/logging.h')
-rw-r--r-- | base/logging.h | 178 |
1 files changed, 170 insertions, 8 deletions
diff --git a/base/logging.h b/base/logging.h index a1d439c..de8de71 100644 --- a/base/logging.h +++ b/base/logging.h @@ -75,6 +75,18 @@ // // We also override the standard 'assert' to use 'DLOG_ASSERT'. // +// Lastly, there is: +// +// PLOG(ERROR) << "Couldn't do foo"; +// DPLOG(ERROR) << "Couldn't do foo"; +// PLOG_IF(ERROR, cond) << "Couldn't do foo"; +// DPLOG_IF(ERROR, cond) << "Couldn't do foo"; +// PCHECK(condition) << "Couldn't do foo"; +// DPCHECK(condition) << "Couldn't do foo"; +// +// which append the last system error to the message in string form (taken from +// GetLastError() on Windows and errno on POSIX). +// // The supported severity levels for macros that allow you to specify one // are (in increasing order of severity) INFO, WARNING, ERROR, ERROR_REPORT, // and FATAL. @@ -192,18 +204,33 @@ const LogSeverity LOG_DFATAL_LEVEL = LOG_FATAL; // A few definitions of macros that don't generate much code. These are used // by LOG() and LOG_IF, etc. Since these are used all over our code, it's // better to have compact code for these operations. +#define COMPACT_GOOGLE_LOG_EX_INFO(ClassName, ...) \ + logging::ClassName(__FILE__, __LINE__, logging::LOG_INFO , ##__VA_ARGS__) +#define COMPACT_GOOGLE_LOG_EX_WARNING(ClassName, ...) \ + logging::ClassName(__FILE__, __LINE__, logging::LOG_WARNING , ##__VA_ARGS__) +#define COMPACT_GOOGLE_LOG_EX_ERROR(ClassName, ...) \ + logging::ClassName(__FILE__, __LINE__, logging::LOG_ERROR , ##__VA_ARGS__) +#define COMPACT_GOOGLE_LOG_EX_ERROR_REPORT(ClassName, ...) \ + logging::ClassName(__FILE__, __LINE__, \ + logging::LOG_ERROR_REPORT , ##__VA_ARGS__) +#define COMPACT_GOOGLE_LOG_EX_FATAL(ClassName, ...) \ + logging::ClassName(__FILE__, __LINE__, logging::LOG_FATAL , ##__VA_ARGS__) +#define COMPACT_GOOGLE_LOG_EX_DFATAL(ClassName, ...) \ + logging::ClassName(__FILE__, __LINE__, \ + logging::LOG_DFATAL_LEVEL , ##__VA_ARGS__) + #define COMPACT_GOOGLE_LOG_INFO \ - logging::LogMessage(__FILE__, __LINE__) + COMPACT_GOOGLE_LOG_EX_INFO(LogMessage) #define COMPACT_GOOGLE_LOG_WARNING \ - logging::LogMessage(__FILE__, __LINE__, logging::LOG_WARNING) + COMPACT_GOOGLE_LOG_EX_WARNING(LogMessage) #define COMPACT_GOOGLE_LOG_ERROR \ - logging::LogMessage(__FILE__, __LINE__, logging::LOG_ERROR) + COMPACT_GOOGLE_LOG_EX_ERROR(LogMessage) #define COMPACT_GOOGLE_LOG_ERROR_REPORT \ - logging::LogMessage(__FILE__, __LINE__, logging::LOG_ERROR_REPORT) + COMPACT_GOOGLE_LOG_EX_ERROR_REPORT(LogMessage) #define COMPACT_GOOGLE_LOG_FATAL \ - logging::LogMessage(__FILE__, __LINE__, logging::LOG_FATAL) + COMPACT_GOOGLE_LOG_EX_FATAL(LogMessage) #define COMPACT_GOOGLE_LOG_DFATAL \ - logging::LogMessage(__FILE__, __LINE__, logging::LOG_DFATAL_LEVEL) + COMPACT_GOOGLE_LOG_EX_DFATAL(LogMessage) // wingdi.h defines ERROR to be 0. When we call LOG(ERROR), it gets // substituted with 0, and it expands to COMPACT_GOOGLE_LOG_0. To allow us @@ -211,8 +238,9 @@ const LogSeverity LOG_DFATAL_LEVEL = LOG_FATAL; // as COMPACT_GOOGLE_LOG_ERROR, and also define ERROR the same way that // the Windows SDK does for consistency. #define ERROR 0 -#define COMPACT_GOOGLE_LOG_0 \ - logging::LogMessage(__FILE__, __LINE__, logging::LOG_ERROR) +#define COMPACT_GOOGLE_LOG_EX_0(ClassName, ...) \ + COMPACT_GOOGLE_LOG_EX_ERROR(ClassName , ##__VA_ARGS__) +#define COMPACT_GOOGLE_LOG_0 COMPACT_GOOGLE_LOG_ERROR // We use the preprocessor's merging operator, "##", so that, e.g., // LOG(INFO) becomes the token COMPACT_GOOGLE_LOG_INFO. There's some funny @@ -235,12 +263,38 @@ const LogSeverity LOG_DFATAL_LEVEL = LOG_FATAL; #define SYSLOG_ASSERT(condition) \ SYSLOG_IF(FATAL, !(condition)) << "Assert failed: " #condition ". " +#if defined(OS_WIN) +#define LOG_GETLASTERROR(severity) \ + COMPACT_GOOGLE_LOG_EX_ ## severity(Win32ErrorLogMessage, \ + ::logging::GetLastSystemErrorCode()).stream() +#define LOG_GETLASTERROR_MODULE(severity, module) \ + COMPACT_GOOGLE_LOG_EX_ ## severity(Win32ErrorLogMessage, \ + ::logging::GetLastSystemErrorCode(), module).stream() +// PLOG is the usual error logging macro for each platform. +#define PLOG(severity) LOG_GETLASTERROR(severity) +#define DPLOG(severity) DLOG_GETLASTERROR(severity) +#elif defined(OS_POSIX) +#define LOG_ERRNO(severity) \ + COMPACT_GOOGLE_LOG_EX_ ## severity(ErrnoLogMessage, \ + ::logging::GetLastSystemErrorCode()).stream() +// PLOG is the usual error logging macro for each platform. +#define PLOG(severity) LOG_ERRNO(severity) +#define DPLOG(severity) DLOG_ERRNO(severity) +// TODO(tschmelcher): Should we add OSStatus logging for Mac? +#endif + +#define PLOG_IF(severity, condition) \ + !(condition) ? (void) 0 : logging::LogMessageVoidify() & PLOG(severity) + // CHECK dies with a fatal error if condition is not true. It is *not* // controlled by NDEBUG, so the check will be executed regardless of // compilation mode. #define CHECK(condition) \ LOG_IF(FATAL, !(condition)) << "Check failed: " #condition ". " +#define PCHECK(condition) \ + PLOG_IF(FATAL, !(condition)) << "Check failed: " #condition ". " + // A container for a string pointer which can be evaluated to a bool - // true iff the pointer is NULL. struct CheckOpString { @@ -301,6 +355,20 @@ std::string* MakeCheckOpString(const int& v1, #define DLOG_ASSERT(condition) \ true ? (void) 0 : LOG_ASSERT(condition) +#if defined(OS_WIN) +#define DLOG_GETLASTERROR(severity) \ + true ? (void) 0 : logging::LogMessageVoidify() & LOG_GETLASTERROR(severity) +#define DLOG_GETLASTERROR_MODULE(severity, module) \ + true ? (void) 0 : logging::LogMessageVoidify() & \ + LOG_GETLASTERROR_MODULE(severity, module) +#elif defined(OS_POSIX) +#define DLOG_ERRNO(severity) \ + true ? (void) 0 : logging::LogMessageVoidify() & LOG_ERRNO(severity) +#endif + +#define DPLOG_IF(severity, condition) \ + true ? (void) 0 : logging::LogMessageVoidify() & PLOG(severity) + enum { DEBUG_MODE = 0 }; // This macro can be followed by a sequence of stream parameters in @@ -315,6 +383,9 @@ enum { DEBUG_MODE = 0 }; #define DCHECK(condition) \ while (false && (condition)) NDEBUG_EAT_STREAM_PARAMETERS +#define DPCHECK(condition) \ + while (false && (condition)) NDEBUG_EAT_STREAM_PARAMETERS + #define DCHECK_EQ(val1, val2) \ while (false && (val1) == (val2)) NDEBUG_EAT_STREAM_PARAMETERS @@ -354,11 +425,24 @@ enum { DEBUG_MODE = 0 }; #define DLOG_IF(severity, condition) LOG_IF(severity, condition) #define DLOG_ASSERT(condition) LOG_ASSERT(condition) +#if defined(OS_WIN) +#define DLOG_GETLASTERROR(severity) LOG_GETLASTERROR(severity) +#define DLOG_GETLASTERROR_MODULE(severity, module) \ + LOG_GETLASTERROR_MODULE(severity, module) +#elif defined(OS_POSIX) +#define DLOG_ERRNO(severity) LOG_ERRNO(severity) +#endif + +#define DPLOG_IF(severity, condition) PLOG_IF(severity, condition) + // debug-only checking. not executed in NDEBUG mode. enum { DEBUG_MODE = 1 }; #define DCHECK(condition) \ LOG_IF(FATAL, !(condition)) << "Check failed: " #condition ". " +#define DPCHECK(condition) \ + PLOG_IF(FATAL, !(condition)) << "Check failed: " #condition ". " + // Helper macro for binary operators. // Don't use this macro directly in your code, use DCHECK_EQ et al below. #define DCHECK_OP(name, op, val1, val2) \ @@ -413,6 +497,20 @@ DECLARE_DCHECK_STROP_IMPL(_stricmp, false) #define DLOG_ASSERT(condition) \ true ? (void) 0 : LOG_ASSERT(condition) +#if defined(OS_WIN) +#define DLOG_GETLASTERROR(severity) \ + true ? (void) 0 : logging::LogMessageVoidify() & LOG_GETLASTERROR(severity) +#define DLOG_GETLASTERROR_MODULE(severity, module) \ + true ? (void) 0 : logging::LogMessageVoidify() & \ + LOG_GETLASTERROR_MODULE(severity, module) +#elif defined(OS_POSIX) +#define DLOG_ERRNO(severity) \ + true ? (void) 0 : logging::LogMessageVoidify() & LOG_ERRNO(severity) +#endif + +#define DPLOG_IF(severity, condition) \ + true ? (void) 0 : logging::LogMessageVoidify() & PLOG(severity) + enum { DEBUG_MODE = 0 }; // This macro can be followed by a sequence of stream parameters in @@ -428,6 +526,10 @@ extern bool g_enable_dcheck; !logging::g_enable_dcheck ? void (0) : \ LOG_IF(ERROR_REPORT, !(condition)) << "Check failed: " #condition ". " +#define DPCHECK(condition) \ + !logging::g_enable_dcheck ? void (0) : \ + PLOG_IF(ERROR_REPORT, !(condition)) << "Check failed: " #condition ". " + // Helper macro for binary operators. // Don't use this macro directly in your code, use DCHECK_EQ et al below. #define DCHECK_OP(name, op, val1, val2) \ @@ -597,6 +699,66 @@ class LogMessageVoidify { void operator&(std::ostream&) { } }; +#if defined(OS_WIN) +typedef unsigned long SystemErrorCode; +#elif defined(OS_POSIX) +typedef int SystemErrorCode; +#endif + +// Alias for ::GetLastError() on Windows and errno on POSIX. Avoids having to +// pull in windows.h just for GetLastError() and DWORD. +SystemErrorCode GetLastSystemErrorCode(); + +#if defined(OS_WIN) +// Appends a formatted system message of the GetLastError() type. +class Win32ErrorLogMessage { + public: + Win32ErrorLogMessage(const char* file, + int line, + LogSeverity severity, + SystemErrorCode err, + const char* module); + + Win32ErrorLogMessage(const char* file, + int line, + LogSeverity severity, + SystemErrorCode err); + + std::ostream& stream() { return log_message_.stream(); } + + // Appends the error message before destructing the encapsulated class. + ~Win32ErrorLogMessage(); + + private: + SystemErrorCode err_; + // Optional name of the module defining the error. + const char* module_; + LogMessage log_message_; + + DISALLOW_COPY_AND_ASSIGN(Win32ErrorLogMessage); +}; +#elif defined(OS_POSIX) +// Appends a formatted system message of the errno type +class ErrnoLogMessage { + public: + ErrnoLogMessage(const char* file, + int line, + LogSeverity severity, + SystemErrorCode err); + + std::ostream& stream() { return log_message_.stream(); } + + // Appends the error message before destructing the encapsulated class. + ~ErrnoLogMessage(); + + private: + SystemErrorCode err_; + LogMessage log_message_; + + DISALLOW_COPY_AND_ASSIGN(ErrnoLogMessage); +}; +#endif // OS_WIN + // Closes the log file explicitly if open. // NOTE: Since the log file is opened as necessary by the action of logging // statements, there's no guarantee that it will stay closed |