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);
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
183 ///////////////////////////////////////////////////////////////////////////
184 ///\name Structors and default members
191 ///////////////////////////////////////////////////////////////////////////
197 template <class Stream, class Area, class Level> void route(
198 action_t action = ACCEPT, int index = -1); ///< Add route (static)
199 /**< Add a route for the given combination of \a Stream, \a
200 Area and \a Level. All parameters (\a Stream, \a Area
201 and \a Level) are optional (the template signature is
202 shown simplified here). So possible commands are:
205 target.route<SomeStream>();
206 target.route<SomeArea>();
207 target.route<SomeLevel>();
208 target.route<SomeStream, SomeArea>();
209 target.route<SomeStream, SomeLevel>();
210 target.route<SomeArea, SomeLevel>();
211 target.route<SomeStream, SomeArea, SomeLevel>();
214 See the class description for information on the \a
215 action and \a index parameters
217 \tparam Stream stream to match
218 \tparam Area area to match
219 \tparam Level level, matches messages with
220 at least the given level.
221 \param[in] action routing action to take
222 \param[in] index position of new route in the routing
227 void route(std::string const & stream, std::string const & area = "",
228 unsigned level = NONE::value, action_t action = ACCEPT, int index = -1);
229 ///< Add route (dynamic)
230 /**< Add a route for the given combination of \a stream, \a
231 area and \a level. All parameters (\a Stream, \a Area
232 and \a Level) are optional and may be omitted by
233 setting them to the empty string or the
234 senf::log::NONE::value respectively.
236 See the class description for information on the \a
237 action and \a index parameters
239 \throws InvalidStreamException if the given \a stream
240 is not found in the StreamRegistry
241 \throws InvalidAreaException if the given \a area is
242 not found in the AreaRegistry
244 \param[in] stream stream to match
245 \param[in] area area to match
246 \param[in] level level, matches messages with at least
248 \param[in] action routing action to take
249 \param[in] index position of new route in the routing
254 template <class Stream, class Area, class Level>
255 void unroute(action_t action = ACCEPT);
256 ///< Remove route (static)
257 /**< This member removes an arbitrary routing entry. The
258 template parameters are the same as for the
259 corresponding \ref route() call.
261 The routing table is searched for a route exactly
262 matching the given specification. If such a route is
263 found, it will be removed, otherwise the call will be
266 \tparam Stream stream to match
267 \tparam Area area to match
268 \tparam Level level, matches messages with
269 at least the given level.
270 \param[in] action routing action to take */
274 void unroute(std::string const & stream, std::string const & area = "",
275 unsigned level = NONE::value, action_t action = ACCEPT);
276 ///< Remove route (dynamic)
277 /**< This member removes an arbitrary routing entry. The \a
278 stream parameter is mandatory while either \a area or
279 \a level may be left unspecified by setting them to the
280 empty string or senf::log::NONE::value respectively.
282 The routing table is searched for a route exactly
283 matching the given specification. If such a route is
284 found, it will be removed, otherwise the call will be
287 \param[in] stream stream to match
288 \param[in] area area to match
289 \param[in] level level, matches messages with at least
291 \param[in] action routing action to take */
292 void unroute(int index=-1); ///< Remove route (indexed)
293 /**< This call will remove the route with the given index.
295 See the class documentation for more information on
298 \param[in] index index of routing entry to remove */
302 void route(action_t action = ACCEPT, int index = -1);
304 void route(action_t action = ACCEPT, int index = -1);
305 template <class A1, class A2>
306 void route(action_t action = ACCEPT, int index = -1);
307 template <class A1, class A2, class A3>
308 void route(action_t action = ACCEPT, int index = -1);
310 void unroute(action_t action = ACCEPT);
312 void unroute(action_t action = ACCEPT);
313 template <class A1, class A2>
314 void unroute(action_t action = ACCEPT);
315 template <class A1, class A2, class A3>
316 void unroute(action_t action = ACCEPT);
322 /** \brief Exception: Invalid stream */
323 struct InvalidStreamException : public senf::Exception
324 { InvalidStreamException()
325 : senf::Exception("senf::log::Target::InvalidStreamException"){} };
327 /** \brief Exception: Invalid area */
328 struct InvalidAreaException : public senf::Exception
329 { InvalidAreaException()
330 : senf::Exception("senf::log::Target::InvalidAreaException"){} };
332 iterator begin() const; ///< Iterator to beginning of routing table
333 iterator end() const; ///< Iterator past the end of routing table
336 void route(detail::StreamBase const * stream, detail::AreaBase const * area,
337 unsigned level, action_t action, int index);
338 void unroute(detail::StreamBase const * stream, detail::AreaBase const * area,
339 unsigned level, action_t action);
341 void updateRoutingCache(detail::StreamBase const * stream, detail::AreaBase const * area);
343 void write(time_type timestamp, detail::StreamBase const & stream,
344 detail::AreaBase const & area, unsigned level, std::string const & message);
350 virtual void v_write(time_type timestamp, std::string const & stream,
351 std::string const & area, unsigned level,
352 std::string const & message) = 0;
353 ///< Called to write out the routing message
354 /**< This member must be defined in the derived class to
355 somehow format and write the %log message.
357 Every %log message always possesses a complete set of
358 meta information (\a stream, \a area and \a level).
360 \note This member must \e not block since it may be
361 called from any unknown context. This prohibits
362 simple logging over NFS or many other network
365 \param[in] timestamp %log message timing information
366 \param[in] stream message stream
367 \param[in] area message area
368 \param[in] level message level
369 \param[in] message the message string */
377 friend class detail::AreaBase;
378 friend class detail::TargetRegistry;
383 ///////////////////////////////hh.e////////////////////////////////////////
384 #include "Target.cci"
385 //#include "Target.ct"
386 #include "Target.cti"
393 // comment-column: 40
394 // c-file-style: "senf"
395 // indent-tabs-mode: nil
396 // ispell-local-dictionary: "american"
397 // compile-command: "scons -u test"