LogCabin
Core/Debug.h
Go to the documentation of this file.
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 */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines