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"
40 //#include "Target.mpp"
41 ///////////////////////////////hh.p////////////////////////////////////////
43 /** \defgroup targets Targets
45 Targets receive log messages and write them to some destination: The console, a log file, an SQL
46 DB and so on. Every target is derived from the \ref senf::log::Target base class. This base
47 class provides the target with the necessary routing infrastructure. The different targets only
48 differ in the way, they write the data.
50 \see senf::log::Target
56 namespace detail { class TargetRegistry; }
57 namespace detail { class AreaBase; }
59 /** \brief Logging target base class
61 Targets are the final destination of %log messages. Every message is eventually routed to
62 one or several targets.
64 \section target_routing Routing
66 Each target manages a routing table. The message meta-data (stream, area and level) is
67 matched against this table. If an entry matches, the action associated with this entry is
68 taken (either \c ACCEPT or \c REJECT).
70 Every target manages it's own routing table. Conceptually, every message will be routed to
71 every target where it will then be matched against each targets routing table (the
72 implementation is more efficient and utilizes a routing cache).
74 Each routing entry consists of the following parameters
75 \li (optional) \e stream. If specified, the entry will match only messages directed at that
77 \li (optional) \e area. If the area is specified, only messages directed at that area are
78 matched, otherwise any area will be allowed
79 \li (optional) \e level. If the log level is specified, messages will be accepted if their
80 level is at least that value. If the value is not specified, the limit will be taken
81 from the stream's default value.
83 Each parameter (stream, area and level) has two representations: A static (compile time
84 constant) representation, which is the representation also used in the log statements, and a
85 dynamic representation, which may be used for manipulating the routing table.
87 The static representation is used, when passing routing parameters via template arguments:
89 target.route<foo::SomeStream, senf::log::NOTICE>(senf::log::Target::REJECT);
90 target.route<foo::SomeStream>();
93 The identical routing statements may be expressed using dynamic routing via:
95 target.route("foo::SomeStream", "", senf::log::NOTICE::value, senf::log::Target::REJECT);
96 target.route("foo::SomeStream");
99 The static representation has the benefit of being compile-time type checked: Invalid
100 routing parameters will be caught while compiling the code. The dynamic representation is
101 more flexible as it allows to adjust routing from user input (e.g. configuration files).
103 The different object representations are:
104 \li The \e streams is statically represented by it's name, which is the name of a class
105 defined with \ref SENF_LOG_DEFINE_STREAM. The dynamic representation is a string
106 representation of this name.
107 \li The \e area is statically represented by it's name, which again is the name of a class
108 defined with \ref SENF_LOG_DEFINE_STREAM. The dynamic representation again is a string
109 representation of this class's name. The dynamic representation represents an absent
110 area with the empty string.
111 \li The \e level is statically represented by a level class from \ref
112 loglevels. Dynamically, it is represented by an unsigned integer number, the \c value
113 member of that class.
115 \section target_impl Implementing new targets
117 To implement a new target type, you need to derive from senf::log::Target and implement the
118 single \c v_write member. This member will be called whenever a message should be output.
120 The target may process the message in any arbitrary way: reformat it, write it into an SQL
121 DB, whatever can be envisioned. However, there is one important limitation: The \c v_write
122 call must \e not block. So for more complex scenarios, additional measures must be taken
123 (e.g. writing a %log backend daemon which receives the messages via UDP and processes
124 them). Of course, in rare cases messages might be lost but this cannot be avoided.
128 class Target : private boost::noncopyable
131 ///////////////////////////////////////////////////////////////////////////
134 /** \brief Routing action
136 Every routing entry is associated with a routing action. This action is final (for this
137 target. Each target is processed independently).
140 ACCEPT /** Output message */
141 , REJECT /** Suppress message output */
144 /** \brief Target routing entry
146 A single routing entry matches messages against their \e stream, \e area and \e
147 level. If the entry matches, the given \e action is performed.
149 \see senf::log::Target
153 std::string stream() const; ///< Stream to match
154 std::string area() const; ///< Area to match (empty of unspecified)
155 unsigned level() const; ///< Level to match (senf::log::NONE::value if unspecified)
156 action_t action() const; ///< Action to take
163 bool operator==(RoutingEntry const & other) const;
166 RoutingEntry(detail::StreamBase const * stream, detail::AreaBase const * area,
167 unsigned level, action_t action);
169 detail::StreamBase const * stream_;
170 detail::AreaBase const * area_;
178 typedef std::vector<RoutingEntry> RIB;
181 typedef RIB::const_iterator iterator; ///< Routing table iterator
182 typedef RIB::size_type size_type;
184 ///////////////////////////////////////////////////////////////////////////
185 ///\name Structors and default members
192 ///////////////////////////////////////////////////////////////////////////
198 template <class Stream, class Area, class Level> void route(
199 action_t action = ACCEPT, int index = -1); ///< Add route (static)
200 /**< Add a route for the given combination of \a Stream, \a
201 Area and \a Level. All parameters (\a Stream, \a Area
202 and \a Level) are optional (the template signature is
203 shown simplified here). So possible commands are:
206 target.route<SomeStream>();
207 target.route<SomeArea>();
208 target.route<SomeLevel>();
209 target.route<SomeStream, SomeArea>();
210 target.route<SomeStream, SomeLevel>();
211 target.route<SomeArea, SomeLevel>();
212 target.route<SomeStream, SomeArea, SomeLevel>();
215 See the class description for information on the \a
216 action and \a index parameters
218 \tparam Stream stream to match
219 \tparam Area area to match
220 \tparam Level level, matches messages with
221 at least the given level.
222 \param[in] action routing action to take
223 \param[in] index position of new route in the routing
228 void route(std::string const & stream, std::string const & area = "",
229 unsigned level = NONE::value, action_t action = ACCEPT, int index = -1);
230 ///< Add route (dynamic)
231 /**< Add a route for the given combination of \a stream, \a
232 area and \a level. All parameters (\a Stream, \a Area
233 and \a Level) are optional and may be omitted by
234 setting them to the empty string or the
235 senf::log::NONE::value respectively.
237 See the class description for information on the \a
238 action and \a index parameters
240 \throws InvalidStreamException if the given \a stream
241 is not found in the StreamRegistry
242 \throws InvalidAreaException if the given \a area is
243 not found in the AreaRegistry
245 \param[in] stream stream to match
246 \param[in] area area to match
247 \param[in] level level, matches messages with at least
249 \param[in] action routing action to take
250 \param[in] index position of new route in the routing
255 template <class Stream, class Area, class Level>
256 void unroute(action_t action = ACCEPT);
257 ///< Remove route (static)
258 /**< This member removes an arbitrary routing entry. The
259 template parameters are the same as for the
260 corresponding \ref route() call.
262 The routing table is searched for a route exactly
263 matching the given specification. If such a route is
264 found, it will be removed, otherwise the call will be
267 \tparam Stream stream to match
268 \tparam Area area to match
269 \tparam Level level, matches messages with
270 at least the given level.
271 \param[in] action routing action to take */
275 void unroute(std::string const & stream, std::string const & area = "",
276 unsigned level = NONE::value, action_t action = ACCEPT);
277 ///< Remove route (dynamic)
278 /**< This member removes an arbitrary routing entry. The \a
279 stream parameter is mandatory while either \a area or
280 \a level may be left unspecified by setting them to the
281 empty string or senf::log::NONE::value respectively.
283 The routing table is searched for a route exactly
284 matching the given specification. If such a route is
285 found, it will be removed, otherwise the call will be
288 \param[in] stream stream to match
289 \param[in] area area to match
290 \param[in] level level, matches messages with at least
292 \param[in] action routing action to take */
293 void unroute(int index=-1); ///< Remove route (indexed)
294 /**< This call will remove the route with the given index.
296 See the class documentation for more information on
299 \param[in] index index of routing entry to remove */
303 void route(action_t action = ACCEPT, int index = -1);
305 void route(action_t action = ACCEPT, int index = -1);
306 template <class A1, class A2>
307 void route(action_t action = ACCEPT, int index = -1);
308 template <class A1, class A2, class A3>
309 void route(action_t action = ACCEPT, int index = -1);
311 void unroute(action_t action = ACCEPT);
313 void unroute(action_t action = ACCEPT);
314 template <class A1, class A2>
315 void unroute(action_t action = ACCEPT);
316 template <class A1, class A2, class A3>
317 void unroute(action_t action = ACCEPT);
323 /** \brief Exception: Invalid stream */
324 struct InvalidStreamException : public senf::Exception
325 { InvalidStreamException()
326 : senf::Exception("senf::log::Target::InvalidStreamException"){} };
328 /** \brief Exception: Invalid area */
329 struct InvalidAreaException : public senf::Exception
330 { InvalidAreaException()
331 : senf::Exception("senf::log::Target::InvalidAreaException"){} };
333 iterator begin() const; ///< Iterator to beginning of routing table
334 iterator end() const; ///< Iterator past the end of routing table
336 RoutingEntry const & operator[](size_type i) const; ///< Access routing entry
338 size_type size() const; ///< Number of routing table entries
339 bool empty() const; ///< \c true, if routing table empty, \c false otherwise
341 void flush(); ///< Clear routing table
344 void route(detail::StreamBase const * stream, detail::AreaBase const * area,
345 unsigned level, action_t action, int index);
346 void unroute(detail::StreamBase const * stream, detail::AreaBase const * area,
347 unsigned level, action_t action);
349 void updateRoutingCache(detail::StreamBase const * stream, detail::AreaBase const * area);
351 void write(time_type timestamp, detail::StreamBase const & stream,
352 detail::AreaBase const & area, unsigned level, std::string const & message);
358 virtual void v_write(time_type timestamp, std::string const & stream,
359 std::string const & area, unsigned level,
360 std::string const & message) = 0;
361 ///< Called to write out the routing message
362 /**< This member must be defined in the derived class to
363 somehow format and write the %log message.
365 Every %log message always possesses a complete set of
366 meta information (\a stream, \a area and \a level).
368 \note This member must \e not block since it may be
369 called from any unknown context. This prohibits
370 simple logging over NFS or many other network
373 \param[in] timestamp %log message timing information
374 \param[in] stream message stream
375 \param[in] area message area
376 \param[in] level message level
377 \param[in] message the message string */
385 friend class detail::AreaBase;
386 friend class detail::TargetRegistry;
389 /** \brief Write route action
392 std::ostream & operator<<(std::ostream & os, Target::action_t const & action);
396 ///////////////////////////////hh.e////////////////////////////////////////
397 #include "Target.cci"
398 //#include "Target.ct"
399 #include "Target.cti"
406 // comment-column: 40
407 // c-file-style: "senf"
408 // indent-tabs-mode: nil
409 // ispell-local-dictionary: "american"
410 // compile-command: "scons -u test"