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