summaryrefslogtreecommitdiff
path: root/cpp/src/qpid/log
diff options
context:
space:
mode:
authorRafael H. Schloming <rhs@apache.org>2009-12-26 12:42:57 +0000
committerRafael H. Schloming <rhs@apache.org>2009-12-26 12:42:57 +0000
commit248f1fe188fe2307b9dcf2c87a83b653eaa1920c (patch)
treed5d0959a70218946ff72e107a6c106e32479a398 /cpp/src/qpid/log
parent3c83a0e3ec7cf4dc23e83a340b25f5fc1676f937 (diff)
downloadqpid-python-248f1fe188fe2307b9dcf2c87a83b653eaa1920c.tar.gz
synchronized with trunk except for ruby dir
git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/qpid.rnr@893970 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/src/qpid/log')
-rw-r--r--cpp/src/qpid/log/Logger.cpp92
-rw-r--r--cpp/src/qpid/log/Logger.h117
-rw-r--r--cpp/src/qpid/log/Options.cpp148
-rw-r--r--cpp/src/qpid/log/Options.h56
-rw-r--r--cpp/src/qpid/log/OstreamOutput.cpp41
-rw-r--r--cpp/src/qpid/log/OstreamOutput.h41
-rw-r--r--cpp/src/qpid/log/Selector.cpp10
-rw-r--r--cpp/src/qpid/log/Selector.h70
-rw-r--r--cpp/src/qpid/log/Statement.cpp14
-rw-r--r--cpp/src/qpid/log/Statement.h128
-rw-r--r--cpp/src/qpid/log/posix/SinkOptions.cpp215
-rw-r--r--cpp/src/qpid/log/posix/SinkOptions.h64
-rw-r--r--cpp/src/qpid/log/windows/SinkOptions.cpp148
-rw-r--r--cpp/src/qpid/log/windows/SinkOptions.h54
14 files changed, 630 insertions, 568 deletions
diff --git a/cpp/src/qpid/log/Logger.cpp b/cpp/src/qpid/log/Logger.cpp
index 54df54bb94..939e2502cc 100644
--- a/cpp/src/qpid/log/Logger.cpp
+++ b/cpp/src/qpid/log/Logger.cpp
@@ -16,20 +16,19 @@
*
*/
-#include "Logger.h"
-#include "Options.h"
+#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 <boost/pool/detail/singleton.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>
-#include <boost/scoped_ptr.hpp>
#include <algorithm>
#include <sstream>
-#include <fstream>
#include <iomanip>
#include <stdexcept>
-#include <syslog.h>
#include <time.h>
@@ -44,45 +43,6 @@ inline void Logger::enable_unlocked(Statement* s) {
s->enabled=selector.isEnabled(s->level, s->function);
}
-struct OstreamOutput : public Logger::Output {
- OstreamOutput(std::ostream& o) : out(&o) {}
-
- OstreamOutput(const 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 log(const Statement&, const std::string& m) {
- *out << m << flush;
- }
-
- ostream* out;
- boost::scoped_ptr<ostream> mine;
-};
-
-struct SyslogOutput : public Logger::Output {
- SyslogOutput(const Options& opts)
- : name(opts.syslogName), facility(opts.syslogFacility.value)
- {
- ::openlog(name.c_str(), LOG_PID, facility);
- }
-
- ~SyslogOutput() {
- ::closelog();
- }
-
- void log(const Statement& s, const std::string& m)
- {
- syslog(LevelTraits::priority(s.level), "%s", m.c_str());
- }
-
- std::string name;
- int facility;
-};
-
Logger& Logger::instance() {
return boost::details::pool::singleton_default<Logger>::instance();
}
@@ -114,25 +74,7 @@ void Logger::log(const Statement& s, const std::string& msg) {
if (!prefix.empty())
os << prefix << ": ";
if (flags&TIME)
- {
- const char * month_abbrevs[] = { "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec" };
- time_t rawtime;
- struct tm * timeinfo;
-
- time ( & rawtime );
- timeinfo = localtime ( &rawtime );
- char time_string[100];
- sprintf ( time_string,
- "%d-%s-%02d %02d:%02d:%02d",
- 1900 + timeinfo->tm_year,
- month_abbrevs[timeinfo->tm_mon],
- timeinfo->tm_mday,
- timeinfo->tm_hour,
- timeinfo->tm_min,
- timeinfo->tm_sec
- );
- os << time_string << " ";
- }
+ qpid::sys::outputFormattedNow(os);
if (flags&LEVEL)
os << LevelTraits::name(s.level) << " ";
if (flags&THREAD)
@@ -159,25 +101,6 @@ void Logger::output(std::auto_ptr<Output> out) {
outputs.push_back(out.release());
}
-void Logger::output(std::ostream& out) {
- output(make_auto_ptr<Output>(new OstreamOutput(out)));
-}
-
-void Logger::syslog(const Options& opts) {
- output(make_auto_ptr<Output>(new SyslogOutput(opts)));
-}
-
-void Logger::output(const std::string& name, const Options& opts) {
- if (name=="stderr")
- output(clog);
- else if (name=="stdout")
- output(cout);
- else if (name=="syslog")
- syslog(opts);
- else
- output(make_auto_ptr<Output>(new OstreamOutput(name)));
-}
-
void Logger::clear() {
select(Selector()); // locked
format(0); // locked
@@ -212,16 +135,15 @@ void Logger::add(Statement& s) {
}
void Logger::configure(const Options& opts) {
+ options = opts;
clear();
Options o(opts);
if (o.trace)
o.selectors.push_back("trace+");
format(o);
select(Selector(o));
- void (Logger::* outputFn)(const std::string&, const Options&) = &Logger::output;
- for_each(o.outputs.begin(), o.outputs.end(),
- boost::bind(outputFn, this, _1, boost::cref(o)));
setPrefix(opts.prefix);
+ options.sinkOptions->setup(this);
}
void Logger::setPrefix(const std::string& p) { prefix = p; }
diff --git a/cpp/src/qpid/log/Logger.h b/cpp/src/qpid/log/Logger.h
deleted file mode 100644
index fa38678bba..0000000000
--- a/cpp/src/qpid/log/Logger.h
+++ /dev/null
@@ -1,117 +0,0 @@
-#ifndef LOGGER_H
-#define 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 "Selector.h"
-#include "qpid/sys/Mutex.h"
-#include <boost/ptr_container/ptr_vector.hpp>
-#include <boost/noncopyable.hpp>
-#include <set>
-
-namespace qpid {
-namespace log {
-
-class Options;
-
-/**
- * Central logging agent.
- *
- * Thread safe, singleton.
- */
-class 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};
-
- /** Interface for log output destination.
- *
- * Implementations must be thread safe.
- */
- class Output {
- public:
- Output();
- virtual ~Output();
- /** Receives the statemnt of origin and formatted message to log. */
- virtual void log(const Statement&, const std::string&) =0;
- };
-
- static Logger& instance();
-
- Logger();
- ~Logger();
-
- /** Select the messages to be logged. */
- void select(const Selector& s);
-
- /** Set the formatting flags, bitwise OR of FormatFlag values. */
- void format(int formatFlags);
-
- /** Set format flags from options object.
- *@returns computed flags.
- */
- int format(const Options&);
-
- /** Configure logger from Options */
- void configure(const Options& o);
-
- /** Add a statement. */
- void add(Statement& s);
-
- /** Log a message. */
- void log(const Statement&, const std::string&);
-
- /** Add an ostream to outputs.
- *
- * The ostream must not be destroyed while the Logger might
- * still be using it. This is the case for std streams cout,
- * cerr, clog.
- */
- void output(std::ostream&);
-
- /** Add syslog to outputs. */
- void syslog(const Options&);
-
- /** Add an output.
- *@param name a file name or one of the special tokens:
- *stdout, stderr, syslog.
- */
- void output(const std::string& name, const Options&);
-
- /** Add an output destination for messages */
- void output(std::auto_ptr<Output> out);
-
- /** Set a prefix for all messages */
- void setPrefix(const std::string& prefix);
-
- /** Reset the logger to it's original state. */
- void clear();
-
-
- 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;
-};
-
-}} // namespace qpid::log
-
-
-#endif /*!LOGGER_H*/
diff --git a/cpp/src/qpid/log/Options.cpp b/cpp/src/qpid/log/Options.cpp
index e28f82648e..24ef413cbc 100644
--- a/cpp/src/qpid/log/Options.cpp
+++ b/cpp/src/qpid/log/Options.cpp
@@ -16,116 +16,39 @@
*
*/
-#include "Options.h"
-#include "Statement.h"
+#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>
-#include <syslog.h>
namespace qpid {
namespace log {
using namespace std;
-namespace {
-
-class SyslogFacilities {
- public:
- typedef map<string, int> ByName;
- typedef map<int, string> ByValue;
-
- SyslogFacilities() {
- struct NameValue { const char* name; int value; };
- NameValue nameValue[] = {
- { "AUTH", LOG_AUTH },
- { "AUTHPRIV", LOG_AUTHPRIV },
- { "CRON", LOG_CRON },
- { "DAEMON", LOG_DAEMON },
- { "FTP", LOG_FTP },
- { "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);
- 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: " + value);
- return i->second;
- }
-
- private:
- ByName byName;
- ByValue byValue;
-};
-
-}
-
-ostream& operator<<(ostream& o, const SyslogFacility& f) {
- return o << SyslogFacilities().name(f.value);
-}
-
-istream& operator>>(istream& i, SyslogFacility& f) {
- std::string name;
- i >> name;
- f.value = SyslogFacilities().value(name);
- return i;
-}
-
-namespace {
-std::string basename(const std::string path) {
- size_t i = path.find_last_of('/');
- return path.substr((i == std::string::npos) ? 0 : i+1);
-}
-}
-
-Options::Options(const std::string& argv0, const std::string& name) :
- qpid::Options(name),
- time(true), level(true), thread(false), source(false), function(false), trace(false),
- syslogName(basename(argv0)), syslogFacility(LOG_DAEMON)
+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),
+ trace(false),
+ sinkOptions (SinkOptions::create(argv0_))
{
- outputs.push_back("stderr");
- selectors.push_back("error+");
+ selectors.push_back("notice+");
ostringstream levels;
levels << LevelTraits::name(Level(0));
for (int i = 1; i < LevelTraits::COUNT; ++i)
levels << " " << LevelTraits::name(Level(i));
-
+
addOptions()
- ("log-output", optValue(outputs, "FILE"), "Send log output to FILE. "
- "FILE can be a file name or one of the special values:\n"
- "stderr, stdout, syslog")
("trace,t", optValue(trace), "Enables all logging" )
("log-enable", optValue(selectors, "RULE"),
("Enables logging for selected levels and components. "
@@ -143,9 +66,42 @@ Options::Options(const std::string& argv0, const std::string& name) :
("log-thread", optValue(thread,"yes|no"), "Include thread ID in log messages")
("log-function", optValue(function,"yes|no"), "Include function signature in log messages")
("log-prefix", optValue(prefix,"STRING"), "Prefix to append to all log messages")
- ("syslog-name", optValue(syslogName, "NAME"), "Name to use in syslog messages")
- ("syslog-facility", optValue(syslogFacility,"LOG_XXX"), "Facility to use in syslog messages")
;
-}
+ add(*sinkOptions);
+}
+
+Options::Options(const Options &o) :
+ qpid::Options(o.name),
+ argv0(o.argv0),
+ name(o.name),
+ selectors(o.selectors),
+ time(o.time),
+ level(o.level),
+ thread(o.thread),
+ source(o.source),
+ function(o.function),
+ 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;
+ time = x.time;
+ level= x.level;
+ thread = x.thread;
+ source = x.source;
+ function = x.function;
+ trace = x.trace;
+ prefix = x.prefix;
+ *sinkOptions = *x.sinkOptions;
+ }
+ return *this;
+}
}} // namespace qpid::log
diff --git a/cpp/src/qpid/log/Options.h b/cpp/src/qpid/log/Options.h
deleted file mode 100644
index 13fca38f9d..0000000000
--- a/cpp/src/qpid/log/Options.h
+++ /dev/null
@@ -1,56 +0,0 @@
-#ifndef OPTIONS_H
-#define 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 <iosfwd>
-
-namespace qpid {
-namespace log {
-
-/** Provides << and >> operators to convert syslog facility values to/from strings. */
-struct SyslogFacility {
- int value;
- SyslogFacility(int i=0) : value(i) {}
-};
-
-std::ostream& operator<<(std::ostream&, const SyslogFacility&);
-std::istream& operator>>(std::istream&, SyslogFacility&);
-
-/** Logging options for config parser. */
-struct Options : public qpid::Options {
- /** Pass argv[0] for use in syslog output */
- Options(const std::string& argv0,
- const std::string& name="Logging options");
-
- std::vector<std::string> selectors;
- std::vector<std::string> outputs;
- bool time, level, thread, source, function;
- bool trace;
- std::string syslogName;
- SyslogFacility syslogFacility;
- std::string prefix;
-};
-
-
-}} // namespace qpid::log
-
-
-
-#endif /*!OPTIONS_H*/
diff --git a/cpp/src/qpid/log/OstreamOutput.cpp b/cpp/src/qpid/log/OstreamOutput.cpp
new file mode 100644
index 0000000000..9b6ec1f8aa
--- /dev/null
+++ b/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/cpp/src/qpid/log/OstreamOutput.h b/cpp/src/qpid/log/OstreamOutput.h
new file mode 100644
index 0000000000..12fd4ce425
--- /dev/null
+++ b/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/cpp/src/qpid/log/Selector.cpp b/cpp/src/qpid/log/Selector.cpp
index 994421d0ff..a4bc580470 100644
--- a/cpp/src/qpid/log/Selector.cpp
+++ b/cpp/src/qpid/log/Selector.cpp
@@ -16,10 +16,11 @@
*
*/
-#include "Selector.h"
-#include "Options.h"
+#include "qpid/log/Selector.h"
+#include "qpid/log/Options.h"
#include <boost/bind.hpp>
#include <algorithm>
+#include <string.h>
namespace qpid {
namespace log {
@@ -52,12 +53,13 @@ Selector::Selector(const Options& opt){
boost::bind(&Selector::enable, this, _1));
}
-bool Selector::isEnabled(Level level, const std::string& function) {
+bool Selector::isEnabled(Level level, const char* function) {
+ const char* functionEnd = function+::strlen(function);
for (std::vector<std::string>::iterator i=substrings[level].begin();
i != substrings[level].end();
++i)
{
- if (function.find(*i) != std::string::npos)
+ if (std::search(function, functionEnd, i->begin(), i->end()) != functionEnd)
return true;
}
return false;
diff --git a/cpp/src/qpid/log/Selector.h b/cpp/src/qpid/log/Selector.h
deleted file mode 100644
index 7c98bc6f8f..0000000000
--- a/cpp/src/qpid/log/Selector.h
+++ /dev/null
@@ -1,70 +0,0 @@
-#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 "Statement.h"
-#include <vector>
-
-namespace qpid {
-namespace log {
-class Options;
-
-/**
- * A selector identifies the set of log messages to enable.
- *
- * Thread object unsafe, pass-by-value type.
- */
-class Selector {
- public:
- /** Empty selector selects nothing */
- Selector() {}
-
- /** Set selector from Options */
- Selector(const Options&);
-
- /** Equavlient to: Selector s; s.enable(l, s) */
- Selector(Level l, const std::string& s=std::string()) {
- enable(l,s);
- }
-
- Selector(const std::string& enableStr) { enable(enableStr); }
- /**
- * Enable messages with level in levels where the file
- * name contains substring. Empty string matches all.
- */
- void enable(Level level, const std::string& substring=std::string()) {
- substrings[level].push_back(substring);
- }
-
- /** Enable based on a 'level[+]:file' string */
- void enable(const std::string& enableStr);
-
- /** True if level is enabld for file. */
- bool isEnabled(Level level, const std::string& function);
-
- private:
- std::vector<std::string> substrings[LevelTraits::COUNT];
-};
-
-
-}} // namespace qpid::log
-
-
-#endif /*!SELECTOR_H*/
diff --git a/cpp/src/qpid/log/Statement.cpp b/cpp/src/qpid/log/Statement.cpp
index c2b286f1e7..6a32b50096 100644
--- a/cpp/src/qpid/log/Statement.cpp
+++ b/cpp/src/qpid/log/Statement.cpp
@@ -16,12 +16,11 @@
*
*/
-#include "Statement.h"
-#include "Logger.h"
+#include "qpid/log/Statement.h"
+#include "qpid/log/Logger.h"
#include <boost/bind.hpp>
#include <stdexcept>
#include <algorithm>
-#include <syslog.h>
#include <ctype.h>
namespace qpid {
@@ -67,11 +66,6 @@ const char* names[LevelTraits::COUNT] = {
"trace", "debug", "info", "notice", "warning", "error", "critical"
};
-int priorities[LevelTraits::COUNT] = {
- LOG_DEBUG, LOG_DEBUG, LOG_INFO, LOG_NOTICE,
- LOG_WARNING, LOG_ERR, LOG_CRIT
-};
-
} // namespace
Level LevelTraits::level(const char* name) {
@@ -86,8 +80,4 @@ const char* LevelTraits::name(Level l) {
return names[l];
}
-int LevelTraits::priority(Level l) {
- return priorities[l];
-}
-
}} // namespace qpid::log
diff --git a/cpp/src/qpid/log/Statement.h b/cpp/src/qpid/log/Statement.h
deleted file mode 100644
index f765df1cf4..0000000000
--- a/cpp/src/qpid/log/Statement.h
+++ /dev/null
@@ -1,128 +0,0 @@
-#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 <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);
-
- /** Syslog priority of level */
- static int priority(Level);
-};
-
-/** POD struct representing a logging statement in source code. */
-struct Statement {
- bool enabled;
- const char* file;
- int line;
- const char* function;
- Level level;
-
- void log(const std::string& message);
-
- struct Initializer {
- Initializer(Statement& s);
- Statement& statement;
- };
-};
-
-///@internal static initializer for a Statement.
-#define QPID_LOG_STATEMENT_INIT(level) \
- { 0, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, (::qpid::log::level) }
-
-/**
- * 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)
-
-/**
- * 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
- *
- * All code with logging statements should be built with
- * -DQPID_COMPONENT=<component name>
- * where component name is the name of the component this file belongs to.
- *
- * 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);
-
-}} // namespace qpid::log
-
-
-
-
-#endif /*!STATEMENT_H*/
-
diff --git a/cpp/src/qpid/log/posix/SinkOptions.cpp b/cpp/src/qpid/log/posix/SinkOptions.cpp
new file mode 100644
index 0000000000..292e9147f6
--- /dev/null
+++ b/cpp/src/qpid/log/posix/SinkOptions.cpp
@@ -0,0 +1,215 @@
+/*
+ *
+ * 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/memory.h"
+#include "qpid/Exception.h"
+#include <iostream>
+#include <map>
+#include <string>
+#include <syslog.h>
+
+using std::string;
+using qpid::Exception;
+
+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: " + 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
+
+namespace qpid {
+namespace log {
+namespace posix {
+
+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) {
+ 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/cpp/src/qpid/log/posix/SinkOptions.h b/cpp/src/qpid/log/posix/SinkOptions.h
new file mode 100644
index 0000000000..d929c29025
--- /dev/null
+++ b/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/cpp/src/qpid/log/windows/SinkOptions.cpp b/cpp/src/qpid/log/windows/SinkOptions.cpp
new file mode 100644
index 0000000000..28f4b267e0
--- /dev/null
+++ b/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/cpp/src/qpid/log/windows/SinkOptions.h b/cpp/src/qpid/log/windows/SinkOptions.h
new file mode 100644
index 0000000000..605822fd46
--- /dev/null
+++ b/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 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*/