LogCabin
|
00001 /* Copyright (c) 2010-2012 Stanford University 00002 * Copyright (c) 2014 Diego Ongaro 00003 * 00004 * Permission to use, copy, modify, and distribute this software for any 00005 * purpose with or without fee is hereby granted, provided that the above 00006 * copyright notice and this permission notice appear in all copies. 00007 * 00008 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES 00009 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 00010 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR 00011 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 00012 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 00013 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 00014 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 00015 */ 00016 00017 #include <cinttypes> 00018 #include <cstdlib> 00019 #include <string> 00020 00021 #include "include/LogCabin/Debug.h" 00022 00023 #ifndef LOGCABIN_CORE_DEBUG_H 00024 #define LOGCABIN_CORE_DEBUG_H 00025 00026 namespace LogCabin { 00027 namespace Core { 00028 00029 namespace StringUtil { 00030 std::string format(const char* format, ...) 00031 __attribute__((format(printf, 1, 2))); 00032 } 00033 00034 namespace Debug { 00035 00036 // Configuring logging is exposed to clients as well as servers, 00037 // so that stuff goes in a public header file: "include/LogCabin/Debug.h" 00038 00039 /** 00040 * Output a LogLevel to a stream. Having this improves gtest error messages. 00041 */ 00042 std::ostream& operator<<(std::ostream& ostream, LogLevel level); 00043 00044 /** 00045 * Return whether the current logging configuration includes messages of 00046 * the given level for the given filename. 00047 * This is normally called by LOG(). 00048 * \warning 00049 * fileName must be a string literal! 00050 * \param level 00051 * The log level to query. 00052 * \param fileName 00053 * This should be a string literal, probably __FILE__, since the result of 00054 * this call will be cached based on the memory address pointed to by 00055 * 'fileName'. 00056 */ 00057 bool 00058 isLogging(LogLevel level, const char* fileName); 00059 00060 /** 00061 * Unconditionally log the given message to stderr. 00062 * This is normally called by LOG(). 00063 * \param level 00064 * The level of importance of the message. 00065 * \param fileName 00066 * The output of __FILE__. 00067 * \param lineNum 00068 * The output of __LINE__. 00069 * \param functionName 00070 * The output of __FUNCTION__. 00071 * \param message 00072 * A descriptive message to print, which should not include a line break 00073 * at the end. 00074 */ 00075 void 00076 log(LogLevel level, 00077 const char* fileName, uint32_t lineNum, const char* functionName, 00078 const char* message); 00079 00080 /** 00081 * A short name to be used in log messages to identify this process. 00082 * This defaults to the UNIX process ID. 00083 */ 00084 extern std::string processName; 00085 00086 } // namespace LogCabin::Core::Debug 00087 } // namespace LogCabin::Core 00088 } // namespace LogCabin 00089 00090 /** 00091 * Unconditionally log the given message to stderr. 00092 * This is normally called by ERROR(), WARNING(), NOTICE(), or VERBOSE(). 00093 * \param level 00094 * The level of importance of the message. 00095 * \param _format 00096 * A printf-style format string for the message. It should not include a 00097 * line break at the end, as LOG will add one. 00098 * \param ... 00099 * The arguments to the format string, as in printf. 00100 */ 00101 #define LOG(level, _format, ...) do { \ 00102 if (::LogCabin::Core::Debug::isLogging(level, __FILE__)) { \ 00103 ::LogCabin::Core::Debug::log(level, \ 00104 __FILE__, __LINE__, __FUNCTION__, \ 00105 ::LogCabin::Core::StringUtil::format( \ 00106 _format, ##__VA_ARGS__).c_str()); \ 00107 } \ 00108 } while (0) 00109 00110 /** 00111 * Log an ERROR message and abort the process. 00112 * \copydetails ERROR 00113 */ 00114 #define PANIC(format, ...) do { \ 00115 ERROR(format " Exiting...", ##__VA_ARGS__); \ 00116 ::abort(); \ 00117 } while (0) 00118 00119 /** 00120 * Log an ERROR message and exit the process with status 1. 00121 * \copydetails ERROR 00122 */ 00123 #define EXIT(format, ...) do { \ 00124 ERROR(format " Exiting...", ##__VA_ARGS__); \ 00125 ::exit(1); \ 00126 } while (0) 00127 00128 /** 00129 * Log an ERROR message. 00130 * \param format 00131 * A printf-style format string for the message. It should not include a 00132 * line break at the end, as LOG will add one. 00133 * \param ... 00134 * The arguments to the format string, as in printf. 00135 */ 00136 #define ERROR(format, ...) \ 00137 LOG((::LogCabin::Core::Debug::LogLevel::ERROR), format, ##__VA_ARGS__) 00138 00139 /** 00140 * Log a WARNING message. 00141 * \copydetails ERROR 00142 */ 00143 #define WARNING(format, ...) \ 00144 LOG((::LogCabin::Core::Debug::LogLevel::WARNING), format, ##__VA_ARGS__) 00145 00146 /** 00147 * Log a NOTICE message. 00148 * \copydetails ERROR 00149 */ 00150 #define NOTICE(format, ...) \ 00151 LOG((::LogCabin::Core::Debug::LogLevel::NOTICE), format, ##__VA_ARGS__) 00152 00153 /** 00154 * Log a VERBOSE message. 00155 * \copydetails ERROR 00156 */ 00157 #define VERBOSE(format, ...) \ 00158 LOG((::LogCabin::Core::Debug::LogLevel::VERBOSE), format, ##__VA_ARGS__) 00159 00160 #endif /* LOGCABIN_CORE_DEBUG_H */