Return-Path: X-Original-To: apmail-qpid-commits-archive@www.apache.org Delivered-To: apmail-qpid-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 80EC510168 for ; Fri, 3 Jan 2014 18:56:56 +0000 (UTC) Received: (qmail 26889 invoked by uid 500); 3 Jan 2014 18:55:17 -0000 Delivered-To: apmail-qpid-commits-archive@qpid.apache.org Received: (qmail 26818 invoked by uid 500); 3 Jan 2014 18:55:16 -0000 Mailing-List: contact commits-help@qpid.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@qpid.apache.org Delivered-To: mailing list commits@qpid.apache.org Received: (qmail 26682 invoked by uid 99); 3 Jan 2014 18:55:14 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 03 Jan 2014 18:55:14 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 03 Jan 2014 18:55:09 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 1240A238897A; Fri, 3 Jan 2014 18:54:47 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1555202 - in /qpid/trunk/qpid/cpp: include/qpid/messaging/ src/ src/qpid/log/ src/qpid/messaging/ src/tests/ Date: Fri, 03 Jan 2014 18:54:46 -0000 To: commits@qpid.apache.org From: astitcher@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20140103185447.1240A238897A@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org 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 + +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 <>- 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; }; +/** 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 * Model * Unspecified */ 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 +#include +#include + +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 selectors; + std::vector 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 + (new qpid::log::OstreamOutput(std::clog))); + if (logToStdout) + logger().output(std::auto_ptr + (new qpid::log::OstreamOutput(std::cout))); + + if (logFile.length() > 0) + logger().output(std::auto_ptr + (new qpid::log::OstreamOutput(logFile))); +} +catch (std::exception& e) +{ + throw MessagingException(e.what()); +} + +void Logger::setOutput(LoggerOutput& o) +{ + logger().output(std::auto_ptr(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 +#include +#include + +#include + +#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