diff options
Diffstat (limited to 'lib/common/Logging.cpp')
-rw-r--r-- | lib/common/Logging.cpp | 294 |
1 files changed, 247 insertions, 47 deletions
diff --git a/lib/common/Logging.cpp b/lib/common/Logging.cpp index 7ce0dd3f..0928a4d4 100644 --- a/lib/common/Logging.cpp +++ b/lib/common/Logging.cpp @@ -13,19 +13,19 @@ #include <time.h> #include <string.h> // for stderror -// c.f. http://bugs.debian.org/512510 -#include <cstdio> +#ifdef HAVE_PROCESS_H +# include <process.h> +#endif #ifdef HAVE_SYSLOG_H - #include <syslog.h> +# include <syslog.h> #endif + #ifdef HAVE_UNISTD_H - #include <unistd.h> -#endif -#ifdef WIN32 - #include <process.h> +# include <unistd.h> #endif +#include <cstdio> #include <cstring> #include <iomanip> @@ -42,16 +42,14 @@ std::vector<Logger*> Logging::sLoggers; std::string Logging::sContext; Console* Logging::spConsole = NULL; Syslog* Logging::spSyslog = NULL; -Log::Level Logging::sGlobalLevel = Log::EVERYTHING; -Logging Logging::sGlobalLogging; //automatic initialisation +Logging Logging::sGlobalLogging; // automatic initialisation std::string Logging::sProgramName; +const Log::Category Logging::UNCATEGORISED("Uncategorised"); +std::auto_ptr<HideFileGuard> Logging::sapHideFileGuard; HideSpecificExceptionGuard::SuppressedExceptions_t HideSpecificExceptionGuard::sSuppressedExceptions; -int Logging::Guard::sGuardCount = 0; -Log::Level Logging::Guard::sOriginalLevel = Log::INVALID; - Logging::Logging() { ASSERT(!spConsole); @@ -139,14 +137,10 @@ void Logging::Remove(Logger* pOldLogger) } } -void Logging::Log(Log::Level level, const std::string& rFile, - int line, const std::string& rMessage) +void Logging::Log(Log::Level level, const std::string& file, int line, + const std::string& function, const Log::Category& category, + const std::string& message) { - if (level > sGlobalLevel) - { - return; - } - std::string newMessage; if (sContextSet) @@ -154,12 +148,13 @@ void Logging::Log(Log::Level level, const std::string& rFile, newMessage += "[" + sContext + "] "; } - newMessage += rMessage; + newMessage += message; for (std::vector<Logger*>::iterator i = sLoggers.begin(); i != sLoggers.end(); i++) { - bool result = (*i)->Log(level, rFile, line, newMessage); + bool result = (*i)->Log(level, file, line, function, category, + newMessage); if (!result) { return; @@ -167,19 +162,15 @@ void Logging::Log(Log::Level level, const std::string& rFile, } } -void Logging::LogToSyslog(Log::Level level, const std::string& rFile, - int line, const std::string& rMessage) +void Logging::LogToSyslog(Log::Level level, const std::string& rFile, int line, + const std::string& function, const Log::Category& category, + const std::string& message) { if (!sLogToSyslog) { return; } - if (level > sGlobalLevel) - { - return; - } - std::string newMessage; if (sContextSet) @@ -187,9 +178,9 @@ void Logging::LogToSyslog(Log::Level level, const std::string& rFile, newMessage += "[" + sContext + "] "; } - newMessage += rMessage; + newMessage += message; - spSyslog->Log(level, rFile, line, newMessage); + spSyslog->Log(level, rFile, line, function, category, newMessage); } void Logging::SetContext(std::string context) @@ -255,8 +246,7 @@ Logger::~Logger() bool Logger::IsEnabled(Log::Level level) { - return Logging::IsEnabled(level) && - (int)mCurrentLevel >= (int)level; + return (int)mCurrentLevel >= (int)level; } bool Console::sShowTime = false; @@ -290,8 +280,9 @@ void Console::SetShowPID(bool enabled) sShowPID = enabled; } -bool Console::Log(Log::Level level, const std::string& rFile, - int line, std::string& rMessage) +bool Console::Log(Log::Level level, const std::string& file, int line, + const std::string& function, const Log::Category& category, + const std::string& message) { if (level > GetLevel()) { @@ -299,12 +290,6 @@ bool Console::Log(Log::Level level, const std::string& rFile, } FILE* target = stdout; - - if (level <= Log::WARNING) - { - target = stderr; - } - std::ostringstream buf; if (sShowTime) @@ -354,7 +339,7 @@ bool Console::Log(Log::Level level, const std::string& rFile, buf << "TRACE: "; } - buf << rMessage; + buf << message; #ifdef WIN32 std::string output = buf.str(); @@ -376,8 +361,9 @@ bool Console::Log(Log::Level level, const std::string& rFile, return true; } -bool Syslog::Log(Log::Level level, const std::string& rFile, - int line, std::string& rMessage) +bool Syslog::Log(Log::Level level, const std::string& file, int line, + const std::string& function, const Log::Category& category, + const std::string& message) { if (level > GetLevel()) { @@ -418,7 +404,7 @@ bool Syslog::Log(Log::Level level, const std::string& rFile, msg = "NOTICE: "; } - msg += rMessage; + msg += message; syslog(syslogLevel, "%s", msg.c_str()); @@ -432,6 +418,11 @@ Syslog::Syslog() : mFacility(LOG_LOCAL6) Syslog::~Syslog() { + Shutdown(); +} + +void Syslog::Shutdown() +{ ::closelog(); } @@ -467,8 +458,9 @@ int Syslog::GetNamedFacility(const std::string& rFacility) return LOG_LOCAL6; } -bool FileLogger::Log(Log::Level Level, const std::string& rFile, - int line, std::string& rMessage) +bool FileLogger::Log(Log::Level Level, const std::string& file, int line, + const std::string& function, const Log::Category& category, + const std::string& message) { if (mLogFile.StreamClosed()) { @@ -515,7 +507,7 @@ bool FileLogger::Log(Log::Level Level, const std::string& rFile, buf << "[TRACE] "; } - buf << rMessage << "\n"; + buf << message << "\n"; std::string output = buf.str(); #ifdef WIN32 @@ -564,3 +556,211 @@ bool HideSpecificExceptionGuard::IsHidden(int type, int subtype) return false; } +// -------------------------------------------------------------------------- +// +// Function +// Name: Logging::OptionParser::GetOptionString() +// Purpose: Returns the valid Getopt command-line options +// that Logging::OptionParser::ProcessOption will handle. +// Created: 2014/04/09 +// +// -------------------------------------------------------------------------- +std::string Logging::OptionParser::GetOptionString() +{ + return "L:NPqQt:TUvVW:"; +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: Logging::OptionParser::ProcessOption(signed int option) +// Purpose: Processes the supplied option (equivalent to the +// return code from getopt()). Return zero if the +// option was handled successfully, or nonzero to +// abort the program with that return value. +// Created: 2007/09/18 +// +// -------------------------------------------------------------------------- +int Logging::OptionParser::ProcessOption(signed int option) +{ + switch(option) + { + case 'L': + { + if(sapHideFileGuard.get()) + { + sapHideFileGuard->Add(optarg); + } + else + { + sapHideFileGuard.reset(new HideFileGuard( + optarg, true)); // HideAllButSelected + } + } + break; + + case 'N': + { + mTruncateLogFile = true; + } + break; + + case 'P': + { + Console::SetShowPID(true); + } + break; + + case 'q': + { + if(mCurrentLevel == Log::NOTHING) + { + BOX_FATAL("Too many '-q': " + "Cannot reduce logging " + "level any more"); + return 2; + } + mCurrentLevel--; + } + break; + + case 'Q': + { + mCurrentLevel = Log::NOTHING; + } + break; + + case 't': + { + Logging::SetProgramName(optarg); + Console::SetShowTag(true); + } + break; + + case 'T': + { + Console::SetShowTime(true); + } + break; + + case 'U': + { + Console::SetShowTime(true); + Console::SetShowTimeMicros(true); + } + break; + + case 'v': + { + if(mCurrentLevel == Log::EVERYTHING) + { + BOX_FATAL("Too many '-v': " + "Cannot increase logging " + "level any more"); + return 2; + } + mCurrentLevel++; + } + break; + + case 'V': + { + mCurrentLevel = Log::EVERYTHING; + } + break; + + case 'W': + { + mCurrentLevel = Logging::GetNamedLevel(optarg); + if (mCurrentLevel == Log::INVALID) + { + BOX_FATAL("Invalid logging level: " << optarg); + return 2; + } + } + break; + + case '?': + { + BOX_FATAL("Unknown option on command line: " + << "'" << (char)optopt << "'"); + return 2; + } + break; + + default: + { + BOX_FATAL("Unknown error in getopt: returned " + << "'" << option << "'"); + return 1; + } + } + + // If we didn't explicitly return an error code above, then the option + // was fine, so return 0 to continue processing. + return 0; +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: Logging::OptionParser::GetUsageString() +// Purpose: Returns a string suitable for displaying as part +// of a program's command-line usage help message, +// describing the logging options. +// Created: 2014/04/09 +// +// -------------------------------------------------------------------------- +std::string Logging::OptionParser::GetUsageString() +{ + return + " -L <file> Filter out log messages except from specified file, can repeat\n" + " (for example, -L " __FILE__ ")\n" + " -N Truncate log file at startup and on backup start\n" + " -P Show process ID (PID) in console output\n" + " -q Run more quietly, reduce verbosity level by one, can repeat\n" + " -Q Run at minimum verbosity, log nothing to console and system\n" + " -t <tag> Tag console output with specified marker\n" + " -T Timestamp console output\n" + " -U Timestamp console output with microseconds\n" + " -v Run more verbosely, increase verbosity level by one, can repeat\n" + " -V Run at maximum verbosity, log everything to console and system\n" + " -W <level> Set verbosity to error/warning/notice/info/trace/everything\n"; +} + +bool HideCategoryGuard::Log(Log::Level level, const std::string& file, int line, + const std::string& function, const Log::Category& category, + const std::string& message) +{ + std::list<Log::Category>::iterator i = std::find(mCategories.begin(), + mCategories.end(), category); + // Return false if category is in our list, to suppress further + // logging (thus, return true if it's not in our list, i.e. we + // found nothing, to allow it). + return (i == mCategories.end()); +} + +bool HideFileGuard::Log(Log::Level level, const std::string& file, int line, + const std::string& function, const Log::Category& category, + const std::string& message) +{ + std::list<std::string>::iterator i = std::find(mFileNames.begin(), + mFileNames.end(), file); + bool allow_log_message; + if(mHideAllButSelected) + { + // Return true if filename is in our list, to allow further + // logging (thus, return false if it's not in our list, i.e. we + // found nothing, to suppress it). + allow_log_message = (i != mFileNames.end()); + } + else + { + // Return false if filename is in our list, to suppress further + // logging (thus, return true if it's not in our list, i.e. we + // found nothing, to allow it). + allow_log_message = (i == mFileNames.end()); + } + return allow_log_message; +} + |