Missing files ...
[senf.git] / Utils / Logger / Target.hh
index 664f5b2..dbbad15 100644 (file)
 /** \file
     \brief Target public header */
 
-#ifndef HH_Target_
-#define HH_Target_ 1
+#ifndef HH_SENF_Utils_Logger_Target_
+#define HH_SENF_Utils_Logger_Target_ 1
 
 // Custom includes
 #include <set>
-#include <boost/date_time/posix_time/posix_time.hpp>
+#include <vector>
 #include <boost/utility.hpp>
 #include <boost/type_traits/is_convertible.hpp>
 #include "../singleton.hh"
 #include "../mpl.hh"
 #include "StreamRegistry.hh"
-#include "AreaRegistry.hh"
 #include "../Exception.hh"
+#include "TimeSource.hh"
+#include "../Console/LazyDirectory.hh"
 
 //#include "Target.mpp"
 ///////////////////////////////hh.p////////////////////////////////////////
 
 namespace senf {
 namespace log {
-    
+
     namespace detail { class TargetRegistry; }
+    namespace detail { class AreaBase; }
+    namespace detail { struct LogParameters; }
 
     /** \brief Logging target base class
-        
-        Targets are the final destination of %log messages. Every message is eventually routed to one
-        or several targets.
+
+        Targets are the final destination of %log messages. Every message is eventually routed to
+        one or several targets.
 
         \section target_routing Routing
 
@@ -66,31 +69,34 @@ namespace log {
         matched against this table. If an entry matches, the action associated with this entry is
         taken (either \c ACCEPT or \c REJECT).
 
-        Every target manages it's own routing table. Conceptually, every routing message will be
-        routed to every target where it will then be matched against each targets routing table (the
+        Every target manages it's own routing table. Conceptually, every message will be routed to
+        every target where it will then be matched against each targets routing table (the
         implementation is more efficient and utilizes a routing cache).
 
         Each routing entry consists of the following parameters
-        \li (optional) \e stream. The entry will match only messages directed at that stream
+        \li (optional) \e stream. If specified, the entry will match only messages directed at that
+            stream
         \li (optional) \e area. If the area is specified, only messages directed at that area are
             matched, otherwise any area will be allowed
-        \li (optional) \e level. If the log level is specified, messages will be accepted if their
+        \li (optional) \e level. If the %log level is specified, messages will be accepted if their
             level is at least that value. If the value is not specified, the limit will be taken
             from the stream's default value.
 
         Each parameter (stream, area and level) has two representations: A static (compile time
-        constant) representation, which is the representation also used in the log statements, and a
-        dynamic representation, which may be used for manipulating the routing table.
+        constant) representation, which is the representation also used in the %log statements, and a
+        dynamic (runtime) representation.
 
         The static representation is used, when passing routing parameters via template arguments:
         \code
         target.route<foo::SomeStream, senf::log::NOTICE>(senf::log::Target::REJECT);
         target.route<foo::SomeStream>();
+        target.route();
         \endcode
         The identical routing statements may be expressed using dynamic routing via:
         \code
         target.route("foo::SomeStream", "", senf::log::NOTICE::value, senf::log::Target::REJECT);
         target.route("foo::SomeStream");
+        target.route();
         \endcode
         The static representation has the benefit of being compile-time type checked: Invalid
         routing parameters will be caught while compiling the code. The dynamic representation is
@@ -108,16 +114,31 @@ namespace log {
             loglevels. Dynamically, it is represented by an unsigned integer number, the \c value
             member of that class.
 
+        \subsection target_routing_processing Ordering routing entries and route processing
+
+        The routing table is processed from first route to last route, the first matching entry
+        determines the fate of a log messages. Therefore, the ordering of routing entries is
+        important.
+        
+        If no position is explicitly specified, new routing entries are added to the end of the
+        routing table. All routing statements however take an index as optional argument to
+        explicitly specify the position of the new routing entry.
+
+        The index value starts from 0 for the first route. The value gives the position the new
+        routing entry will have after it has been added. An index of 0 will thus insert the new
+        routing entry at the beginning of the table. Negative values count from the back, -1 being
+        the last entry.
+
         \section target_impl Implementing new targets
 
         To implement a new target type, you need to derive from senf::log::Target and implement the
-        single \c v_write member. This member will be called whenever a message should be output. 
+        single \c v_write member. This member will be called whenever a message should be output.
 
-        The target may process in any arbitrary way: reformat, writing it into an SQL DB, whatever
-        can be envisioned. However, there is one important limitation: The \c v_write call must not
-        block. So for more complex scenarios, additional measures must be taken (e.g. writing a %log
-        backend daemon which receives the messages via UDP and processes them). Of course, in rare
-        cases messages might be lost but this cannot be avoided.
+        The target may process the message in any arbitrary way: reformat it, write it into an SQL
+        DB, whatever can be envisioned. However, there is one important limitation: The \c v_write
+        call must \e not block. So for more complex scenarios, additional measures must be taken
+        (e.g. writing a %log backend daemon which receives the messages via UDP and processes
+        them). Of course, in rare cases messages might be lost but this cannot be avoided.
 
         \see \ref targets
       */
@@ -132,7 +153,7 @@ namespace log {
             Every routing entry is associated with a routing action. This action is final (for this
             target. Each target is processed independently).
          */
-        enum action_t { 
+        enum action_t {
             ACCEPT /** Output message */
           , REJECT /** Suppress message output */
         };
@@ -144,29 +165,29 @@ namespace log {
 
             \see senf::log::Target
          */
-        struct RoutingEntry 
+        struct RoutingEntry
         {
             std::string stream() const; ///< Stream to match
             std::string area() const;   ///< Area to match (empty of unspecified)
             unsigned level() const;     ///< Level to match (senf::log::NONE::value if unspecified)
             action_t action() const;    ///< Action to take
-            
+
 #           ifdef DOXYGEN
         private:
 #           endif
 
             RoutingEntry();
-            bool operator==(RoutingEntry const & other);
+            bool operator==(RoutingEntry const & other) const;
 
         private:
-            RoutingEntry(detail::StreamBase const * stream, detail::AreaBase const * area, 
+            RoutingEntry(detail::StreamBase const * stream, detail::AreaBase const * area,
                          unsigned level, action_t action);
 
             detail::StreamBase const * stream_;
             detail::AreaBase const * area_;
             unsigned level_;
             action_t action_;
-            
+
             friend class Target;
         };
 
@@ -175,12 +196,13 @@ namespace log {
 
     public:
         typedef RIB::const_iterator iterator; ///< Routing table iterator
+        typedef RIB::size_type size_type;
 
         ///////////////////////////////////////////////////////////////////////////
         ///\name Structors and default members
         ///@{
 
-        Target();
+        explicit Target(std::string const & name);
         virtual ~Target();
 
         ///@}
@@ -195,29 +217,32 @@ namespace log {
                                         /**< Add a route for the given combination of \a Stream, \a
                                              Area and \a Level. All parameters (\a Stream, \a Area
                                              and \a Level) are optional (the template signature is
-                                             shown simplified here). Examples:
+                                             shown simplified here). So possible commands are:
                                              \code
-                                             target.route<SomeLevel>();
+                                             target.route();
                                              target.route<SomeStream>();
-                                             target.route<SomeStream, SomeLevel>();
+                                             target.route<SomeArea>();
+                                             target.route<SomeLevel>();
                                              target.route<SomeStream, SomeArea>();
+                                             target.route<SomeStream, SomeLevel>();
+                                             target.route<SomeArea, SomeLevel>();
                                              target.route<SomeStream, SomeArea, SomeLevel>();
                                              \endcode
 
                                              See the class description for information on the \a
-                                             action and \a index parameters 
+                                             action and \a index parameters
 
                                              \tparam Stream stream to match
                                              \tparam Area area to match
                                              \tparam Level level, matches messages with
-                                                 at least the given level. 
+                                                 at least the given level.
                                              \param[in] action routing action to take
                                              \param[in] index position of new route in the routing
                                                  table */
 
 #       endif
 
-        void route(std::string const & stream, std::string const & area = "", 
+        void route(std::string const & stream, std::string const & area = "",
                    unsigned level = NONE::value, action_t action = ACCEPT, int index = -1);
                                         ///< Add route (dynamic)
                                         /**< Add a route for the given combination of \a stream, \a
@@ -227,7 +252,7 @@ namespace log {
                                              senf::log::NONE::value respectively.
 
                                              See the class description for information on the \a
-                                             action and \a index parameters 
+                                             action and \a index parameters
 
                                              \throws InvalidStreamException if the given \a stream
                                                  is not found in the StreamRegistry
@@ -244,7 +269,7 @@ namespace log {
 
 #       ifdef DOXYGEN
 
-        template <class Stream, class Area, class Level> 
+        template <class Stream, class Area, class Level>
         void unroute(action_t action = ACCEPT);
                                         ///< Remove route (static)
                                         /**< This member removes an arbitrary routing entry. The
@@ -259,12 +284,12 @@ namespace log {
                                              \tparam Stream stream to match
                                              \tparam Area area to match
                                              \tparam Level level, matches messages with
-                                                 at least the given level. 
+                                                 at least the given level.
                                              \param[in] action routing action to take */
 
 #       endif
 
-        void unroute(std::string const & stream, std::string const & area = "", 
+        void unroute(std::string const & stream, std::string const & area = "",
                      unsigned level = NONE::value, action_t action = ACCEPT);
                                         ///< Remove route (dynamic)
                                         /**< This member removes an arbitrary routing entry. The \a
@@ -284,14 +309,15 @@ namespace log {
                                              \param[in] action routing action to take */
         void unroute(int index=-1);     ///< Remove route (indexed)
                                         /**< This call will remove the route with the given index.
-                                             
+
                                              See the class documentation for more information on
-                                             indexing. 
+                                             indexing.
 
                                              \param[in] index index of routing entry to remove */
 
 #       ifndef DOXYGEN
 
+        void route(action_t action = ACCEPT, int index = -1);
         template <class A1>
         void route(action_t action = ACCEPT, int index = -1);
         template <class A1, class A2>
@@ -299,6 +325,7 @@ namespace log {
         template <class A1, class A2, class A3>
         void route(action_t action = ACCEPT, int index = -1);
 
+        void unroute(action_t action = ACCEPT);
         template <class A1>
         void unroute(action_t action = ACCEPT);
         template <class A1, class A2>
@@ -312,38 +339,51 @@ namespace log {
 
         /** \brief Exception: Invalid stream */
         struct InvalidStreamException : public senf::Exception
-        { InvalidStreamException() 
+        { InvalidStreamException()
               : senf::Exception("senf::log::Target::InvalidStreamException"){} };
-        
+
         /** \brief Exception: Invalid area */
         struct InvalidAreaException : public senf::Exception
-        { InvalidAreaException() 
+        { InvalidAreaException()
               : senf::Exception("senf::log::Target::InvalidAreaException"){} };
 
         iterator begin() const;         ///< Iterator to beginning of routing table
         iterator end() const;           ///< Iterator past the end of routing table
-        
+
+        RoutingEntry const & operator[](size_type i) const; ///< Access routing entry
+
+        size_type size() const;         ///< Number of routing table entries
+        bool empty() const;             ///< \c true, if routing table empty, \c false otherwise
+
+        void flush();                   ///< Clear routing table
+
+        senf::console::ScopedDirectory<> & consoleDir(); ///< Get console/config directory
+
     private:
-        void route(detail::StreamBase const * stream, detail::AreaBase const * area, 
+        void route(detail::StreamBase const * stream, detail::AreaBase const * area,
                    unsigned level, action_t action, int index);
-        void unroute(detail::StreamBase const * stream, detail::AreaBase const * area, 
+        void unroute(detail::StreamBase const * stream, detail::AreaBase const * area,
                      unsigned level, action_t action);
 
         void updateRoutingCache(detail::StreamBase const * stream, detail::AreaBase const * area);
 
-        void write(boost::posix_time::ptime timestamp, detail::StreamBase const & stream,
+        void write(time_type timestamp, detail::StreamBase const & stream,
                    detail::AreaBase const & area, unsigned level, std::string const & message);
 
+        void consoleList(std::ostream & os);
+        void consoleRoute(int index, detail::LogParameters const & pm, action_t action);
+        void consoleUnroute(detail::LogParameters const & pm, action_t action);
+
 #   ifdef DOXYGEN
     protected:
 #   endif
 
-        virtual void v_write(boost::posix_time::ptime timestamp, std::string const & stream, 
-                             std::string const & area, unsigned level, 
+        virtual void v_write(time_type timestamp, std::string const & stream,
+                             std::string const & area, unsigned level,
                              std::string const & message) = 0;
                                         ///< Called to write out the routing message
                                         /**< This member must be defined in the derived class to
-                                             somehow format and write the %log message. 
+                                             somehow format and write the %log message.
 
                                              Every %log message always possesses a complete set of
                                              meta information (\a stream, \a area and \a level).
@@ -364,59 +404,17 @@ namespace log {
 #   endif
 
         RIB rib_;
-        
-        friend class detail::AreaBase;
-        friend class detail::TargetRegistry;
-    };
-
-    /** \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().
+        console::LazyDirectory consoleDir_;
 
-        \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;
+        friend class detail::AreaBase;
+        friend class detail::TargetRegistry;
     };
 
-    /** \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
+    /** \brief Write route action
+        \related Target
      */
-    template <class Source> void timeSource();
+    std::ostream & operator<<(std::ostream & os, Target::action_t const & action);
 
 }}
 
@@ -426,7 +424,7 @@ namespace log {
 #include "Target.cti"
 #endif
 
-\f
+
 // Local Variables:
 // mode: c++
 // fill-column: 100