Skip to content

Commit

Permalink
Modify command-line -L option to override log level for a specific file
Browse files Browse the repository at this point in the history
This allows enabling TRACE logging for a specific file (e.g. to enable
exception backtraces for that file) without enabling TRACE globally.

Replace HideFileGuard with LogLevelOverrideByFileGuard.

(cherry picked from commit 29f74be)
  • Loading branch information
qris committed Jul 23, 2017
1 parent 4127ec1 commit 05f0e98
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 56 deletions.
70 changes: 48 additions & 22 deletions lib/common/Logging.cpp
Expand Up @@ -45,7 +45,7 @@ Syslog* Logging::spSyslog = NULL;
Logging Logging::sGlobalLogging; // automatic initialisation
std::string Logging::sProgramName;
const Log::Category Logging::UNCATEGORISED("Uncategorised");
std::auto_ptr<HideFileGuard> Logging::sapHideFileGuard;
std::vector<LogLevelOverrideByFileGuard> Logging::sLogLevelOverrideByFileGuards;

HideSpecificExceptionGuard::SuppressedExceptions_t
HideSpecificExceptionGuard::sSuppressedExceptions;
Expand Down Expand Up @@ -280,12 +280,32 @@ void Console::SetShowPID(bool enabled)
sShowPID = enabled;
}

bool Logging::ShouldLog(Log::Level default_level, Log::Level message_level,
const std::string& file, int line, const std::string& function, const Log::Category& category,
const std::string& message)
{
Log::Level level_filter = default_level;
for(std::vector<LogLevelOverrideByFileGuard>::iterator
i = Logging::sLogLevelOverrideByFileGuards.begin();
i != Logging::sLogLevelOverrideByFileGuards.end(); i++)
{
if(i->IsOverridden(message_level, file, line, function, category, message))
{
level_filter = i->GetNewLevel();
}
}

// Should log if the message level is less than the filter level, otherwise not.
return (message_level <= level_filter);
}

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())
if(!Logging::ShouldLog(GetLevel(), level, file, line, function, category, message))
{
// Skip the rest of this logger, but continue with the others
return true;
}

Expand Down Expand Up @@ -365,8 +385,9 @@ 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())
if(!Logging::ShouldLog(GetLevel(), level, file, line, function, category, message))
{
// Skip the rest of this logger, but continue with the others
return true;
}

Expand Down Expand Up @@ -587,15 +608,26 @@ int Logging::OptionParser::ProcessOption(signed int option)
{
case 'L':
{
if(sapHideFileGuard.get())
std::string arg_value(optarg);
std::string::size_type equals_pos = arg_value.find('=');
if(equals_pos == std::string::npos)
{
sapHideFileGuard->Add(optarg);
BOX_FATAL("Option -L argument should be 'filename=level'");
return 2;
}
else

std::string filename = arg_value.substr(0, equals_pos);
std::string level_name = arg_value.substr(equals_pos + 1);
Log::Level level = Logging::GetNamedLevel(level_name);
if (level == Log::INVALID)
{
sapHideFileGuard.reset(new HideFileGuard(
optarg, true)); // HideAllButSelected
BOX_FATAL("Invalid logging level: " << level_name);
return 2;
}

sLogLevelOverrideByFileGuards.push_back(
LogLevelOverrideByFileGuard(filename, level, false) // !OverrideAllButSelected
);
}
break;

Expand Down Expand Up @@ -714,8 +746,8 @@ int Logging::OptionParser::ProcessOption(signed int option)
std::string Logging::OptionParser::GetUsageString()
{
return
" -L <file> Filter out log messages except from specified file, can repeat\n"
" (for example, -L " __FILE__ ")\n"
" -L <file>=<level> Override log level for specified file, can repeat\n"
" (for example, -L '" __FILE__ "=trace')\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"
Expand All @@ -740,27 +772,21 @@ bool HideCategoryGuard::Log(Log::Level level, const std::string& file, int line,
return (i == mCategories.end());
}

bool HideFileGuard::Log(Log::Level level, const std::string& file, int line,
bool LogLevelOverrideByFileGuard::IsOverridden(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)
if(!mOverrideAllButSelected)
{
// 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());
// Return true if filename is in our list, i.e. its level is overridden.
return (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 true if filename is not in our list, i.e. its level is overridden.
return (i == mFileNames.end());
}
return allow_log_message;
}

66 changes: 32 additions & 34 deletions lib/common/Logging.h
Expand Up @@ -26,7 +26,7 @@
{ \
std::ostringstream _box_log_line; \
_box_log_line << stuff; \
Logging::Log(level, __FILE__, __LINE__, __FUNCTION__, \
Logging::Log(level, BOX_CURRENT_FILE, __LINE__, __FUNCTION__, \
Logging::UNCATEGORISED, _box_log_line.str()); \
}

Expand Down Expand Up @@ -410,8 +410,33 @@ class Capture : public Logger
}
};

// Forward declaration
class HideFileGuard;
class LogLevelOverrideByFileGuard
{
private:
std::list<std::string> mFileNames;
Log::Level mNewLevel;
bool mOverrideAllButSelected;

public:
LogLevelOverrideByFileGuard(const std::string& rFileName, Log::Level NewLevel,
bool OverrideAllButSelected = false)
: mNewLevel(NewLevel), mOverrideAllButSelected(OverrideAllButSelected)
{
mFileNames.push_back(rFileName);
}
virtual ~LogLevelOverrideByFileGuard()
{
}
void Add(const std::string& rFileName)
{
mFileNames.push_back(rFileName);
}
bool IsOverridden(Log::Level level, const std::string& file, int line,
const std::string& function, const Log::Category& category,
const std::string& message);
Log::Level GetNewLevel() { return mNewLevel; }
};


// --------------------------------------------------------------------------
//
Expand All @@ -434,7 +459,7 @@ class Logging
static Syslog* spSyslog;
static Logging sGlobalLogging;
static std::string sProgramName;
static std::auto_ptr<HideFileGuard> sapHideFileGuard;
static std::vector<LogLevelOverrideByFileGuard> sLogLevelOverrideByFileGuards;

public:
Logging ();
Expand All @@ -445,6 +470,9 @@ class Logging
static void FilterConsole (Log::Level level);
static void Add (Logger* pNewLogger);
static void Remove (Logger* pOldLogger);
static bool ShouldLog(Log::Level default_level, Log::Level message_level,
const std::string& file, int line, const std::string& function,
const Log::Category& category, const std::string& message);
static void Log(Log::Level level, const std::string& file, int line,
const std::string& function, const Log::Category& category,
const std::string& message);
Expand Down Expand Up @@ -663,36 +691,6 @@ class HideCategoryGuard : public Logger
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

0 comments on commit 05f0e98

Please sign in to comment.