summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles E. Rolke <chug@apache.org>2012-05-17 20:07:28 +0000
committerCharles E. Rolke <chug@apache.org>2012-05-17 20:07:28 +0000
commit219e068084f926dc0bd3847818fedc3b87fedae2 (patch)
tree609daff4169f24337b169dd3053797e3753fbf8d
parentf63ed524a7bf4d6dac49617b87d30380478d0547 (diff)
downloadqpid-python-219e068084f926dc0bd3847818fedc3b87fedae2.tar.gz
QPID-3902 Add formal message categories to C++ Broker log messages
Facilities are defined to issue a log message of any category from source module. Log messages issued with QPID_LOG macro are compiled to use the Undefined category. This checkin version uses a lookup to autogenerate a category for Undefined log messages. In practice a 'qpidd -t' trace of a connection appears as shown. 2012-05-17 16:01:37 [IO] info Listening to: 0.0.0.0:5672 2012-05-17 16:01:37 [IO] debug Listened to: 5672 2012-05-17 16:01:37 [IO] info Listening to: [::]:5672 2012-05-17 16:01:37 [IO] debug Listened to: 5672 2012-05-17 16:01:37 [IO] notice Listening on TCP/TCP6 port 5672 2012-05-17 16:01:37 [Management] debug ManagementAgent added package org.apache.qpid.acl 2012-05-17 16:01:37 [Management] debug SEND PackageInd package=org.apache.qpid.acl to=schema.package 2012-05-17 16:01:37 [Management] debug ManagementAgent added class org.apache.qpid.acl:acl 2012-05-17 16:01:37 [Management] debug ManagementAgent added class org.apache.qpid.acl:allow 2012-05-17 16:01:37 [Management] debug ManagementAgent added class org.apache.qpid.acl:deny 2012-05-17 16:01:37 [Management] debug ManagementAgent added class org.apache.qpid.acl:connectionDeny 2012-05-17 16:01:37 [Management] debug ManagementAgent added class org.apache.qpid.acl:fileLoaded 2012-05-17 16:01:37 [Management] debug ManagementAgent added class org.apache.qpid.acl:fileLoadFailed 2012-05-17 16:01:37 [Management] debug Management object (V1) added: org.apache.qpid.acl:acl:org.apache.qpid.broker:broker:amqp-broker 2012-05-17 16:01:37 [Security] notice ACL: Read file "/home/chug/svn/qpid/cpp/src/tests/policy.acl" 2012-05-17 16:01:37 [Security] debug ACL: Group list: 0 groups found: 2012-05-17 16:01:37 [Security] debug ACL: name list: 1 names found: 2012-05-17 16:01:37 [Security] debug ACL: * 2012-05-17 16:01:37 [Security] debug ACL: Rule list: 1 ACL rules found: 2012-05-17 16:01:37 [Security] debug ACL: 1 allow [*] * 2012-05-17 16:01:37 [Security] debug ACL: Load Rules 2012-05-17 16:01:37 [Security] debug ACL: Processing 1 allow [*] * 2012-05-17 16:01:37 [Security] debug ACL: FoundMode allow 2012-05-17 16:01:37 [Management] debug SEND raiseEvent (v1) class=org.apache.qpid.acl.fileLoaded 2012-05-17 16:01:37 [Management] debug SEND raiseEvent (v2) class=org.apache.qpid.acl.fileLoaded 2012-05-17 16:01:37 [Security] info ACL Plugin loaded 2012-05-17 16:01:37 [Broker] notice Broker running 2012-05-17 16:01:42 [IO] debug RECV [[::1]:5672-[::1]:53468]: INIT(0-10) 2012-05-17 16:01:42 [Security] debug SASL: No Authentication Performed 2012-05-17 16:01:42 [Broker] debug LinkRegistry::notifyConnection(); key=[::1]:5672-[::1]:53468 2012-05-17 16:01:42 [Security] trace ACL ConnectionCounter connection IP:[::1]:5672-[::1]:53468, userId: 2012-05-17 16:01:42 [Management] debug Management object (V1) added: org.apache.qpid.broker:connection:[::1]:5672-[::1]:53468 2012-05-17 16:01:42 [Amqp] trace SENT [[::1]:5672-[::1]:53468]: INIT(0-10) 2012-05-17 16:01:42 [Amqp] trace SENT [[::1]:5672-[::1]:53468]: Frame[BEbe; channel=0; {ConnectionStartBody: server-properties={qpid.federation_tag:V2:36:str16(5787d304-441c-4266-9702-11ecc9a521bc)}; mechanisms=str16{V2:9:str16(ANONYMOUS), V2:5:str16(PLAIN)}; locales=str16{V2:5:str16(en_US)}; }] 2012-05-17 16:01:42 [Amqp] trace RECV [[::1]:5672-[::1]:53468]: Frame[BEbe; channel=0; {ConnectionStartOkBody: client-properties={platform:V2:5:str16(posix),product:V2:18:str16(qpid python client),qpid.client_pid:F8:int64(28802),qpid.client_ppid:F8:int64(1994),qpid.client_process:V2:9:str16(qpid-tool),version:V2:11:str16(development)}; mechanism=ANONYMOUS; }] 2012-05-17 16:01:42 [Management] debug SEND raiseEvent (v1) class=org.apache.qpid.broker.clientConnect 2012-05-17 16:01:42 [Management] debug SEND raiseEvent (v2) class=org.apache.qpid.broker.clientConnect 2012-05-17 16:01:42 [Amqp] trace SENT [[::1]:5672-[::1]:53468]: Frame[BEbe; channel=0; {ConnectionTuneBody: channel-max=32767; max-frame-size=65535; heartbeat-min=0; heartbeat-max=120; }] 2012-05-17 16:01:42 [Amqp] trace RECV [[::1]:5672-[::1]:53468]: Frame[BEbe; channel=0; {ConnectionTuneOkBody: }] 2012-05-17 16:01:42 [Amqp] trace RECV [[::1]:5672-[::1]:53468]: Frame[BEbe; channel=0; {ConnectionOpenBody: }] 2012-05-17 16:01:42 [Security] trace ACL ConnectionCounter Opened IP:[::1]:5672-[::1]:53468, userId:anonymous 2012-05-17 16:01:42 [Amqp] trace SENT [[::1]:5672-[::1]:53468]: Frame[BEbe; channel=0; {ConnectionOpenOkBody: known-hosts=str16{V2:49:str16(amqp:tcp:10.16.185.91:5672,tcp:192.168.122.1:5672)}; }] 2012-05-17 16:01:42 [Amqp] trace RECV [[::1]:5672-[::1]:53468]: Frame[BEbe; channel=1; {SessionAttachBody: name=ummmm.28802.1; }] 2012-05-17 16:01:42 [Broker] debug SessionState::SessionState anonymous.ummmm.28802.1: 0x7ffff0044960 2012-05-17 16:01:42 [Management] debug Management object (V1) added: org.apache.qpid.broker:session:ummmm.28802.1 2012-05-17 16:01:42 [Broker] debug anonymous.ummmm.28802.1: attached on broker. 2012-05-17 16:01:42 [Amqp] debug Attached channel 1 to anonymous.ummmm.28802.1 2012-05-17 16:01:42 [Broker] debug anonymous.ummmm.28802.1: ready to send, activating output. git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/qpid-3902@1339836 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--qpid/cpp/include/qpid/log/Logger.h2
-rw-r--r--qpid/cpp/include/qpid/log/Options.h2
-rw-r--r--qpid/cpp/include/qpid/log/Selector.h27
-rw-r--r--qpid/cpp/include/qpid/log/Statement.h111
-rw-r--r--qpid/cpp/src/qpid/log/Logger.cpp7
-rw-r--r--qpid/cpp/src/qpid/log/Options.cpp18
-rw-r--r--qpid/cpp/src/qpid/log/Selector.cpp31
-rw-r--r--qpid/cpp/src/qpid/log/Statement.cpp93
-rw-r--r--qpid/cpp/src/tests/logging.cpp2
9 files changed, 271 insertions, 22 deletions
diff --git a/qpid/cpp/include/qpid/log/Logger.h b/qpid/cpp/include/qpid/log/Logger.h
index d255b7e150..9464fa52dd 100644
--- a/qpid/cpp/include/qpid/log/Logger.h
+++ b/qpid/cpp/include/qpid/log/Logger.h
@@ -36,7 +36,7 @@ namespace log {
class QPID_COMMON_CLASS_EXTERN Logger : private boost::noncopyable {
public:
/** Flags indicating what to include in the log output */
- enum FormatFlag { FILE=1, LINE=2, FUNCTION=4, LEVEL=8, TIME=16, THREAD=32, HIRES=64};
+ enum FormatFlag { FILE=1, LINE=2, FUNCTION=4, LEVEL=8, TIME=16, THREAD=32, HIRES=64, CATEGORY=128};
/**
* Logging output sink.
diff --git a/qpid/cpp/include/qpid/log/Options.h b/qpid/cpp/include/qpid/log/Options.h
index 17cbfde9bc..819f2c85f1 100644
--- a/qpid/cpp/include/qpid/log/Options.h
+++ b/qpid/cpp/include/qpid/log/Options.h
@@ -39,7 +39,7 @@ struct Options : public qpid::Options {
std::string argv0;
std::string name;
std::vector<std::string> selectors;
- bool time, level, thread, source, function, hiresTs;
+ bool time, level, thread, source, function, hiresTs, category;
bool trace;
std::string prefix;
std::auto_ptr<SinkOptions> sinkOptions;
diff --git a/qpid/cpp/include/qpid/log/Selector.h b/qpid/cpp/include/qpid/log/Selector.h
index 061152d7e2..498d4a7342 100644
--- a/qpid/cpp/include/qpid/log/Selector.h
+++ b/qpid/cpp/include/qpid/log/Selector.h
@@ -35,17 +35,24 @@ struct Options;
class Selector {
public:
/** Empty selector selects nothing */
- Selector() {}
+ Selector() {
+ reset();
+ }
/** Set selector from Options */
QPID_COMMON_EXTERN Selector(const Options&);
/** Equavlient to: Selector s; s.enable(l, s) */
Selector(Level l, const std::string& s=std::string()) {
+ reset();
enable(l,s);
}
- Selector(const std::string& enableStr) { enable(enableStr); }
+ Selector(const std::string& enableStr) {
+ reset();
+ enable(enableStr);
+ }
+
/**
* Enable messages with level in levels where the file
* name contains substring. Empty string matches all.
@@ -54,14 +61,30 @@ class Selector {
substrings[level].push_back(substring);
}
+ /**
+ * Enable messages at this level for this category
+ */
+ void enable(Level level, Category category) {
+ catFlags[level][category] = true;
+ }
+
/** Enable based on a 'level[+]:file' string */
QPID_COMMON_EXTERN void enable(const std::string& enableStr);
/** True if level is enabled for file. */
QPID_COMMON_EXTERN bool isEnabled(Level level, const char* function);
+ QPID_COMMON_EXTERN bool isEnabled(Level level, const char* function, Category category);
+
+ /** Reset the category enable flags */
+ QPID_COMMON_EXTERN void reset() {
+ for (int lt = 0; lt < LevelTraits::COUNT; ++lt)
+ for (int ct = 0; ct < CategoryTraits::COUNT; ++ct)
+ catFlags[lt][ct] = false;
+ }
private:
std::vector<std::string> substrings[LevelTraits::COUNT];
+ bool catFlags[LevelTraits::COUNT][CategoryTraits::COUNT];
};
diff --git a/qpid/cpp/include/qpid/log/Statement.h b/qpid/cpp/include/qpid/log/Statement.h
index 7b3ab60b81..94e38d721b 100644
--- a/qpid/cpp/include/qpid/log/Statement.h
+++ b/qpid/cpp/include/qpid/log/Statement.h
@@ -55,15 +55,61 @@ struct LevelTraits {
static const char* name(Level);
};
-/** POD struct representing a logging statement in source code. */
+/** Add formal message categories
+ * https://issues.apache.org/jira/browse/QPID-3902
+ *
+ * Category Source code directory
+ * -------- ---------------------
+ * Security acl ssl gssapi sasl cyrus
+ * Broker broker
+ * Management agent console qmf
+ * Amqp amqp_0_10 framing
+ * System log sys types xml thread mutex fork pipe time ...
+ * HA cluster ha replication
+ * Messaging messaging client
+ * Store store
+ * IO tcp rdma AsynchIO socket epoll
+ * Test
+ * Unspecified
+ */
+enum Category { security, broker, management, amqp, system, ha, messaging,
+ store, io, test, unspecified };
+struct CategoryTraits {
+ static const int COUNT=unspecified+1;
+
+ /** Test if given name is a Category name
+ */
+ static bool isCategory(const std::string& name);
+
+ /** Get category from string name
+ * @exception if name invalid.
+ */
+ static Category category(const char* name);
+
+ /** Get category from string name.
+ * @exception if name invalid.
+ */
+ static Category category(const std::string& name) {
+ return category(name.c_str());
+ }
+
+ /** String name of category */
+ static const char* name(Category);
+};
+
+
+ /** POD struct representing a logging statement in source code. */
struct Statement {
bool enabled;
const char* file;
int line;
const char* function;
Level level;
+ Category category;
QPID_COMMON_EXTERN void log(const std::string& message);
+ QPID_COMMON_EXTERN static void categorize(Statement& s);
+ QPID_COMMON_EXTERN static Category categoryOf(const char* const function);
struct Initializer {
QPID_COMMON_EXTERN Initializer(Statement& s);
@@ -72,8 +118,14 @@ struct Statement {
};
///@internal static initializer for a Statement.
-#define QPID_LOG_STATEMENT_INIT(level) \
- { 0, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, (::qpid::log::level) }
+#define QPID_LOG_STATEMENT_INIT_CAT(LEVEL, CATEGORY) \
+{ 0, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, (::qpid::log::LEVEL), \
+(::qpid::log::CATEGORY) }
+
+
+///@internal static initializer for a Statement with unspecified category
+#define QPID_LOG_STATEMENT_INIT(LEVEL) \
+QPID_LOG_STATEMENT_INIT_CAT ( LEVEL , unspecified )
/**
* Like QPID_LOG but computes an additional boolean test expression
@@ -96,13 +148,26 @@ struct Statement {
} while(0)
/**
+ * Line QPID_LOG_IF but with the additional specification of a category.
+ * @param CATEGORY message category.
+ */
+#define QPID_LOG_IF_CAT(LEVEL, CATEGORY, TEST, MESSAGE) \
+ do { \
+ using ::qpid::log::Statement; \
+ static Statement stmt_= QPID_LOG_STATEMENT_INIT_CAT(LEVEL, CATEGORY); \
+ static Statement::Initializer init_(stmt_); \
+ if (stmt_.enabled && (TEST)) \
+ stmt_.log(::qpid::Msg() << MESSAGE); \
+ } while(0)
+
+/**
* FLAG must be a boolean variable. Assigns FLAG to true iff logging
* is enabled for LEVEL in the calling context. Use when extra
* support code is needed to generate log messages, to ensure that it
* is only run if the logging level is enabled.
* e.g.
* bool logWarning;
- * QPID_LOG_TEST(LEVEL, logWarning);
+ * QPID_LOG_TEST(warning, logWarning);
* if (logWarning) { do stuff needed for warning log messages }
*/
#define QPID_LOG_TEST(LEVEL, FLAG) \
@@ -113,12 +178,31 @@ struct Statement {
FLAG = stmt_.enabled; \
} while(0)
+ /**
+ * FLAG must be a boolean variable. Assigns FLAG to true iff logging
+ * is enabled for LEVEL in the calling context. Use when extra
+ * support code is needed to generate log messages, to ensure that it
+ * is only run if the logging level is enabled.
+ * e.g.
+ * bool logWarning;
+ * QPID_LOG_TEST_CAT(warning, System, logWarning);
+ * if (logWarning) { do stuff needed for warning log messages }
+ */
+ #define QPID_LOG_TEST_CAT(LEVEL, CATEGORY, FLAG) \
+ do { \
+ using ::qpid::log::Statement; \
+ static Statement stmt_= QPID_LOG_STATEMENT_INIT_CAT(LEVEL, CATEGORY); \
+ static Statement::Initializer init_(stmt_); \
+ FLAG = stmt_.enabled; \
+ } while(0)
+
/**
* Macro for log statements. Example of use:
* @code
* QPID_LOG(debug, "There are " << foocount << " foos in the bar.");
* QPID_LOG(error, boost::format("Dohickey %s exploded") % dohicky.name());
* @endcode
+ * Using QPID_LOG implies a category of Unspecified.
*
* You can subscribe to log messages by level, by component, by filename
* or a combination @see Configuration.
@@ -130,6 +214,25 @@ struct Statement {
*/
#define QPID_LOG(LEVEL, MESSAGE) QPID_LOG_IF(LEVEL, true, MESSAGE);
+/**
+ * Macro for log statements. Example of use:
+ * @code
+ * QPID_LOG_CAT(debug, System, "There are " << foocount << " foos in the bar.");
+ * QPID_LOG_CAT(error, System, boost::format("Dohickey %s exploded") % dohicky.name());
+ * @endcode
+ * Using QPID_LOG_CAT requires the specification of a category.
+ *
+ * You can subscribe to log messages by level, by component, by filename
+ * or a combination @see Configuration.
+ *
+ *@param LEVEL severity Level for message, should be one of:
+ * debug, info, notice, warning, error, critical. NB no qpid::log:: prefix.
+ *@param CATEGORY basic Category for the message.
+ *@param MESSAGE any object with an @eostream operator<<, or a sequence
+ * like of ostreamable objects separated by @e<<.
+ */
+#define QPID_LOG_CAT(LEVEL, CATEGORY, MESSAGE) QPID_LOG_IF_CAT(LEVEL, CATEGORY, true, MESSAGE);
+
}} // namespace qpid::log
diff --git a/qpid/cpp/src/qpid/log/Logger.cpp b/qpid/cpp/src/qpid/log/Logger.cpp
index 800881c077..7c2e807ca9 100644
--- a/qpid/cpp/src/qpid/log/Logger.cpp
+++ b/qpid/cpp/src/qpid/log/Logger.cpp
@@ -47,7 +47,7 @@ using namespace std;
typedef sys::Mutex::ScopedLock ScopedLock;
inline void Logger::enable_unlocked(Statement* s) {
- s->enabled=selector.isEnabled(s->level, s->function);
+ s->enabled=selector.isEnabled(s->level, s->function, s->category);
}
Logger& Logger::instance() {
@@ -95,6 +95,8 @@ void Logger::log(const Statement& s, const std::string& msg) {
else
qpid::sys::outputFormattedNow(os);
}
+ if (flags&CATEGORY)
+ os << "[" << CategoryTraits::name(s.category) << "] ";
if (flags&LEVEL)
os << LevelTraits::name(s.level) << " ";
if (flags&THREAD)
@@ -144,7 +146,8 @@ int Logger::format(const Options& opts) {
bitIf(opts.source, (FILE|LINE)) |
bitIf(opts.function, FUNCTION) |
bitIf(opts.thread, THREAD) |
- bitIf(opts.hiresTs, HIRES);
+ bitIf(opts.hiresTs, HIRES) |
+ bitIf(opts.category, CATEGORY);
format(flags);
return flags;
}
diff --git a/qpid/cpp/src/qpid/log/Options.cpp b/qpid/cpp/src/qpid/log/Options.cpp
index 1259244297..10422bbb1e 100644
--- a/qpid/cpp/src/qpid/log/Options.cpp
+++ b/qpid/cpp/src/qpid/log/Options.cpp
@@ -39,6 +39,7 @@ Options::Options(const std::string& argv0_, const std::string& name_) :
source(false),
function(false),
hiresTs(false),
+ category(true),
trace(false),
sinkOptions (SinkOptions::create(argv0_))
{
@@ -49,15 +50,23 @@ Options::Options(const std::string& argv0_, const std::string& name_) :
for (int i = 1; i < LevelTraits::COUNT; ++i)
levels << " " << LevelTraits::name(Level(i));
+ ostringstream categories;
+ categories << CategoryTraits::name(Category(0));
+ for (int i = 1; i < CategoryTraits::COUNT; ++i)
+ categories << " " << CategoryTraits::name(Category(i));
+
addOptions()
("trace,t", optValue(trace), "Enables all logging" )
("log-enable", optValue(selectors, "RULE"),
- ("Enables logging for selected levels and components. "
+ ("Enables logging for selected levels and components. "
"RULE is in the form 'LEVEL[+][:PATTERN]' "
- "Levels are one of: \n\t "+levels.str()+"\n"
+ "LEVEL is one of: \n\t "+levels.str()+"\n"
+ "PATTERN is a function name or a catogory: \n\t "+categories.str()+"\n"
"For example:\n"
"\t'--log-enable warning+' "
"logs all warning, error and critical messages.\n"
+ "\t'--log-enable trace+:Broker' "
+ "logs all category 'Broker' messages.\n"
"\t'--log-enable debug:framing' "
"logs debug messages from the framing namespace. "
"This option can be used multiple times").c_str())
@@ -67,6 +76,7 @@ Options::Options(const std::string& argv0_, const std::string& name_) :
("log-thread", optValue(thread,"yes|no"), "Include thread ID in log messages")
("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")
;
add(*sinkOptions);
@@ -83,6 +93,7 @@ Options::Options(const Options &o) :
source(o.source),
function(o.function),
hiresTs(o.hiresTs),
+ category(o.category),
trace(o.trace),
prefix(o.prefix),
sinkOptions (SinkOptions::create(o.argv0))
@@ -101,11 +112,12 @@ Options& Options::operator=(const Options& x) {
source = x.source;
function = x.function;
hiresTs = x.hiresTs;
+ category = x.category;
trace = x.trace;
prefix = x.prefix;
*sinkOptions = *x.sinkOptions;
}
return *this;
}
-
+
}} // namespace qpid::log
diff --git a/qpid/cpp/src/qpid/log/Selector.cpp b/qpid/cpp/src/qpid/log/Selector.cpp
index a4bc580470..8757486d88 100644
--- a/qpid/cpp/src/qpid/log/Selector.cpp
+++ b/qpid/cpp/src/qpid/log/Selector.cpp
@@ -37,18 +37,29 @@ void Selector::enable(const string& enableStr) {
level=enableStr.substr(0,c);
pattern=enableStr.substr(c+1);
}
+ 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)
- enable(Level(i), pattern);
+ ++i) {
+ if (isCat) {
+ enable(Level(i), CategoryTraits::category(pattern));
+ } else {
+ enable(Level(i), pattern);
+ }
+ }
}
else {
- enable(LevelTraits::level(level), pattern);
+ if (isCat) {
+ enable(LevelTraits::level(level), CategoryTraits::category(pattern));
+ } else {
+ enable(LevelTraits::level(level), pattern);
+ }
}
}
Selector::Selector(const Options& opt){
+ reset();
for_each(opt.selectors.begin(), opt.selectors.end(),
boost::bind(&Selector::enable, this, _1));
}
@@ -58,11 +69,17 @@ bool Selector::isEnabled(Level level, const char* function) {
for (std::vector<std::string>::iterator i=substrings[level].begin();
i != substrings[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, Category category) {
+ if (catFlags[level][category])
+ return true;
+ return isEnabled(level, function);
+}
+
}} // namespace qpid::log
diff --git a/qpid/cpp/src/qpid/log/Statement.cpp b/qpid/cpp/src/qpid/log/Statement.cpp
index 09d1c9449f..2347b2b4cb 100644
--- a/qpid/cpp/src/qpid/log/Statement.cpp
+++ b/qpid/cpp/src/qpid/log/Statement.cpp
@@ -54,6 +54,72 @@ void Statement::log(const std::string& message) {
Logger::instance().log(*this, quote(message));
}
+#define test(STR, CAT) \
+if (strstr(fName, (STR)) != 0) {\
+ return (::qpid::log::CAT); \
+}
+// std::cout << "File: " << fName << " categorized as " << CategoryTraits::name(::qpid::log::CAT) << std::endl;
+
+Category Statement::categoryOf(const char*const fName) {
+ test("AsynchIO", io);
+ test("TCP", io);
+ test("epoll", io);
+ test("Pollable", io);
+ test("Socket", io);
+
+ test("Sasl", security);
+ test("Ssl", security);
+ test("Acl", security);
+ test("acl", security);
+ test("cyrus", security);
+
+ test("amqp_", amqp);
+ test("framing", amqp);
+
+ test("management", management);
+ test("qmf", management);
+ test("console", management);
+
+ test("cluster", ha);
+ test("qpid/ha", ha);
+ test("qpid\\ha", ha);
+ test("replication", ha);
+ test("ClusterSafe", ha);
+
+ test("broker", broker);
+ test("SessionState",broker);
+ test("DataDir", broker);
+ test("qpidd", broker);
+
+ test("store", store);
+
+ test("assert", system);
+ test("Exception", system);
+ test("sys", system);
+ test("SCM", system);
+
+ test("tests", test);
+
+ test("messaging", messaging);
+ test("types", messaging);
+
+ std::cout << "Unspecified file:" << fName << std::endl;
+ return unspecified;
+}
+
+
+void Statement::categorize(Statement& s) {
+ // given a statement and it's category
+ // if the category is Unspecified then try to find a
+ // better category based on the path/file function name.
+ if (s.category == log::unspecified) {
+ s.category = categoryOf(s.file);
+ } else {
+ // already has a category so leave it alone
+ }
+}
+
+
Statement::Initializer::Initializer(Statement& s) : statement(s) {
// QPID-3891
// From the given BOOST_CURRENT_FUNCTION name extract only the
@@ -99,16 +165,22 @@ Statement::Initializer::Initializer(Statement& s) : statement(s) {
// no function-name pointer to process
}
+ Statement::categorize(s);
Logger::instance().add(s);
}
+
namespace {
const char* names[LevelTraits::COUNT] = {
"trace", "debug", "info", "notice", "warning", "error", "critical"
};
-} // namespace
+const char* catNames[CategoryTraits::COUNT] = {
+ "Security", "Broker", "Management", "Amqp", "System", "HA", "Messaging",
+ "Store", "IO", "Test", "Unspecified"
+};
+} // namespace
Level LevelTraits::level(const char* name) {
for (int i =0; i < LevelTraits::COUNT; ++i) {
if (strcmp(names[i], name)==0)
@@ -121,4 +193,23 @@ const char* LevelTraits::name(Level l) {
return names[l];
}
+bool CategoryTraits::isCategory(const std::string& name) {
+ for (int i =0; i < CategoryTraits::COUNT; ++i) {
+ if (strcmp(catNames[i], name.c_str())==0)
+ return true;
+ }
+ return false;
+}
+
+Category CategoryTraits::category(const char* name) {
+ for (int i =0; i < CategoryTraits::COUNT; ++i) {
+ if (strcmp(catNames[i], name)==0)
+ return Category(i);
+ }
+ throw std::runtime_error(std::string("Invalid log category name: ")+name);
+}
+
+const char* CategoryTraits::name(Category c) {
+ return catNames[c];
+}
}} // namespace qpid::log
diff --git a/qpid/cpp/src/tests/logging.cpp b/qpid/cpp/src/tests/logging.cpp
index 5d5bb1feef..47e601ed05 100644
--- a/qpid/cpp/src/tests/logging.cpp
+++ b/qpid/cpp/src/tests/logging.cpp
@@ -258,7 +258,7 @@ QPID_AUTO_TEST_CASE(testOverhead) {
Statement statement(
Level level, const char* file="", int line=0, const char* fn=0)
{
- Statement s={0, file, line, fn, level};
+ Statement s={0, file, line, fn, level, ::qpid::log::unspecified};
return s;
}