From: g0dil Date: Fri, 26 Oct 2007 15:00:30 +0000 (+0000) Subject: Utils/Logger: Implement targets X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=ae06fe86f16fdabb7ffb219d255444d2eb4f4f79;p=senf.git Utils/Logger: Implement targets Utils/Logger: Implement message routing -> logging library is working now Move 'nil' class into Utils/mpl.hh git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@476 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Socket/SocketPolicy.ih b/Socket/SocketPolicy.ih index ccc0371..413635b 100644 --- a/Socket/SocketPolicy.ih +++ b/Socket/SocketPolicy.ih @@ -111,8 +111,6 @@ namespace senf { namespace impl { - struct nil {}; - template struct MakeSocketPolicy_merge {}; @@ -150,7 +148,7 @@ namespace impl { {}; template - struct apply + struct apply { typedef Base type; }; @@ -201,7 +199,7 @@ namespace impl { template < BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( SENF_SOCKET_POLICIES_N, class T, - senf::impl::nil ) > + mpl::nil ) > class MakeSocketPolicy : public boost::mpl::if_< boost::is_convertible< T0*, SocketPolicyBase* >, impl::MakeSocketPolicy_impl< diff --git a/Utils/Logger/Config.hh b/Utils/Logger/Config.hh index a9bf7c7..27a9af8 100644 --- a/Utils/Logger/Config.hh +++ b/Utils/Logger/Config.hh @@ -46,6 +46,12 @@ Runtime configuration on the other hand deals with routing all those messages, which are enabled at compile time to the logging targets. If a message is not routed, it will be discarded. This allows to additionally disable messages at run-time. + + \fixme Restructure compile-time configuration: Only allow stream based configuration using + SENF_LOG_CONF. For more complex configuration, accept a macro SENF_LOG_CONFFILE which, if + defined, must define the path of a file to be included. Area specific configuration must be + done in this include file. The area must be complete (not only a predeclaration) at that + point. */ namespace senf { @@ -118,7 +124,7 @@ namespace log { struct Enabled { static const bool value = ( - (Level::value == senf::log::NONE::value ? Stream::defaultLevel::value : Level::value) + (Level::value == NONE::value ? Stream::defaultLevel::value : Level::value) >= detail::Config::compileLimit::value ); }; diff --git a/Utils/Logger/ConsoleTarget.cc b/Utils/Logger/ConsoleTarget.cc new file mode 100644 index 0000000..411b2e4 --- /dev/null +++ b/Utils/Logger/ConsoleTarget.cc @@ -0,0 +1,56 @@ +// $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 ConsoleTarget non-inline non-template implementation */ + +#include "ConsoleTarget.hh" +//#include "ConsoleTarget.ih" + +// Custom includes +#include + +//#include "ConsoleTarget.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////// +// senf::log::ConsoleTarget + +prefix_ senf::log::ConsoleTarget::ConsoleTarget() + : IOStreamTarget(std::cout) +{} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ +//#include "ConsoleTarget.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/ConsoleTarget.hh b/Utils/Logger/ConsoleTarget.hh new file mode 100644 index 0000000..b345ef7 --- /dev/null +++ b/Utils/Logger/ConsoleTarget.hh @@ -0,0 +1,72 @@ +// $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 ConsoleTarget public header */ + +#ifndef HH_ConsoleTarget_ +#define HH_ConsoleTarget_ 1 + +// Custom includes +#include "IOStreamTarget.hh" + +//#include "ConsoleTarget.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace senf { +namespace log { + + /** \brief Write log messages to std::cout + + IOStreamTarget writing to std::cout + */ + class ConsoleTarget : public IOStreamTarget + { + public: + /////////////////////////////////////////////////////////////////////////// + ///\name Structors and default members + ///@{ + + ConsoleTarget(); + + ///@} + /////////////////////////////////////////////////////////////////////////// + }; + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "ConsoleTarget.cci" +//#include "ConsoleTarget.ct" +//#include "ConsoleTarget.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/Definitions.hh b/Utils/Logger/Definitions.hh index 5e9d5cc..ecf05b5 100644 --- a/Utils/Logger/Definitions.hh +++ b/Utils/Logger/Definitions.hh @@ -60,6 +60,8 @@ namespace log { typedef runtimeLimit_ runtimeLimit; \ typedef compileLimit_ compileLimit; \ static std::string name() { return instance().v_name(); } \ + unsigned defaultRuntimeLimit() const { return runtimeLimit::value; } \ + using senf::singleton::instance; \ private: \ stream() { init(); } \ friend class senf::singleton; \ @@ -70,7 +72,6 @@ namespace log { Defines a new log area named \a area. The area is defined as a symbol in the current scope. \hideinitializer - \ingroup logging */ # define SENF_LOG_DEF_AREA(area) SENF_LOG_DEF_AREA_I(area, ; ) @@ -78,6 +79,8 @@ namespace log { This command declares the containing class to be it's own default log area. It is such like a combination of \ref SENF_LOG_DEF_AREA and \ref SENF_LOG_DEFAULT_AREA with a twist. + + \hideinitializer */ # define SENF_LOG_CLASS_AREA() \ SENF_LOG_DEF_AREA_I( \ @@ -105,7 +108,7 @@ namespace log { } /** \brief Default global log stream */ - SENF_LOG_DEF_STREAM(Debug, MESSAGE, DISABLED, DISABLED); + SENF_LOG_DEF_STREAM(Debug, MESSAGE, MESSAGE, MESSAGE); /** \brief Default global log area */ SENF_LOG_DEF_AREA_I(DefaultArea, diff --git a/Utils/Logger/Definitions.ih b/Utils/Logger/Definitions.ih index 7e97381..ae3639c 100644 --- a/Utils/Logger/Definitions.ih +++ b/Utils/Logger/Definitions.ih @@ -35,6 +35,7 @@ : public senf::log::detail::AreaBase, public senf::singleton \ { \ static std::string name() { return instance().v_name(); } \ + using senf::singleton::instance; \ decls \ private: \ area() { init(); } \ diff --git a/Utils/Logger/IOStreamTarget.cc b/Utils/Logger/IOStreamTarget.cc new file mode 100644 index 0000000..f70fdd7 --- /dev/null +++ b/Utils/Logger/IOStreamTarget.cc @@ -0,0 +1,74 @@ +// $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 IOStreamTarget non-inline non-template implementation */ + +#include "IOStreamTarget.hh" +//#include "IOStreamTarget.ih" + +// Custom includes +#include + +//#include "IOStreamTarget.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////// +// senf::log::IOStreamTarget + +prefix_ senf::log::IOStreamTarget::IOStreamTarget(std::ostream & os) + : stream_(os) +{ + std::locale const & loc (stream_.getloc()); + if (!std::has_facet(loc)) + stream_.imbue( std::locale(loc, new boost::posix_time::time_facet("%Y-%m-%d %H:%M:%S.%f-0000")) ); +} + +//////////////////////////////////////// +// private members + +prefix_ void senf::log::IOStreamTarget::v_write(boost::posix_time::ptime timestamp, + std::string const & stream, + std::string const & area, unsigned level, + std::string const & message) +{ + stream_ << timestamp << " "; + if (! area.empty()) + stream_ << "[" << area << "] "; + stream_ << message << std::endl; +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ +//#include "IOStreamTarget.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/IOStreamTarget.hh b/Utils/Logger/IOStreamTarget.hh new file mode 100644 index 0000000..94f9999 --- /dev/null +++ b/Utils/Logger/IOStreamTarget.hh @@ -0,0 +1,101 @@ +// $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 IOStreamTarget public header */ + +#ifndef HH_IOStreamTarget_ +#define HH_IOStreamTarget_ 1 + +// Custom includes +#include +#include +#include "Target.hh" + +//#include "IOStreamTarget.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace senf { +namespace log { + + /** \brief Write log messages to arbitrary std::ostream + + This target will write log messages to an arbitrary std::ostream in the format +
+         [] 
+        
+ + The date formatting is set using the Boost.DateTime date_facet, e.g.: + \code + stream.imbue( std::locale(stream.getloc(), + new boost::posix_time::time_facet("%Y%m%d %H:%M:%S")) ); + \endcode + + By default, the date-time will be written in extended ISO format. + + \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. + */ + class IOStreamTarget + : public Target + { + public: + /////////////////////////////////////////////////////////////////////////// + ///\name Structors and default members + ///@{ + + explicit IOStreamTarget(std::ostream & os); + + ///@} + /////////////////////////////////////////////////////////////////////////// + + protected: + + private: + void v_write(boost::posix_time::ptime timestamp, std::string const & stream, + std::string const & area, unsigned level, + std::string const & message); + + std::ostream & stream_; + }; + + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "IOStreamTarget.cci" +//#include "IOStreamTarget.ct" +//#include "IOStreamTarget.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/Log.hh b/Utils/Logger/Log.hh index 81b7703..53f0629 100644 --- a/Utils/Logger/Log.hh +++ b/Utils/Logger/Log.hh @@ -65,10 +65,9 @@ be \c senf::log::Debug (\e stream), senf::log::DefaultArea (\e area), and senf::log::NONE (\e level). - There is one special log level, senf::log::NONE. If the log level is set to this value, the log - level will be set from the stream provided default value. + 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 compile time constants (they are all types, so it's difficult form them to be something else). */ diff --git a/Utils/Logger/Log.ih b/Utils/Logger/Log.ih index d669ff5..9e259c2 100644 --- a/Utils/Logger/Log.ih +++ b/Utils/Logger/Log.ih @@ -27,15 +27,16 @@ #define IH_Log_ 1 // Custom includes +#include ///////////////////////////////ih.p//////////////////////////////////////// #define SENF_LOG_BLOCK_(parameters, block) \ do { \ - if (parameters::compile_enabled && parameters::enabled()) { \ - std::ostream & log (parameters::log_stream()); \ + if (parameters::compileEnabled && parameters::enabled()) { \ + std::stringstream log; \ do block while(0); \ - log << std::endl; \ + senf::log::write(log.str()); \ } \ } while(0) diff --git a/Utils/Logger/Log.test.cc b/Utils/Logger/Log.test.cc index 000164e..b4a1cbd 100644 --- a/Utils/Logger/Log.test.cc +++ b/Utils/Logger/Log.test.cc @@ -26,20 +26,12 @@ //#include "Log.test.hh" //#include "Log.test.ih" -// Custom includes -#include - // We need to put all tests into this single file to not violate the ODR -#define _senf_LOG_STREAM logstream -namespace { - std::stringstream logstream; -} - #define SENF_LOG_CONF (( (senf)(log)(Debug), (_), NOTICE )) +// Custom includes #include "Logger.hh" - #include #include @@ -66,30 +58,46 @@ using namespace not_anonymous; BOOST_AUTO_UNIT_TEST(logger) { + senf::log::StringTarget target; + + target.route(); + + // We cannot easily check the exact log string since that includes the current date/time + SENF_LOG_DEFAULT_STREAM(senf::log::Debug); SENF_LOG_DEFAULT_AREA(senf::log::DefaultArea); SENF_LOG_DEFAULT_LEVEL(senf::log::VERBOSE); - // should be disabled SENF_LOG(("Log message")); + BOOST_CHECK( target.str().empty() ); + target.clear(); + SENF_LOG((senf::log::VERBOSE)("Log message 2")); - // should be enabled + BOOST_CHECK( target.str().empty() ); + target.clear(); + SENF_LOG((senf::log::IMPORTANT)("Important message")); + BOOST_CHECK( ! target.str().empty() ); + target.clear(); + SENF_LOG((LogCritical) ("Another log message: " << 10)); + BOOST_CHECK( ! target.str().empty() ); + target.clear(); SENF_LOG_BLOCK((senf::log::Debug) (senf::log::IMPORTANT) ({ log << "Last message"; log << " continued here"; })); + BOOST_CHECK( ! target.str().empty() ); + target.clear(); Foo::log(); - SENF_LOG((Foo)("Foo area")); + BOOST_CHECK( ! target.str().empty() ); + target.clear(); - BOOST_CHECK_EQUAL( logstream.str(), - "Important message\n" - "Another log message: 10\n" - "Last message continued here\n" - "Foo::log\n" ); + SENF_LOG((Foo)("Foo area")); + BOOST_CHECK( target.str().empty() ); + target.clear(); } BOOST_AUTO_UNIT_TEST(streamRegistry) diff --git a/Utils/Logger/Mainpage.dox b/Utils/Logger/Mainpage.dox index f30c1fb..8eab9f3 100644 --- a/Utils/Logger/Mainpage.dox +++ b/Utils/Logger/Mainpage.dox @@ -43,7 +43,7 @@ // Define a new log stream with default level, runtime limit and compile time limit // set to senf::log::MESSAGE - SENF_LOG_DEF_STREAM( UserLog, senf::log::MESSAAGE, senf::log::MESSAGE, senf::log::MESSAGE ); + SENF_LOG_DEF_STREAM( UserLog, senf::log::MESSAGE, senf::log::MESSAGE, senf::log::MESSAGE ); class Froblizer { diff --git a/Utils/Logger/Parameters.ih b/Utils/Logger/Parameters.ih index d323241..9c6529c 100644 --- a/Utils/Logger/Parameters.ih +++ b/Utils/Logger/Parameters.ih @@ -33,15 +33,12 @@ #include #include #include +#include #include "../mpl.hh" #include "Config.hh" ///////////////////////////////ih.p//////////////////////////////////////// -#ifndef _senf_LOG_STREAM -# define _senf_LOG_STREAM std::cerr -#endif - namespace senf { namespace log { @@ -107,13 +104,20 @@ namespace detail { template struct Parameters : public Base { - static bool const compile_enabled = senf::log::Enabled< + typedef typename boost::mpl::if_c< Base::level::value == NONE::value, + typename Base::stream::defaultLevel, + typename Base::level >::type level; + + static bool const compileEnabled = senf::log::Enabled< typename Base::stream, typename Base::area, - typename Base::level>::value; + level>::value; - static bool enabled() { return compile_enabled; } - static std::ostream & log_stream() { return _senf_LOG_STREAM; } + static bool enabled() { + return compileEnabled + && Base::area::instance().streamLimit(Base::stream::instance()) + <= Base::level::value; + } }; /// Internal: Empty base class diff --git a/Utils/Logger/StreamRegistry.ih b/Utils/Logger/StreamRegistry.ih index 5eae6c2..13b8f68 100644 --- a/Utils/Logger/StreamRegistry.ih +++ b/Utils/Logger/StreamRegistry.ih @@ -43,6 +43,7 @@ namespace detail { std::string fullName() const; virtual std::string v_name() const; + virtual unsigned defaultRuntimeLimit() const = 0; void init(); diff --git a/Utils/Logger/StringTarget.cti b/Utils/Logger/StringTarget.cti new file mode 100644 index 0000000..fc9880b --- /dev/null +++ b/Utils/Logger/StringTarget.cti @@ -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 StringTarget inline template implementation */ + +//#include "StringTarget.ih" + +// Custom includes + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////// +// senf::log::StringTarget + +prefix_ senf::log::StringTarget::StringTarget() + : IOStreamTarget(stream_base::member) +{} + +prefix_ std::string senf::log::StringTarget::str() + const +{ + return stream_base::member.str(); +} + +prefix_ void senf::log::StringTarget::clear() +{ + stream_base::member.str(""); +} + + +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// 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/StringTarget.hh b/Utils/Logger/StringTarget.hh new file mode 100644 index 0000000..6aa740b --- /dev/null +++ b/Utils/Logger/StringTarget.hh @@ -0,0 +1,85 @@ +// $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 StringTarget public header */ + +#ifndef HH_StringTarget_ +#define HH_StringTarget_ 1 + +// Custom includes +#include +#include "IOStreamTarget.hh" + +//#include "StringTarget.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace senf { +namespace log { + + /** \brief Store log messages in a string buffer + */ + class StringTarget + : private boost::base_from_member, + public IOStreamTarget + { + typedef boost::base_from_member stream_base; + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + /////////////////////////////////////////////////////////////////////////// + ///\name Structors and default members + ///@{ + + StringTarget(); + + ///@} + /////////////////////////////////////////////////////////////////////////// + + std::string str() const; + void clear(); + + protected: + + private: + + }; + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "StringTarget.cci" +//#include "StringTarget.ct" +#include "StringTarget.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/Target.cc b/Utils/Logger/Target.cc index 651671e..997696a 100644 --- a/Utils/Logger/Target.cc +++ b/Utils/Logger/Target.cc @@ -35,24 +35,52 @@ /////////////////////////////////////////////////////////////////////////// // senf::log::Target +prefix_ senf::log::Target::Target() +{ + TargetRegistry::instance().registerTarget(this); +} + prefix_ senf::log::Target::~Target() -{} +{ + while( ! rib_.empty()) { + // This is slower but simplifies the area cache handling and removing a target + // should be quite seldom + RIB::reverse_iterator i (rib_.rbegin()); + unroute(i->stream, i->area, i->level); + } + TargetRegistry::instance().unregisterTarget(this); +} -prefix_ void senf::log::Target::write(detail::StreamBase const & stream, - detail::AreaBase const & area, - unsigned level, std::string const & message) +prefix_ void senf::log::Target::write(boost::posix_time::ptime timestamp, + detail::StreamBase const & stream, + detail::AreaBase const & area, unsigned level, + std::string const & message) { RIB::iterator i (rib_.begin()); RIB::iterator const i_end (rib_.end()); for (; i != i_end; ++i) if ( ( ! i->stream || i->stream == &stream ) && ( ! i->area || i->area == &area ) && - i->level <= level ) { - v_write(stream.v_name(), area.v_name(), level, message); + (i->level == NONE::value ? i->stream->defaultRuntimeLimit() : i->level) <= level ) { + v_write(timestamp, stream.v_name(), area.v_name(), level, message); return; } } +/////////////////////////////////////////////////////////////////////////// +// senf::log::TargetRegistry + +prefix_ void senf::log::TargetRegistry::write(detail::StreamBase const & stream, + detail::AreaBase const & area, unsigned level, + std::string msg) +{ + boost::posix_time::ptime timestamp (boost::posix_time::microsec_clock::universal_time()); + Targets::iterator i (targets_.begin()); + Targets::iterator i_end (targets_.end()); + for(; i != i_end; ++i) + (*i)->write(timestamp, stream, area, level, msg); +} + ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_ //#include "Target.mpp" diff --git a/Utils/Logger/Target.cci b/Utils/Logger/Target.cci index 07db6d6..129bef5 100644 --- a/Utils/Logger/Target.cci +++ b/Utils/Logger/Target.cci @@ -78,6 +78,19 @@ prefix_ void senf::log::Target::unroute(detail::StreamBase const * stream, // can never lower the logging limit. Not updating the cache just reduces the performance. } +/////////////////////////////////////////////////////////////////////////// +// senf::log::TargetRegistry + +prefix_ void senf::log::TargetRegistry::registerTarget(Target * target) +{ + targets_.insert(target); +} + +prefix_ void senf::log::TargetRegistry::unregisterTarget(Target * target) +{ + targets_.erase(target); +} + /////////////////////////////cci.e/////////////////////////////////////// #undef prefix_ diff --git a/Utils/Logger/Target.cti b/Utils/Logger/Target.cti new file mode 100644 index 0000000..ea7f5e2 --- /dev/null +++ b/Utils/Logger/Target.cti @@ -0,0 +1,93 @@ +// $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 inline template implementation */ + +//#include "Target.ih" + +// Custom includes +#include "Levels.hh" + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////// +// senf::log::Target + +template +prefix_ void senf::log::Target::route() +{ + route(&Stream::instance(), 0, NONE::value); +} + +template +prefix_ void senf::log::Target::route() +{ + route(&Stream::instance(), static_cast(0)); +} + +template +prefix_ void senf::log::Target::route() +{ + route(&Stream::instance(), &Area::instance(), Level::value); +} + +//////////////////////////////////////// +// private members + +template +prefix_ void senf::log::Target::route(detail::StreamBase const * stream, + detail::AreaBase const *) +{ + route(stream, &Area::instance(), NONE::value); +} + +template +prefix_ void senf::log::Target::route(detail::StreamBase const * stream, + detail::LevelBase const *) +{ + route(stream, 0, Level::value); +} + +/////////////////////////////////////////////////////////////////////////// +// namespace senf::log members + +template +prefix_ void senf::log::write(std::string msg) +{ + TargetRegistry::instance().write(Stream::instance(), Area::instance(), Level::value, msg); +} + +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// 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/Target.hh b/Utils/Logger/Target.hh index 6298800..9a47194 100644 --- a/Utils/Logger/Target.hh +++ b/Utils/Logger/Target.hh @@ -27,7 +27,11 @@ #define HH_Target_ 1 // Custom includes +#include +#include +#include #include "../singleton.hh" +#include "../mpl.hh" #include "StreamRegistry.hh" #include "AreaRegistry.hh" @@ -37,6 +41,8 @@ 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 @@ -45,8 +51,7 @@ namespace log { passed the log message and a complete set of logging parameters (\e stream, \e area and \e level). */ - class Target - : public senf::singleton + class Target : private boost::noncopyable { public: /////////////////////////////////////////////////////////////////////////// @@ -56,19 +61,24 @@ namespace log { ///\name Structors and default members ///@{ + Target(); virtual ~Target(); - // default default constructor - // default copy constructor - // default copy assignment - // default destructor + ///@} + + template + void route(); - // no conversion constructors + template + void route(); - ///@} + template + void route(); protected: + std::string timestamp(); + private: void route(detail::StreamBase const * stream, detail::AreaBase const * area, @@ -76,15 +86,30 @@ namespace log { void unroute(detail::StreamBase const * stream, detail::AreaBase const * area, unsigned level); + template + void route(detail::StreamBase const * stream, detail::AreaBase const *); + + template + void route(detail::StreamBase const * stream, detail::LevelBase const *); + void updateAreaCache(detail::AreaBase const & area, detail::StreamBase const * stream, unsigned level); - 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, + void write(boost::posix_time::ptime timestamp, detail::StreamBase const & stream, + detail::AreaBase const & area, unsigned level, std::string const & message); + +# ifdef DOXYGEN + protected: +# endif + + 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 + struct RoutingEntry { RoutingEntry(detail::StreamBase const * stream_, detail::AreaBase const * area_, @@ -104,14 +129,43 @@ namespace log { typedef std::vector RIB; RIB rib_; + + friend class TargetRegistry; }; + /** \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//////////////////////////////////////// #include "Target.cci" //#include "Target.ct" -//#include "Target.cti" +#include "Target.cti" #endif diff --git a/Utils/mpl.hh b/Utils/mpl.hh index bb9115e..761ebf4 100644 --- a/Utils/mpl.hh +++ b/Utils/mpl.hh @@ -39,6 +39,15 @@ namespace mpl { /** \defgroup senfmpl Low-level template meta programming helpers */ + /** \brief Marker class for empty default values etc. + + This is like Boosts \c boost::mpl::na just an empty class used as template default argument + to mark missing arguments + + \note Don't use this as an empty base class. We may add some informative members to this. + */ + struct nil {}; + /** \brief Return-value type used to implement overload selection The senf::mpl::rv type is used together with \ref SENF_MPL_RV() to select template