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; }
60 /** \brief Logging target base class
62 Targets are the final destination of %log messages. Every message is eventually routed to
63 one or several targets.
65 \section target_routing Routing
67 Each target manages a routing table. The message meta-data (stream, area and level) is
68 matched against this table. If an entry matches, the action associated with this entry is
69 taken (either \c ACCEPT or \c REJECT).
71 Every target manages it's own routing table. Conceptually, every message will be routed to
72 every target where it will then be matched against each targets routing table (the
73 implementation is more efficient and utilizes a routing cache).
75 Each routing entry consists of the following parameters
76 \li (optional) \e stream. If specified, the entry will match only messages directed at that
78 \li (optional) \e area. If the area is specified, only messages directed at that area are
79 matched, otherwise any area will be allowed
80 \li (optional) \e level. If the log level is specified, messages will be accepted if their
81 level is at least that value. If the value is not specified, the limit will be taken
82 from the stream's default value.
84 Each parameter (stream, area and level) has two representations: A static (compile time
85 constant) representation, which is the representation also used in the log statements, and a
86 dynamic representation, which may be used for manipulating the routing table.
88 The static representation is used, when passing routing parameters via template arguments:
90 target.route<foo::SomeStream, senf::log::NOTICE>(senf::log::Target::REJECT);
91 target.route<foo::SomeStream>();
94 The identical routing statements may be expressed using dynamic routing via:
96 target.route("foo::SomeStream", "", senf::log::NOTICE::value, senf::log::Target::REJECT);
97 target.route("foo::SomeStream");
100 The static representation has the benefit of being compile-time type checked: Invalid
101 routing parameters will be caught while compiling the code. The dynamic representation is
102 more flexible as it allows to adjust routing from user input (e.g. configuration files).
104 The different object representations are:
105 \li The \e streams is statically represented by it's name, which is the name of a class
106 defined with \ref SENF_LOG_DEFINE_STREAM. The dynamic representation is a string
107 representation of this name.
108 \li The \e area is statically represented by it's name, which again is the name of a class
109 defined with \ref SENF_LOG_DEFINE_STREAM. The dynamic representation again is a string
110 representation of this class's name. The dynamic representation represents an absent
111 area with the empty string.
112 \li The \e level is statically represented by a level class from \ref
113 loglevels. Dynamically, it is represented by an unsigned integer number, the \c value
114 member of that class.
116 \section target_impl Implementing new targets
118 To implement a new target type, you need to derive from senf::log::Target and implement the
119 single \c v_write member. This member will be called whenever a message should be output.
121 The target may process the message in any arbitrary way: reformat it, write it into an SQL
122 DB, whatever can be envisioned. However, there is one important limitation: The \c v_write
123 call must \e not block. So for more complex scenarios, additional measures must be taken
124 (e.g. writing a %log backend daemon which receives the messages via UDP and processes
125 them). Of course, in rare cases messages might be lost but this cannot be avoided.
129 class Target : private boost::noncopyable
132 ///////////////////////////////////////////////////////////////////////////
135 /** \brief Routing action
137 Every routing entry is associated with a routing action. This action is final (for this
138 target. Each target is processed independently).
141 ACCEPT /** Output message */
142 , REJECT /** Suppress message output */
145 /** \brief Target routing entry
147 A single routing entry matches messages against their \e stream, \e area and \e
148 level. If the entry matches, the given \e action is performed.
150 \see senf::log::Target
154 std::string stream() const; ///< Stream to match
155 std::string area() const; ///< Area to match (empty of unspecified)
156 unsigned level() const; ///< Level to match (senf::log::NONE::value if unspecified)
157 action_t action() const; ///< Action to take
164 bool operator==(RoutingEntry const & other) const;
167 RoutingEntry(detail::StreamBase const * stream, detail::AreaBase const * area,
168 unsigned level, action_t action);
170 detail::StreamBase const * stream_;
171 detail::AreaBase const * area_;
179 typedef std::vector<RoutingEntry> RIB;
182 typedef RIB::const_iterator iterator; ///< Routing table iterator
183 typedef RIB::size_type size_type;
185 ///////////////////////////////////////////////////////////////////////////
186 ///\name Structors and default members
189 explicit Target(std::string const & name);
193 ///////////////////////////////////////////////////////////////////////////
199 template <class Stream, class Area, class Level> void route(
200 action_t action = ACCEPT, int index = -1); ///< Add route (static)
201 /**< Add a route for the given combination of \a Stream, \a
202 Area and \a Level. All parameters (\a Stream, \a Area
203 and \a Level) are optional (the template signature is
204 shown simplified here). So possible commands are:
207 target.route<SomeStream>();
208 target.route<SomeArea>();
209 target.route<SomeLevel>();
210 target.route<SomeStream, SomeArea>();
211 target.route<SomeStream, SomeLevel>();
212 target.route<SomeArea, SomeLevel>();
213 target.route<SomeStream, SomeArea, SomeLevel>();
216 See the class description for information on the \a
217 action and \a index parameters
219 \tparam Stream stream to match
220 \tparam Area area to match
221 \tparam Level level, matches messages with
222 at least the given level.
223 \param[in] action routing action to take
224 \param[in] index position of new route in the routing
229 void route(std::string const & stream, std::string const & area = "",
230 unsigned level = NONE::value, action_t action = ACCEPT, int index = -1);
231 ///< Add route (dynamic)
232 /**< Add a route for the given combination of \a stream, \a
233 area and \a level. All parameters (\a Stream, \a Area
234 and \a Level) are optional and may be omitted by
235 setting them to the empty string or the
236 senf::log::NONE::value respectively.
238 See the class description for information on the \a
239 action and \a index parameters
241 \throws InvalidStreamException if the given \a stream
242 is not found in the StreamRegistry
243 \throws InvalidAreaException if the given \a area is
244 not found in the AreaRegistry
246 \param[in] stream stream to match
247 \param[in] area area to match
248 \param[in] level level, matches messages with at least
250 \param[in] action routing action to take
251 \param[in] index position of new route in the routing
256 template <class Stream, class Area, class Level>
257 void unroute(action_t action = ACCEPT);
258 ///< Remove route (static)
259 /**< This member removes an arbitrary routing entry. The
260 template parameters are the same as for the
261 corresponding \ref route() call.
263 The routing table is searched for a route exactly
264 matching the given specification. If such a route is
265 found, it will be removed, otherwise the call will be
268 \tparam Stream stream to match
269 \tparam Area area to match
270 \tparam Level level, matches messages with
271 at least the given level.
272 \param[in] action routing action to take */
276 void unroute(std::string const & stream, std::string const & area = "",
277 unsigned level = NONE::value, action_t action = ACCEPT);
278 ///< Remove route (dynamic)
279 /**< This member removes an arbitrary routing entry. The \a
280 stream parameter is mandatory while either \a area or
281 \a level may be left unspecified by setting them to the
282 empty string or senf::log::NONE::value respectively.
284 The routing table is searched for a route exactly
285 matching the given specification. If such a route is
286 found, it will be removed, otherwise the call will be
289 \param[in] stream stream to match
290 \param[in] area area to match
291 \param[in] level level, matches messages with at least
293 \param[in] action routing action to take */
294 void unroute(int index=-1); ///< Remove route (indexed)
295 /**< This call will remove the route with the given index.
297 See the class documentation for more information on
300 \param[in] index index of routing entry to remove */
304 void route(action_t action = ACCEPT, int index = -1);
306 void route(action_t action = ACCEPT, int index = -1);
307 template <class A1, class A2>
308 void route(action_t action = ACCEPT, int index = -1);
309 template <class A1, class A2, class A3>
310 void route(action_t action = ACCEPT, int index = -1);
312 void unroute(action_t action = ACCEPT);
314 void unroute(action_t action = ACCEPT);
315 template <class A1, class A2>
316 void unroute(action_t action = ACCEPT);
317 template <class A1, class A2, class A3>
318 void unroute(action_t action = ACCEPT);
324 /** \brief Exception: Invalid stream */
325 struct InvalidStreamException : public senf::Exception
326 { InvalidStreamException()
327 : senf::Exception("senf::log::Target::InvalidStreamException"){} };
329 /** \brief Exception: Invalid area */
330 struct InvalidAreaException : public senf::Exception
331 { InvalidAreaException()
332 : senf::Exception("senf::log::Target::InvalidAreaException"){} };
334 iterator begin() const; ///< Iterator to beginning of routing table
335 iterator end() const; ///< Iterator past the end of routing table
337 RoutingEntry const & operator[](size_type i) const; ///< Access routing entry
339 size_type size() const; ///< Number of routing table entries
340 bool empty() const; ///< \c true, if routing table empty, \c false otherwise
342 void flush(); ///< Clear routing table
345 void route(detail::StreamBase const * stream, detail::AreaBase const * area,
346 unsigned level, action_t action, int index);
347 void unroute(detail::StreamBase const * stream, detail::AreaBase const * area,
348 unsigned level, action_t action);
350 void updateRoutingCache(detail::StreamBase const * stream, detail::AreaBase const * area);
352 void write(time_type timestamp, detail::StreamBase const & stream,
353 detail::AreaBase const & area, unsigned level, std::string const & message);
355 void consoleList(std::ostream & os);
361 virtual void v_write(time_type timestamp, std::string const & stream,
362 std::string const & area, unsigned level,
363 std::string const & message) = 0;
364 ///< Called to write out the routing message
365 /**< This member must be defined in the derived class to
366 somehow format and write the %log message.
368 Every %log message always possesses a complete set of
369 meta information (\a stream, \a area and \a level).
371 \note This member must \e not block since it may be
372 called from any unknown context. This prohibits
373 simple logging over NFS or many other network
376 \param[in] timestamp %log message timing information
377 \param[in] stream message stream
378 \param[in] area message area
379 \param[in] level message level
380 \param[in] message the message string */
388 console::LazyDirectory consoleDir_;
390 friend class detail::AreaBase;
391 friend class detail::TargetRegistry;
394 /** \brief Write route action
397 std::ostream & operator<<(std::ostream & os, Target::action_t const & action);
401 ///////////////////////////////hh.e////////////////////////////////////////
402 #include "Target.cci"
403 //#include "Target.ct"
404 #include "Target.cti"
411 // comment-column: 40
412 // c-file-style: "senf"
413 // indent-tabs-mode: nil
414 // ispell-local-dictionary: "american"
415 // compile-command: "scons -u test"