qpid-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From astitc...@apache.org
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 GMT
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


Mime
View raw message