Author: astitcher
Date: Fri Jan 3 18:54:46 2014
New Revision: 1555202
URL: http://svn.apache.org/r1555202
Log:
QPID-5415: Implement control of internal log output in qpid::messaging API
Added:
qpid/trunk/qpid/cpp/include/qpid/messaging/Logger.h
qpid/trunk/qpid/cpp/src/qpid/messaging/Logger.cpp
qpid/trunk/qpid/cpp/src/tests/MessagingLogger.cpp
Modified:
qpid/trunk/qpid/cpp/src/CMakeLists.txt
qpid/trunk/qpid/cpp/src/qpid/log/Logger.cpp
qpid/trunk/qpid/cpp/src/qpid/log/Options.cpp
qpid/trunk/qpid/cpp/src/qpid/log/Options.h
qpid/trunk/qpid/cpp/src/qpid/log/Statement.cpp
qpid/trunk/qpid/cpp/src/qpid/log/Statement.h
qpid/trunk/qpid/cpp/src/tests/CMakeLists.txt
Added: qpid/trunk/qpid/cpp/include/qpid/messaging/Logger.h
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/include/qpid/messaging/Logger.h?rev=1555202&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/include/qpid/messaging/Logger.h (added)
+++ qpid/trunk/qpid/cpp/include/qpid/messaging/Logger.h Fri Jan 3 18:54:46 2014
@@ -0,0 +1,165 @@
+#ifndef QPID_MESSAGING_LOGGING_H
+#define QPID_MESSAGING_LOGGING_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/messaging/ImportExport.h"
+
+#include <string>
+
+namespace qpid {
+namespace messaging {
+/**
+ * These log levels need to be kept in sync with the log levels
+ * defined internally in qpid::log (but I don't think they are likely
+ * to change anyway
+ */
+enum Level { trace, debug, info, notice, warning, error, critical };
+
+/** \ingroup messaging
+ * Interface class to allow redirection of log output
+ */
+class QPID_MESSAGING_CLASS_EXTERN LoggerOutput
+{
+public:
+ virtual ~LoggerOutput();
+
+ /**
+ * Override this member function to receive log messages.
+ *
+ * log() will be called for every log message that would be output from the qpid::messaging
+ * logging subsystem after applying the specified logging filters.
+ *
+ * The logging subsystem ensures that log() will not be called simultaneously in different
threads.
+ * @param level The severity of the log message can be (in order of severity)
+ * trace, debug, info, notice, warning, error, critical
+ * @param user Flag which is set if the log message came from the user application (
using qpid::messaging::Logger::log() )
+ * (if not set then the message comes from the qpid library)
+ * @param file The source code file name reported as the origin of the log message
+ * @param line The source code line number reported as the origin of the log message
+ * @param function The source code function reported as the origin of the log message
+ * @param message The log message
+ */
+ virtual void log(Level level, bool user, const char* file, int line, const char* function,
const std::string& message) = 0;
+};
+
+/** \ingroup messaging
+ * A utility class to allow the application to control the logging
+ * output of the qpid messaging library
+ *
+ * This class represents a singleton logging facility within the qpid messaging library so
there are only static
+ * methods in the class
+ */
+class QPID_MESSAGING_CLASS_EXTERN Logger
+{
+public:
+ /**
+ * Configure the logging subsystem
+ *
+ * This function takes an array of text options (which could easily come from a programs
+ * command line) and uses them to configure the logging subsystem.
+ *
+ * If the prefix parameter is specified then the accepted command line options are prefixed
+ * by <<prefix>>- for example if the prefix is "qpid" then the options all
start "--qpid-log..."
+ *
+ * Accepted options are:
+ * --log-enable RULE
+ * --log-disable RULE
+ *
+ * Both --log-enable and --log-disable can be specified multiple times in a single command
line.
+ * The enables are acted upon and after them the disables are acted upon.
+ *
+ * RULE is in the form LEVEL[("+"|"-")][:PATTERN]
+ * LEVEL is one of "trace", "debug", "info", "notice", "warning", "error", "critical"
+ * "+" operates on the level and all higher levels
+ * "-" operates on the level and all lower levels
+ * PATTERN is a category name or a fragment of a fully namespace qualified function (Case
sensitive).
+ *
+ * --log-to-stdout ("on"|"off|"0"|"1")
+ * --log-to-stderr ("on"|"off|"0"|"1")
+ * --log-to-file FILENAME
+ *
+ * These options control where the qpid logging subsystem sends log messages
+ *
+ * --log-time ("on"|"off|"0"|"1")
+ * --log-level ("on"|"off|"0"|"1")
+ * --log-source ("on"|"off|"0"|"1")
+ * --log-thread ("on"|"off|"0"|"1")
+ * --log-function ("on"|"off|"0"|"1")
+ * --log-hires-timestamp ("on"|"off|"0"|"1")
+ *
+ * These options control what information is included in the logging message sent by
the logging subsystem.
+ *
+ * @param argc count of options - identical to meaning for main().
+ * @param argv array of pointers to options - identical to meaning for main().
+ * @param prefix (optional) If present prefix all logging options with this string
+ * @throws MessagingException if it cannot parse an option it recognises
+ */
+ QPID_MESSAGING_EXTERN static void configure(int argc, const char* argv[], const std::string&
prefix=std::string());
+
+ /**
+ * Get a user friendly usage message.
+ *
+ * This returns a usage message that is suitable for outputting directly to
+ * a console user. The message only contains the command line options that
+ * are understood by qpid::messaging::Logger::configure().
+ *
+ * NB. You must call qpid::messaging::Logger::configure() before calling this
+ * to populate the usage string as the usage string depends on the prefix that
+ * is passed in to qpid::messaging::Logger::configure().
+ *
+ * @return string containing the usage message for the command line options
+ */
+ QPID_MESSAGING_EXTERN static std::string usage();
+
+ /**
+ * Register a custom handler for log messages
+ *
+ * This allows application programs to intercept the log messages coming from qpid::messaging
+ * and handle them in whatever way is consonent with the applications own handling of
+ * log messages.
+ *
+ * In order to do this create a class that inherits from qpid::messaging::LoggerOutput
+ * and override the log() member function.
+ */
+ QPID_MESSAGING_EXTERN static void setOutput(LoggerOutput& output);
+
+ /**
+ * Output a log message. This will get sent to all the specified logging outputs including
any
+ * the application has registered. The message will get filtered along with the internal
messages
+ * according to the specified logging filters.
+ *
+ * When a log message output using log() is received by a LoggerOutput::log() method
the "user" bool parameter will be set true.
+ */
+ QPID_MESSAGING_EXTERN static void log(Level level, const char* file, int line, const
char* function, const std::string& message);
+
+private:
+ //This class has only one instance so no need to copy
+ Logger();
+ ~Logger();
+
+ Logger(const Logger&);
+ Logger operator=(const Logger&);
+};
+}} // namespace qpid::messaging
+
+#endif /*!QPID_MESSAGING_LOGGING_H*/
Modified: qpid/trunk/qpid/cpp/src/CMakeLists.txt
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/CMakeLists.txt?rev=1555202&r1=1555201&r2=1555202&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/CMakeLists.txt (original)
+++ qpid/trunk/qpid/cpp/src/CMakeLists.txt Fri Jan 3 18:54:46 2014
@@ -1055,6 +1055,7 @@ set (qpidmessaging_SOURCES
qpid/messaging/Duration.cpp
qpid/messaging/exceptions.cpp
qpid/messaging/FailoverUpdates.cpp
+ qpid/messaging/Logger.cpp
qpid/messaging/Message.cpp
qpid/messaging/Receiver.cpp
qpid/messaging/Session.cpp
@@ -1073,7 +1074,7 @@ set (qpidmessaging_SOURCES
add_msvc_version (qpidmessaging library dll)
add_library (qpidmessaging SHARED ${qpidmessaging_SOURCES})
-target_link_libraries (qpidmessaging qpidtypes qpidclient qpidcommon ${PROTON_LIBRARIES})
+target_link_libraries (qpidmessaging qpidtypes qpidclient qpidcommon "${Boost_PROGRAM_OPTIONS_LIBRARY}"
${PROTON_LIBRARIES})
set_target_properties (qpidmessaging PROPERTIES
LINK_FLAGS "${HIDE_SYMBOL_FLAGS} ${LINK_VERSION_SCRIPT_FLAG}"
COMPILE_FLAGS "${HIDE_SYMBOL_FLAGS}"
Modified: qpid/trunk/qpid/cpp/src/qpid/log/Logger.cpp
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/log/Logger.cpp?rev=1555202&r1=1555201&r2=1555202&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/log/Logger.cpp (original)
+++ qpid/trunk/qpid/cpp/src/qpid/log/Logger.cpp Fri Jan 3 18:54:46 2014
@@ -68,7 +68,7 @@ Logger::Logger() : flags(0) {
// Initialize myself from env variables so all programs
// (e.g. tests) can use logging even if they don't parse
// command line args.
- Options opts("");
+ Options opts;
opts.parse(0, 0);
configure(opts);
}
Modified: qpid/trunk/qpid/cpp/src/qpid/log/Options.cpp
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/log/Options.cpp?rev=1555202&r1=1555201&r2=1555202&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/log/Options.cpp (original)
+++ qpid/trunk/qpid/cpp/src/qpid/log/Options.cpp Fri Jan 3 18:54:46 2014
@@ -27,8 +27,6 @@
namespace qpid {
namespace log {
-using namespace std;
-
Options::Options(const std::string& argv0_, const std::string& name_) :
qpid::Options(name_),
argv0(argv0_),
@@ -45,25 +43,15 @@ Options::Options(const std::string& argv
{
selectors.push_back("notice+");
- ostringstream levels;
- levels << LevelTraits::name(Level(0));
- 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. "
"RULE is in the form 'LEVEL[+-][:PATTERN]'\n"
- "LEVEL is one of: \n\t "+levels.str()+"\n"
+ "LEVEL is one of: \n\t "+getLevels()+"\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"
+ "Logging category names are: \n\t "+getCategories()+"\n"
"For example:\n"
"\t'--log-enable warning+'\n"
"logs all warning, error and critical messages.\n"
@@ -75,10 +63,10 @@ Options::Options(const std::string& argv
("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"
+ "LEVEL is one of: \n\t "+getLevels()+"\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"
+ "Logging category names are: \n\t "+getCategories()+"\n"
"For example:\n"
"\t'--log-disable warning-'\n"
"disables logging all warning, notice, info, debug, and trace messages.\n"
@@ -139,4 +127,22 @@ Options& Options::operator=(const Option
return *this;
}
+std::string getLevels()
+{
+ std::ostringstream levels;
+ levels << LevelTraits::name(Level(0));
+ for (int i = 1; i < LevelTraits::COUNT; ++i)
+ levels << " " << LevelTraits::name(Level(i));
+ return levels.str();
+}
+
+std::string getCategories()
+{
+ std::ostringstream categories;
+ categories << CategoryTraits::name(Category(0));
+ for (int i = 1; i < CategoryTraits::COUNT; ++i)
+ categories << " " << CategoryTraits::name(Category(i));
+ return categories.str();
+}
+
}} // namespace qpid::log
Modified: qpid/trunk/qpid/cpp/src/qpid/log/Options.h
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/log/Options.h?rev=1555202&r1=1555201&r2=1555202&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/log/Options.h (original)
+++ qpid/trunk/qpid/cpp/src/qpid/log/Options.h Fri Jan 3 18:54:46 2014
@@ -46,6 +46,12 @@ struct Options : public qpid::Options {
std::auto_ptr<SinkOptions> sinkOptions;
};
+/** Get a string list of the allowed levels */
+QPID_COMMON_EXTERN std::string getLevels();
+
+/** Get a string list of the allowed categories */
+QPID_COMMON_EXTERN std::string getCategories();
+
}} // namespace qpid::log
#endif /*!QPID_LOG_OPTIONS_H*/
Modified: qpid/trunk/qpid/cpp/src/qpid/log/Statement.cpp
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/log/Statement.cpp?rev=1555202&r1=1555201&r2=1555202&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/log/Statement.cpp (original)
+++ qpid/trunk/qpid/cpp/src/qpid/log/Statement.cpp Fri Jan 3 18:54:46 2014
@@ -200,7 +200,7 @@ const char* names[LevelTraits::COUNT] =
const char* catNames[CategoryTraits::COUNT] = {
"Security", "Broker", "Management", "Protocol", "System", "HA", "Messaging",
- "Store", "Network", "Test", "Client", "Model", "Unspecified"
+ "Store", "Network", "Test", "Client", "Application", "Model", "Unspecified"
};
} // namespace
@@ -235,4 +235,5 @@ Category CategoryTraits::category(const
const char* CategoryTraits::name(Category c) {
return catNames[c];
}
+
}} // namespace qpid::log
Modified: qpid/trunk/qpid/cpp/src/qpid/log/Statement.h
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/log/Statement.h?rev=1555202&r1=1555201&r2=1555202&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/log/Statement.h (original)
+++ qpid/trunk/qpid/cpp/src/qpid/log/Statement.h Fri Jan 3 18:54:46 2014
@@ -71,11 +71,12 @@ struct LevelTraits {
* Store store
* Network tcp rdma AsynchIO socket epoll
* Test
+ * External_application <no directory - signifies log message from non qpid application
code>
* Model <not related to a directory>
* Unspecified <must be last in enum>
*/
enum Category { security, broker, management, protocol, system, ha, messaging,
- store, network, test, client, model, unspecified };
+ store, network, test, client, external_application, model, unspecified };
struct CategoryTraits {
static const int COUNT=unspecified+1;
Added: qpid/trunk/qpid/cpp/src/qpid/messaging/Logger.cpp
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/messaging/Logger.cpp?rev=1555202&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/messaging/Logger.cpp (added)
+++ qpid/trunk/qpid/cpp/src/qpid/messaging/Logger.cpp Fri Jan 3 18:54:46 2014
@@ -0,0 +1,200 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/messaging/Logger.h"
+
+#include "qpid/log/Logger.h"
+#include "qpid/log/OstreamOutput.h"
+#include "qpid/messaging/exceptions.h"
+
+#include <sstream>
+#include <string>
+#include <vector>
+
+using std::string;
+using std::vector;
+
+namespace qpid {
+namespace messaging {
+
+// Proxy class to call the users output class/routine
+class ProxyOutput : public qpid::log::Logger::Output {
+ LoggerOutput& output;
+
+ void log(const qpid::log::Statement& s, const string& message) {
+ output.log(qpid::messaging::Level(s.level), s.category==qpid::log::external_application,
s.file, s.line, s.function, message);
+ }
+
+public:
+ ProxyOutput(LoggerOutput& o) :
+ output(o)
+ {}
+};
+
+LoggerOutput::~LoggerOutput()
+{
+}
+
+inline qpid::log::Logger& logger() {
+ static qpid::log::Logger& theLogger=qpid::log::Logger::instance();
+ return theLogger;
+}
+
+namespace {
+ std::string loggerUsage;
+ qpid::log::Selector loggerSelector;
+}
+
+std::string Logger::usage()
+{
+ return loggerUsage;
+}
+
+void Logger::configure(int argc, const char* argv[], const string& pre)
+try
+{
+ bool logToStdout = false;
+ bool logToStderr = false;
+ string logFile;
+ std::vector<std::string> selectors;
+ std::vector<std::string> deselectors;
+ bool time = false;
+ bool level = false;
+ bool thread = false;
+ bool source = false;
+ bool function = false;
+ bool hiresTs = false;
+
+ selectors.push_back("notice+"); // Set this for the usage message default
+
+ string prefix = pre.empty() ? pre : pre+"-";
+ qpid::Options myOptions;
+ myOptions.addOptions()
+ ((prefix+"log-enable").c_str(), optValue(selectors, "RULE"),
+ ("Enables logging for selected levels and components. "
+ "RULE is in the form 'LEVEL[+-][:PATTERN]'\n"
+ "LEVEL is one of: \n\t "+qpid::log::getLevels()+"\n"
+ "PATTERN is a logging category name, or a namespace-qualified "
+ "function name or name fragment. "
+ "Logging category names are: \n\t "+qpid::log::getCategories()+"\n"
+ "The category \"Application\" contains all messages logged by the application.\n"
+ "For example:\n"
+ "\t'--log-enable warning+'\n"
+ "logs all warning, error and critical messages.\n"
+ "\t'--log-enable trace+:Application --log-enable notice+'\n"
+ "logs all application messages, but only notice or higher for the qpid library messages\n"
+ "\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())
+ ((prefix+"log-disable").c_str(), optValue(deselectors, "RULE"),
+ ("Disables logging for selected levels and components. "
+ "RULE is in the form 'LEVEL[+-][:PATTERN]'\n"
+ "LEVEL is one of: \n\t "+qpid::log::getLevels()+"\n"
+ "PATTERN is a logging category name, or a namespace-qualified "
+ "function name or name fragment. "
+ "Logging category names are: \n\t "+qpid::log::getCategories()+"\n"
+ "For example:\n"
+ "\t'--log-disable warning-'\n"
+ "disables logging all warning, notice, info, debug, and trace messages.\n"
+ "\t'--log-disable trace:Application'\n"
+ "disables all application 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())
+ ((prefix+"log-time").c_str(), optValue(time, "yes|no"), "Include time in log messages")
+ ((prefix+"log-level").c_str(), optValue(level,"yes|no"), "Include severity level in log
messages")
+ ((prefix+"log-source").c_str(), optValue(source,"yes|no"), "Include source file:line
in log messages")
+ ((prefix+"log-thread").c_str(), optValue(thread,"yes|no"), "Include thread ID in log
messages")
+ ((prefix+"log-function").c_str(), optValue(function,"yes|no"), "Include function signature
in log messages")
+ ((prefix+"log-hires-timestamp").c_str(), optValue(hiresTs,"yes|no"), "Use hi-resolution
timestamps in log messages")
+ ((prefix+"log-to-stderr").c_str(), optValue(logToStderr, "yes|no"), "Send logging output
to stderr")
+ ((prefix+"log-to-stdout").c_str(), optValue(logToStdout, "yes|no"), "Send logging output
to stdout")
+ ((prefix+"log-to-file").c_str(), optValue(logFile, "FILE"), "Send log output to FILE.")
+ ;
+
+ std::ostringstream loggerSStream;
+ myOptions.print(loggerSStream);
+
+ loggerUsage=loggerSStream.str();
+
+ selectors.clear(); // Clear to give passed in options precedence
+
+ // Parse the command line not failing for unrecognised options
+ myOptions.parse(argc, argv, std::string(), true);
+
+ // If no passed in enable or disable log specification then go back to default
+ if (selectors.empty() && deselectors.empty())
+ selectors.push_back("notice+");
+ // Set the logger options according to what we just parsed
+ qpid::log::Options logOptions;
+ logOptions.selectors = selectors;
+ logOptions.deselectors = deselectors;
+ logOptions.time = time;
+ logOptions.level = level;
+ logOptions.category = false;
+ logOptions.thread = thread;
+ logOptions.source = source;
+ logOptions.function = function;
+ logOptions.hiresTs = hiresTs;
+
+ loggerSelector = qpid::log::Selector(logOptions);
+ logger().clear(); // Need to clear before configuring as it will have been initialised
statically already
+ logger().format(logOptions);
+ logger().select(loggerSelector);
+
+ // Have to set up the standard output sinks manually
+ if (logToStderr)
+ logger().output(std::auto_ptr<qpid::log::Logger::Output>
+ (new qpid::log::OstreamOutput(std::clog)));
+ if (logToStdout)
+ logger().output(std::auto_ptr<qpid::log::Logger::Output>
+ (new qpid::log::OstreamOutput(std::cout)));
+
+ if (logFile.length() > 0)
+ logger().output(std::auto_ptr<qpid::log::Logger::Output>
+ (new qpid::log::OstreamOutput(logFile)));
+}
+catch (std::exception& e)
+{
+ throw MessagingException(e.what());
+}
+
+void Logger::setOutput(LoggerOutput& o)
+{
+ logger().output(std::auto_ptr<qpid::log::Logger::Output>(new ProxyOutput(o)));
+}
+
+void Logger::log(Level level, const char* file, int line, const char* function, const string&
message)
+{
+ if (loggerSelector.isEnabled(qpid::log::Level(level), function, qpid::log::unspecified))
{
+ qpid::log::Statement s = {
+ true,
+ file,
+ line,
+ function,
+ qpid::log::Level(level),
+ qpid::log::external_application,
+ };
+ logger().log(s, message);
+ }
+}
+
+}} // namespace qpid::messaging
Modified: qpid/trunk/qpid/cpp/src/tests/CMakeLists.txt
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/CMakeLists.txt?rev=1555202&r1=1555201&r2=1555202&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/CMakeLists.txt (original)
+++ qpid/trunk/qpid/cpp/src/tests/CMakeLists.txt Fri Jan 3 18:54:46 2014
@@ -42,6 +42,11 @@ macro(remember_location testname)
set (${testname}_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/${testname}${CMAKE_EXECUTABLE_SUFFIX})
endmacro(remember_location)
+# If we're using GCC allow variadic macros (even though they're c99 not c++01)
+if (CMAKE_COMPILER_IS_GNUCXX)
+ add_definitions(-Wno-variadic-macros)
+endif (CMAKE_COMPILER_IS_GNUCXX)
+
# Windows uses some process-startup calls to ensure that errors, etc. don't
# result in error boxes being thrown up. Since it's expected that most test
# runs will be in scripts, the default is to force these outputs to stderr
@@ -175,6 +180,7 @@ set(all_unit_tests
ManagementTest
MessageReplayTracker
MessageTest
+ MessagingLogger
MessagingSessionTests
PollableCondition
ProxyTest
Added: qpid/trunk/qpid/cpp/src/tests/MessagingLogger.cpp
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/MessagingLogger.cpp?rev=1555202&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/MessagingLogger.cpp (added)
+++ qpid/trunk/qpid/cpp/src/tests/MessagingLogger.cpp Fri Jan 3 18:54:46 2014
@@ -0,0 +1,149 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/log/Statement.h"
+#include "qpid/messaging/Connection.h"
+#include "qpid/messaging/exceptions.h"
+#include "qpid/messaging/Logger.h"
+
+#include <iostream>
+#include <memory>
+#include <stdexcept>
+
+#include <vector>
+
+#include "unit_test.h"
+
+namespace qpid {
+namespace tests {
+
+QPID_AUTO_TEST_SUITE(MessagingLoggerSuite)
+
+class StringLogger : public qpid::messaging::LoggerOutput {
+ std::string& outString;
+
+ void log(qpid::messaging::Level /*level*/, bool user, const char* /*file*/, int /*line*/,
const char* /*function*/, const std::string& message){
+ if (user) outString += "User ";
+ outString += message;
+ }
+
+public:
+ StringLogger(std::string& os) :
+ outString(os)
+ {}
+};
+
+#define SETUP_LOGGING(logger, ...) \
+do {\
+ const char* args[]={"", __VA_ARGS__, 0};\
+ qpid::messaging::Logger::configure((sizeof (args)/sizeof (char*))-1, args);\
+ logOutput.clear();\
+ qpid::messaging::Logger::setOutput(logger);\
+} while (0)
+#define LOG_LEVEL(level)\
+ QPID_LOG(level, #level " level output")
+#define LOG_ALL_LOGGING_LEVELS \
+do { \
+ LOG_LEVEL(trace); \
+ LOG_LEVEL(debug); \
+ LOG_LEVEL(info); \
+ LOG_LEVEL(notice); \
+ LOG_LEVEL(warning); \
+ LOG_LEVEL(critical); \
+} while (0)
+#define LOG_USER_LEVEL(level)\
+ qpid::messaging::Logger::log(qpid::messaging::level, __FILE__, __LINE__, __FUNCTION__,
#level " message")
+#define LOG_ALL_USER_LOGGING_LEVELS \
+do { \
+ LOG_USER_LEVEL(trace); \
+ LOG_USER_LEVEL(debug); \
+ LOG_USER_LEVEL(info); \
+ LOG_USER_LEVEL(notice); \
+ LOG_USER_LEVEL(warning); \
+ LOG_USER_LEVEL(critical); \
+} while (0)
+
+std::string logOutput;
+
+QPID_AUTO_TEST_CASE(testLoggerLevels)
+{
+ StringLogger logger(logOutput);
+
+ SETUP_LOGGING(logger, "--log-enable", "debug");
+ LOG_ALL_LOGGING_LEVELS;
+ BOOST_CHECK_EQUAL(logOutput, "debug level output\ncritical level output\n");
+
+ SETUP_LOGGING(logger, "--log-enable", "trace+", "--log-disable", "notice");
+ LOG_ALL_LOGGING_LEVELS;
+ BOOST_CHECK_EQUAL(logOutput, "trace level output\ndebug level output\ninfo level output\nwarning
level output\ncritical level output\n");
+
+ SETUP_LOGGING(logger, "--log-enable", "info-");
+ LOG_ALL_LOGGING_LEVELS;
+ BOOST_CHECK_EQUAL(logOutput, "trace level output\ndebug level output\ninfo level output\ncritical
level output\n");
+
+ SETUP_LOGGING(logger, "--log-enable", "trace+", "--log-disable", "notice+");
+ LOG_ALL_LOGGING_LEVELS;
+ BOOST_CHECK_EQUAL(logOutput, "trace level output\ndebug level output\ninfo level output\ncritical
level output\n");
+}
+
+QPID_AUTO_TEST_CASE(testUserLoggerLevels)
+{
+ StringLogger logger(logOutput);
+
+ SETUP_LOGGING(logger, "--log-enable", "debug");
+ LOG_ALL_USER_LOGGING_LEVELS;
+ BOOST_CHECK_EQUAL(logOutput, "User debug message\nUser critical message\n");
+
+ SETUP_LOGGING(logger, "--log-enable", "trace+", "--log-disable", "notice");
+ LOG_ALL_USER_LOGGING_LEVELS;
+ BOOST_CHECK_EQUAL(logOutput, "User trace message\nUser debug message\nUser info message\nUser
warning message\nUser critical message\n");
+
+ SETUP_LOGGING(logger, "--log-enable", "info-");
+ LOG_ALL_USER_LOGGING_LEVELS;
+ BOOST_CHECK_EQUAL(logOutput, "User trace message\nUser debug message\nUser info message\nUser
critical message\n");
+
+ SETUP_LOGGING(logger, "--log-enable", "trace+", "--log-disable", "notice+");
+ LOG_ALL_USER_LOGGING_LEVELS;
+ BOOST_CHECK_EQUAL(logOutput, "User trace message\nUser debug message\nUser info message\nUser
critical message\n");
+
+ SETUP_LOGGING(logger, "--log-disable", "trace+");
+ LOG_ALL_LOGGING_LEVELS;
+ LOG_ALL_USER_LOGGING_LEVELS;
+ BOOST_CHECK_EQUAL(logOutput, "critical level output\nUser critical message\n");
+}
+
+QPID_AUTO_TEST_CASE(testLoggerUsage)
+{
+ qpid::messaging::Logger::configure(0, 0, "blah");
+ std::string u = qpid::messaging::Logger::usage();
+
+ BOOST_CHECK(!u.empty());
+ BOOST_CHECK( u.find("--blah-log-enable")!=u.npos );
+}
+
+QPID_AUTO_TEST_CASE(testLoggerException)
+{
+ const char* args[]={"", "--blah-log-enable", "illegal", 0};
+ BOOST_CHECK_THROW(qpid::messaging::Logger::configure(3, args, "blah"), qpid::messaging::MessagingException);
+}
+
+QPID_AUTO_TEST_SUITE_END()
+}}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
|