summaryrefslogtreecommitdiff
path: root/lib/common/Logging.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/common/Logging.h')
-rw-r--r--lib/common/Logging.h388
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