summaryrefslogtreecommitdiff
path: root/qpid/cpp/src/qpid/log
diff options
context:
space:
mode:
Diffstat (limited to 'qpid/cpp/src/qpid/log')
-rw-r--r--qpid/cpp/src/qpid/log/Helpers.h79
-rw-r--r--qpid/cpp/src/qpid/log/Logger.cpp200
-rw-r--r--qpid/cpp/src/qpid/log/Logger.h122
-rw-r--r--qpid/cpp/src/qpid/log/Options.cpp148
-rw-r--r--qpid/cpp/src/qpid/log/Options.h57
-rw-r--r--qpid/cpp/src/qpid/log/OstreamOutput.cpp41
-rw-r--r--qpid/cpp/src/qpid/log/OstreamOutput.h41
-rw-r--r--qpid/cpp/src/qpid/log/Selector.cpp237
-rw-r--r--qpid/cpp/src/qpid/log/Selector.h99
-rw-r--r--qpid/cpp/src/qpid/log/SinkOptions.h64
-rw-r--r--qpid/cpp/src/qpid/log/Statement.cpp218
-rw-r--r--qpid/cpp/src/qpid/log/Statement.h244
-rw-r--r--qpid/cpp/src/qpid/log/posix/SinkOptions.cpp222
-rw-r--r--qpid/cpp/src/qpid/log/posix/SinkOptions.h64
-rw-r--r--qpid/cpp/src/qpid/log/windows/SinkOptions.cpp148
-rw-r--r--qpid/cpp/src/qpid/log/windows/SinkOptions.h54
16 files changed, 2038 insertions, 0 deletions
diff --git a/qpid/cpp/src/qpid/log/Helpers.h b/qpid/cpp/src/qpid/log/Helpers.h
new file mode 100644
index 0000000000..82ef8244be
--- /dev/null
+++ b/qpid/cpp/src/qpid/log/Helpers.h
@@ -0,0 +1,79 @@
+#ifndef QPID_LOG_HELPERS_H
+#define QPID_LOG_HELPERS_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 <boost/range.hpp>
+
+#include <ostream>
+
+namespace qpid {
+namespace log {
+
+/** @file Helper classes for logging complex types */
+
+/// @internal
+template <class Range>
+struct ListFormatter {
+ typedef typename boost::range_const_iterator<Range>::type Iterator;
+ boost::iterator_range<Iterator> range;
+ const char* separator;
+
+ ListFormatter(const Range& r, const char* s=", ") : range(r), separator(s) {}
+};
+
+/// @internal
+template <class Range>
+std::ostream& operator<<(std::ostream& out, const ListFormatter<Range>& sl) {
+ typename ListFormatter<Range>::Iterator i = sl.range.begin();
+ if (i != sl.range.end()) out << *(i++);
+ while (i != sl.range.end()) out << sl.separator << *(i++);
+ return out;
+}
+
+/** Return a formatting object with operator <<
+ * to stream range as a separated list.
+ *@param range: a range - all standard containers are ranges,
+ * as is a pair of iterators.
+ *@param separator: printed between elements, default ", "
+ */
+template <class Range>
+ListFormatter<Range> formatList(const Range& range, const char* separator=", ") {
+ return ListFormatter<Range>(range, separator);
+}
+
+/** Return a formatting object with operator <<
+ * to stream the range defined by iterators [begin, end)
+ * as a separated list.
+ *@param begin, end: Beginning and end of range.
+ *@param separator: printed between elements, default ", "
+ */
+template <class U, class V>
+ListFormatter<std::pair<U,V> > formatList(U begin, V end, const char* separator=", ") {
+ return formatList(std::make_pair(begin,end), separator);
+}
+
+
+}} // namespace qpid::log
+
+
+
+#endif /*!QPID_LOG_HELPERS_H*/
diff --git a/qpid/cpp/src/qpid/log/Logger.cpp b/qpid/cpp/src/qpid/log/Logger.cpp
new file mode 100644
index 0000000000..fc254f2857
--- /dev/null
+++ b/qpid/cpp/src/qpid/log/Logger.cpp
@@ -0,0 +1,200 @@
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * Licensed 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/Logger.h"
+#include "qpid/log/Options.h"
+#include "qpid/log/SinkOptions.h"
+#include "qpid/memory.h"
+#include "qpid/sys/Thread.h"
+#include "qpid/sys/Time.h"
+#include "qpid/DisableExceptionLogging.h"
+
+#include "boost/version.hpp"
+#if (BOOST_VERSION >= 104000)
+#include <boost/serialization/singleton.hpp>
+#else
+#include <boost/pool/detail/singleton.hpp>
+#endif
+
+#include <boost/bind.hpp>
+#include <boost/function.hpp>
+#include <algorithm>
+#include <sstream>
+#include <iomanip>
+#include <stdexcept>
+#include <time.h>
+
+
+namespace qpid {
+namespace log {
+
+using namespace std;
+
+typedef sys::Mutex::ScopedLock ScopedLock;
+
+inline void Logger::enable_unlocked(Statement* s) {
+ s->enabled=selector.isEnabled(s->level, s->function, s->category);
+}
+
+Logger& Logger::instance() {
+#if (BOOST_VERSION >= 104000)
+ return boost::serialization::singleton<Logger>::get_mutable_instance();
+#else
+ return boost::details::pool::singleton_default<Logger>::instance();
+#endif
+}
+
+Logger::Logger() : flags(0) {
+ // Disable automatic logging in Exception constructors to avoid
+ // re-entrant use of logger singleton if there is an error in
+ // option parsing.
+ DisableExceptionLogging del;
+
+ // 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;
+ opts.parse(0, 0);
+ configure(opts);
+}
+
+Logger::~Logger() {}
+
+void Logger::select(const Selector& s) {
+ ScopedLock l(lock);
+ selector=s;
+ std::for_each(statements.begin(), statements.end(),
+ boost::bind(&Logger::enable_unlocked, this, _1));
+}
+
+Logger::Output::Output() {}
+Logger::Output::~Output() {}
+
+void Logger::log(const Statement& s, const std::string& msg) {
+ // Format the message outside the lock.
+ std::ostringstream os;
+ if (!prefix.empty())
+ os << prefix << ": ";
+ if (flags&TIME) {
+ if (flags&HIRES)
+ qpid::sys::outputHiresNow(os);
+ else
+ qpid::sys::outputFormattedNow(os);
+ }
+ if (flags&CATEGORY)
+ os << "[" << CategoryTraits::name(s.category) << "] ";
+ if (flags&LEVEL)
+ os << LevelTraits::name(s.level) << " ";
+ if (flags&THREAD)
+ os << "[0x" << hex << qpid::sys::Thread::logId() << "] ";
+ if (flags&FILE)
+ os << s.file << ":";
+ if (flags&LINE)
+ os << dec << s.line << ":";
+ if ((flags&FUNCTION) && s.function)
+ os << s.function << ":";
+ if (flags & (FILE|LINE|FUNCTION))
+ os << " ";
+ os << msg << endl;
+ std::string formatted=os.str();
+ {
+ ScopedLock l(lock);
+ std::for_each(outputs.begin(), outputs.end(),
+ boost::bind(&Output::log, _1, s, formatted));
+ }
+}
+
+void Logger::output(std::auto_ptr<Output> out) {
+ ScopedLock l(lock);
+ outputs.push_back(out.release());
+}
+
+void Logger::clear() {
+ select(Selector()); // locked
+ format(0); // locked
+ ScopedLock l(lock);
+ outputs.clear();
+}
+
+void Logger::format(int formatFlags) {
+ ScopedLock l(lock);
+ flags=formatFlags;
+}
+
+static int bitIf(bool test, int bit) {
+ return test ? bit : 0;
+}
+
+int Logger::format(const Options& opts) {
+ int flags=
+ bitIf(opts.level, LEVEL) |
+ bitIf(opts.time, TIME) |
+ bitIf(opts.source, (FILE|LINE)) |
+ bitIf(opts.function, FUNCTION) |
+ bitIf(opts.thread, THREAD) |
+ bitIf(opts.hiresTs, HIRES) |
+ bitIf(opts.category, CATEGORY);
+ format(flags);
+ return flags;
+}
+
+void Logger::add(Statement& s) {
+ ScopedLock l(lock);
+ enable_unlocked(&s);
+ statements.insert(&s);
+}
+
+void Logger::configure(const Options& opts) {
+ clear();
+ Options o(opts);
+ if (o.trace)
+ o.selectors.push_back("trace+");
+ format(o);
+ select(Selector(o));
+ options = opts;
+ setPrefix(opts.prefix);
+ options.sinkOptions->setup(this);
+}
+
+void Logger::reconfigure(const std::vector<std::string>& selectors) {
+ Options o(options);
+ o.selectors = selectors;
+ o.deselectors.clear();
+ select(Selector(o));
+ options = o; // Don't update options till selectors has been validated.
+}
+
+void Logger::setPrefix(const std::string& p) { prefix = p; }
+
+
+bool Logger::getHiresTimestamp()
+{
+ return flags & HIRES;
+}
+
+
+void Logger::setHiresTimestamp(bool setting)
+{
+ ScopedLock l(lock);
+ if (setting)
+ flags |= HIRES;
+ else
+ flags &= ~HIRES;
+}
+
+}} // namespace qpid::log
diff --git a/qpid/cpp/src/qpid/log/Logger.h b/qpid/cpp/src/qpid/log/Logger.h
new file mode 100644
index 0000000000..8c4beb0785
--- /dev/null
+++ b/qpid/cpp/src/qpid/log/Logger.h
@@ -0,0 +1,122 @@
+#ifndef QPID_LOG_LOGGER_H
+#define QPID_LOG_LOGGER_H
+
+/*
+ * 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/Selector.h"
+#include "qpid/log/Options.h"
+#include "qpid/sys/Mutex.h"
+#include <boost/ptr_container/ptr_vector.hpp>
+#include <boost/noncopyable.hpp>
+#include <set>
+#include "qpid/CommonImportExport.h"
+
+namespace qpid {
+namespace log {
+
+/**
+ * Central logging agent.
+ *
+ * Thread safe, singleton.
+ *
+ * The Logger provides all needed functionality for selecting and
+ * formatting logging output. The actual outputting of log records
+ * is handled by Logger::Output-derived classes instantiated by the
+ * platform's sink-related options.
+ */
+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, CATEGORY=128};
+
+ /**
+ * Logging output sink.
+ *
+ * The Output sink provides an interface to direct logging output to.
+ * Logging sinks are primarily platform-specific as provided for on
+ * each platform.
+ *
+ * Implementations of Output must be thread safe.
+ */
+ class Output {
+ public:
+ QPID_COMMON_EXTERN Output();
+ QPID_COMMON_EXTERN virtual ~Output();
+ /** Receives the statemnt of origin and formatted message to log. */
+ virtual void log(const Statement&, const std::string&) =0;
+ };
+
+ QPID_COMMON_EXTERN static Logger& instance();
+
+ QPID_COMMON_EXTERN Logger();
+ QPID_COMMON_EXTERN ~Logger();
+
+ /** Select the messages to be logged. */
+ QPID_COMMON_EXTERN void select(const Selector& s);
+
+ /** Set the formatting flags, bitwise OR of FormatFlag values. */
+ QPID_COMMON_EXTERN void format(int formatFlags);
+
+ /** Set format flags from options object.
+ *@returns computed flags.
+ */
+ QPID_COMMON_EXTERN int format(const Options&);
+
+ /** Configure logger from Options */
+ QPID_COMMON_EXTERN void configure(const Options& o);
+
+ /** Reset the log selectors */
+ QPID_COMMON_EXTERN void reconfigure(const std::vector<std::string>& selectors);
+
+ /** Add a statement. */
+ QPID_COMMON_EXTERN void add(Statement& s);
+
+ /** Log a message. */
+ QPID_COMMON_EXTERN void log(const Statement&, const std::string&);
+
+ /** Add an output destination for messages */
+ QPID_COMMON_EXTERN void output(std::auto_ptr<Output> out);
+
+ /** Set a prefix for all messages */
+ QPID_COMMON_EXTERN void setPrefix(const std::string& prefix);
+
+ /** Reset the logger. */
+ QPID_COMMON_EXTERN void clear();
+
+ /** Get the options used to configure the logger. */
+ QPID_COMMON_INLINE_EXTERN const Options& getOptions() const { return options; }
+
+ /** Get the hires timestamp setting */
+ QPID_COMMON_EXTERN bool getHiresTimestamp();
+
+ /** Set the hires timestamp setting */
+ QPID_COMMON_EXTERN void setHiresTimestamp(bool setting);
+
+ private:
+ typedef boost::ptr_vector<Output> Outputs;
+ typedef std::set<Statement*> Statements;
+
+ sys::Mutex lock;
+ inline void enable_unlocked(Statement* s);
+
+ Statements statements;
+ Outputs outputs;
+ Selector selector;
+ int flags;
+ std::string prefix;
+ Options options;
+};
+
+}} // namespace qpid::log
+
+
+#endif /*!QPID_LOG_LOGGER_H*/
diff --git a/qpid/cpp/src/qpid/log/Options.cpp b/qpid/cpp/src/qpid/log/Options.cpp
new file mode 100644
index 0000000000..f816124b4e
--- /dev/null
+++ b/qpid/cpp/src/qpid/log/Options.cpp
@@ -0,0 +1,148 @@
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * Licensed 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/Options.h"
+#include "qpid/log/SinkOptions.h"
+#include "qpid/log/Statement.h"
+#include "qpid/Options.h"
+#include <map>
+#include <string>
+#include <algorithm>
+
+namespace qpid {
+namespace log {
+
+Options::Options(const std::string& argv0_, const std::string& name_) :
+ qpid::Options(name_),
+ argv0(argv0_),
+ name(name_),
+ time(true),
+ level(true),
+ thread(false),
+ source(false),
+ function(false),
+ hiresTs(false),
+ category(true),
+ trace(false),
+ sinkOptions (SinkOptions::create(argv0_))
+{
+ selectors.push_back("notice+");
+
+ 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 "+getLevels()+"\n"
+ "PATTERN is a logging category name, or a namespace-qualified "
+ "function name or name fragment. "
+ "Logging category names are: \n\t "+getCategories()+"\n"
+ "For example:\n"
+ "\t'--log-enable warning+'\n"
+ "logs all warning, error and critical messages.\n"
+ "\t'--log-enable trace+:Broker'\n"
+ "logs all category 'Broker' 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())
+ ("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 "+getLevels()+"\n"
+ "PATTERN is a logging category name, or a namespace-qualified "
+ "function name or name fragment. "
+ "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"
+ "\t'--log-disable trace:Broker'\n"
+ "disables all category 'Broker' trace messages.\n"
+ "\t'--log-disable debug-:qmf::'\n"
+ "disables logging debug and trace messages from all functions with 'qmf::' in the namespace.\n"
+ "This option can be used multiple times").c_str())
+ ("log-time", optValue(time, "yes|no"), "Include time in log messages")
+ ("log-level", optValue(level,"yes|no"), "Include severity level in log messages")
+ ("log-source", optValue(source,"yes|no"), "Include source file:line in log messages")
+ ("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 prepend to all log messages")
+ ;
+ add(*sinkOptions);
+}
+
+Options::Options(const Options &o) :
+ qpid::Options(o.name),
+ argv0(o.argv0),
+ name(o.name),
+ selectors(o.selectors),
+ deselectors(o.deselectors),
+ time(o.time),
+ level(o.level),
+ thread(o.thread),
+ source(o.source),
+ function(o.function),
+ hiresTs(o.hiresTs),
+ category(o.category),
+ trace(o.trace),
+ prefix(o.prefix),
+ sinkOptions (SinkOptions::create(o.argv0))
+{
+ *sinkOptions = *o.sinkOptions;
+}
+
+Options& Options::operator=(const Options& x) {
+ if (this != &x) {
+ argv0 = x.argv0;
+ name = x.name;
+ selectors = x.selectors;
+ deselectors = x.deselectors;
+ time = x.time;
+ level= x.level;
+ thread = x.thread;
+ source = x.source;
+ function = x.function;
+ hiresTs = x.hiresTs;
+ category = x.category;
+ trace = x.trace;
+ prefix = x.prefix;
+ *sinkOptions = *x.sinkOptions;
+ }
+ 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
diff --git a/qpid/cpp/src/qpid/log/Options.h b/qpid/cpp/src/qpid/log/Options.h
new file mode 100644
index 0000000000..ed534168e8
--- /dev/null
+++ b/qpid/cpp/src/qpid/log/Options.h
@@ -0,0 +1,57 @@
+#ifndef QPID_LOG_OPTIONS_H
+#define QPID_LOG_OPTIONS_H
+
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * Licensed 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/Options.h"
+#include "qpid/CommonImportExport.h"
+#include "qpid/log/SinkOptions.h"
+#include <iosfwd>
+#include <memory>
+
+namespace qpid {
+namespace log {
+
+/** Logging options for config parser. */
+struct Options : public qpid::Options {
+ /** Pass argv[0] for use in syslog output */
+ QPID_COMMON_EXTERN Options(const std::string& argv0_=std::string(),
+ const std::string& name_="Logging options");
+ QPID_COMMON_EXTERN Options(const Options &);
+
+ QPID_COMMON_EXTERN Options& operator=(const Options&);
+
+ std::string argv0;
+ std::string name;
+ std::vector<std::string> selectors;
+ std::vector<std::string> deselectors;
+ bool time, level, thread, source, function, hiresTs, category;
+ bool trace;
+ std::string prefix;
+ 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*/
diff --git a/qpid/cpp/src/qpid/log/OstreamOutput.cpp b/qpid/cpp/src/qpid/log/OstreamOutput.cpp
new file mode 100644
index 0000000000..9b6ec1f8aa
--- /dev/null
+++ b/qpid/cpp/src/qpid/log/OstreamOutput.cpp
@@ -0,0 +1,41 @@
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * Licensed 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/OstreamOutput.h"
+#include <stdexcept>
+
+using namespace std;
+
+namespace qpid {
+namespace log {
+
+OstreamOutput::OstreamOutput(std::ostream& o) : out(&o) {}
+
+OstreamOutput::OstreamOutput(const std::string& file)
+ : out(new ofstream(file.c_str(), ios_base::out | ios_base::app)),
+ mine(out)
+{
+ if (!out->good())
+ throw std::runtime_error("Can't open log file: "+file);
+}
+
+void OstreamOutput::log(const Statement&, const std::string& m) {
+ *out << m << flush;
+}
+
+}} // namespace qpid::log
diff --git a/qpid/cpp/src/qpid/log/OstreamOutput.h b/qpid/cpp/src/qpid/log/OstreamOutput.h
new file mode 100644
index 0000000000..12fd4ce425
--- /dev/null
+++ b/qpid/cpp/src/qpid/log/OstreamOutput.h
@@ -0,0 +1,41 @@
+#ifndef QPID_LOG_OSTREAMOUTPUT_H
+#define QPID_LOG_OSTREAMOUTPUT_H
+
+/*
+ * 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/Logger.h"
+#include <boost/scoped_ptr.hpp>
+#include <fstream>
+#include <ostream>
+
+namespace qpid {
+namespace log {
+
+/**
+ * OstreamOutput is a reusable logging sink that directs logging to a C++
+ * ostream.
+ */
+class OstreamOutput : public qpid::log::Logger::Output {
+public:
+ QPID_COMMON_EXTERN OstreamOutput(std::ostream& o);
+ QPID_COMMON_EXTERN OstreamOutput(const std::string& file);
+
+ virtual void log(const Statement&, const std::string& m);
+
+private:
+ std::ostream* out;
+ boost::scoped_ptr<std::ostream> mine;
+};
+
+}} // namespace qpid::log
+
+#endif /*!QPID_LOG_OSTREAMOUTPUT_H*/
diff --git a/qpid/cpp/src/qpid/log/Selector.cpp b/qpid/cpp/src/qpid/log/Selector.cpp
new file mode 100644
index 0000000000..a517cb34f4
--- /dev/null
+++ b/qpid/cpp/src/qpid/log/Selector.cpp
@@ -0,0 +1,237 @@
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * Licensed 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/Selector.h"
+#include "qpid/log/Options.h"
+#include <boost/bind.hpp>
+#include <algorithm>
+#include <string.h>
+
+namespace qpid {
+namespace log {
+
+using namespace std;
+
+const char LOG_SYMBOL_DISABLE ('!');
+const char LOG_SYMBOL_SEPERATOR(':');
+const char LOG_SYMBOL_AND_ABOVE('+');
+const char LOG_SYMBOL_AND_BELOW('-');
+
+//
+// Parse an enable or disable entry into usable fields.
+// Throws if 'level' field is not recognized.
+//
+SelectorElement::SelectorElement(const std::string cliEntry) :
+ level(qpid::log::debug),
+ category(qpid::log::unspecified),
+ isDisable(false),
+ isCategory(false),
+ isLevelAndAbove(false),
+ isLevelAndBelow(false)
+{
+ if (cliEntry.empty())
+ return;
+ std::string working(cliEntry);
+ if (LOG_SYMBOL_DISABLE == working[0]) {
+ isDisable = true;
+ working = working.substr(1);
+ }
+ size_t c=working.find(LOG_SYMBOL_SEPERATOR);
+ if (c==string::npos) {
+ levelStr=working;
+ } else {
+ levelStr=working.substr(0,c);
+ patternStr=working.substr(c+1);
+ }
+ if (!levelStr.empty()) {
+ if (levelStr[levelStr.size()-1]==LOG_SYMBOL_AND_ABOVE) {
+ isLevelAndAbove = true;
+ levelStr = levelStr.substr(0, levelStr.size()-1);
+ } else if (levelStr[levelStr.size()-1]==LOG_SYMBOL_AND_BELOW) {
+ isLevelAndBelow = true;
+ levelStr = levelStr.substr(0, levelStr.size()-1);
+ }
+ }
+ level = LevelTraits::level(levelStr); // throws if bad level name
+ isCategory = CategoryTraits::isCategory(patternStr);
+ if (isCategory) {
+ category = CategoryTraits::category(patternStr);
+ }
+}
+
+// Empty selector
+Selector::Selector() {
+ reset();
+}
+
+
+// Selector from options
+Selector::Selector(const Options& opt){
+ reset();
+ for_each(opt.selectors.begin(), opt.selectors.end(),
+ boost::bind(&Selector::enable, this, _1));
+ for_each(opt.deselectors.begin(), opt.deselectors.end(),
+ boost::bind(&Selector::disable, this, _1));
+}
+
+
+// Selector from single level
+Selector::Selector(Level l, const std::string& s) {
+ reset();
+ enable(l, s);
+}
+
+
+// Selector from single enable
+Selector::Selector(const std::string& selector) {
+ reset();
+ enable(selector);
+}
+
+
+/**
+ * Process a single CLI --log-enable option
+ */
+void Selector::enable(const string& enableStr) {
+ if (enableStr.empty())
+ return;
+ SelectorElement se(enableStr);
+ if (se.isDisable) {
+ // Disable statements are allowed in an enable string as a convenient
+ // way to process management strings that have enable/disable mixed.
+ disable(enableStr);
+ } else if (se.isLevelAndAbove) {
+ for (int lvl = se.level; lvl < LevelTraits::COUNT; ++lvl) {
+ if (se.isCategory) {
+ enableFlags[lvl][se.category] = true;
+ } else {
+ enable(Level(lvl), se.patternStr);
+ }
+ }
+ } else if (se.isLevelAndBelow) {
+ for (int lvl = se.level; lvl >= 0; --lvl) {
+ if (se.isCategory) {
+ enableFlags[lvl][se.category] = true;
+ } else {
+ enable(Level(lvl), se.patternStr);
+ }
+ }
+ } else {
+ if (se.isCategory) {
+ enableFlags[se.level][se.category] = true;
+ } else {
+ enable(se.level, se.patternStr);
+ }
+ }
+}
+
+void Selector::disable(const string& disableStr) {
+ if (disableStr.empty())
+ return;
+ SelectorElement se(disableStr);
+ if (se.isLevelAndAbove) {
+ for (int lvl = se.level; lvl < LevelTraits::COUNT; ++lvl) {
+ if (se.isCategory) {
+ disableFlags[lvl][se.category] = true;
+ } else {
+ disable(Level(lvl), se.patternStr);
+ }
+ }
+ } else if (se.isLevelAndBelow) {
+ for (int lvl = se.level; lvl >= 0; --lvl) {
+ if (se.isCategory) {
+ disableFlags[lvl][se.category] = true;
+ } else {
+ disable(Level(lvl), se.patternStr);
+ }
+ }
+ } else {
+ if (se.isCategory) {
+ disableFlags[se.level][se.category] = true;
+ } else {
+ disable(se.level, se.patternStr);
+ }
+ }
+}
+
+
+/**
+* Enable/disable messages with level in levels where the file
+* name contains substring.
+*/
+void Selector::enable(Level level, const std::string& substring) {
+ enabledFunctions[level].push_back(substring);
+}
+
+
+void Selector::disable(Level level, const std::string& substring) {
+ disabledFunctions[level].push_back(substring);
+}
+
+
+void Selector::reset() {
+ // Initialize fields in a Selector that are not automatically set
+ for (int lt = 0; lt < LevelTraits::COUNT; ++lt)
+ for (int ct = 0; ct < CategoryTraits::COUNT; ++ct)
+ enableFlags[lt][ct] = disableFlags[lt][ct] = false;
+}
+
+
+bool Selector::lookupFuncName(Level level, const char* function, FunctionNameTable& table) {
+ const char* functionEnd = function+::strlen(function);
+ for (std::vector<std::string>::iterator i=table[level].begin();
+ i != table[level].end();
+ ++i)
+ {
+ if (std::search(function, functionEnd, i->begin(), i->end()) != functionEnd)
+ return true;
+ }
+ return false;
+}
+
+
+bool Selector::isEnabled(Level level, const char* function) {
+ return lookupFuncName(level, function, enabledFunctions);
+}
+
+bool Selector::isDisabled(Level level, const char* function) {
+ return lookupFuncName(level, function, disabledFunctions);
+}
+
+//
+// isEnabled
+//
+// Determines if all the fields in this Selector enable or disable a
+// level/function/category set from an actual QPID_LOG Statement.
+//
+bool Selector::isEnabled(Level level, const char* function, Category category) {
+ if (level==critical)
+ return true; // critical cannot be disabled
+ if (isDisabled(level, function))
+ return false; // Disabled by function name
+ if (disableFlags[level][category])
+ return false; // Disabled by category name
+ if (isEnabled(level, function))
+ return true; // Enabled by function name
+ if (enableFlags[level][category])
+ return true; // Enabled by category name
+ else
+ return false; // Unspecified defaults to disabled
+}
+
+}} // namespace qpid::log
diff --git a/qpid/cpp/src/qpid/log/Selector.h b/qpid/cpp/src/qpid/log/Selector.h
new file mode 100644
index 0000000000..1d025e9646
--- /dev/null
+++ b/qpid/cpp/src/qpid/log/Selector.h
@@ -0,0 +1,99 @@
+#ifndef SELECTOR_H
+#define SELECTOR_H
+
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * Licensed 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/CommonImportExport.h"
+#include <vector>
+
+namespace qpid {
+namespace log {
+struct Options;
+
+/**
+ * SelectorElement parses a cli/mgmt enable/disable entry into usable fields
+ * where cliEntry = [!]LEVEL[+-][:PATTERN]
+ */
+struct SelectorElement {
+ QPID_COMMON_EXTERN SelectorElement(const std::string cliEntry);
+ std::string levelStr;
+ std::string patternStr;
+ Level level;
+ Category category;
+ bool isDisable;
+ bool isCategory;
+ bool isLevelAndAbove;
+ bool isLevelAndBelow;
+};
+
+/**
+ * A selector identifies the set of log messages to enable.
+ *
+ * Thread object unsafe, pass-by-value type.
+ */
+class Selector {
+ public:
+ /** Empty selector selects nothing */
+ QPID_COMMON_EXTERN Selector();
+
+ /** Set selector from Options */
+ QPID_COMMON_EXTERN Selector(const Options&);
+
+ /** Equavlient to: Selector s; s.enable(l, s) */
+ QPID_COMMON_EXTERN Selector(Level l, const std::string& s=std::string());
+
+ /** Selector from string */
+ QPID_COMMON_EXTERN Selector(const std::string& selector);
+
+ /** push option settings into runtime lookup structs */
+ QPID_COMMON_EXTERN void enable(const std::string& enableStr);
+ QPID_COMMON_EXTERN void disable(const std::string& disableStr);
+
+ /**
+ * Enable/disable messages with level in levels where the file
+ * name contains substring. Empty string matches all.
+ */
+ QPID_COMMON_EXTERN void enable(Level level, const std::string& substring=std::string());
+ QPID_COMMON_EXTERN void disable(Level level, const std::string& substring=std::string());
+
+ /** Tests to determine if function names are in enable/disable tables */
+ QPID_COMMON_EXTERN bool isEnabled(Level level, const char* function);
+ QPID_COMMON_EXTERN bool isDisabled(Level level, const char* function);
+
+ /** Test to determine if log Statement is enabled */
+ QPID_COMMON_EXTERN bool isEnabled(Level level, const char* function, Category category);
+
+ private:
+ typedef std::vector<std::string> FunctionNameTable [LevelTraits::COUNT];
+ FunctionNameTable enabledFunctions; // log function names explicitly enabled
+ FunctionNameTable disabledFunctions; // log function names explicitly disabled
+ bool enableFlags[LevelTraits::COUNT][CategoryTraits::COUNT];
+ bool disableFlags[LevelTraits::COUNT][CategoryTraits::COUNT];
+
+ bool lookupFuncName(Level level, const char* function, FunctionNameTable& table);
+ /** Reset the category enable flags */
+ QPID_COMMON_EXTERN void reset();
+};
+
+
+}} // namespace qpid::log
+
+
+#endif /*!SELECTOR_H*/
diff --git a/qpid/cpp/src/qpid/log/SinkOptions.h b/qpid/cpp/src/qpid/log/SinkOptions.h
new file mode 100644
index 0000000000..7ec2cfbc17
--- /dev/null
+++ b/qpid/cpp/src/qpid/log/SinkOptions.h
@@ -0,0 +1,64 @@
+#ifndef QPID_LOG_SINKOPTIONS_H
+#define QPID_LOG_SINKOPTIONS_H
+
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * Licensed 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/Options.h"
+#include <string>
+
+namespace qpid {
+namespace log {
+
+class Logger;
+
+/**
+ * Logging sink options.
+ *
+ * Most logging sink options will be platform-specific, even if some are
+ * duplicated. The range of platforms to which this code may be ported
+ * can't be assumed to all have C++ iostreams or files. Thus, this class
+ * is primarily for implementing in a platform-specific way.
+ */
+struct SinkOptions : public qpid::Options {
+
+ // Create a platform's SinkOptions. Pass argv0 as the program name,
+ // useful for syslog-type logging.
+ static SinkOptions *create(const std::string& argv0=std::string());
+
+ SinkOptions(const std::string& name="Logging sink options")
+ : qpid::Options(name)
+ {}
+ virtual ~SinkOptions() {}
+
+ virtual SinkOptions& operator=(const SinkOptions&) = 0;
+
+ // This allows the caller to indicate that there's no normal outputs
+ // available. For example, when running as a daemon. In these cases, the
+ // platform's "syslog"-type output should replace the default stderr
+ // unless some other sink has been selected.
+ virtual void detached(void) = 0;
+
+ // The Logger acting on these options calls setup() to request any
+ // Sinks be set up and fed back to the logger.
+ virtual void setup(Logger *logger) = 0;
+};
+
+}} // namespace qpid::log
+
+#endif /*!QPID_LOG_OPTIONS_H*/
diff --git a/qpid/cpp/src/qpid/log/Statement.cpp b/qpid/cpp/src/qpid/log/Statement.cpp
new file mode 100644
index 0000000000..86b069fd91
--- /dev/null
+++ b/qpid/cpp/src/qpid/log/Statement.cpp
@@ -0,0 +1,218 @@
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * Licensed 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/log/Logger.h"
+#include <boost/bind.hpp>
+#include <stdexcept>
+#include <algorithm>
+#include <list>
+#include <ctype.h>
+
+namespace qpid {
+namespace log {
+
+namespace {
+struct NonPrint { bool operator()(unsigned char c) { return !isprint(c) && !isspace(c); } };
+
+const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+std::string quote(const std::string& str) {
+ NonPrint nonPrint;
+ size_t n = std::count_if(str.begin(), str.end(), nonPrint);
+ if (n==0) return str;
+ std::string ret;
+ ret.reserve(str.size()+3*n); // Avoid extra allocations.
+ for (std::string::const_iterator i = str.begin(); i != str.end(); ++i) {
+ if (nonPrint(*i)) {
+ ret.push_back('\\');
+ ret.push_back('x');
+ ret.push_back(hex[((*i) >> 4)&0xf]);
+ ret.push_back(hex[(*i) & 0xf]);
+ }
+ else ret.push_back(*i);
+ }
+ return ret;
+}
+}
+
+//
+// Instance of name hints
+//
+class CategoryFileNameHints {
+public:
+ CategoryFileNameHints(){
+ hintList.push_back(std::make_pair("AsynchIo", network));
+ hintList.push_back(std::make_pair("TCP", network));
+ hintList.push_back(std::make_pair("epoll", network));
+ hintList.push_back(std::make_pair("Pollable", network));
+ hintList.push_back(std::make_pair("Socket", network));
+
+ hintList.push_back(std::make_pair("Sasl", security));
+ hintList.push_back(std::make_pair("Ssl", security));
+ hintList.push_back(std::make_pair("Acl", security));
+ hintList.push_back(std::make_pair("acl", security));
+ hintList.push_back(std::make_pair("cyrus", security));
+
+ hintList.push_back(std::make_pair("amqp_", protocol));
+ hintList.push_back(std::make_pair("framing", protocol));
+
+ hintList.push_back(std::make_pair("management", management));
+ hintList.push_back(std::make_pair("qmf", management));
+ hintList.push_back(std::make_pair("console", management));
+ hintList.push_back(std::make_pair("Management", management));
+
+ hintList.push_back(std::make_pair("cluster", ha));
+ hintList.push_back(std::make_pair("qpid/ha", ha));
+ hintList.push_back(std::make_pair("qpid\\ha", ha));
+ hintList.push_back(std::make_pair("replication", ha));
+ hintList.push_back(std::make_pair("ClusterSafe", ha));
+
+ hintList.push_back(std::make_pair("broker", broker));
+ hintList.push_back(std::make_pair("SessionState",broker));
+ hintList.push_back(std::make_pair("DataDir", broker));
+ hintList.push_back(std::make_pair("qpidd", broker));
+ hintList.push_back(std::make_pair("xml", broker));
+ hintList.push_back(std::make_pair("QpidBroker", broker));
+
+ hintList.push_back(std::make_pair("store", store));
+
+ hintList.push_back(std::make_pair("assert", system));
+ hintList.push_back(std::make_pair("Exception", system));
+ hintList.push_back(std::make_pair("sys", system));
+ hintList.push_back(std::make_pair("SCM", system));
+
+ hintList.push_back(std::make_pair("tests", test));
+
+ hintList.push_back(std::make_pair("messaging", messaging));
+ hintList.push_back(std::make_pair("types", messaging));
+
+ hintList.push_back(std::make_pair("client", client));
+ }
+
+ static Category categoryOf(const char*const fName);
+
+private:
+ std::list<std::pair<const char* const, Category> > hintList;
+};
+
+static CategoryFileNameHints filenameHints;
+
+Category CategoryFileNameHints::categoryOf(const char* const fName) {
+ for (std::list<std::pair<const char* const, Category> >::iterator
+ it = filenameHints.hintList.begin();
+ it != filenameHints.hintList.end();
+ ++it) {
+ if (strstr(fName, (const char* const)it->first) != 0) {
+ return it->second;
+ }
+ }
+ 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 and file name.
+ if (s.category == log::unspecified) {
+ s.category = CategoryFileNameHints::categoryOf(s.file);
+ } else {
+ // already has a category so leave it alone
+ }
+}
+
+
+void Statement::log(const std::string& message) {
+ Logger::instance().log(*this, quote(message));
+}
+
+
+Statement::Initializer::Initializer(Statement& s) : statement(s) {
+ // QPID-3891:
+ // From the given BOOST_CURRENT_FUNCTION name extract only the
+ // namespace-qualified-functionName, skipping return and calling args.
+ // Given:
+ // <possible return value type> qpid::name::space::Function(args)
+ // Return:
+ // "qpid::name::space::Function".
+ if (s.function) {
+ const char* end = s.function + strlen(s.function);
+ const char* fEnd = std::find(s.function, end, '(');
+ typedef std::reverse_iterator<const char*> Reverse;
+ const char* fBegin = find(Reverse(fEnd), Reverse(s.function), ' ').base();
+ size_t n = fEnd - fBegin;
+ char* name = new char[n+1];
+ std::copy(fBegin, fEnd, name);
+ name[n] = '\0';
+ s.function = name;
+ }
+ Statement::categorize(s);
+ Logger::instance().add(s);
+}
+
+Statement::Initializer::~Initializer() {
+ delete[] const_cast<char*>(statement.function);
+ statement.function = 0;
+}
+
+
+namespace {
+const char* names[LevelTraits::COUNT] = {
+ "trace", "debug", "info", "notice", "warning", "error", "critical"
+};
+
+const char* catNames[CategoryTraits::COUNT] = {
+ "Security", "Broker", "Management", "Protocol", "System", "HA", "Messaging",
+ "Store", "Network", "Test", "Client", "Application", "Model", "Unspecified"
+};
+
+} // namespace
+Level LevelTraits::level(const char* name) {
+ for (int i =0; i < LevelTraits::COUNT; ++i) {
+ if (strcmp(names[i], name)==0)
+ return Level(i);
+ }
+ throw std::runtime_error(std::string("Invalid log level name: ")+name);
+}
+
+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/qpid/log/Statement.h b/qpid/cpp/src/qpid/log/Statement.h
new file mode 100644
index 0000000000..410ffaaa3d
--- /dev/null
+++ b/qpid/cpp/src/qpid/log/Statement.h
@@ -0,0 +1,244 @@
+#ifndef STATEMENT_H
+#define STATEMENT_H
+
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * Licensed 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/Msg.h"
+#include "qpid/CommonImportExport.h"
+#include <boost/current_function.hpp>
+
+namespace qpid {
+namespace log {
+
+/** Debugging severity levels
+ * - trace: High-volume debugging messages.
+ * - debug: Debugging messages.
+ * - info: Informational messages.
+ * - notice: Normal but significant condition.
+ * - warning: Warn of a possible problem.
+ * - error: A definite error has occured.
+ * - critical: System in danger of severe failure.
+ */
+enum Level { trace, debug, info, notice, warning, error, critical };
+struct LevelTraits {
+ static const int COUNT=critical+1;
+
+ /** Get level from string name.
+ *@exception if name invalid.
+ */
+ static Level level(const char* name);
+
+ /** Get level from string name.
+ *@exception if name invalid.
+ */
+ static Level level(const std::string& name) {
+ return level(name.c_str());
+ }
+
+ /** String name of level */
+ static const char* name(Level);
+};
+
+/** 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
+ * Protocol amqp_0_10 framing
+ * System log sys types xml thread mutex fork pipe time ...
+ * HA cluster ha replication
+ * Messaging messaging
+ * Client client
+ * 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, external_application, model, 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);
+
+ struct Initializer {
+ QPID_COMMON_EXTERN Initializer(Statement& s);
+ QPID_COMMON_EXTERN ~Initializer();
+ Statement& statement;
+ };
+};
+
+///@internal static initializer for a Statement.
+#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
+ * to determine if the message should be logged. Evaluation of both
+ * the test and message expressions occurs only if the requested log level
+ * is enabled.
+ *@param LEVEL severity Level for message, should be one of:
+ * debug, info, notice, warning, error, critical. NB no qpid::log:: prefix.
+ *@param TEST message is logged only if expression TEST evaluates to true.
+ *@param MESSAGE any object with an @eostream operator<<, or a sequence
+ * like of ostreamable objects separated by @e<<.
+ */
+#define QPID_LOG_IF(LEVEL, TEST, MESSAGE) \
+ do { \
+ using ::qpid::log::Statement; \
+ static Statement stmt_= QPID_LOG_STATEMENT_INIT(LEVEL); \
+ static Statement::Initializer init_(stmt_); \
+ if (stmt_.enabled && (TEST)) \
+ stmt_.log(::qpid::Msg() << MESSAGE); \
+ } 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(warning, logWarning);
+ * if (logWarning) { do stuff needed for warning log messages }
+ */
+#define QPID_LOG_TEST(LEVEL, FLAG) \
+ do { \
+ using ::qpid::log::Statement; \
+ static Statement stmt_= QPID_LOG_STATEMENT_INIT(LEVEL); \
+ static Statement::Initializer init_(stmt_); \
+ 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.
+
+ *@param LEVEL severity Level for message, should be one of:
+ * debug, info, notice, warning, error, critical. NB no qpid::log:: prefix.
+ *@param MESSAGE any object with an @eostream operator<<, or a sequence
+ * like of ostreamable objects separated by @e<<.
+ */
+#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
+
+
+
+
+#endif /*!STATEMENT_H*/
+
diff --git a/qpid/cpp/src/qpid/log/posix/SinkOptions.cpp b/qpid/cpp/src/qpid/log/posix/SinkOptions.cpp
new file mode 100644
index 0000000000..210022551e
--- /dev/null
+++ b/qpid/cpp/src/qpid/log/posix/SinkOptions.cpp
@@ -0,0 +1,222 @@
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * Licensed 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/posix/SinkOptions.h"
+#include "qpid/log/SinkOptions.h"
+#include "qpid/log/Logger.h"
+#include "qpid/log/OstreamOutput.h"
+#include "qpid/OptionsTemplates.h"
+#include "qpid/memory.h"
+#include "qpid/Exception.h"
+
+#include <iostream>
+#include <map>
+#include <string>
+#include <syslog.h>
+
+#include <boost/lexical_cast.hpp>
+
+using std::string;
+using qpid::Exception;
+
+namespace qpid {
+
+template po::value_semantic* create_value(log::posix::SyslogFacility& val, const std::string& arg);
+
+namespace log {
+namespace posix {
+
+namespace {
+
+// SyslogFacilities maps from syslog values to the text equivalents.
+class SyslogFacilities {
+public:
+ typedef std::map<string, int> ByName;
+ typedef std::map<int, string> ByValue;
+
+ SyslogFacilities() {
+ struct NameValue { const char* name; int value; };
+ NameValue nameValue[] = {
+ { "AUTH", LOG_AUTH },
+#ifdef HAVE_LOG_AUTHPRIV
+ { "AUTHPRIV", LOG_AUTHPRIV },
+#endif
+ { "CRON", LOG_CRON },
+ { "DAEMON", LOG_DAEMON },
+#ifdef HAVE_LOG_FTP
+ { "FTP", LOG_FTP },
+#endif
+ { "KERN", LOG_KERN },
+ { "LOCAL0", LOG_LOCAL0 },
+ { "LOCAL1", LOG_LOCAL1 },
+ { "LOCAL2", LOG_LOCAL2 },
+ { "LOCAL3", LOG_LOCAL3 },
+ { "LOCAL4", LOG_LOCAL4 },
+ { "LOCAL5", LOG_LOCAL5 },
+ { "LOCAL6", LOG_LOCAL6 },
+ { "LOCAL7", LOG_LOCAL7 },
+ { "LPR", LOG_LPR },
+ { "MAIL", LOG_MAIL },
+ { "NEWS", LOG_NEWS },
+ { "SYSLOG", LOG_SYSLOG },
+ { "USER", LOG_USER },
+ { "UUCP", LOG_UUCP }
+ };
+ for (size_t i = 0; i < sizeof(nameValue)/sizeof(nameValue[0]); ++i) {
+ byName.insert(ByName::value_type(nameValue[i].name, nameValue[i].value));
+ // Recognise with and without LOG_ prefix e.g.: AUTH and LOG_AUTH
+ byName.insert(ByName::value_type(string("LOG_")+nameValue[i].name, nameValue[i].value));
+ byValue.insert(ByValue::value_type(nameValue[i].value, string("LOG_")+nameValue[i].name));
+ }
+ }
+
+ int value(const string& name) const {
+ string key(name);
+ std::transform(key.begin(), key.end(), key.begin(), ::toupper);
+ ByName::const_iterator i = byName.find(key);
+ if (i == byName.end())
+ throw Exception("Not a valid syslog facility: " + name);
+ return i->second;
+ }
+
+ string name(int value) const {
+ ByValue::const_iterator i = byValue.find(value);
+ if (i == byValue.end())
+ throw Exception("Not a valid syslog value: " + boost::lexical_cast<string>(value));
+ return i->second;
+ }
+
+ private:
+ ByName byName;
+ ByValue byValue;
+};
+
+// 'priorities' maps qpid log levels to syslog priorities. They are in
+// order of qpid log levels and must map to:
+// "trace", "debug", "info", "notice", "warning", "error", "critical"
+static int priorities[qpid::log::LevelTraits::COUNT] = {
+ LOG_DEBUG, LOG_DEBUG, LOG_INFO, LOG_NOTICE,
+ LOG_WARNING, LOG_ERR, LOG_CRIT
+};
+
+std::string basename(const std::string path) {
+ size_t i = path.find_last_of('/');
+ return path.substr((i == std::string::npos) ? 0 : i+1);
+}
+
+} // namespace
+
+std::ostream& operator<<(std::ostream& o, const SyslogFacility& f) {
+ return o << SyslogFacilities().name(f.value);
+}
+
+std::istream& operator>>(std::istream& i, SyslogFacility& f) {
+ std::string name;
+ i >> name;
+ f.value = SyslogFacilities().value(name);
+ return i;
+}
+
+class SyslogOutput : public qpid::log::Logger::Output {
+public:
+ SyslogOutput(const std::string& logName, const SyslogFacility& logFacility)
+ : name(logName), facility(logFacility.value)
+ {
+ ::openlog(name.c_str(), LOG_PID, facility);
+ }
+
+ virtual ~SyslogOutput() {
+ ::closelog();
+ }
+
+ virtual void log(const Statement& s, const std::string& m)
+ {
+ syslog(priorities[s.level], "%s", m.c_str());
+ }
+
+private:
+ std::string name;
+ int facility;
+};
+
+SinkOptions::SinkOptions(const std::string& argv0)
+ : qpid::log::SinkOptions(),
+ logToStderr(true),
+ logToStdout(false),
+ logToSyslog(false),
+ syslogName(basename(argv0)),
+ syslogFacility(LOG_DAEMON) {
+
+ addOptions()
+ ("log-to-stderr", optValue(logToStderr, "yes|no"), "Send logging output to stderr")
+ ("log-to-stdout", optValue(logToStdout, "yes|no"), "Send logging output to stdout")
+ ("log-to-file", optValue(logFile, "FILE"), "Send log output to FILE.")
+ ("log-to-syslog", optValue(logToSyslog, "yes|no"), "Send logging output to syslog;\n\tcustomize using --syslog-name and --syslog-facility")
+ ("syslog-name", optValue(syslogName, "NAME"), "Name to use in syslog messages")
+ ("syslog-facility", optValue(syslogFacility,"LOG_XXX"), "Facility to use in syslog messages")
+ ;
+
+}
+
+qpid::log::SinkOptions& SinkOptions::operator=(const qpid::log::SinkOptions& rhs) {
+ const SinkOptions *prhs = dynamic_cast<const SinkOptions*>(&rhs);
+ if (this != prhs) {
+ logToStderr = prhs->logToStderr;
+ logToStdout = prhs->logToStdout;
+ logToSyslog = prhs->logToSyslog;
+ logFile = prhs->logFile;
+ syslogName = prhs->syslogName;
+ syslogFacility.value = prhs->syslogFacility.value;
+ }
+ return *this;
+}
+
+void SinkOptions::detached(void) {
+ if (logToStderr && !logToStdout && !logToSyslog && logFile.empty()) {
+ logToStderr = false;
+ logToSyslog = true;
+ }
+}
+
+// The Logger acting on these options calls setup() to request any
+// Sinks be set up and fed back to the logger.
+void SinkOptions::setup(qpid::log::Logger *logger) {
+ if (logToStderr)
+ logger->output(make_auto_ptr<qpid::log::Logger::Output>
+ (new qpid::log::OstreamOutput(std::clog)));
+ if (logToStdout)
+ logger->output(make_auto_ptr<qpid::log::Logger::Output>
+ (new qpid::log::OstreamOutput(std::cout)));
+
+ if (logFile.length() > 0)
+ logger->output(make_auto_ptr<qpid::log::Logger::Output>
+ (new qpid::log::OstreamOutput(logFile)));
+
+ if (logToSyslog)
+ logger->output(make_auto_ptr<qpid::log::Logger::Output>
+ (new SyslogOutput(syslogName, syslogFacility)));
+
+}
+
+} // namespace qpid::log::posix
+
+SinkOptions* SinkOptions::create(const std::string& argv0) {
+ return new qpid::log::posix::SinkOptions (argv0);
+}
+
+}} // namespace qpid::log
diff --git a/qpid/cpp/src/qpid/log/posix/SinkOptions.h b/qpid/cpp/src/qpid/log/posix/SinkOptions.h
new file mode 100644
index 0000000000..d929c29025
--- /dev/null
+++ b/qpid/cpp/src/qpid/log/posix/SinkOptions.h
@@ -0,0 +1,64 @@
+#ifndef QPID_LOG_POSIX_SINKOPTIONS_H
+#define QPID_LOG_POSIX_SINKOPTIONS_H
+
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * Licensed 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/SinkOptions.h"
+#include <string>
+
+namespace qpid {
+namespace log {
+namespace posix {
+
+/**
+ * Provides a type that can be passed to << and >> operators to convert
+ * syslog facility values to/from strings.
+ */
+struct SyslogFacility {
+ int value;
+ SyslogFacility(int i=0) : value(i) {}
+};
+
+struct SinkOptions : public qpid::log::SinkOptions {
+ SinkOptions(const std::string& argv0);
+ virtual ~SinkOptions() {}
+
+ virtual qpid::log::SinkOptions& operator=(const qpid::log::SinkOptions& rhs);
+
+ // This allows the caller to indicate that there's no normal outputs
+ // available. For example, when running as a daemon. In these cases, the
+ // platform's "syslog"-type output should replace the default stderr
+ // unless some other sink has been selected.
+ virtual void detached(void);
+
+ // The Logger acting on these options calls setup() to request any
+ // Sinks be set up and fed back to the logger.
+ virtual void setup(qpid::log::Logger *logger);
+
+ bool logToStderr;
+ bool logToStdout;
+ bool logToSyslog;
+ std::string logFile;
+ std::string syslogName;
+ SyslogFacility syslogFacility;
+};
+
+}}} // namespace qpid::log::posix
+
+#endif /*!QPID_LOG_POSIX_SINKOPTIONS_H*/
diff --git a/qpid/cpp/src/qpid/log/windows/SinkOptions.cpp b/qpid/cpp/src/qpid/log/windows/SinkOptions.cpp
new file mode 100644
index 0000000000..0c74bea64e
--- /dev/null
+++ b/qpid/cpp/src/qpid/log/windows/SinkOptions.cpp
@@ -0,0 +1,148 @@
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * Licensed 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/windows/SinkOptions.h"
+#include "qpid/log/SinkOptions.h"
+#include "qpid/log/Logger.h"
+#include "qpid/log/OstreamOutput.h"
+#include "qpid/memory.h"
+#include "qpid/Exception.h"
+#include <iostream>
+#include <map>
+#include <string>
+
+#include <windows.h>
+
+using qpid::Exception;
+
+namespace qpid {
+namespace log {
+namespace windows {
+
+namespace {
+
+// 'eventTypes' maps qpid log levels to Windows event types. They are in
+// order of qpid log levels and must map to:
+// "trace", "debug", "info", "notice", "warning", "error", "critical"
+static int eventTypes[qpid::log::LevelTraits::COUNT] = {
+ EVENTLOG_INFORMATION_TYPE, /* trace */
+ EVENTLOG_INFORMATION_TYPE, /* debug */
+ EVENTLOG_INFORMATION_TYPE, /* info */
+ EVENTLOG_INFORMATION_TYPE, /* notice */
+ EVENTLOG_WARNING_TYPE, /* warning */
+ EVENTLOG_ERROR_TYPE, /* error */
+ EVENTLOG_ERROR_TYPE /* critical */
+};
+
+} // namespace
+
+class EventLogOutput : public qpid::log::Logger::Output {
+public:
+ EventLogOutput(const std::string& /*sourceName*/) : logHandle(0)
+ {
+ logHandle = OpenEventLog(0, "Application");
+ }
+
+ virtual ~EventLogOutput() {
+ if (logHandle)
+ CloseEventLog(logHandle);
+ }
+
+ virtual void log(const Statement& s, const std::string& m)
+ {
+ if (logHandle) {
+ const char *msg = m.c_str();
+ ReportEvent(logHandle,
+ eventTypes[s.level],
+ 0, /* category unused */
+ 0, /* event id */
+ 0, /* user security id */
+ 1, /* number of strings */
+ 0, /* no event-specific data */
+ &msg,
+ 0);
+ }
+ }
+
+private:
+ HANDLE logHandle;
+};
+
+SinkOptions::SinkOptions(const std::string& /*argv0*/)
+ : qpid::log::SinkOptions(),
+ logToStderr(true),
+ logToStdout(false),
+ logToEventLog(false),
+ eventSource("Application")
+{
+ addOptions()
+ ("log-to-stderr", optValue(logToStderr, "yes|no"), "Send logging output to stderr")
+ ("log-to-stdout", optValue(logToStdout, "yes|no"), "Send logging output to stdout")
+ ("log-to-file", optValue(logFile, "FILE"), "Send log output to FILE.")
+ ("log-to-eventlog", optValue(logToEventLog, "yes|no"), "Send logging output to event log;\n\tcustomize using --syslog-name and --syslog-facility")
+ ("eventlog-source-name", optValue(eventSource, "Application"), "Event source to log to")
+ ;
+
+}
+
+qpid::log::SinkOptions& SinkOptions::operator=(const qpid::log::SinkOptions& rhs) {
+ const SinkOptions *prhs = dynamic_cast<const SinkOptions*>(&rhs);
+ if (this != prhs) {
+ logToStderr = prhs->logToStderr;
+ logToStdout = prhs->logToStdout;
+ logToEventLog = prhs->logToEventLog;
+ eventSource = prhs->eventSource;
+ logFile = prhs->logFile;
+ }
+ return *this;
+}
+
+void SinkOptions::detached(void) {
+ if (logToStderr && !logToStdout && !logToEventLog) {
+ logToStderr = false;
+ logToEventLog = true;
+ }
+}
+
+// The Logger acting on these options calls setup() to request any
+// Sinks be set up and fed back to the logger.
+void SinkOptions::setup(qpid::log::Logger *logger) {
+ if (logToStderr)
+ logger->output(make_auto_ptr<qpid::log::Logger::Output>
+ (new qpid::log::OstreamOutput(std::clog)));
+ if (logToStdout)
+ logger->output(make_auto_ptr<qpid::log::Logger::Output>
+ (new qpid::log::OstreamOutput(std::cout)));
+
+ if (logFile.length() > 0)
+ logger->output(make_auto_ptr<qpid::log::Logger::Output>
+ (new qpid::log::OstreamOutput(logFile)));
+
+ if (logToEventLog)
+ logger->output(make_auto_ptr<qpid::log::Logger::Output>
+ (new EventLogOutput(eventSource)));
+
+}
+
+} // namespace windows
+
+SinkOptions* SinkOptions::create(const std::string& argv0) {
+ return new qpid::log::windows::SinkOptions (argv0);
+}
+
+}} // namespace qpid::log
diff --git a/qpid/cpp/src/qpid/log/windows/SinkOptions.h b/qpid/cpp/src/qpid/log/windows/SinkOptions.h
new file mode 100644
index 0000000000..f270c504a2
--- /dev/null
+++ b/qpid/cpp/src/qpid/log/windows/SinkOptions.h
@@ -0,0 +1,54 @@
+#ifndef QPID_LOG_WINDOWS_SINKOPTIONS_H
+#define QPID_LOG_WINDOWS_SINKOPTIONS_H
+
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * Licensed 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/SinkOptions.h"
+#include <string>
+
+namespace qpid {
+namespace log {
+namespace windows {
+
+struct QPID_COMMON_CLASS_EXTERN SinkOptions : public qpid::log::SinkOptions {
+ QPID_COMMON_EXTERN SinkOptions(const std::string& argv0);
+ virtual ~SinkOptions() {}
+
+ QPID_COMMON_EXTERN virtual qpid::log::SinkOptions& operator=(const qpid::log::SinkOptions& rhs);
+
+ // This allows the caller to indicate that there's no normal outputs
+ // available. For example, when running as a service. In these cases, the
+ // platform's "syslog"-type output should replace the default stderr
+ // unless some other sink has been selected.
+ QPID_COMMON_EXTERN virtual void detached(void);
+
+ // The Logger acting on these options calls setup() to request any
+ // Sinks be set up and fed back to the logger.
+ QPID_COMMON_EXTERN virtual void setup(qpid::log::Logger *logger);
+
+ bool logToStderr;
+ bool logToStdout;
+ bool logToEventLog;
+ std::string eventSource;
+ std::string logFile;
+};
+
+}}} // namespace qpid::log::windows
+
+#endif /*!QPID_LOG_WINDOWS_SINKOPTIONS_H*/