4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 // Stefan Bund <g0dil@berlios.de>
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 \brief Target public header */
26 #ifndef HH_SENF_Utils_Logger_Target_
27 #define HH_SENF_Utils_Logger_Target_ 1
32 #include <boost/utility.hpp>
33 #include <boost/type_traits/is_convertible.hpp>
34 #include "../singleton.hh"
36 #include "StreamRegistry.hh"
37 #include "../Exception.hh"
38 #include "TimeSource.hh"
39 #include "../Console/LazyDirectory.hh"
41 //#include "Target.mpp"
42 ///////////////////////////////hh.p////////////////////////////////////////
44 /** \defgroup targets Targets
46 Targets receive log messages and write them to some destination: The console, a log file, an SQL
47 DB and so on. Every target is derived from the \ref senf::log::Target base class. This base
48 class provides the target with the necessary routing infrastructure. The different targets only
49 differ in the way, they write the data.
51 \see senf::log::Target
57 namespace detail { class TargetRegistry; }
58 namespace detail { class AreaBase; }
59 namespace detail { struct LogParameters; }
61 /** \brief Logging target base class
63 Targets are the final destination of %log messages. Every message is eventually routed to
64 one or several targets.
66 \section target_routing Routing
68 Each target manages a routing table. The message meta-data (stream, area and level) is
69 matched against this table. If an entry matches, the action associated with this entry is
70 taken (either \c ACCEPT or \c REJECT).
72 Every target manages it's own routing table. Conceptually, every message will be routed to
73 every target where it will then be matched against each targets routing table (the
74 implementation is more efficient and utilizes a routing cache).
76 Each routing entry consists of the following parameters
77 \li (optional) \e stream. If specified, the entry will match only messages directed at that
79 \li (optional) \e area. If the area is specified, only messages directed at that area are
80 matched, otherwise any area will be allowed
81 \li (optional) \e level. If the %log level is specified, messages will be accepted if their
82 level is at least that value. If the value is not specified, the limit will be taken
83 from the stream's default value.
85 Each parameter (stream, area and level) has two representations: A static (compile time
86 constant) representation, which is the representation also used in the %log statements, and a
87 dynamic (runtime) representation.
89 The static representation is used, when passing routing parameters via template arguments:
91 target.route<foo::SomeStream, senf::log::NOTICE>(senf::log::Target::REJECT);
92 target.route<foo::SomeStream>();
95 The identical routing statements may be expressed using dynamic routing via:
97 target.route("foo::SomeStream", "", senf::log::NOTICE::value, senf::log::Target::REJECT);
98 target.route("foo::SomeStream");
101 The static representation has the benefit of being compile-time type checked: Invalid
102 routing parameters will be caught while compiling the code. The dynamic representation is
103 more flexible as it allows to adjust routing from user input (e.g. configuration files).
105 The different object representations are:
106 \li The \e streams is statically represented by it's name, which is the name of a class
107 defined with \ref SENF_LOG_DEFINE_STREAM. The dynamic representation is a string
108 representation of this name.
109 \li The \e area is statically represented by it's name, which again is the name of a class
110 defined with \ref SENF_LOG_DEFINE_STREAM. The dynamic representation again is a string
111 representation of this class's name. The dynamic representation represents an absent
112 area with the empty string.
113 \li The \e level is statically represented by a level class from \ref
114 loglevels. Dynamically, it is represented by an unsigned integer number, the \c value
115 member of that class.
117 \subsection target_routing_processing Ordering routing entries and route processing
119 The routing table is processed from first route to last route, the first matching entry
120 determines the fate of a log messages. Therefore, the ordering of routing entries is
123 If no position is explicitly specified, new routing entries are added to the end of the
124 routing table. All routing statements however take an index as optional argument to
125 explicitly specify the position of the new routing entry.
127 The index value starts from 0 for the first route. The value gives the position the new
128 routing entry will have after it has been added. An index of 0 will thus insert the new
129 routing entry at the beginning of the table. Negative values count from the back, -1 being
132 \section target_impl Implementing new targets
134 To implement a new target type, you need to derive from senf::log::Target and implement the
135 single \c v_write member. This member will be called whenever a message should be output.
137 The target may process the message in any arbitrary way: reformat it, write it into an SQL
138 DB, whatever can be envisioned. However, there is one important limitation: The \c v_write
139 call must \e not block. So for more complex scenarios, additional measures must be taken
140 (e.g. writing a %log backend daemon which receives the messages via UDP and processes
141 them). Of course, in rare cases messages might be lost but this cannot be avoided.
145 class Target : private boost::noncopyable
148 ///////////////////////////////////////////////////////////////////////////
151 /** \brief Routing action
153 Every routing entry is associated with a routing action. This action is final (for this
154 target. Each target is processed independently).
157 ACCEPT /** Output message */
158 , REJECT /** Suppress message output */
161 /** \brief Target routing entry
163 A single routing entry matches messages against their \e stream, \e area and \e
164 level. If the entry matches, the given \e action is performed.
166 \see senf::log::Target
170 std::string stream() const; ///< Stream to match
171 std::string area() const; ///< Area to match (empty of unspecified)
172 unsigned level() const; ///< Level to match (senf::log::NONE::value if unspecified)
173 action_t action() const; ///< Action to take
180 bool operator==(RoutingEntry const & other) const;
183 RoutingEntry(detail::StreamBase const * stream, detail::AreaBase const * area,
184 unsigned level, action_t action);
186 detail::StreamBase const * stream_;
187 detail::AreaBase const * area_;
195 typedef std::vector<RoutingEntry> RIB;
198 typedef RIB::const_iterator iterator; ///< Routing table iterator
199 typedef RIB::size_type size_type;
201 ///////////////////////////////////////////////////////////////////////////
202 ///\name Structors and default members
205 explicit Target(std::string const & name);
209 ///////////////////////////////////////////////////////////////////////////
215 template <class Stream, class Area, class Level> void route(
216 action_t action = ACCEPT, int index = -1); ///< Add route (static)
217 /**< Add a route for the given combination of \a Stream, \a
218 Area and \a Level. All parameters (\a Stream, \a Area
219 and \a Level) are optional (the template signature is
220 shown simplified here). So possible commands are:
223 target.route<SomeStream>();
224 target.route<SomeArea>();
225 target.route<SomeLevel>();
226 target.route<SomeStream, SomeArea>();
227 target.route<SomeStream, SomeLevel>();
228 target.route<SomeArea, SomeLevel>();
229 target.route<SomeStream, SomeArea, SomeLevel>();
232 See the class description for information on the \a
233 action and \a index parameters
235 \tparam Stream stream to match
236 \tparam Area area to match
237 \tparam Level level, matches messages with
238 at least the given level.
239 \param[in] action routing action to take
240 \param[in] index position of new route in the routing
245 void route(std::string const & stream, std::string const & area = "",
246 unsigned level = NONE::value, action_t action = ACCEPT, int index = -1);
247 ///< Add route (dynamic)
248 /**< Add a route for the given combination of \a stream, \a
249 area and \a level. All parameters (\a Stream, \a Area
250 and \a Level) are optional and may be omitted by
251 setting them to the empty string or the
252 senf::log::NONE::value respectively.
254 See the class description for information on the \a
255 action and \a index parameters
257 \throws InvalidStreamException if the given \a stream
258 is not found in the StreamRegistry
259 \throws InvalidAreaException if the given \a area is
260 not found in the AreaRegistry
262 \param[in] stream stream to match
263 \param[in] area area to match
264 \param[in] level level, matches messages with at least
266 \param[in] action routing action to take
267 \param[in] index position of new route in the routing
272 template <class Stream, class Area, class Level>
273 void unroute(action_t action = ACCEPT);
274 ///< Remove route (static)
275 /**< This member removes an arbitrary routing entry. The
276 template parameters are the same as for the
277 corresponding \ref route() call.
279 The routing table is searched for a route exactly
280 matching the given specification. If such a route is
281 found, it will be removed, otherwise the call will be
284 \tparam Stream stream to match
285 \tparam Area area to match
286 \tparam Level level, matches messages with
287 at least the given level.
288 \param[in] action routing action to take */
292 void unroute(std::string const & stream, std::string const & area = "",
293 unsigned level = NONE::value, action_t action = ACCEPT);
294 ///< Remove route (dynamic)
295 /**< This member removes an arbitrary routing entry. The \a
296 stream parameter is mandatory while either \a area or
297 \a level may be left unspecified by setting them to the
298 empty string or senf::log::NONE::value respectively.
300 The routing table is searched for a route exactly
301 matching the given specification. If such a route is
302 found, it will be removed, otherwise the call will be
305 \param[in] stream stream to match
306 \param[in] area area to match
307 \param[in] level level, matches messages with at least
309 \param[in] action routing action to take */
310 void unroute(int index=-1); ///< Remove route (indexed)
311 /**< This call will remove the route with the given index.
313 See the class documentation for more information on
316 \param[in] index index of routing entry to remove */
320 void route(action_t action = ACCEPT, int index = -1);
322 void route(action_t action = ACCEPT, int index = -1);
323 template <class A1, class A2>
324 void route(action_t action = ACCEPT, int index = -1);
325 template <class A1, class A2, class A3>
326 void route(action_t action = ACCEPT, int index = -1);
328 void unroute(action_t action = ACCEPT);
330 void unroute(action_t action = ACCEPT);
331 template <class A1, class A2>
332 void unroute(action_t action = ACCEPT);
333 template <class A1, class A2, class A3>
334 void unroute(action_t action = ACCEPT);
340 /** \brief Exception: Invalid stream */
341 struct InvalidStreamException : public senf::Exception
342 { InvalidStreamException()
343 : senf::Exception("senf::log::Target::InvalidStreamException"){} };
345 /** \brief Exception: Invalid area */
346 struct InvalidAreaException : public senf::Exception
347 { InvalidAreaException()
348 : senf::Exception("senf::log::Target::InvalidAreaException"){} };
350 iterator begin() const; ///< Iterator to beginning of routing table
351 iterator end() const; ///< Iterator past the end of routing table
353 RoutingEntry const & operator[](size_type i) const; ///< Access routing entry
355 size_type size() const; ///< Number of routing table entries
356 bool empty() const; ///< \c true, if routing table empty, \c false otherwise
358 void flush(); ///< Clear routing table
360 senf::console::ScopedDirectory<> & consoleDir(); ///< Get console/config directory
363 void route(detail::StreamBase const * stream, detail::AreaBase const * area,
364 unsigned level, action_t action, int index);
365 void unroute(detail::StreamBase const * stream, detail::AreaBase const * area,
366 unsigned level, action_t action);
368 void updateRoutingCache(detail::StreamBase const * stream, detail::AreaBase const * area);
370 void write(time_type timestamp, detail::StreamBase const & stream,
371 detail::AreaBase const & area, unsigned level, std::string const & message);
373 void consoleList(std::ostream & os);
374 void consoleRoute(int index, detail::LogParameters const & pm, action_t action);
375 void consoleUnroute(detail::LogParameters const & pm, action_t action);
381 virtual void v_write(time_type timestamp, std::string const & stream,
382 std::string const & area, unsigned level,
383 std::string const & message) = 0;
384 ///< Called to write out the routing message
385 /**< This member must be defined in the derived class to
386 somehow format and write the %log message.
388 Every %log message always possesses a complete set of
389 meta information (\a stream, \a area and \a level).
391 \note This member must \e not block since it may be
392 called from any unknown context. This prohibits
393 simple logging over NFS or many other network
396 \param[in] timestamp %log message timing information
397 \param[in] stream message stream
398 \param[in] area message area
399 \param[in] level message level
400 \param[in] message the message string */
408 console::LazyDirectory consoleDir_;
410 friend class detail::AreaBase;
411 friend class detail::TargetRegistry;
414 /** \brief Write route action
417 std::ostream & operator<<(std::ostream & os, Target::action_t const & action);
421 ///////////////////////////////hh.e////////////////////////////////////////
422 #include "Target.cci"
423 //#include "Target.ct"
424 #include "Target.cti"
431 // comment-column: 40
432 // c-file-style: "senf"
433 // indent-tabs-mode: nil
434 // ispell-local-dictionary: "american"
435 // compile-command: "scons -u test"