Utils/Logger: Implement TimeSource facility
g0dil [Thu, 1 Nov 2007 11:35:47 +0000 (11:35 +0000)]
Utils/Logger: Add Alias documentation
Scheduler: Add scheduler based logger time source

git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@490 270642c3-0616-0410-b53a-bc976706d245

Scheduler/Scheduler.cc
Scheduler/Scheduler.hh
Utils/Logger/Config.hh
Utils/Logger/Log.hh
Utils/Logger/Target.cc
Utils/Logger/Target.cci
Utils/Logger/Target.cti
Utils/Logger/Target.hh
Utils/Logger/Target.ih

index 09971a8..adbb6a6 100644 (file)
@@ -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_
 
index 3ec8147..babc199 100644 (file)
@@ -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////////////////////////////////////////
index 8e55030..634d723 100644 (file)
@@ -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:
     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 {
index 028d14e..33d9ad3 100644 (file)
 
     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
index 3c32f95..01864ec 100644 (file)
@@ -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////////////////////////////////////////
index e7b2409..da1ee4e 100644 (file)
@@ -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_
 
index ccc364d..0f7e287 100644 (file)
@@ -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_
 
index 02226ca..c5ac368 100644 (file)
@@ -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////////////////////////////////////////
index 115c71e..0506fc5 100644 (file)
@@ -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 */