namespace impl {
- struct nil {};
-
template <class Base, class Policy, int _>
struct MakeSocketPolicy_merge
{};
{};
template <class Base>
- struct apply<Base,nil>
+ struct apply<Base,mpl::nil>
{
typedef Base type;
};
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<
<em>Runtime</em> 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 {
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<Stream,Area>::compileLimit::value );
};
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2007
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer NETwork research (NET)
+// Stefan Bund <g0dil@berlios.de>
+//
+// 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 <iostream>
+
+//#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"
+
+\f
+// 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:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2007
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer NETwork research (NET)
+// Stefan Bund <g0dil@berlios.de>
+//
+// 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
+
+\f
+// 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:
typedef runtimeLimit_ runtimeLimit; \
typedef compileLimit_ compileLimit; \
static std::string name() { return instance().v_name(); } \
+ unsigned defaultRuntimeLimit() const { return runtimeLimit::value; } \
+ using senf::singleton<stream>::instance; \
private: \
stream() { init(); } \
friend class senf::singleton<stream>; \
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, ; )
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( \
}
/** \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,
: public senf::log::detail::AreaBase, public senf::singleton<area> \
{ \
static std::string name() { return instance().v_name(); } \
+ using senf::singleton<area>::instance; \
decls \
private: \
area() { init(); } \
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2007
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer NETwork research (NET)
+// Stefan Bund <g0dil@berlios.de>
+//
+// 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 <locale>
+
+//#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<boost::posix_time::time_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"
+
+\f
+// 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:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2007
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer NETwork research (NET)
+// Stefan Bund <g0dil@berlios.de>
+//
+// 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 <boost/utility.hpp>
+#include <boost/scoped_ptr.hpp>
+#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
+ <pre>
+ <date> [<area>] <message>
+ </pre>
+
+ 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
+
+\f
+// 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:
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 <em>compile time constants</em> (they are all types, so it's
difficult form them to be something else).
*/
#define IH_Log_ 1
// Custom includes
+#include <sstream>
///////////////////////////////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<parameters::stream, parameters::area, parameters::level>(log.str()); \
} \
} while(0)
//#include "Log.test.hh"
//#include "Log.test.ih"
-// Custom includes
-#include <sstream>
-
// 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 <boost/test/auto_unit_test.hpp>
#include <boost/test/test_tools.hpp>
BOOST_AUTO_UNIT_TEST(logger)
{
+ senf::log::StringTarget target;
+
+ target.route<senf::log::Debug>();
+
+ // 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)
// 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
{
#include <boost/preprocessor/punctuation/comma_if.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/fold.hpp>
+#include <boost/mpl/if.hpp>
#include "../mpl.hh"
#include "Config.hh"
///////////////////////////////ih.p////////////////////////////////////////
-#ifndef _senf_LOG_STREAM
-# define _senf_LOG_STREAM std::cerr
-#endif
-
namespace senf {
namespace log {
template <class Base>
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
std::string fullName() const;
virtual std::string v_name() const;
+ virtual unsigned defaultRuntimeLimit() const = 0;
void init();
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2007
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer NETwork research (NET)
+// Stefan Bund <g0dil@berlios.de>
+//
+// 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_
+
+\f
+// 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:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2007
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer NETwork research (NET)
+// Stefan Bund <g0dil@berlios.de>
+//
+// 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 <sstream>
+#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<std::stringstream>,
+ public IOStreamTarget
+ {
+ typedef boost::base_from_member<std::stringstream> 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
+
+\f
+// 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:
///////////////////////////////////////////////////////////////////////////
// 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"
// 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_
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2007
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer NETwork research (NET)
+// Stefan Bund <g0dil@berlios.de>
+//
+// 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 <class Stream>
+prefix_ void senf::log::Target::route()
+{
+ route(&Stream::instance(), 0, NONE::value);
+}
+
+template <class Stream, class Arg0>
+prefix_ void senf::log::Target::route()
+{
+ route<Arg0>(&Stream::instance(), static_cast<Arg0*>(0));
+}
+
+template <class Stream, class Area, class Level>
+prefix_ void senf::log::Target::route()
+{
+ route(&Stream::instance(), &Area::instance(), Level::value);
+}
+
+////////////////////////////////////////
+// private members
+
+template <class Area>
+prefix_ void senf::log::Target::route(detail::StreamBase const * stream,
+ detail::AreaBase const *)
+{
+ route(stream, &Area::instance(), NONE::value);
+}
+
+template <class Level>
+prefix_ void senf::log::Target::route(detail::StreamBase const * stream,
+ detail::LevelBase const *)
+{
+ route(stream, 0, Level::value);
+}
+
+///////////////////////////////////////////////////////////////////////////
+// namespace senf::log members
+
+template <class Stream, class Area, class Level>
+prefix_ void senf::log::write(std::string msg)
+{
+ TargetRegistry::instance().write(Stream::instance(), Area::instance(), Level::value, msg);
+}
+
+///////////////////////////////cti.e///////////////////////////////////////
+#undef prefix_
+
+\f
+// 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:
#define HH_Target_ 1
// Custom includes
+#include <set>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/utility.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
passed the log message and a complete set of logging parameters (\e stream, \e area and \e
level).
*/
- class Target
- : public senf::singleton<Target>
+ class Target : private boost::noncopyable
{
public:
///////////////////////////////////////////////////////////////////////////
///\name Structors and default members
///@{
+ Target();
virtual ~Target();
- // default default constructor
- // default copy constructor
- // default copy assignment
- // default destructor
+ ///@}
+
+ template <class Stream>
+ void route();
- // no conversion constructors
+ template <class Stream, class Arg0>
+ void route();
- ///@}
+ template <class Stream, class Area, class Level>
+ void route();
protected:
+ std::string timestamp();
+
private:
void route(detail::StreamBase const * stream, detail::AreaBase const * area,
void unroute(detail::StreamBase const * stream, detail::AreaBase const * area,
unsigned level);
+ template <class Area>
+ void route(detail::StreamBase const * stream, detail::AreaBase const *);
+
+ template <class Level>
+ 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_,
typedef std::vector<RoutingEntry> RIB;
RIB rib_;
+
+ friend class TargetRegistry;
};
+ /** \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
/** \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