diff options
| author | Rafael H. Schloming <rhs@apache.org> | 2009-12-26 12:42:57 +0000 |
|---|---|---|
| committer | Rafael H. Schloming <rhs@apache.org> | 2009-12-26 12:42:57 +0000 |
| commit | 248f1fe188fe2307b9dcf2c87a83b653eaa1920c (patch) | |
| tree | d5d0959a70218946ff72e107a6c106e32479a398 /cpp/src/qpid/log | |
| parent | 3c83a0e3ec7cf4dc23e83a340b25f5fc1676f937 (diff) | |
| download | qpid-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.cpp | 92 | ||||
| -rw-r--r-- | cpp/src/qpid/log/Logger.h | 117 | ||||
| -rw-r--r-- | cpp/src/qpid/log/Options.cpp | 148 | ||||
| -rw-r--r-- | cpp/src/qpid/log/Options.h | 56 | ||||
| -rw-r--r-- | cpp/src/qpid/log/OstreamOutput.cpp | 41 | ||||
| -rw-r--r-- | cpp/src/qpid/log/OstreamOutput.h | 41 | ||||
| -rw-r--r-- | cpp/src/qpid/log/Selector.cpp | 10 | ||||
| -rw-r--r-- | cpp/src/qpid/log/Selector.h | 70 | ||||
| -rw-r--r-- | cpp/src/qpid/log/Statement.cpp | 14 | ||||
| -rw-r--r-- | cpp/src/qpid/log/Statement.h | 128 | ||||
| -rw-r--r-- | cpp/src/qpid/log/posix/SinkOptions.cpp | 215 | ||||
| -rw-r--r-- | cpp/src/qpid/log/posix/SinkOptions.h | 64 | ||||
| -rw-r--r-- | cpp/src/qpid/log/windows/SinkOptions.cpp | 148 | ||||
| -rw-r--r-- | cpp/src/qpid/log/windows/SinkOptions.h | 54 |
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*/ |
