X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Utils%2FLogger%2FTarget.cc;h=22d5823d400f58bf7b5b9ce88fb6b1e452508961;hb=41eff772147b6df1961d9029ba6815b553b4f81d;hp=a7b734b2e5aac8791c9e20342324ee6b23c1ab8e;hpb=0d797005aea3471b1d4311709232ccf2c292f3c5;p=senf.git diff --git a/Utils/Logger/Target.cc b/Utils/Logger/Target.cc index a7b734b..22d5823 100644 --- a/Utils/Logger/Target.cc +++ b/Utils/Logger/Target.cc @@ -1,8 +1,8 @@ // $Id$ // -// Copyright (C) 2007 -// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) -// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Copyright (C) 2007 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY // Stefan Bund // // This program is free software; you can redistribute it and/or modify @@ -24,10 +24,15 @@ \brief Target non-inline non-template implementation */ #include "Target.hh" -//#include "Target.ih" +#include "Target.ih" // Custom includes #include +#include +#include "ConsoleTarget.hh" +#include "../Console/Console.hh" +#include "../Console/Sysdir.hh" +#include "../membind.hh" //#include "Target.mpp" #define prefix_ @@ -36,28 +41,128 @@ /////////////////////////////////////////////////////////////////////////// // senf::log::Target -prefix_ senf::log::Target::Target() +namespace senf { +namespace log { + + SENF_CONSOLE_REGISTER_ENUM_MEMBER( Target, action_t, (ACCEPT)(REJECT) ); + +}} + +namespace { +namespace local { + + enum Level { + VERBOSE = senf::log::VERBOSE::value, + NOTICE = senf::log::NOTICE::value, + MESSAGE = senf::log::MESSAGE::value, + IMPORTANT = senf::log::IMPORTANT::value, + CRITICAL = senf::log::CRITICAL::value, + FATAL = senf::log::FATAL::value + }; + SENF_CONSOLE_REGISTER_ENUM( Level, + (VERBOSE)(NOTICE)(MESSAGE)(IMPORTANT)(CRITICAL)(FATAL) ); + +}} + +prefix_ senf::log::Target::Target(std::string const & name) { - TargetRegistry::instance().registerTarget(this); + namespace kw = senf::console::kw; + + detail::TargetRegistry::instance().registerTarget(this, name); + consoleDir_().add("list", senf::membind(&Target::consoleList, this)) + .doc("Show routing table\n" + "\n" + "Columns:\n" + " # rule index\n" + " STREAM stream to match, empty to match all streams\n" + " AREA area to match, empty to match all targets\n" + " LEVEL match messages with level above this. Log levels in increasing order\n" + " are:\n" + " verbose, notice, message, important, critical, fatal\n" + " ACTION action to take: accept or reject"); + consoleDir_().add("route", + boost::function( + senf::membind( + static_cast(&Target::route), + this))) + .arg("stream", "stream to match or empty to match any stream", + kw::default_value="") + .arg("area", "area to match or empty to match any area", + kw::default_value="") + .arg("level", "log level, one of: VERBOSE, NOTICE, MESSAGE, IMPORTANT, CRITICAL, FATAL", + kw::default_value=local::VERBOSE) + .arg("action", "routing action, one of: ACCEPT, REJECT", + kw::default_value=ACCEPT) + .arg("index", "index at which to insert new rule", + kw::default_value=-1) + .doc("Add routing entry. Log messages are matched against the routing table beginning\n" + "with the first entry. The action of the first matching entry determines the\n" + "handling of the message.\n" + "\n" + "Examples:\n" + "\n" + " route\n" + " route all messages to this target.\n" + "\n" + " route \"\" my::Class\n" + " route all messages which are in the my::Class area.\n" + "\n" + " route senf::log::Debug \"\" VERBOSE REJECT\n" + " route \"\" \"\" VERBOSE\n" + " route all messages not in the senf::log::Debug stream to the current area.\n" + "\n" + "The additional optional index argument identifies the position in the routing table\n" + "where the new routing entry will be added. Positive numbers count from the\n" + "beginning, 0 being the first routing entry. Negative values count from the end.\n"); + consoleDir_().add("unroute", + senf::membind(static_cast(&Target::unroute), this)) + .arg("index", "index of routing entry to remove") + .overloadDoc("Remove routing entry with the given index"); + consoleDir_().add("unroute", + boost::function( + senf::membind( + static_cast(&Target::unroute), + this))) + .arg("stream", "stream to match or empty to match any stream", + kw::default_value="") + .arg("area", "area to match or empty to match any area", + kw::default_value="") + .arg("level", "log level, one of: VERBOSE, NOTICE, MESSAGE, IMPORTANT, CRITICAL, FATAL", + kw::default_value=local::VERBOSE) + .arg("action", "routing action, one of: ACCEPT, REJECT", + kw::default_value=ACCEPT) + .overloadDoc("Remove the routing entry matching the specified arguments."); + consoleDir_().add("flush", senf::membind(&Target::flush, this)) + .doc("Remove all routing entries clearing the routing table. This will disable all\n" + "logging output on this target."); } prefix_ senf::log::Target::~Target() { while( ! rib_.empty()) { - // This is terribly slow but simplifies the area cache handling and removing a target should - // be quite seldom + // This is slow but simplifies the area cache handling and removing a target should be + // relatively seldom 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, unsigned level, action_t action, int index) { - detail::StreamBase const * s (StreamRegistry::instance().lookup(stream)); - if (!s) - throw InvalidStreamException(); + detail::StreamBase const * s (0); + if (! stream.empty()) { + s = StreamRegistry::instance().lookup(stream); + if (!s) + throw InvalidStreamException(); + } detail::AreaBase const * a (0); if (! area.empty()) { a = AreaRegistry::instance().lookup(area); @@ -67,15 +172,35 @@ prefix_ void senf::log::Target::route(std::string const & stream, std::string co route(s, a, level, action, index); } +prefix_ void senf::log::Target::unroute(std::string const & stream, std::string const & area, + unsigned level, action_t action) +{ + detail::StreamBase const * s (0); + if (! stream.empty()) { + s = StreamRegistry::instance().lookup(stream); + if (!s) + throw InvalidStreamException(); + } + detail::AreaBase const * a (0); + if (! area.empty()) { + a = AreaRegistry::instance().lookup(area); + if (!a) + throw InvalidAreaException(); + } + unroute(s, a, level, action); +} + prefix_ void senf::log::Target::unroute(int index) { + if (rib_.empty()) + return; RIB::iterator i; if (index < 0) { if (RIB::size_type(-index) >= rib_.size()) i = rib_.begin(); else { i = rib_.end(); - std::advance(i, -index); + std::advance(i, index); } } else { if (RIB::size_type(index+1) >= rib_.size()) { @@ -86,12 +211,34 @@ 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) updateRoutingCache(entry.stream_, entry.area_); } +prefix_ void senf::log::Target::flush() +{ + RIB old; + rib_.swap(old); + RIB::const_iterator i (old.begin()); + RIB::const_iterator const i_end (old.end()); + for (; i != i_end; ++i) + if (i->action_ == ACCEPT) + updateRoutingCache(i->stream_, i->area_); +} + +//////////////////////////////////////// +// protected members + +prefix_ senf::log::detail::TargetRegistry::TargetRegistry() + : fallbackRouting_(true) +{ + console::sysdir().add("log", consoleDir_()); +} + //////////////////////////////////////// // private members @@ -105,7 +252,7 @@ prefix_ void senf::log::Target::route(detail::StreamBase const * stream, i = rib_.begin(); else { i = rib_.end(); - std::advance(i, -index - 1); + std::advance(i, index + 1 ); } } else { if (RIB::size_type(index) >= rib_.size()) @@ -118,13 +265,15 @@ prefix_ void senf::log::Target::route(detail::StreamBase const * stream, rib_.insert(i, RoutingEntry(stream, area, level, action)); if (action == ACCEPT) updateRoutingCache(stream, area); + // This disables the initial fallback routing + detail::TargetRegistry::instance().routed(); } prefix_ void senf::log::Target::unroute(detail::StreamBase const * stream, - detail::AreaBase const * area, unsigned level, + detail::AreaBase const * area, unsigned level, action_t action) { - RIB::iterator i = std::find(rib_.begin(), rib_.end(), + RIB::iterator i = std::find(rib_.begin(), rib_.end(), RoutingEntry(stream, area, level, action)); if (i != rib_.end()) unroute(std::distance(rib_.begin(), i)); @@ -154,7 +303,7 @@ prefix_ void senf::log::Target::updateRoutingCache(detail::StreamBase const * st if ( (! i->stream_ || i->stream_ == stream) && (! i->area_ || i->area_ == area) && i->action_ == ACCEPT ) { - unsigned l (i->level_ == NONE::value ? i->stream_->defaultRuntimeLimit() : i->level_); + unsigned l (i->level_ == NONE::value ? stream->defaultRuntimeLimit() : i->level_); if (l < limit) limit = l; } @@ -164,7 +313,7 @@ prefix_ void senf::log::Target::updateRoutingCache(detail::StreamBase const * st area->updateRoutingCache(*this, *stream, limit); } -prefix_ void senf::log::Target::write(boost::posix_time::ptime timestamp, +prefix_ void senf::log::Target::write(time_type timestamp, detail::StreamBase const & stream, detail::AreaBase const & area, unsigned level, std::string const & message) @@ -174,29 +323,80 @@ prefix_ void senf::log::Target::write(boost::posix_time::ptime timestamp, for (; i != i_end; ++i) if ( (! i->stream_ || i->stream_ == &stream) && (! i->area_ || i->area_ == &area) && - (i->level_ == NONE::value ? i->stream_->defaultRuntimeLimit() : i->level_) <= level ) { + (i->level_ == NONE::value ? stream.defaultRuntimeLimit() : i->level_) <= level ) { if (i->action_ == ACCEPT) v_write(timestamp, stream.v_name(), area.v_name(), level, message); return; } } +namespace { + std::string formatLabel(std::string const & l) + { + if (l.empty()) + return "-"; + if (l.size() > 29) + return l.substr(l.size()-29); + return l; + } +} + +prefix_ void senf::log::Target::consoleList(std::ostream & os) +{ + static char const * levels[] = { + "none", "verbose", "notice", "message", "important", "critical", "fatal", "disabled" }; + + boost::format fmt ("%2d %-29s %-29s %-9s %-6s\n"); + os << fmt % "#" % "STREAM" % "AREA" % "LEVEL" % "ACTION"; + unsigned n (0); + for (iterator i (begin()); i != end(); ++i, ++n) + os << fmt + % n + % formatLabel(i->stream()) + % formatLabel(i->area()) + % levels[i->level()] + % (i->action() == ACCEPT ? "accept" : "reject"); +} + /////////////////////////////////////////////////////////////////////////// -// senf::log::TargetRegistry +// senf::log::detail::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::registerTarget(Target * target, + std::string const & name) { - boost::posix_time::ptime timestamp (boost::posix_time::microsec_clock::universal_time()); - area.write(timestamp, stream, level, msg); + targets_.insert(target); + consoleDir_().add(name, target->consoleDir_()); } +prefix_ void senf::log::detail::TargetRegistry::write(StreamBase const & stream, + AreaBase const & area, unsigned level, + std::string const & msg) +{ + if (fallbackRouting_) { + if (level >= stream.defaultRuntimeLimit()) + static_cast(ConsoleTarget::instance()).v_write( + TimeSource::now(), stream.v_name(), area.v_name(), level, msg ); + } + else + area.write( TimeSource::now(), stream, level, msg ); +} +/////////////////////////////////////////////////////////////////////////// +// namespace members + +prefix_ std::ostream & senf::log::operator<<(std::ostream & os, senf::log::Target::action_t const & action) +{ + if( action == Target::ACCEPT) os << "ACCEPT"; + else if( action == Target::REJECT) os << "REJECT"; + else os << "unknown action"; + return os; +} + + ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_ //#include "Target.mpp" - + // Local Variables: // mode: c++ // fill-column: 100