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
31 #include <boost/utility.hpp>
32 #include <senf/Utils/Exception.hh>
33 #include <senf/Utils/Console/LazyDirectory.hh>
34 #include "TimeSource.hh"
37 //#include "Target.mpp"
38 //-/////////////////////////////////////////////////////////////////////////////////////////////////
40 /** \defgroup targets Targets
42 Targets receive log messages and write them to some destination: The console, a log file, an SQL
43 DB and so on. Every target is derived from the \ref senf::log::Target base class. This base
44 class provides the target with the necessary routing infrastructure. The different targets only
45 differ in the way, they write the data.
47 \see senf::log::Target
53 namespace detail { class TargetRegistry; }
54 namespace detail { class AreaBase; }
55 namespace detail { struct LogParameters; }
56 namespace detail { struct StreamBase; }
58 /** \brief Logging target base class
60 Targets are the final destination of %log messages. Every message is eventually routed to
61 one or several targets.
63 \section target_routing Routing
65 Each target manages a routing table. The message meta-data (stream, area and level) is
66 matched against this table. If an entry matches, the action associated with this entry is
67 taken (either \c ACCEPT or \c REJECT).
69 Every target manages it's own routing table. Conceptually, every message will be routed to
70 every target where it will then be matched against each targets routing table (the
71 implementation is more efficient and utilizes a routing cache).
73 Each routing entry consists of the following parameters
74 \li (optional) \e stream. If specified, the entry will match only messages directed at that
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 (runtime) representation.
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>();
92 The identical routing statements may be expressed using dynamic routing via:
94 target.route("foo::SomeStream", "", senf::log::NOTICE::value, senf::log::Target::REJECT);
95 target.route("foo::SomeStream");
98 The static representation has the benefit of being compile-time type checked: Invalid
99 routing parameters will be caught while compiling the code. The dynamic representation is
100 more flexible as it allows to adjust routing from user input (e.g. configuration files).
102 The different object representations are:
103 \li The \e streams is statically represented by it's name, which is the name of a class
104 defined with \ref SENF_LOG_DEFINE_STREAM. The dynamic representation is a string
105 representation of this name.
106 \li The \e area is statically represented by it's name, which again is the name of a class
107 defined with \ref SENF_LOG_DEFINE_STREAM. The dynamic representation again is a string
108 representation of this class's name. The dynamic representation represents an absent
109 area with the empty string.
110 \li The \e level is statically represented by a level class from \ref
111 loglevels. Dynamically, it is represented by an unsigned integer number, the \c value
112 member of that class.
114 \subsection target_routing_processing Ordering routing entries and route processing
116 The routing table is processed from first route to last route, the first matching entry
117 determines the fate of a log messages. Therefore, the ordering of routing entries is
120 If no position is explicitly specified, new routing entries are added to the end of the
121 routing table. All routing statements however take an index as optional argument to
122 explicitly specify the position of the new routing entry.
124 The index value starts from 0 for the first route. The value gives the position the new
125 routing entry will have after it has been added. An index of 0 will thus insert the new
126 routing entry at the beginning of the table. Negative values count from the back, -1 being
129 \section target_impl Implementing new targets
131 To implement a new target type, you need to derive from senf::log::Target and implement the
132 single \c v_write member. This member will be called whenever a message should be output.
134 The target may process the message in any arbitrary way: reformat it, write it into an SQL
135 DB, whatever can be envisioned. However, there is one important limitation: The \c v_write
136 call must \e not block. So for more complex scenarios, additional measures must be taken
137 (e.g. writing a %log backend daemon which receives the messages via UDP and processes
138 them). Of course, in rare cases messages might be lost but this cannot be avoided.
142 class Target : private boost::noncopyable
145 //-////////////////////////////////////////////////////////////////////////
148 /** \brief Routing action
150 Every routing entry is associated with a routing action. This action is final (for this
151 target. Each target is processed independently).
154 ACCEPT /** Output message */
155 , REJECT /** Suppress message output */
158 /** \brief Target routing entry
160 A single routing entry matches messages against their \e stream, \e area and \e
161 level. If the entry matches, the given \e action is performed.
163 \see senf::log::Target
167 std::string stream() const; ///< Stream to match
168 std::string area() const; ///< Area to match (empty of unspecified)
169 unsigned level() const; ///< Level to match (senf::log::NONE::value if unspecified)
170 action_t action() const; ///< Action to take
177 bool operator==(RoutingEntry const & other) const;
180 RoutingEntry(detail::StreamBase const * stream, detail::AreaBase const * area,
181 unsigned level, action_t action);
183 detail::StreamBase const * stream_;
184 detail::AreaBase const * area_;
192 typedef std::vector<RoutingEntry> RIB;
195 typedef RIB::const_iterator iterator; ///< Routing table iterator
196 typedef RIB::size_type size_type;
198 //-////////////////////////////////////////////////////////////////////////
199 ///\name Structors and default members
202 explicit Target(std::string const & name);
206 //-////////////////////////////////////////////////////////////////////////
212 template <class Stream, class Area, class Level> void route(
213 action_t action = ACCEPT, int index = -1); ///< Add route (static)
214 /**< Add a route for the given combination of \a Stream, \a
215 Area and \a Level. All parameters (\a Stream, \a Area
216 and \a Level) are optional (the template signature is
217 shown simplified here). So possible commands are:
220 target.route<SomeStream>();
221 target.route<SomeArea>();
222 target.route<SomeLevel>();
223 target.route<SomeStream, SomeArea>();
224 target.route<SomeStream, SomeLevel>();
225 target.route<SomeArea, SomeLevel>();
226 target.route<SomeStream, SomeArea, SomeLevel>();
229 See the class description for information on the \a
230 action and \a index parameters
232 \tparam Stream stream to match
233 \tparam Area area to match
234 \tparam Level level, matches messages with
235 at least the given level.
236 \param[in] action routing action to take
237 \param[in] index position of new route in the routing
242 void route(std::string const & stream, std::string const & area = "",
243 unsigned level = NONE::value, action_t action = ACCEPT, int index = -1);
244 ///< Add route (dynamic)
245 /**< Add a route for the given combination of \a stream, \a
246 area and \a level. All parameters (\a Stream, \a Area
247 and \a Level) are optional and may be omitted by
248 setting them to the empty string or the
249 senf::log::NONE::value respectively.
251 See the class description for information on the \a
252 action and \a index parameters
254 \throws InvalidStreamException if the given \a stream
255 is not found in the StreamRegistry
256 \throws InvalidAreaException if the given \a area is
257 not found in the AreaRegistry
259 \param[in] stream stream to match
260 \param[in] area area to match
261 \param[in] level level, matches messages with at least
263 \param[in] action routing action to take
264 \param[in] index position of new route in the routing
269 template <class Stream, class Area, class Level>
270 void unroute(action_t action = ACCEPT);
271 ///< Remove route (static)
272 /**< This member removes an arbitrary routing entry. The
273 template parameters are the same as for the
274 corresponding \ref route() call.
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 \tparam Stream stream to match
282 \tparam Area area to match
283 \tparam Level level, matches messages with
284 at least the given level.
285 \param[in] action routing action to take */
289 void unroute(std::string const & stream, std::string const & area = "",
290 unsigned level = NONE::value, action_t action = ACCEPT);
291 ///< Remove route (dynamic)
292 /**< This member removes an arbitrary routing entry. The \a
293 stream parameter is mandatory while either \a area or
294 \a level may be left unspecified by setting them to the
295 empty string or senf::log::NONE::value respectively.
297 The routing table is searched for a route exactly
298 matching the given specification. If such a route is
299 found, it will be removed, otherwise the call will be
302 \param[in] stream stream to match
303 \param[in] area area to match
304 \param[in] level level, matches messages with at least
306 \param[in] action routing action to take */
307 void unroute(int index=-1); ///< Remove route (indexed)
308 /**< This call will remove the route with the given index.
310 See the class documentation for more information on
313 \param[in] index index of routing entry to remove */
317 void route(action_t action = ACCEPT, int index = -1);
319 void route(action_t action = ACCEPT, int index = -1);
320 template <class A1, class A2>
321 void route(action_t action = ACCEPT, int index = -1);
322 template <class A1, class A2, class A3>
323 void route(action_t action = ACCEPT, int index = -1);
325 void unroute(action_t action = ACCEPT);
327 void unroute(action_t action = ACCEPT);
328 template <class A1, class A2>
329 void unroute(action_t action = ACCEPT);
330 template <class A1, class A2, class A3>
331 void unroute(action_t action = ACCEPT);
337 /** \brief Exception: Invalid stream */
338 struct InvalidStreamException : public senf::Exception
339 { InvalidStreamException()
340 : senf::Exception("senf::log::Target::InvalidStreamException") {} };
342 /** \brief Exception: Invalid area */
343 struct InvalidAreaException : public senf::Exception
344 { InvalidAreaException()
345 : senf::Exception("senf::log::Target::InvalidAreaException") {} };
347 iterator begin() const; ///< Iterator to beginning of routing table
348 iterator end() const; ///< Iterator past the end of routing table
350 RoutingEntry const & operator[](size_type i) const; ///< Access routing entry
352 size_type size() const; ///< Number of routing table entries
353 bool empty() const; ///< \c true, if routing table empty, \c false otherwise
355 void flush(); ///< Clear routing table
357 senf::console::ScopedDirectory<> & consoleDir(); ///< Get console/config directory
360 void route(detail::StreamBase const * stream, detail::AreaBase const * area,
361 unsigned level, action_t action, int index);
362 void unroute(detail::StreamBase const * stream, detail::AreaBase const * area,
363 unsigned level, action_t action);
365 void updateRoutingCache(detail::StreamBase const * stream, detail::AreaBase const * area);
367 void write(time_type timestamp, detail::StreamBase const & stream,
368 detail::AreaBase const & area, unsigned level, std::string const & message);
370 void consoleList(std::ostream & os);
371 void consoleRoute(int index, detail::LogParameters const & pm, action_t action);
372 void consoleUnroute(detail::LogParameters const & pm, action_t action);
378 virtual void v_write(time_type timestamp, std::string const & stream,
379 std::string const & area, unsigned level,
380 std::string const & message) = 0;
381 ///< Called to write out the routing message
382 /**< This member must be defined in the derived class to
383 somehow format and write the %log message.
385 Every %log message always possesses a complete set of
386 meta information (\a stream, \a area and \a level).
388 \note This member must \e not block since it may be
389 called from any unknown context. This prohibits
390 simple logging over NFS or many other network
393 \param[in] timestamp %log message timing information
394 \param[in] stream message stream
395 \param[in] area message area
396 \param[in] level message level
397 \param[in] message the message string */
405 console::LazyDirectory consoleDir_;
407 friend class detail::AreaBase;
408 friend class detail::TargetRegistry;
411 /** \brief Write route action
414 std::ostream & operator<<(std::ostream & os, Target::action_t const & action);
418 //-/////////////////////////////////////////////////////////////////////////////////////////////////
419 #include "Target.cci"
420 //#include "Target.ct"
421 #include "Target.cti"
428 // comment-column: 40
429 // c-file-style: "senf"
430 // indent-tabs-mode: nil
431 // ispell-local-dictionary: "american"
432 // compile-command: "scons -u test"