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 */
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 one
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 routing message will be
71 routed to 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. The entry will match only messages directed at that stream
76 \li (optional) \e area. If the area is specified, only messages directed at that area are
77 matched, otherwise any area will be allowed
78 \li (optional) \e level. If the log level is specified, messages will be accepted if their
79 level is at least that value. If the value is not specified, the limit will be taken
80 from the stream's default value.
82 Each parameter (stream, area and level) has two representations: A static (compile time
83 constant) representation, which is the representation also used in the log statements, and a
84 dynamic representation, which may be used for manipulating the routing table.
86 The static representation is used, when passing routing parameters via template arguments:
88 target.route<foo::SomeStream, senf::log::NOTICE>(senf::log::Target::REJECT);
89 target.route<foo::SomeStream>();
91 The identical routing statements may be expressed using dynamic routing via:
93 target.route("foo::SomeStream", "", senf::log::NOTICE::value, senf::log::Target::REJECT);
94 target.route("foo::SomeStream");
96 The static representation has the benefit of being compile-time type checked: Invalid
97 routing parameters will be caught while compiling the code. The dynamic representation is
98 more flexible as it allows to adjust routing from user input (e.g. configuration files).
100 The different object representations are:
101 \li The \e streams is statically represented by it's name, which is the name of a class
102 defined with \ref SENF_LOG_DEFINE_STREAM. The dynamic representation is a string
103 representation of this name.
104 \li The \e area is statically represented by it's name, which again is the name of a class
105 defined with \ref SENF_LOG_DEFINE_STREAM. The dynamic representation again is a string
106 representation of this class's name. The dynamic representation represents an absent
107 area with the empty string.
108 \li The \e level is statically represented by a level class from \ref
109 loglevels. Dynamically, it is represented by an unsigned integer number, the \c value
110 member of that class.
112 \section target_impl Implementing new targets
114 To implement a new target type, you need to derive from senf::log::Target and implement the
115 single \c v_write member. This member will be called whenever a message should be output.
117 The target may process in any arbitrary way: reformat, writing it into an SQL DB, whatever
118 can be envisioned. However, there is one important limitation: The \c v_write call must not
119 block. So for more complex scenarios, additional measures must be taken (e.g. writing a %log
120 backend daemon which receives the messages via UDP and processes them). Of course, in rare
121 cases messages might be lost but this cannot be avoided.
125 class Target : private boost::noncopyable
128 ///////////////////////////////////////////////////////////////////////////
131 /** \brief Routing action
133 Every routing entry is associated with a routing action. This action is final (for this
134 target. Each target is processed independently).
137 ACCEPT /** Output message */
138 , REJECT /** Suppress message output */
141 /** \brief Target routing entry
143 A single routing entry matches messages against their \e stream, \e area and \e
144 level. If the entry matches, the given \e action is performed.
146 \see senf::log::Target
150 std::string stream() const; ///< Stream to match
151 std::string area() const; ///< Area to match (empty of unspecified)
152 unsigned level() const; ///< Level to match (senf::log::NONE::value if unspecified)
153 action_t action() const; ///< Action to take
160 bool operator==(RoutingEntry const & other);
163 RoutingEntry(detail::StreamBase const * stream, detail::AreaBase const * area,
164 unsigned level, action_t action);
166 detail::StreamBase const * stream_;
167 detail::AreaBase const * area_;
175 typedef std::vector<RoutingEntry> RIB;
178 typedef RIB::const_iterator iterator; ///< Routing table iterator
180 ///////////////////////////////////////////////////////////////////////////
181 ///\name Structors and default members
188 ///////////////////////////////////////////////////////////////////////////
194 template <class Stream, class Area, class Level> void route(
195 action_t action = ACCEPT, int index = -1); ///< Add route (static)
196 /**< Add a route for the given combination of \a Stream, \a
197 Area and \a Level. All parameters (\a Stream, \a Area
198 and \a Level) are optional (the template signature is
199 shown simplified here). Examples:
201 target.route<SomeLevel>();
202 target.route<SomeStream>();
203 target.route<SomeStream, SomeLevel>();
204 target.route<SomeStream, SomeArea>();
205 target.route<SomeStream, SomeArea, SomeLevel>();
208 See the class description for information on the \a
209 action and \a index parameters
211 \tparam Stream stream to match
212 \tparam Area area to match
213 \tparam Level level, matches messages with
214 at least the given level.
215 \param[in] action routing action to take
216 \param[in] index position of new route in the routing
221 void route(std::string const & stream, std::string const & area = "",
222 unsigned level = NONE::value, action_t action = ACCEPT, int index = -1);
223 ///< Add route (dynamic)
224 /**< Add a route for the given combination of \a stream, \a
225 area and \a level. All parameters (\a Stream, \a Area
226 and \a Level) are optional and may be omitted by
227 setting them to the empty string or the
228 senf::log::NONE::value respectively.
230 See the class description for information on the \a
231 action and \a index parameters
233 \throws InvalidStreamException if the given \a stream
234 is not found in the StreamRegistry
235 \throws InvalidAreaException if the given \a area is
236 not found in the AreaRegistry
238 \param[in] stream stream to match
239 \param[in] area area to match
240 \param[in] level level, matches messages with at least
242 \param[in] action routing action to take
243 \param[in] index position of new route in the routing
248 template <class Stream, class Area, class Level>
249 void unroute(action_t action = ACCEPT);
250 ///< Remove route (static)
251 /**< This member removes an arbitrary routing entry. The
252 template parameters are the same as for the
253 corresponding \ref route() call.
255 The routing table is searched for a route exactly
256 matching the given specification. If such a route is
257 found, it will be removed, otherwise the call will be
260 \tparam Stream stream to match
261 \tparam Area area to match
262 \tparam Level level, matches messages with
263 at least the given level.
264 \param[in] action routing action to take */
268 void unroute(std::string const & stream, std::string const & area = "",
269 unsigned level = NONE::value, action_t action = ACCEPT);
270 ///< Remove route (dynamic)
271 /**< This member removes an arbitrary routing entry. The \a
272 stream parameter is mandatory while either \a area or
273 \a level may be left unspecified by setting them to the
274 empty string or senf::log::NONE::value respectively.
276 The routing table is searched for a route exactly
277 matching the given specification. If such a route is
278 found, it will be removed, otherwise the call will be
281 \param[in] stream stream to match
282 \param[in] area area to match
283 \param[in] level level, matches messages with at least
285 \param[in] action routing action to take */
286 void unroute(int index=-1); ///< Remove route (indexed)
287 /**< This call will remove the route with the given index.
289 See the class documentation for more information on
292 \param[in] index index of routing entry to remove */
297 void route(action_t action = ACCEPT, int index = -1);
298 template <class A1, class A2>
299 void route(action_t action = ACCEPT, int index = -1);
300 template <class A1, class A2, class A3>
301 void route(action_t action = ACCEPT, int index = -1);
304 void unroute(action_t action = ACCEPT);
305 template <class A1, class A2>
306 void unroute(action_t action = ACCEPT);
307 template <class A1, class A2, class A3>
308 void unroute(action_t action = ACCEPT);
314 /** \brief Exception: Invalid stream */
315 struct InvalidStreamException : public senf::Exception
316 { InvalidStreamException()
317 : senf::Exception("senf::log::Target::InvalidStreamException"){} };
319 /** \brief Exception: Invalid area */
320 struct InvalidAreaException : public senf::Exception
321 { InvalidAreaException()
322 : senf::Exception("senf::log::Target::InvalidAreaException"){} };
324 iterator begin() const; ///< Iterator to beginning of routing table
325 iterator end() const; ///< Iterator past the end of routing table
328 void route(detail::StreamBase const * stream, detail::AreaBase const * area,
329 unsigned level, action_t action, int index);
330 void unroute(detail::StreamBase const * stream, detail::AreaBase const * area,
331 unsigned level, action_t action);
333 void updateRoutingCache(detail::StreamBase const * stream, detail::AreaBase const * area);
335 void write(time_type timestamp, detail::StreamBase const & stream,
336 detail::AreaBase const & area, unsigned level, std::string const & message);
342 virtual void v_write(time_type timestamp, std::string const & stream,
343 std::string const & area, unsigned level,
344 std::string const & message) = 0;
345 ///< Called to write out the routing message
346 /**< This member must be defined in the derived class to
347 somehow format and write the %log message.
349 Every %log message always possesses a complete set of
350 meta information (\a stream, \a area and \a level).
352 \note This member must \e not block since it may be
353 called from any unknown context. This prohibits
354 simple logging over NFS or many other network
357 \param[in] timestamp %log message timing information
358 \param[in] stream message stream
359 \param[in] area message area
360 \param[in] level message level
361 \param[in] message the message string */
369 friend class detail::AreaBase;
370 friend class detail::TargetRegistry;
375 ///////////////////////////////hh.e////////////////////////////////////////
376 #include "Target.cci"
377 //#include "Target.ct"
378 #include "Target.cti"
385 // comment-column: 40
386 // c-file-style: "senf"
387 // indent-tabs-mode: nil
388 // ispell-local-dictionary: "american"
389 // compile-command: "scons -u test"