summaryrefslogtreecommitdiff
path: root/cpp/src/qpid/log
diff options
context:
space:
mode:
authorCharles E. Rolke <chug@apache.org>2013-04-26 21:38:07 +0000
committerCharles E. Rolke <chug@apache.org>2013-04-26 21:38:07 +0000
commit73c2b2cb960135d39c9eb476357d9d57ef68d489 (patch)
tree413c68a47cc3c5534db12fd1bc5dbaf064f9b948 /cpp/src/qpid/log
parent0890df638db03bae29b3bd6099f13a5433ab05cd (diff)
downloadqpid-python-73c2b2cb960135d39c9eb476357d9d57ef68d489.tar.gz
QPID-4651: C++ Broker add --log-disable option
Reviewed at https://reviews.apache.org/r/10799/ git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@1476409 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/src/qpid/log')
-rw-r--r--cpp/src/qpid/log/Logger.cpp1
-rw-r--r--cpp/src/qpid/log/Options.cpp33
-rw-r--r--cpp/src/qpid/log/Selector.cpp216
3 files changed, 210 insertions, 40 deletions
diff --git a/cpp/src/qpid/log/Logger.cpp b/cpp/src/qpid/log/Logger.cpp
index 7e7e1e94c1..16b2f56049 100644
--- a/cpp/src/qpid/log/Logger.cpp
+++ b/cpp/src/qpid/log/Logger.cpp
@@ -172,6 +172,7 @@ void Logger::configure(const Options& opts) {
void Logger::reconfigure(const std::vector<std::string>& selectors) {
options.selectors = selectors;
+ options.deselectors.clear();
select(Selector(options));
}
diff --git a/cpp/src/qpid/log/Options.cpp b/cpp/src/qpid/log/Options.cpp
index 10422bbb1e..b310b7cfac 100644
--- a/cpp/src/qpid/log/Options.cpp
+++ b/cpp/src/qpid/log/Options.cpp
@@ -59,16 +59,33 @@ Options::Options(const std::string& argv0_, const std::string& name_) :
("trace,t", optValue(trace), "Enables all logging" )
("log-enable", optValue(selectors, "RULE"),
("Enables logging for selected levels and components. "
- "RULE is in the form 'LEVEL[+][:PATTERN]' "
+ "RULE is in the form 'LEVEL[+-][:PATTERN]'\n"
"LEVEL is one of: \n\t "+levels.str()+"\n"
- "PATTERN is a function name or a catogory: \n\t "+categories.str()+"\n"
+ "PATTERN is a logging category name, or a namespace-qualified "
+ "function name or name fragment. "
+ "Logging category names are: \n\t "+categories.str()+"\n"
"For example:\n"
- "\t'--log-enable warning+' "
+ "\t'--log-enable warning+'\n"
"logs all warning, error and critical messages.\n"
- "\t'--log-enable trace+:Broker' "
+ "\t'--log-enable trace+:Broker'\n"
"logs all category 'Broker' messages.\n"
- "\t'--log-enable debug:framing' "
- "logs debug messages from the framing namespace. "
+ "\t'--log-enable debug:framing'\n"
+ "logs debug messages from all functions with 'framing' in the namespace or function name.\n"
+ "This option can be used multiple times").c_str())
+ ("log-disable", optValue(deselectors, "RULE"),
+ ("Disables logging for selected levels and components. "
+ "RULE is in the form 'LEVEL[+-][:PATTERN]'\n"
+ "LEVEL is one of: \n\t "+levels.str()+"\n"
+ "PATTERN is a logging category name, or a namespace-qualified "
+ "function name or name fragment. "
+ "Logging category names are: \n\t "+categories.str()+"\n"
+ "For example:\n"
+ "\t'--log-disable warning-'\n"
+ "disables logging all warning, notice, info, debug, and trace messages.\n"
+ "\t'--log-disable trace:Broker'\n"
+ "disables all category 'Broker' trace messages.\n"
+ "\t'--log-disable debug-:qmf::'\n"
+ "disables logging debug and trace messages from all functions with 'qmf::' in the namespace.\n"
"This option can be used multiple times").c_str())
("log-time", optValue(time, "yes|no"), "Include time in log messages")
("log-level", optValue(level,"yes|no"), "Include severity level in log messages")
@@ -77,7 +94,7 @@ Options::Options(const std::string& argv0_, const std::string& name_) :
("log-function", optValue(function,"yes|no"), "Include function signature in log messages")
("log-hires-timestamp", optValue(hiresTs,"yes|no"), "Use hi-resolution timestamps in log messages")
("log-category", optValue(category,"yes|no"), "Include category in log messages")
- ("log-prefix", optValue(prefix,"STRING"), "Prefix to append to all log messages")
+ ("log-prefix", optValue(prefix,"STRING"), "Prefix to prepend to all log messages")
;
add(*sinkOptions);
}
@@ -87,6 +104,7 @@ Options::Options(const Options &o) :
argv0(o.argv0),
name(o.name),
selectors(o.selectors),
+ deselectors(o.deselectors),
time(o.time),
level(o.level),
thread(o.thread),
@@ -106,6 +124,7 @@ Options& Options::operator=(const Options& x) {
argv0 = x.argv0;
name = x.name;
selectors = x.selectors;
+ deselectors = x.deselectors;
time = x.time;
level= x.level;
thread = x.thread;
diff --git a/cpp/src/qpid/log/Selector.cpp b/cpp/src/qpid/log/Selector.cpp
index 8757486d88..9f52242694 100644
--- a/cpp/src/qpid/log/Selector.cpp
+++ b/cpp/src/qpid/log/Selector.cpp
@@ -27,59 +27,209 @@ namespace log {
using namespace std;
-void Selector::enable(const string& enableStr) {
- string level, pattern;
- size_t c=enableStr.find(':');
+const char LOG_SYMBOL_DISABLE ('!');
+const char LOG_SYMBOL_SEPERATOR(':');
+const char LOG_SYMBOL_AND_ABOVE('+');
+const char LOG_SYMBOL_AND_BELOW('-');
+
+//
+// Parse an enable or disable entry into usable fields.
+// Throws if 'level' field is not recognized.
+//
+SelectorElement::SelectorElement(const std::string cliEntry) :
+ level(qpid::log::debug),
+ category(qpid::log::unspecified),
+ isDisable(false),
+ isCategory(false),
+ isLevelAndAbove(false),
+ isLevelAndBelow(false)
+{
+ if (cliEntry.empty())
+ return;
+ std::string working(cliEntry);
+ if (LOG_SYMBOL_DISABLE == working[0]) {
+ isDisable = true;
+ working = working.substr(1);
+ }
+ size_t c=working.find(LOG_SYMBOL_SEPERATOR);
if (c==string::npos) {
- level=enableStr;
+ levelStr=working;
+ } else {
+ levelStr=working.substr(0,c);
+ patternStr=working.substr(c+1);
+ }
+ if (!levelStr.empty()) {
+ if (levelStr[levelStr.size()-1]==LOG_SYMBOL_AND_ABOVE) {
+ isLevelAndAbove = true;
+ levelStr = levelStr.substr(0, levelStr.size()-1);
+ } else if (levelStr[levelStr.size()-1]==LOG_SYMBOL_AND_BELOW) {
+ isLevelAndBelow = true;
+ levelStr = levelStr.substr(0, levelStr.size()-1);
+ }
}
- else {
- level=enableStr.substr(0,c);
- pattern=enableStr.substr(c+1);
+ level = LevelTraits::level(levelStr); // throws if bad level name
+ isCategory = CategoryTraits::isCategory(patternStr);
+ if (isCategory) {
+ category = CategoryTraits::category(patternStr);
}
- bool isCat = CategoryTraits::isCategory(pattern);
- if (!level.empty() && level[level.size()-1]=='+') {
- for (int i = LevelTraits::level(level.substr(0,level.size()-1));
- i < LevelTraits::COUNT;
- ++i) {
- if (isCat) {
- enable(Level(i), CategoryTraits::category(pattern));
+}
+
+// Empty selector
+Selector::Selector() {
+ reset();
+}
+
+
+// Selector from options
+Selector::Selector(const Options& opt){
+ reset();
+ for_each(opt.selectors.begin(), opt.selectors.end(),
+ boost::bind(&Selector::enable, this, _1));
+ for_each(opt.deselectors.begin(), opt.deselectors.end(),
+ boost::bind(&Selector::disable, this, _1));
+}
+
+
+// Selector from single level
+Selector::Selector(Level l, const std::string& s) {
+ reset();
+ enable(l, s);
+}
+
+
+// Selector from single enable
+Selector::Selector(const std::string& selector) {
+ reset();
+ enable(selector);
+}
+
+
+/**
+ * Process a single CLI --log-enable option
+ */
+void Selector::enable(const string& enableStr) {
+ if (enableStr.empty())
+ return;
+ SelectorElement se(enableStr);
+ if (se.isDisable) {
+ // Disable statements are allowed in an enable string as a convenient
+ // way to process management strings that have enable/disable mixed.
+ disable(enableStr);
+ } else if (se.isLevelAndAbove) {
+ for (int lvl = se.level; lvl < LevelTraits::COUNT; ++lvl) {
+ if (se.isCategory) {
+ enableFlags[lvl][se.category] = true;
+ } else {
+ enable(Level(lvl), se.patternStr);
+ }
+ }
+ } else if (se.isLevelAndBelow) {
+ for (int lvl = se.level; lvl >= 0; --lvl) {
+ if (se.isCategory) {
+ enableFlags[lvl][se.category] = true;
} else {
- enable(Level(i), pattern);
+ enable(Level(lvl), se.patternStr);
}
}
+ } else {
+ if (se.isCategory) {
+ enableFlags[se.level][se.category] = true;
+ } else {
+ enable(se.level, se.patternStr);
+ }
}
- else {
- if (isCat) {
- enable(LevelTraits::level(level), CategoryTraits::category(pattern));
+}
+
+void Selector::disable(const string& disableStr) {
+ if (disableStr.empty())
+ return;
+ SelectorElement se(disableStr);
+ if (se.isLevelAndAbove) {
+ for (int lvl = se.level; lvl < LevelTraits::COUNT; ++lvl) {
+ if (se.isCategory) {
+ disableFlags[lvl][se.category] = true;
+ } else {
+ disable(Level(lvl), se.patternStr);
+ }
+ }
+ } else if (se.isLevelAndBelow) {
+ for (int lvl = se.level; lvl >= 0; --lvl) {
+ if (se.isCategory) {
+ disableFlags[lvl][se.category] = true;
+ } else {
+ disable(Level(lvl), se.patternStr);
+ }
+ }
+ } else {
+ if (se.isCategory) {
+ disableFlags[se.level][se.category] = true;
} else {
- enable(LevelTraits::level(level), pattern);
+ disable(se.level, se.patternStr);
}
}
}
-Selector::Selector(const Options& opt){
- reset();
- for_each(opt.selectors.begin(), opt.selectors.end(),
- boost::bind(&Selector::enable, this, _1));
+
+/**
+* Enable/disable messages with level in levels where the file
+* name contains substring.
+*/
+void Selector::enable(Level level, const std::string& substring) {
+ enabledFunctions[level].push_back(substring);
}
-bool Selector::isEnabled(Level level, const char* function) {
+
+void Selector::disable(Level level, const std::string& substring) {
+ disabledFunctions[level].push_back(substring);
+}
+
+
+void Selector::reset() {
+ // Initialize fields in a Selector that are not automatically set
+ for (int lt = 0; lt < LevelTraits::COUNT; ++lt)
+ for (int ct = 0; ct < CategoryTraits::COUNT; ++ct)
+ enableFlags[lt][ct] = disableFlags[lt][ct] = false;
+}
+
+
+bool Selector::lookupFuncName(Level level, const char* function, FunctionNameTable& table) {
const char* functionEnd = function+::strlen(function);
- for (std::vector<std::string>::iterator i=substrings[level].begin();
- i != substrings[level].end();
+ for (std::vector<std::string>::iterator i=table[level].begin();
+ i != table[level].end();
++i)
- {
- if (std::search(function, functionEnd, i->begin(), i->end()) != functionEnd)
- return true;
- }
+ {
+ if (std::search(function, functionEnd, i->begin(), i->end()) != functionEnd)
+ return true;
+ }
return false;
}
+
+bool Selector::isEnabled(Level level, const char* function) {
+ return lookupFuncName(level, function, enabledFunctions);
+}
+
+bool Selector::isDisabled(Level level, const char* function) {
+ return lookupFuncName(level, function, disabledFunctions);
+}
+
+//
+// isEnabled
+//
+// Determines if all the fields in this Selector enable or disable a
+// level/function/category set from an actual QPID_LOG Statement.
+//
bool Selector::isEnabled(Level level, const char* function, Category category) {
- if (catFlags[level][category])
- return true;
- return isEnabled(level, function);
+ if (isDisabled(level, function))
+ return false; // Disabled by function name
+ if (disableFlags[level][category])
+ return false; // Disabled by category name
+ if (isEnabled(level, function))
+ return true; // Enabled by function name
+ if (enableFlags[level][category])
+ return true; // Enabled by category name
+ else
+ return false; // Unspecified defaults to disabled
}
}} // namespace qpid::log