#define HH_Target_ 1
// Custom includes
+#include <set>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/utility.hpp>
+#include <boost/type_traits/is_convertible.hpp>
#include "../singleton.hh"
+#include "../mpl.hh"
#include "StreamRegistry.hh"
#include "AreaRegistry.hh"
namespace senf {
namespace log {
+ class TargetRegistry;
+
/** \brief Logging target base class
All enabled log messages are eventually routed to one or more logging targets. It is the
to a file, to mail them to the administrator or whatever. To this end, the logging target is
passed the log message and a complete set of logging parameters (\e stream, \e area and \e
level).
+
+ \fixme optionally Integrate with Scheduler / ClockService to reduce number of gettimeofday()
+ calls.
*/
- class Target
- : public senf::singleton<Target>
+ class Target : private boost::noncopyable
{
public:
///////////////////////////////////////////////////////////////////////////
// Types
+ enum action_t { ACCEPT, REJECT };
+
+ struct RoutingEntry
+ {
+ RoutingEntry();
+ bool operator==(RoutingEntry const & other);
+
+ std::string stream() const;
+ std::string area() const;
+ unsigned level() const;
+ action_t action() const;
+
+ private:
+ 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;
+ };
+
+ private:
+ typedef std::vector<RoutingEntry> RIB;
+
+ public:
+ typedef RIB::const_iterator iterator;
+
///////////////////////////////////////////////////////////////////////////
///\name Structors and default members
///@{
+ Target();
virtual ~Target();
- // default default constructor
- // default copy constructor
- // default copy assignment
- // default destructor
-
- // no conversion constructors
-
///@}
- protected:
+ template <class Stream> void route(
+ action_t action = ACCEPT, int index = -1);
+ template <class Stream, class Level> void route(
+ action_t action = ACCEPT, int index = -1,
+ typename boost::enable_if< boost::is_convertible<Level*,
+ detail::LevelBase *> >::type * = 0);
+ template <class Stream, class Area> void route(
+ action_t action = ACCEPT, int index = -1,
+ typename boost::enable_if< boost::is_convertible<Area*,
+ detail::AreaBase *> >::type * = 0);
+ template <class Stream, class AreaClass> void route(
+ action_t action = ACCEPT, int index = -1,
+ typename boost::enable_if< boost::is_convertible<typename AreaClass::SENFLogArea *,
+ detail::AreaBase *> >::type * = 0);
+ template <class Stream, class Area, class Level> void route(
+ action_t action = ACCEPT, int index = -1,
+ typename boost::enable_if< boost::is_convertible<Area *,
+ detail::AreaBase *> >::type * = 0);
+ template <class Stream, class AreaClass, class Level> void route(
+ action_t action = ACCEPT, int index = -1,
+ typename boost::enable_if< boost::is_convertible<typename AreaClass::SENFLogArea *,
+ detail::AreaBase *> >::type * = 0);
+
+ void route(std::string const & stream, std::string const & area = "",
+ unsigned level = NONE::value, action_t action = ACCEPT, int index = -1);
+
+ template <class Stream> void unroute(
+ action_t action = ACCEPT);
+ template <class Stream, class Level> void unroute(
+ action_t action = ACCEPT,
+ typename boost::enable_if< boost::is_convertible<Level*,
+ detail::LevelBase *> >::type * = 0);
+ template <class Stream, class Area> void unroute(
+ action_t action = ACCEPT,
+ typename boost::enable_if< boost::is_convertible<Area*,
+ detail::AreaBase *> >::type * = 0);
+ template <class Stream, class AreaClass> void unroute(
+ action_t action = ACCEPT,
+ typename boost::enable_if< boost::is_convertible<typename AreaClass::SENFLogArea *,
+ detail::AreaBase *> >::type * = 0);
+ template <class Stream, class Area, class Level> void unroute(
+ action_t action = ACCEPT,
+ typename boost::enable_if< boost::is_convertible<Area*,
+ detail::AreaBase *> >::type * = 0);
+ template <class Stream, class AreaClass, class Level> void unroute(
+ action_t action = ACCEPT,
+ typename boost::enable_if< boost::is_convertible<typename AreaClass::SENFLogArea *,
+ detail::AreaBase *> >::type * = 0);
+
+ void unroute(std::string const & stream, std::string const & area = "",
+ unsigned level = NONE::value, action_t action = ACCEPT);
+ void unroute(int index);
+
+ struct InvalidStreamException : public std::exception
+ { virtual char const * what() const throw()
+ { return "senf::log::Target::InvalidStreamException"; } };
+
+ struct InvalidAreaException : public std::exception
+ { virtual char const * what() const throw()
+ { return "senf::log::Target::InvalidAreaException"; } };
+ iterator begin() const;
+ iterator end() const;
+
private:
-
void route(detail::StreamBase const * stream, detail::AreaBase const * area,
- unsigned level);
+ unsigned level, action_t action, int index);
void unroute(detail::StreamBase const * stream, detail::AreaBase const * area,
- unsigned level);
+ unsigned level, action_t action);
- void updateAreaCache(detail::AreaBase const & area, detail::StreamBase const * stream,
- unsigned level);
+ void updateRoutingCache(detail::StreamBase const * stream, detail::AreaBase const * area);
- void write(detail::StreamBase const & stream, detail::AreaBase const & area,
- unsigned level, std::string const & message);
-
- virtual void v_write(std::string const & stream, std::string const & area, unsigned level,
- std::string const & message) = 0;
+ void write(boost::posix_time::ptime timestamp, detail::StreamBase const & stream,
+ detail::AreaBase const & area, unsigned level, std::string const & message);
- struct RoutingEntry
- {
- RoutingEntry(detail::StreamBase const * stream_, detail::AreaBase const * area_,
- unsigned level_)
- : stream(stream_), area(area_), level(level_) {}
- RoutingEntry()
- : stream(0), area(0), level(0) {}
-
- bool operator==(RoutingEntry const & other)
- { return stream == other.stream && area == other.area && level == other.level; }
-
- detail::StreamBase const * stream;
- detail::AreaBase const * area;
- unsigned level;
- };
+# ifdef DOXYGEN
+ protected:
+# endif
- typedef std::vector<RoutingEntry> RIB;
+ virtual void v_write(boost::posix_time::ptime, std::string const & stream,
+ std::string const & area, unsigned level,
+ std::string const & message) = 0;
+
+# ifdef DOXYGEN
+ private:
+# endif
RIB rib_;
+
+ friend class detail::AreaBase;
};
+ /** \brief Target registry
+
+ The TargetRegistry keeps a record of all existing targets.
+ */
+ class TargetRegistry
+ : public senf::singleton<TargetRegistry>
+ {
+ public:
+ using senf::singleton<TargetRegistry>::instance;
+
+ void write(detail::StreamBase const & stream, detail::AreaBase const & area,
+ unsigned level, std::string msg);
+
+ private:
+ void registerTarget(Target * target);
+ void unregisterTarget(Target * target);
+
+ typedef std::set<Target *> Targets;
+ Targets targets_;
+
+ friend class Target;
+ };
+
+
+ template <class Stream, class Area, class Level>
+ void write(std::string msg);
+
}}
///////////////////////////////hh.e////////////////////////////////////////
#include "Target.cci"
//#include "Target.ct"
-//#include "Target.cti"
+#include "Target.cti"
#endif
\f