From: g0dil Date: Wed, 31 Oct 2007 15:31:33 +0000 (+0000) Subject: Utils/Logger: Completed documentation X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=044a1bfb46ce16c3daac307b8c684604b43dd4cf;p=senf.git Utils/Logger: Completed documentation Utils/Logger: FileTarget implementation git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@488 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Packets/MPEGDVBBundle/GREPacket.hh b/Packets/MPEGDVBBundle/GREPacket.hh index fc1d433..fa0b2e2 100644 --- a/Packets/MPEGDVBBundle/GREPacket.hh +++ b/Packets/MPEGDVBBundle/GREPacket.hh @@ -43,8 +43,8 @@ namespace senf { */ struct Parse_GREPacket : public PacketParserBase { - -#include SENF_PARSER() +# include SENF_PARSER() + SENF_PARSER_BITFIELD ( checksum_present, 1, bool ); SENF_PARSER_PRIVATE_BITFIELD ( reserved0_, 12, unsigned ); // TODO: SKIP !! SENF_PARSER_BITFIELD_RO ( version_number, 3, unsigned ); // TODO: Always Zero !! @@ -53,6 +53,7 @@ namespace senf { (VoidPacketParser) (Parse_UInt16) ); SENF_PARSER_PRIVATE_VARIANT ( reserved1_, checksum_present, (VoidPacketParser) (Parse_UInt16) ); + SENF_PARSER_FINALIZE( Parse_GREPacket ); private: diff --git a/SConstruct b/SConstruct index 2753d30..478cfdf 100644 --- a/SConstruct +++ b/SConstruct @@ -168,6 +168,8 @@ if not env.GetOption('clean') and not os.path.exists(".prepare-stamp") \ env.Clean('all', '.prepare-stamp') +# Not nice, but until we get to fixing the dependency jungle +# concerning generated sources ... scripts = [] dependencies = [] diff --git a/Utils/Logger/Config.hh b/Utils/Logger/Config.hh index 7ec3c7f..8e55030 100644 --- a/Utils/Logger/Config.hh +++ b/Utils/Logger/Config.hh @@ -86,8 +86,8 @@ decide a log messages fate for that target. \see - \ref SENF_LOG_CONF: compile time configuration \n - \ref senf::log::Target: runtime configuration + \ref SENF_LOG_CONF compile time configuration \n + \ref senf::log::Target runtime configuration */ namespace senf { diff --git a/Utils/Logger/ConsoleTarget.hh b/Utils/Logger/ConsoleTarget.hh index b345ef7..85cf8d7 100644 --- a/Utils/Logger/ConsoleTarget.hh +++ b/Utils/Logger/ConsoleTarget.hh @@ -38,6 +38,8 @@ namespace log { /** \brief Write log messages to std::cout IOStreamTarget writing to std::cout + + \ingroup targets */ class ConsoleTarget : public IOStreamTarget { diff --git a/Utils/Logger/FileTarget.cc b/Utils/Logger/FileTarget.cc new file mode 100644 index 0000000..c2538c4 --- /dev/null +++ b/Utils/Logger/FileTarget.cc @@ -0,0 +1,64 @@ +// $Id$ +// +// Copyright (C) 2007 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer NETwork research (NET) +// Stefan Bund +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/** \file + \brief FileTarget non-inline non-template implementation */ + +#include "FileTarget.hh" +//#include "FileTarget.ih" + +// Custom includes + +//#include "FileTarget.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +prefix_ senf::log::FileTarget::FileTarget(std::string file) + : ofstream_t(file.c_str(), std::ofstream::app), IOStreamTarget(ofstream_t::member), file_(file) +{} + +prefix_ void senf::log::FileTarget::reopen() +{ + ofstream_t::member.close(); + ofstream_t::member.open(file_.c_str(), std::ofstream::app); +} + +prefix_ void senf::log::FileTarget::reopen(std::string file) +{ + file_ = file; + reopen(); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ +//#include "FileTarget.mpp" + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: diff --git a/Utils/Logger/FileTarget.hh b/Utils/Logger/FileTarget.hh new file mode 100644 index 0000000..a6fac2b --- /dev/null +++ b/Utils/Logger/FileTarget.hh @@ -0,0 +1,90 @@ +// $Id$ +// +// Copyright (C) 2007 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer NETwork research (NET) +// Stefan Bund +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/** \file + \brief FileTarget public header */ + +#ifndef HH_FileTarget_ +#define HH_FileTarget_ 1 + +// Custom includes +#include +#include +#include "IOStreamTarget.hh" + +//#include "FileTarget.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace senf { +namespace log { + + /** \brief Log target writing to a log file. + + The FileTarget will save all log messages in the given file. Messages will be appended at + the end of the file. + + After log files have been rotated, the reopen() member should be called to create a new log + file. + + \ingroup targets + */ + class FileTarget + : private boost::base_from_member, + public IOStreamTarget + { + typedef boost::base_from_member ofstream_t; + + public: + /////////////////////////////////////////////////////////////////////////// + ///\name Structors and default members + ///@{ + + explicit FileTarget(std::string file); ///< Construct FileTarget writing to \a file + + ///@} + /////////////////////////////////////////////////////////////////////////// + + void reopen(); ///< Reopen log after log-file rotation + void reopen(std::string file); ///< Reopen log under a new name + + private: + std::string file_; + }; + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "FileTarget.cci" +//#include "FileTarget.ct" +//#include "FileTarget.cti" +#endif + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: diff --git a/Utils/Logger/IOStreamTarget.hh b/Utils/Logger/IOStreamTarget.hh index 94f9999..3e0b61e 100644 --- a/Utils/Logger/IOStreamTarget.hh +++ b/Utils/Logger/IOStreamTarget.hh @@ -55,7 +55,9 @@ namespace log { \warning The class keeps a reference to the passed stream. \note This class will permanently and globally change the date formating of the given - stream. + stream if no \c boost::posix_time::time_facet has been set. + + \ingroup targets */ class IOStreamTarget : public Target diff --git a/Utils/Logger/Log.ih b/Utils/Logger/Log.ih index 95c6020..e87be73 100644 --- a/Utils/Logger/Log.ih +++ b/Utils/Logger/Log.ih @@ -33,21 +33,25 @@ #define SENF_LOG_BLOCK_(parameters, block) \ do { \ - if (parameters::compileEnabled && parameters::enabled()) { \ + typedef parameters SENFLogParameters; \ + if (SENFLogParameters::compileEnabled && SENFLogParameters::enabled()) { \ std::stringstream log; \ do block while(0); \ - senf::log::write(log.str()); \ + senf::log::detail::write< SENFLogParameters::stream, \ + SENFLogParameters::area, \ + SENFLogParameters::level >(log.str()); \ } \ } while(0) #define SENF_LOG_BLOCK_TPL_(parameters, block) \ do { \ - if (parameters::compileEnabled && parameters::enabled()) { \ + typedef parameters SENFLogParameters; \ + if (SENFLogParameters::compileEnabled && SENFLogParameters::enabled()) { \ std::stringstream log; \ do block while(0); \ - senf::log::write(log.str()); \ + senf::log::detail::write(log.str()); \ } \ } while(0) diff --git a/Utils/Logger/Mainpage.dox b/Utils/Logger/Mainpage.dox index 30b80fa..bc1d220 100644 --- a/Utils/Logger/Mainpage.dox +++ b/Utils/Logger/Mainpage.dox @@ -37,25 +37,31 @@ \section logging_concepts Concepts - The log messages are devided along several categories: \e streams, \e areas and log \e levels. - - A \e stream combines log messages with a single purpose. There is one default stream, called \c - senf::log::Debug. New streams are defined with \ref SENF_LOG_DEF_STREAM. - - An \e area labels a log message with the source location of the message. An area is an arbitrary - tag which may be added to the message. There is one default area called \c - senf::log::DefaultArea. New areas are defined either with \ref SENF_LOG_DEF_AREA or \ref - SENF_LOG_CLASS_AREA, the latter being the more typical. The area will normally indicate the - class or subsystem from which the message was generated. - - The log \e level gives information on the importance of the message. The list lof \ref loglevels - is fixed. - - After log messages have been created, they have to be placed somewhere. This is the - responsibility of the \e target. A target is an arbitrary sink for log messages. The target - manages message routing and will pass the message on to it's destination, be it the system - console, some log file or some other place (e.g. an SQL database). The target is responsible for - formating the message. + Log messages are arbitrarily created throughout the code using simple log statements (which are + macros). Besides the log message itself, every log message is labeled with additional + information: The \e stream, the \e area and a log \e level. If the message is not compile-time + disabled, the message is then directed to one of several log \e targets. + + A \e stream combines log messages with a single purpose: Debug messages, access logging and so + on. Any number of streams may be defined. There is one predefined default stream called \c + senf::log::Debug. (see: \ref SENF_LOG_DEF_STREAM) + + The \e area gives information about the source location of the message. Areas may be defined and + assigned arbitrarily but should be used to label messages from a single class or subsystem. It + is possible to reuse a class as it's own area tag, which is often desireable. (see: \ref + SENF_LOG_DEF_AREA, \ref SENF_LOG_CLASS_AREA) + + The log \e level gives information on the importance of the message. The list of log-levels is + fixed. (see: \ref loglevels) + + Depending on their the \e stream, \e area and \e level information, log messages can be enabled + or disabled at \e compile time. Messages disabled at compile time should not generate any + code. (see: \ref SENF_LOG_CONF) + + To be of any use, the log messages have to be written somewhere. This is the responsibility of + any number of \e targets. A \e target receives messages and using it's routing information + decides, wether the message is output or not. A message may be routed to multiple targets + simultaneously or may not be output by any target at all. (see: \ref targets) \section logging_tutorial Tutorial introduction @@ -106,6 +112,18 @@ SENF_LOG(("Log to UserLog stream in Froblizer area however at VERBOSE level")); } + + int main(int, char **) + { + // Set up the routing targets + senf::log::ConsoleTarget console; + senf::log::FileTarget logfile ("my.log"); + + // Debug messages go to the console + console.route(); + // Important user message are written to the log file + logfile.route(); + } \endcode \implementation I would have much preferred a more C++ like implementation. However given the diff --git a/Utils/Logger/StringTarget.hh b/Utils/Logger/StringTarget.hh index 6aa740b..1981d74 100644 --- a/Utils/Logger/StringTarget.hh +++ b/Utils/Logger/StringTarget.hh @@ -37,6 +37,10 @@ namespace senf { namespace log { /** \brief Store log messages in a string buffer + + This target is mostly useful for debug purposes. + + \ingroup targets */ class StringTarget : private boost::base_from_member, @@ -56,8 +60,8 @@ namespace log { ///@} /////////////////////////////////////////////////////////////////////////// - std::string str() const; - void clear(); + std::string str() const; ///< Get log messages accumulated so far + void clear(); ///< Clear buffer protected: diff --git a/Utils/Logger/Target.cc b/Utils/Logger/Target.cc index c07ba21..3c32f95 100644 --- a/Utils/Logger/Target.cc +++ b/Utils/Logger/Target.cc @@ -24,7 +24,7 @@ \brief Target non-inline non-template implementation */ #include "Target.hh" -//#include "Target.ih" +#include "Target.ih" // Custom includes #include @@ -38,7 +38,7 @@ prefix_ senf::log::Target::Target() { - TargetRegistry::instance().registerTarget(this); + detail::TargetRegistry::instance().registerTarget(this); } prefix_ senf::log::Target::~Target() @@ -49,7 +49,7 @@ prefix_ senf::log::Target::~Target() RIB::reverse_iterator i (rib_.rbegin()); unroute(i->stream_, i->area_, i->level_, i->action_); } - TargetRegistry::instance().unregisterTarget(this); + detail::TargetRegistry::instance().unregisterTarget(this); } prefix_ void senf::log::Target::route(std::string const & stream, std::string const & area, @@ -90,7 +90,7 @@ prefix_ void senf::log::Target::unroute(int index) i = rib_.begin(); else { i = rib_.end(); - std::advance(i, -index); + std::advance(i, index); } } else { if (RIB::size_type(index+1) >= rib_.size()) { @@ -101,6 +101,8 @@ prefix_ void senf::log::Target::unroute(int index) std::advance(i, index); } } + if (i == rib_.end()) + return; RoutingEntry entry (*i); rib_.erase(i); if (entry.action_ == ACCEPT) @@ -199,9 +201,9 @@ prefix_ void senf::log::Target::write(boost::posix_time::ptime timestamp, /////////////////////////////////////////////////////////////////////////// // senf::log::TargetRegistry -prefix_ void senf::log::TargetRegistry::write(detail::StreamBase const & stream, - detail::AreaBase const & area, unsigned level, - std::string msg) +prefix_ void senf::log::detail::TargetRegistry::write(StreamBase const & stream, + AreaBase const & area, unsigned level, + std::string msg) { boost::posix_time::ptime timestamp (boost::posix_time::microsec_clock::universal_time()); area.write(timestamp, stream, level, msg); diff --git a/Utils/Logger/Target.cci b/Utils/Logger/Target.cci index 1d6f6d9..e7b2409 100644 --- a/Utils/Logger/Target.cci +++ b/Utils/Logger/Target.cci @@ -23,7 +23,7 @@ /** \file \brief Target inline non-template implementation */ -//#include "Target.ih" +#include "Target.ih" // Custom includes @@ -92,14 +92,14 @@ prefix_ senf::log::Target::action_t senf::log::Target::RoutingEntry::action() } /////////////////////////////////////////////////////////////////////////// -// senf::log::TargetRegistry +// senf::log::detail::TargetRegistry -prefix_ void senf::log::TargetRegistry::registerTarget(Target * target) +prefix_ void senf::log::detail::TargetRegistry::registerTarget(Target * target) { targets_.insert(target); } -prefix_ void senf::log::TargetRegistry::unregisterTarget(Target * target) +prefix_ void senf::log::detail::TargetRegistry::unregisterTarget(Target * target) { targets_.erase(target); } diff --git a/Utils/Logger/Target.cti b/Utils/Logger/Target.cti index 2312dc6..ccc364d 100644 --- a/Utils/Logger/Target.cti +++ b/Utils/Logger/Target.cti @@ -23,7 +23,7 @@ /** \file \brief Target inline template implementation */ -//#include "Target.ih" +#include "Target.ih" // Custom includes #include "Levels.hh" @@ -36,6 +36,8 @@ // senf::log::Target::route +#ifndef DOXYGEN + template prefix_ void senf::log::Target::route(action_t action, int index) { @@ -130,11 +132,13 @@ unroute(action_t action, unroute(&Stream::instance(), &AreaClass::SENFLogArea::instance(), Level::value, action); } +#endif + /////////////////////////////////////////////////////////////////////////// -// namespace senf::log members +// namespace senf::log::detail members template -prefix_ void senf::log::write(std::string msg) +prefix_ void senf::log::detail::write(std::string msg) { TargetRegistry::instance().write(Stream::instance(), Area::instance(), Level::value, msg); } diff --git a/Utils/Logger/Target.hh b/Utils/Logger/Target.hh index b4137d6..5b8dd1b 100644 --- a/Utils/Logger/Target.hh +++ b/Utils/Logger/Target.hh @@ -39,18 +39,86 @@ //#include "Target.mpp" ///////////////////////////////hh.p//////////////////////////////////////// +/** \defgroup targets Targets + + Targets receive log messages and write them to some destination: The console, a log file, an SQL + DB and so on. Every target is derived from the \ref senf::log::Target base class. This base + class provides the target with the necessary routing infrastructure. The different targets only + differ in the way, they write the data. + + \see senf::log::Target + */ + 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 - responsibility of the logging target to write the log messages somewhere: onto the console, - 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). + + Targets are the final destination of log messages. Every message is eventually routed to one + or several targets. + + \section target_routing Routing + + Each target manages a routing table. The message meta-data (stream, area and level) is + 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 + implementation is more efficient and utilizes a routing cache). + + Each routing entry consists of the following parameters + \li (mandatory) \e stream. 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 + 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. + + The static representation is used, when passing routing parameters via template arguments: + \code + target.route(senf::log::Target::REJECT); + 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"); + \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 + more flexible as it allows to adjust routing from user input (e.g. configuration files). + + The different object representations are: + \li The \e streams is statically represented by it's name, which is the name of a class + defined with \ref SENF_LOG_DEF_STREAM. The dynamic representation is a string + representation of this name. + \li The \e area is statically represented by it's name, which again is the name of a class + defined with \ref SENF_LOG_DEF_STREAM. The dynamic representation again is a string + representation of this class's name. The dynamic representation represents an absent + area with the empty string. + \li The \e level is statically represented by a level class from \ref + loglevels. Dynamically, it is represented by an unsigned integer number, the \c value + member of that class. + + \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. + + 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. + + \see \ref targets \fixme optionally Integrate with Scheduler / ClockService to reduce number of gettimeofday() calls. @@ -61,18 +129,37 @@ namespace log { /////////////////////////////////////////////////////////////////////////// // Types - enum action_t { ACCEPT, REJECT }; + /** \brief Routing action + Every routing entry is associated with a routing action. This action is final (for this + target. Each target is processed independently). + */ + enum action_t { + ACCEPT /** Output message */ + , REJECT /** Suppress message output */ + }; + + /** \brief Target routing entry + + A single routing entry matches messages against their \e stream, \e area and \e + level. If the entry matches, the given \e action is performed. + + \see senf::log::Target + */ 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); - 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); @@ -89,7 +176,7 @@ namespace log { typedef std::vector RIB; public: - typedef RIB::const_iterator iterator; + typedef RIB::const_iterator iterator; ///< Routing table iterator /////////////////////////////////////////////////////////////////////////// ///\name Structors and default members @@ -99,6 +186,112 @@ namespace log { virtual ~Target(); ///@} + /////////////////////////////////////////////////////////////////////////// + ///\name Routing + ///\{ + +# ifdef DOXYGEN + + template void route( + action_t action = ACCEPT, int index = -1); ///< Add route (static) + /**< Add a route for the given combination of \a Stream, \a + Area and \a Level. The \a Stream parameter is mandatory + while either \a Area or \a Level are optional (the + template signature is shown simplified here): + \code + target.route(); + target.route(); + target.route(); + target.route(); + \endcode + + See the class description for information on the \a + action and \a index parameters + + \param[in] Stream mandatory stream to match + \param[in] Area optional area to match + \param[in] Level optional level, matches messages with + 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 = "", + 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 + area and \a level. The \a stream parameter is mandatory + while either \a area or \a level may be left + unspecified by setting them to the empty string or + senf::log::NONE::value respectively. + + See the class description for information on the \a + action and \a index parameters + + \throws InvalidStreamException if the given \a stream + is not found in the StreamRegistry + \throws InvalidAreaException if the given \a area is + not found in the AreaRegistry + + \param[in] stream mandatory stream to match + \param[in] area optional area to match + \param[in] level optional level, matches messages with + at least the given level. + \param[in] action routing action to take + \param[in] index position of new route in the routing + table */ + +# ifdef DOXYGEN + + template + void unroute(action_t action = ACCEPT); + ///< Remove route (static) + /**< This member removes an arbitrary routing entry. The + template parameters are the same as for the + corresponding \ref route() call. + + The routing table is searched for a route exactly + matching the given specification. If such a route is + found, it will be removed, otherwise the call will be + ignored + + \param[in] Stream mandatory stream to match + \param[in] Area optional area to match + \param[in] Level optional level, matches messages with + at least the given level. + \param[in] action routing action to take */ + +# endif + + 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 + stream parameter is mandatory while either \a area or + \a level may be left unspecified by setting them to the + empty string or senf::log::NONE::value respectively. + + The routing table is searched for a route exactly + matching the given specification. If such a route is + found, it will be removed, otherwise the call will be + ignored + + \param[in] stream mandatory stream to match + \param[in] area optional area to match + \param[in] level optional level, matches messages with + at least the given level. + \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. + + \param[in] index index of routing entry to remove */ + +# ifndef DOXYGEN template void route( action_t action = ACCEPT, int index = -1); @@ -123,9 +316,6 @@ namespace log { typename boost::enable_if< boost::is_convertible >::type * = 0); - void route(std::string const & stream, std::string const & area = "", - unsigned level = NONE::value, action_t action = ACCEPT, int index = -1); - template void unroute( action_t action = ACCEPT); template void unroute( @@ -149,20 +339,22 @@ namespace log { typename boost::enable_if< boost::is_convertible >::type * = 0); - void unroute(std::string const & stream, std::string const & area = "", - unsigned level = NONE::value, action_t action = ACCEPT); - void unroute(int index); +# endif + + ///\} + /** \brief Exception: Invalid stream */ struct InvalidStreamException : public std::exception { virtual char const * what() const throw() { return "senf::log::Target::InvalidStreamException"; } }; + /** \brief Exception: Invalid area */ struct InvalidAreaException : public std::exception { virtual char const * what() const throw() { return "senf::log::Target::InvalidAreaException"; } }; - iterator begin() const; - iterator end() const; + iterator begin() const; ///< Iterator to beginning of routing table + iterator end() const; ///< Iterator past the end of routing table private: void route(detail::StreamBase const * stream, detail::AreaBase const * area, @@ -179,9 +371,28 @@ namespace log { protected: # endif - virtual void v_write(boost::posix_time::ptime, std::string const & stream, + virtual void v_write(boost::posix_time::ptime 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. + + Every log message always possesses a complete set of + meta information (\a stream, \a area and \a level). The + \a area may be an empty string if the message was + written from the senf::log::DefaultArea. + + \note This member must \e not block since it may be + called from any unknown context. This prohibits + simple logging over NFS or many other network + protocols. + + \param[in] timestamp log message timing information + \param[in] stream message stream + \param[in] area message area + \param[in] level message level + \param[in] message the message string */ # ifdef DOXYGEN private: @@ -192,33 +403,6 @@ namespace log { friend class detail::AreaBase; }; - /** \brief Target registry - - The TargetRegistry keeps a record of all existing targets. - */ - class TargetRegistry - : public senf::singleton - { - public: - using senf::singleton::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 Targets; - Targets targets_; - - friend class Target; - }; - - - template - void write(std::string msg); - }} ///////////////////////////////hh.e//////////////////////////////////////// diff --git a/Utils/Logger/Target.ih b/Utils/Logger/Target.ih new file mode 100644 index 0000000..115c71e --- /dev/null +++ b/Utils/Logger/Target.ih @@ -0,0 +1,75 @@ +// $Id$ +// +// Copyright (C) 2007 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer NETwork research (NET) +// Stefan Bund +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/** \file + \brief Target internal header */ + +#ifndef IH_Target_ +#define IH_Target_ 1 + +// Custom includes + +///////////////////////////////ih.p//////////////////////////////////////// + +namespace senf { +namespace log { +namespace detail { + + /** \brief Internal: Target registry */ + class TargetRegistry + : public senf::singleton + { + public: + using senf::singleton::instance; + + void write(StreamBase const & stream, AreaBase const & area, unsigned level, + std::string msg); + + private: + void registerTarget(Target * target); + void unregisterTarget(Target * target); + + typedef std::set Targets; + Targets targets_; + + friend class senf::log::Target; + }; + + /** \brief Internal: Write log message */ + template + void write(std::string msg); + +}}} + +///////////////////////////////ih.e//////////////////////////////////////// +#endif + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: