diff options
Diffstat (limited to 'lib/common/Logging.h')
-rw-r--r-- | lib/common/Logging.h | 388 |
1 files changed, 315 insertions, 73 deletions
diff --git a/lib/common/Logging.h b/lib/common/Logging.h index 1074b7c3..3dc3e69c 100644 --- a/lib/common/Logging.h +++ b/lib/common/Logging.h @@ -12,9 +12,11 @@ #include <assert.h> +#include <algorithm> #include <cerrno> #include <cstring> #include <iomanip> +#include <list> #include <sstream> #include <vector> @@ -24,14 +26,24 @@ { \ std::ostringstream _box_log_line; \ _box_log_line << stuff; \ - Logging::Log(level, __FILE__, __LINE__, _box_log_line.str()); \ + Logging::Log(level, __FILE__, __LINE__, __FUNCTION__, \ + Logging::UNCATEGORISED, _box_log_line.str()); \ +} + +#define BOX_LOG_CATEGORY(level, category, stuff) \ +{ \ + std::ostringstream _box_log_line; \ + _box_log_line << stuff; \ + Logging::Log(level, __FILE__, __LINE__, __FUNCTION__, \ + category, _box_log_line.str()); \ } #define BOX_SYSLOG(level, stuff) \ { \ std::ostringstream _box_log_line; \ _box_log_line << stuff; \ - Logging::LogToSyslog(level, __FILE__, __LINE__, _box_log_line.str()); \ + Logging::LogToSyslog(level, __FILE__, __LINE__, __FUNCTION__, \ + Logging::UNCATEGORISED, _box_log_line.str()); \ } #define BOX_FATAL(stuff) BOX_LOG(Log::FATAL, stuff) @@ -39,9 +51,7 @@ #define BOX_WARNING(stuff) BOX_LOG(Log::WARNING, stuff) #define BOX_NOTICE(stuff) BOX_LOG(Log::NOTICE, stuff) #define BOX_INFO(stuff) BOX_LOG(Log::INFO, stuff) -#define BOX_TRACE(stuff) \ - if (Logging::IsEnabled(Log::TRACE)) \ - { BOX_LOG(Log::TRACE, stuff) } +#define BOX_TRACE(stuff) BOX_LOG(Log::TRACE, stuff) #define BOX_SYS_ERRNO_MESSAGE(error_number, stuff) \ stuff << ": " << std::strerror(error_number) << \ @@ -85,18 +95,20 @@ BOX_FILE_MESSAGE(filename, message)) #ifdef WIN32 + #define BOX_WIN_ERRNO_MESSAGE(error_number, stuff) \ + stuff << ": " << GetErrorMessage(error_number) + #define BOX_NATIVE_ERRNO_MESSAGE(error_number, stuff) \ + BOX_WIN_ERRNO_MESSAGE(error_number, stuff) #define BOX_LOG_WIN_ERROR(stuff) \ - BOX_ERROR(stuff << ": " << GetErrorMessage(GetLastError())) + BOX_ERROR(BOX_WIN_ERRNO_MESSAGE(GetLastError(), stuff)) #define BOX_LOG_WIN_WARNING(stuff) \ - BOX_WARNING(stuff << ": " << GetErrorMessage(GetLastError())) + BOX_WARNING(BOX_WIN_ERRNO_MESSAGE(GetLastError(), stuff)) #define BOX_LOG_WIN_ERROR_NUMBER(stuff, number) \ - BOX_ERROR(stuff << ": " << GetErrorMessage(number)) + BOX_ERROR(BOX_WIN_ERRNO_MESSAGE(number, stuff)) #define BOX_LOG_WIN_WARNING_NUMBER(stuff, number) \ - BOX_WARNING(stuff << ": " << GetErrorMessage(number)) + BOX_WARNING(BOX_WIN_ERRNO_MESSAGE(number, stuff)) #define BOX_LOG_NATIVE_ERROR(stuff) BOX_LOG_WIN_ERROR(stuff) #define BOX_LOG_NATIVE_WARNING(stuff) BOX_LOG_WIN_WARNING(stuff) - #define BOX_WIN_ERRNO_MESSAGE(error_number, stuff) \ - stuff << ": " << GetErrorMessage(error_number) #define THROW_WIN_ERROR_NUMBER(message, error_number, exception, subtype) \ THROW_EXCEPTION_MESSAGE(exception, subtype, \ BOX_WIN_ERRNO_MESSAGE(error_number, message)) @@ -106,19 +118,33 @@ #define THROW_WIN_FILE_ERROR(message, filename, exception, subtype) \ THROW_WIN_FILE_ERRNO(message, filename, GetLastError(), \ exception, subtype) + #define EMU_ERRNO winerrno + #define THROW_EMU_ERROR(message, exception, subtype) \ + THROW_EXCEPTION_MESSAGE(exception, subtype, \ + BOX_NATIVE_ERRNO_MESSAGE(EMU_ERRNO, message)) #else + #define BOX_NATIVE_ERRNO_MESSAGE(error_number, stuff) \ + BOX_SYS_ERRNO_MESSAGE(error_number, stuff) #define BOX_LOG_NATIVE_ERROR(stuff) BOX_LOG_SYS_ERROR(stuff) #define BOX_LOG_NATIVE_WARNING(stuff) BOX_LOG_SYS_WARNING(stuff) + #define EMU_ERRNO errno + #define THROW_EMU_ERROR(message, exception, subtype) \ + THROW_EXCEPTION_MESSAGE(exception, subtype, \ + BOX_SYS_ERRNO_MESSAGE(EMU_ERRNO, message)) #endif +#define THROW_EMU_FILE_ERROR(message, filename, exception, subtype) \ + THROW_EMU_ERROR(BOX_FILE_MESSAGE(filename, message), \ + exception, subtype) + #ifdef WIN32 -# define BOX_LOG_SOCKET_ERROR(_type, _name, _port, stuff) \ - BOX_LOG_WIN_ERROR_NUMBER(stuff << " (type " << _type << ", name " << \ - _name << ", port " << _port << ")", WSAGetLastError()) +# define BOX_SOCKET_ERROR_MESSAGE(_type, _name, _port, stuff) \ + BOX_WIN_ERRNO_MESSAGE(WSAGetLastError(), stuff << " (type " << _type << \ + ", name " << _name << ", port " << _port << ")") #else -# define BOX_LOG_SOCKET_ERROR(_type, _name, _port, stuff) \ - BOX_LOG_NATIVE_ERROR(stuff << " (type " << _type << ", name " << \ - _name << ", port " << _port << ")") +# define BOX_SOCKET_ERROR_MESSAGE(_type, _name, _port, stuff) \ + BOX_SYS_ERROR_MESSAGE(stuff << " (type " << _type << ", name " << _name << \ + ", port " << _port << ")") #endif #define BOX_FORMAT_HEX32(number) \ @@ -141,14 +167,16 @@ #define BOX_FORMAT_TIMESPEC(timespec) \ timespec.tv_sec << \ + "." << \ std::setw(6) << \ + std::setfill('0') << \ timespec.tv_usec #define BOX_FORMAT_MICROSECONDS(t) \ (int)((t) / 1000000) << "." << \ - std::setw(6) << \ + std::setw(3) << \ std::setfill('0') << \ - (int)((t) % 1000000) << " seconds" + (int)((t % 1000000) / 1000) << " seconds" #undef ERROR @@ -166,6 +194,18 @@ namespace Log EVERYTHING, INVALID = -1 }; + + class Category { + private: + std::string mName; + + public: + Category(const std::string& name) + : mName(name) + { } + const std::string& ToString() { return mName; } + bool operator==(const Category& other) { return mName == other.mName; } + }; } // -------------------------------------------------------------------------- @@ -187,8 +227,9 @@ class Logger Logger(Log::Level level); virtual ~Logger(); - virtual bool Log(Log::Level level, const std::string& rFile, - int line, std::string& rMessage) = 0; + virtual bool Log(Log::Level level, const std::string& file, int line, + const std::string& function, const Log::Category& category, + const std::string& message) = 0; void Filter(Log::Level level) { @@ -201,19 +242,23 @@ class Logger virtual void SetProgramName(const std::string& rProgramName) = 0; - class Guard + class LevelGuard { private: Logger& mLogger; Log::Level mOldLevel; public: - Guard(Logger& Logger) + LevelGuard(Logger& Logger, Log::Level newLevel = Log::INVALID) : mLogger(Logger) { mOldLevel = Logger.GetLevel(); + if (newLevel != Log::INVALID) + { + Logger.Filter(newLevel); + } } - ~Guard() + ~LevelGuard() { mLogger.Filter(mOldLevel); } @@ -239,8 +284,9 @@ class Console : public Logger static std::string sTag; public: - virtual bool Log(Log::Level level, const std::string& rFile, - int line, std::string& rMessage); + virtual bool Log(Log::Level level, const std::string& file, int line, + const std::string& function, const Log::Category& category, + const std::string& message); virtual const char* GetType() { return "Console"; } virtual void SetProgramName(const std::string& rProgramName); @@ -248,6 +294,33 @@ class Console : public Logger static void SetShowTime(bool enabled); static void SetShowTimeMicros(bool enabled); static void SetShowPID(bool enabled); + static bool GetShowTag() { return sShowTag; } + + class SettingsGuard + { + private: + bool mShowTag; + bool mShowTime; + bool mShowTimeMicros; + bool mShowPID; + std::string mTag; + public: + SettingsGuard() + : mShowTag(Console::sShowTag), + mShowTime(Console::sShowTime), + mShowTimeMicros(Console::sShowTimeMicros), + mShowPID(Console::sShowPID), + mTag(Console::sTag) + { } + ~SettingsGuard() + { + Console::SetShowTag(mShowTag); + Console::SetShowTime(mShowTime); + Console::SetShowTimeMicros(mShowTimeMicros); + Console::SetShowPID(mShowPID); + Console::sTag = mTag; + } + }; }; // -------------------------------------------------------------------------- @@ -269,17 +342,80 @@ class Syslog : public Logger Syslog(); virtual ~Syslog(); - virtual bool Log(Log::Level level, const std::string& rFile, - int line, std::string& rMessage); + virtual bool Log(Log::Level level, const std::string& file, int line, + const std::string& function, const Log::Category& category, + const std::string& message); virtual const char* GetType() { return "Syslog"; } virtual void SetProgramName(const std::string& rProgramName); virtual void SetFacility(int facility); + virtual void Shutdown(); static int GetNamedFacility(const std::string& rFacility); }; // -------------------------------------------------------------------------- // // Class +// Name: Capture +// Purpose: Keeps log messages for analysis in tests. +// Created: 2014/03/08 +// +// -------------------------------------------------------------------------- + +class Capture : public Logger +{ + public: + struct Message + { + Message(const Log::Category& category) + : mCategory(category) { } + Log::Level level; + std::string file; + int line; + std::string function; + Log::Category mCategory; + std::string message; + }; + + private: + std::vector<Message> mMessages; + + public: + virtual ~Capture() { } + + virtual bool Log(Log::Level level, const std::string& file, int line, + const std::string& function, const Log::Category& category, + const std::string& message) + { + Message msg(category); + msg.level = level; + msg.file = file; + msg.line = line; + msg.function = function; + msg.message = message; + mMessages.push_back(msg); + return true; + } + virtual const char* GetType() { return "Capture"; } + virtual void SetProgramName(const std::string& rProgramName) { } + const std::vector<Message>& GetMessages() const { return mMessages; } + std::string GetString() const + { + std::ostringstream oss; + for (std::vector<Message>::const_iterator i = mMessages.begin(); + i != mMessages.end(); i++) + { + oss << i->message << "\n"; + } + return oss.str(); + } +}; + +// Forward declaration +class HideFileGuard; + +// -------------------------------------------------------------------------- +// +// Class // Name: Logging // Purpose: Static logging helper, keeps track of enabled loggers // and distributes log messages to them. @@ -296,10 +432,10 @@ class Logging static bool sContextSet; static Console* spConsole; static Syslog* spSyslog; - static Log::Level sGlobalLevel; static Logging sGlobalLogging; static std::string sProgramName; - + static std::auto_ptr<HideFileGuard> sapHideFileGuard; + public: Logging (); ~Logging(); @@ -309,55 +445,35 @@ class Logging static void FilterConsole (Log::Level level); static void Add (Logger* pNewLogger); static void Remove (Logger* pOldLogger); - static void Log(Log::Level level, const std::string& rFile, - int line, const std::string& rMessage); - static void LogToSyslog(Log::Level level, const std::string& rFile, - int line, const std::string& rMessage); + static void Log(Log::Level level, const std::string& file, int line, + const std::string& function, const Log::Category& category, + const std::string& message); + static void LogToSyslog(Log::Level level, const std::string& rFile, int line, + const std::string& function, const Log::Category& category, + const std::string& message); static void SetContext(std::string context); static void ClearContext(); - static void SetGlobalLevel(Log::Level level) { sGlobalLevel = level; } - static Log::Level GetGlobalLevel() { return sGlobalLevel; } static Log::Level GetNamedLevel(const std::string& rName); - static bool IsEnabled(Log::Level level) - { - return (int)sGlobalLevel >= (int)level; - } static void SetProgramName(const std::string& rProgramName); static std::string GetProgramName() { return sProgramName; } static void SetFacility(int facility); static Console& GetConsole() { return *spConsole; } static Syslog& GetSyslog() { return *spSyslog; } - class Guard + class ShowTagOnConsole { private: - Log::Level mOldLevel; - static int sGuardCount; - static Log::Level sOriginalLevel; - + bool mOldShowTag; + public: - Guard(Log::Level newLevel) - { - mOldLevel = Logging::GetGlobalLevel(); - if(sGuardCount == 0) - { - sOriginalLevel = mOldLevel; - } - sGuardCount++; - Logging::SetGlobalLevel(newLevel); - } - ~Guard() + ShowTagOnConsole() + : mOldShowTag(Console::GetShowTag()) { - sGuardCount--; - Logging::SetGlobalLevel(mOldLevel); + Console::SetShowTag(true); } - - static bool IsActive() { return (sGuardCount > 0); } - static Log::Level GetOriginalLevel() { return sOriginalLevel; } - static bool IsGuardingFrom(Log::Level originalLevel) + ~ShowTagOnConsole() { - return IsActive() && - (int)sOriginalLevel >= (int)originalLevel; + Console::SetShowTag(mOldShowTag); } }; @@ -365,16 +481,19 @@ class Logging { private: std::string mOldTag; + bool mReplace; public: Tagger() - : mOldTag(Logging::GetProgramName()) + : mOldTag(Logging::GetProgramName()), + mReplace(false) { } - Tagger(const std::string& rTempTag) - : mOldTag(Logging::GetProgramName()) + Tagger(const std::string& rTempTag, bool replace = false) + : mOldTag(Logging::GetProgramName()), + mReplace(replace) { - Logging::SetProgramName(mOldTag + " " + rTempTag); + Change(rTempTag); } ~Tagger() { @@ -383,9 +502,73 @@ class Logging void Change(const std::string& newTempTag) { - Logging::SetProgramName(mOldTag + " " + newTempTag); + if(mReplace || mOldTag.empty()) + { + Logging::SetProgramName(newTempTag); + } + else + { + Logging::SetProgramName(mOldTag + " " + newTempTag); + } + } + }; + + class TempLoggerGuard + { + private: + Logger* mpLogger; + + public: + TempLoggerGuard(Logger* pLogger) + : mpLogger(pLogger) + { + Logging::Add(mpLogger); + } + ~TempLoggerGuard() + { + Logging::Remove(mpLogger); + } + }; + + // Process global options + static std::string GetOptionString(); + static int ProcessOption(signed int option); + static std::string GetUsageString(); + + // -------------------------------------------------------------------------- + // + // Class + // Name: Logging::OptionParser + // Purpose: Process command-line options, some global, some local + // Created: 2014/04/09 + // + // -------------------------------------------------------------------------- + class OptionParser + { + public: + OptionParser(Log::Level InitialLevel = + #ifdef BOX_RELEASE_BUILD + Log::NOTICE + #else + Log::INFO + #endif + ) + : mCurrentLevel(InitialLevel), + mTruncateLogFile(false) + { } + + static std::string GetOptionString(); + int ProcessOption(signed int option); + static std::string GetUsageString(); + int mCurrentLevel; // need an int to do math with + bool mTruncateLogFile; + Log::Level GetCurrentLevel() + { + return (Log::Level) mCurrentLevel; } }; + + static const Log::Category UNCATEGORISED; }; class FileLogger : public Logger @@ -396,13 +579,14 @@ class FileLogger : public Logger : mLogFile("") { /* do not call */ } public: - FileLogger(const std::string& rFileName, Log::Level Level) + FileLogger(const std::string& rFileName, Log::Level Level, bool append) : Logger(Level), - mLogFile(rFileName, O_WRONLY | O_CREAT | O_APPEND) + mLogFile(rFileName, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC)) { } - virtual bool Log(Log::Level Level, const std::string& rFile, - int Line, std::string& rMessage); + virtual bool Log(Log::Level level, const std::string& file, int line, + const std::string& function, const Log::Category& category, + const std::string& message); virtual const char* GetType() { return "FileLogger"; } virtual void SetProgramName(const std::string& rProgramName) { } @@ -451,6 +635,64 @@ class HideSpecificExceptionGuard static bool IsHidden(int type, int subtype); }; +class HideCategoryGuard : public Logger +{ + private: + std::list<Log::Category> mCategories; + HideCategoryGuard(const HideCategoryGuard& other); // no copying + HideCategoryGuard& operator=(const HideCategoryGuard& other); // no assignment + + public: + HideCategoryGuard(const Log::Category& category) + { + mCategories.push_back(category); + Logging::Add(this); + } + ~HideCategoryGuard() + { + Logging::Remove(this); + } + void Add(const Log::Category& category) + { + mCategories.push_back(category); + } + virtual bool Log(Log::Level level, const std::string& file, int line, + const std::string& function, const Log::Category& category, + const std::string& message); + virtual const char* GetType() { return "HideCategoryGuard"; } + virtual void SetProgramName(const std::string& rProgramName) { } +}; + +class HideFileGuard : public Logger +{ + private: + std::list<std::string> mFileNames; + HideFileGuard(const HideFileGuard& other); // no copying + HideFileGuard& operator=(const HideFileGuard& other); // no assignment + bool mHideAllButSelected; + + public: + HideFileGuard(const std::string& rFileName, bool HideAllButSelected = false) + : mHideAllButSelected(HideAllButSelected) + { + mFileNames.push_back(rFileName); + Logging::Add(this); + } + ~HideFileGuard() + { + Logging::Remove(this); + } + void Add(const std::string& rFileName) + { + mFileNames.push_back(rFileName); + } + virtual bool Log(Log::Level level, const std::string& file, int line, + const std::string& function, const Log::Category& category, + const std::string& message); + virtual const char* GetType() { return "HideFileGuard"; } + virtual void SetProgramName(const std::string& rProgramName) { } +}; + std::string PrintEscapedBinaryData(const std::string& rInput); #endif // LOGGING__H |