From b146052ebb800c7aa7af3ebae5db54de4d606350 Mon Sep 17 00:00:00 2001 From: g0dil <g0dil@wiback.org> Date: Thu, 1 Nov 2007 11:35:47 +0000 Subject: [PATCH] Utils/Logger: Implement TimeSource facility Utils/Logger: Add Alias documentation Scheduler: Add scheduler based logger time source --- Scheduler/Scheduler.cc | 9 +++++++ Scheduler/Scheduler.hh | 12 ++++++++++ Utils/Logger/Config.hh | 20 +++++++++++++--- Utils/Logger/Log.hh | 25 +++++++++++++++++--- Utils/Logger/Target.cc | 16 ++++++++----- Utils/Logger/Target.cci | 27 +++++++++++++++++++++ Utils/Logger/Target.cti | 6 +++++ Utils/Logger/Target.hh | 52 ++++++++++++++++++++++++++++++++++++++--- Utils/Logger/Target.ih | 8 +++++++ 9 files changed, 160 insertions(+), 15 deletions(-) diff --git a/Scheduler/Scheduler.cc b/Scheduler/Scheduler.cc index 09971a84e..adbb6a6b5 100644 --- a/Scheduler/Scheduler.cc +++ b/Scheduler/Scheduler.cc @@ -243,6 +243,15 @@ prefix_ void senf::Scheduler::process() } } +/////////////////////////////////////////////////////////////////////////// +// senf::SchedulerLogTimeSource + +prefix_ boost::posix_time::ptime senf::SchedulerLogTimeSource::operator()() + const +{ + return ClockService::abstime(Scheduler::instance().eventTime()); +} + ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_ diff --git a/Scheduler/Scheduler.hh b/Scheduler/Scheduler.hh index 3ec8147a2..babc1997e 100644 --- a/Scheduler/Scheduler.hh +++ b/Scheduler/Scheduler.hh @@ -35,6 +35,7 @@ #include <boost/call_traits.hpp> #include <boost/integer.hpp> #include "ClockService.hh" +#include "../Utils/Logger/Target.hh" //#include "scheduler.mpp" ///////////////////////////////hh.p//////////////////////////////////////// @@ -239,6 +240,17 @@ namespace senf { */ int retrieve_filehandle(int fd); + /** \brief Scheduler specific time source for Utils/Logger framework + + This time source may be used to provide timing information for log messages within the + Utils/Logger framework. This time source will use Scheduler::eventTime() to provide timing + information. + */ + struct SchedulerLogTimeSource : public senf::log::TimeSource + { + boost::posix_time::ptime operator()() const; + }; + } ///////////////////////////////hh.e//////////////////////////////////////// diff --git a/Utils/Logger/Config.hh b/Utils/Logger/Config.hh index 8e5503011..634d72326 100644 --- a/Utils/Logger/Config.hh +++ b/Utils/Logger/Config.hh @@ -65,6 +65,8 @@ \c foo::SomeClass area, where it is set to \c VERBOSE. Furthermore, the limit on the \c foo::Transactions stream is set to \c NOTICE. + \see \ref SENF_LOG_CONF + \section config_runtime Runtime configuration The runtime configuration is performed by routing messages to one or more logging targets: @@ -85,9 +87,21 @@ The routing statements are processed by the targets in order, the first matching rule will decide a log messages fate for that target. - \see - \ref SENF_LOG_CONF compile time configuration \n - \ref senf::log::Target runtime configuration + \see \ref senf::log::Target + + \section config_timesource Log message timing + + One auxiliary aspect of logging is message timing. Each message is stamped with a time-stamp + giving the exact time the message was created. How the current date/time value is created may be + changed by setting a \e TimeSource. A TimeSource is an instance derived from + senf::log::TimeSource which will return the current universal time (UTC) when called. + + By default, the logging library will call gettimeofday() for each log message. To change the + time source, just pass the new class or instance to senf::log::timeSource: + \code + // Use senf::Scheduler::instance().eventTime() to time log messages + senf::log::timeSource<senf::SchedulerLogTimeSource>(); + \endcode */ namespace senf { diff --git a/Utils/Logger/Log.hh b/Utils/Logger/Log.hh index 028d14eff..33d9ad387 100644 --- a/Utils/Logger/Log.hh +++ b/Utils/Logger/Log.hh @@ -62,15 +62,34 @@ This current default value is set using \ref SENF_LOG_DEFAULT_STREAM, \ref SENF_LOG_DEFAULT_AREA and \ref SENF_LOG_DEFAULT_LEVEL respectively. These macros set the default stream, area and/or - level of the current scope. The logging library defines the global defaults for these values to - be \c senf::log::Debug (\e stream), senf::log::DefaultArea (\e area), and senf::log::NONE (\e - level). + level <em>of the current scope</em>. They may be used with a class declaration to set defaults + for all class members or within a function or member body to set the default for that member + only. They may be used only \e once within each scope. + + The logging library defines the global defaults for stream, area and level to be \c + senf::log::Debug, senf::log::DefaultArea, and senf::log::NONE respectively. The log level senf::log::NONE is special. If the log level is set to this value, the log level will be set from the stream provided default value. All these parameters must be <em>compile time constants</em> (they are all types, so it's difficult form them to be something else). + + \section logging_aliases Aliases + + To further simplify logging commands, aliases may be defined within any scope. An alias is an + arbitrary collection of log parameters: + \code + SENF_LOG_DEF_ALIAS( VerboseDebug, (senf::log::Debug)(senf::log::VERBOSE) ); + \endcode + Within log statements, aliases may be used like normal parameters. They will be substituted for + the parameter sequence they represent: + \code + SENF_LOG( (VerboseDebug)("Debug message") ) + // is equivalent to + SENF_LOG( (senf::log::Debug)(senf::log::VERBOSE)("Debug message") ) + \endcode + Aliases may be used together with other parameters, even with further aliases in any order. */ ///\ingroup logging diff --git a/Utils/Logger/Target.cc b/Utils/Logger/Target.cc index 3c32f95b5..01864ec65 100644 --- a/Utils/Logger/Target.cc +++ b/Utils/Logger/Target.cc @@ -199,14 +199,18 @@ prefix_ void senf::log::Target::write(boost::posix_time::ptime timestamp, } /////////////////////////////////////////////////////////////////////////// -// senf::log::TargetRegistry +// senf::log::TimeSource -prefix_ void senf::log::detail::TargetRegistry::write(StreamBase const & stream, - AreaBase const & area, unsigned level, - std::string msg) +prefix_ senf::log::TimeSource::~TimeSource() +{} + +/////////////////////////////////////////////////////////////////////////// +// senf::log::SystemTimeSource + +prefix_ boost::posix_time::ptime senf::log::SystemTimeSource::operator()() + const { - boost::posix_time::ptime timestamp (boost::posix_time::microsec_clock::universal_time()); - area.write(timestamp, stream, level, msg); + return boost::posix_time::microsec_clock::universal_time(); } ///////////////////////////////cc.e//////////////////////////////////////// diff --git a/Utils/Logger/Target.cci b/Utils/Logger/Target.cci index e7b240922..da1ee4ed7 100644 --- a/Utils/Logger/Target.cci +++ b/Utils/Logger/Target.cci @@ -94,6 +94,25 @@ prefix_ senf::log::Target::action_t senf::log::Target::RoutingEntry::action() /////////////////////////////////////////////////////////////////////////// // senf::log::detail::TargetRegistry +prefix_ void senf::log::detail::TargetRegistry::write(StreamBase const & stream, + AreaBase const & area, unsigned level, + std::string msg) +{ + area.write((*timeSource_)(), stream, level, msg); +} + +prefix_ void senf::log::detail::TargetRegistry::timeSource(std::auto_ptr<TimeSource> source) +{ + timeSource_.reset(source.release()); +} + +//////////////////////////////////////// +// private members + +prefix_ senf::log::detail::TargetRegistry::TargetRegistry() + : timeSource_(new SystemTimeSource()) +{} + prefix_ void senf::log::detail::TargetRegistry::registerTarget(Target * target) { targets_.insert(target); @@ -104,6 +123,14 @@ prefix_ void senf::log::detail::TargetRegistry::unregisterTarget(Target * target targets_.erase(target); } +/////////////////////////////////////////////////////////////////////////// +// namespace senf::log members + +prefix_ void senf::log::timeSource(std::auto_ptr<TimeSource> source) +{ + detail::TargetRegistry::instance().timeSource(source); +} + /////////////////////////////cci.e/////////////////////////////////////// #undef prefix_ diff --git a/Utils/Logger/Target.cti b/Utils/Logger/Target.cti index ccc364d4d..0f7e287ff 100644 --- a/Utils/Logger/Target.cti +++ b/Utils/Logger/Target.cti @@ -143,6 +143,12 @@ prefix_ void senf::log::detail::write(std::string msg) TargetRegistry::instance().write(Stream::instance(), Area::instance(), Level::value, msg); } +template <class Source> +prefix_ void senf::log::timeSource() +{ + timeSource(std::auto_ptr<Source>(new Source())); +} + ///////////////////////////////cti.e/////////////////////////////////////// #undef prefix_ diff --git a/Utils/Logger/Target.hh b/Utils/Logger/Target.hh index 02226ca89..c5ac36869 100644 --- a/Utils/Logger/Target.hh +++ b/Utils/Logger/Target.hh @@ -119,9 +119,6 @@ namespace log { cases messages might be lost but this cannot be avoided. \see \ref targets - - \fixme optionally Integrate with Scheduler / ClockService to reduce number of gettimeofday() - calls. */ class Target : private boost::noncopyable { @@ -401,6 +398,55 @@ namespace log { friend class detail::AreaBase; }; + /** \brief Log message time source abstract base class + + Instances derived from TimeSource provide the Logging library with the current date/time + value. The \c operator() member must be implemented to return the current universal time + (UTC). + + A new TimeSource may be installed using \ref senf::log::timeSource(). + + \ingroup config + */ + struct TimeSource + { + virtual ~TimeSource(); + virtual boost::posix_time::ptime operator()() const = 0; + }; + + /** \brief Default log message time source + + This time source is installed by default and uses gettimeofday() (via the Boost.DateTime + library) to get the current universal time. + + \ingroup config + */ + struct SystemTimeSource : public TimeSource + { + virtual boost::posix_time::ptime operator()() const; + }; + + /** \brief Change log message time source + + Set the log message time source to \a source. The logging library will take ownership of \e + source and will take care to free it, if necessary. + + Since the time source class will in almost all cases be default constructible, see the + template overload for a simpler interface. + + \ingroup config + */ + void timeSource(std::auto_ptr<TimeSource> source); + + /** \brief Change log message time source + + Set the log message time source to (an instance of) \a Source. \a Source must be default + constructible, otherwise use the non-template senf::log::timeSource() overload. + + \ingroup config + */ + template <class Source> void timeSource(); + }} ///////////////////////////////hh.e//////////////////////////////////////// diff --git a/Utils/Logger/Target.ih b/Utils/Logger/Target.ih index 115c71ed1..0506fc5d2 100644 --- a/Utils/Logger/Target.ih +++ b/Utils/Logger/Target.ih @@ -27,6 +27,8 @@ #define IH_Target_ 1 // Custom includes +#include <memory> +#include <boost/scoped_ptr.hpp> ///////////////////////////////ih.p//////////////////////////////////////// @@ -44,14 +46,20 @@ namespace detail { void write(StreamBase const & stream, AreaBase const & area, unsigned level, std::string msg); + void timeSource(std::auto_ptr<TimeSource> source); + private: + TargetRegistry(); + void registerTarget(Target * target); void unregisterTarget(Target * target); typedef std::set<Target *> Targets; Targets targets_; + boost::scoped_ptr<TimeSource> timeSource_; friend class senf::log::Target; + friend class senf::singleton<TargetRegistry>; }; /** \brief Internal: Write log message */ -- GitLab