4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at
9 // http://senf.berlios.de/license.html
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on,
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
15 // Software distributed under the License is distributed on an "AS IS" basis,
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
17 // for the specific language governing rights and limitations under the License.
19 // The Original Code is Fraunhofer FOKUS code.
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V.
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
26 // Stefan Bund <g0dil@berlios.de>
29 \brief Target public header */
31 #ifndef HH_SENF_Utils_Logger_Target_
32 #define HH_SENF_Utils_Logger_Target_ 1
36 #include <boost/utility.hpp>
37 #include <senf/Utils/Exception.hh>
38 #include <senf/Utils/Console/LazyDirectory.hh>
39 #include "TimeSource.hh"
42 //#include "Target.mpp"
43 //-/////////////////////////////////////////////////////////////////////////////////////////////////
45 /** \defgroup targets Targets
47 Targets receive log messages and write them to some destination: The console, a log file, an SQL
48 DB and so on. Every target is derived from the \ref senf::log::Target base class. This base
49 class provides the target with the necessary routing infrastructure. The different targets only
50 differ in the way, they write the data.
52 \see senf::log::Target
58 namespace detail { class TargetRegistry; }
59 namespace detail { struct AreaBase; }
60 namespace detail { struct LogParameters; }
61 namespace detail { struct StreamBase; }
63 /** \brief Logging target base class
65 Targets are the final destination of %log messages. Every message is eventually routed to
66 one or several targets.
68 \section target_routing Routing
70 Each target manages a routing table. The message meta-data (stream, area and level) is
71 matched against this table. If an entry matches, the action associated with this entry is
72 taken (either \c ACCEPT or \c REJECT).
74 Every target manages it's own routing table. Conceptually, every message will be routed to
75 every target where it will then be matched against each targets routing table (the
76 implementation is more efficient and utilizes a routing cache).
78 Each routing entry consists of the following parameters
79 \li (optional) \e stream. If specified, the entry will match only messages directed at that
81 \li (optional) \e area. If the area is specified, only messages directed at that area are
82 matched, otherwise any area will be allowed
83 \li (optional) \e level. If the %log level is specified, messages will be accepted if their
84 level is at least that value. If the value is not specified, the limit will be taken
85 from the stream's default value.
87 Each parameter (stream, area and level) has two representations: A static (compile time
88 constant) representation, which is the representation also used in the %log statements, and a
89 dynamic (runtime) representation.
91 The static representation is used, when passing routing parameters via template arguments:
93 target.route<foo::SomeStream, senf::log::NOTICE>(senf::log::Target::REJECT);
94 target.route<foo::SomeStream>();
97 The identical routing statements may be expressed using dynamic routing via:
99 target.route("foo::SomeStream", "", senf::log::NOTICE::value, senf::log::Target::REJECT);
100 target.route("foo::SomeStream");
103 The static representation has the benefit of being compile-time type checked: Invalid
104 routing parameters will be caught while compiling the code. The dynamic representation is
105 more flexible as it allows to adjust routing from user input (e.g. configuration files).
107 The different object representations are:
108 \li The \e streams is statically represented by it's name, which is the name of a class
109 defined with \ref SENF_LOG_DEFINE_STREAM. The dynamic representation is a string
110 representation of this name.
111 \li The \e area is statically represented by it's name, which again is the name of a class
112 defined with \ref SENF_LOG_DEFINE_STREAM. The dynamic representation again is a string
113 representation of this class's name. The dynamic representation represents an absent
114 area with the empty string.
115 \li The \e level is statically represented by a level class from \ref
116 loglevels. Dynamically, it is represented by an unsigned integer number, the \c value
117 member of that class.
119 \subsection target_routing_processing Ordering routing entries and route processing
121 The routing table is processed from first route to last route, the first matching entry
122 determines the fate of a log messages. Therefore, the ordering of routing entries is
125 If no position is explicitly specified, new routing entries are added to the end of the
126 routing table. All routing statements however take an index as optional argument to
127 explicitly specify the position of the new routing entry.
129 The index value starts from 0 for the first route. The value gives the position the new
130 routing entry will have after it has been added. An index of 0 will thus insert the new
131 routing entry at the beginning of the table. Negative values count from the back, -1 being
134 \section target_impl Implementing new targets
136 To implement a new target type, you need to derive from senf::log::Target and implement the
137 single \c v_write member. This member will be called whenever a message should be output.
139 The target may process the message in any arbitrary way: reformat it, write it into an SQL
140 DB, whatever can be envisioned. However, there is one important limitation: The \c v_write
141 call must \e not block. So for more complex scenarios, additional measures must be taken
142 (e.g. writing a %log backend daemon which receives the messages via UDP and processes
143 them). Of course, in rare cases messages might be lost but this cannot be avoided.
147 class Target : private boost::noncopyable
150 //-////////////////////////////////////////////////////////////////////////
153 /** \brief Routing action
155 Every routing entry is associated with a routing action. This action is final (for this
156 target. Each target is processed independently).
159 ACCEPT /** Output message */
160 , REJECT /** Suppress message output */
163 /** \brief Target routing entry
165 A single routing entry matches messages against their \e stream, \e area and \e
166 level. If the entry matches, the given \e action is performed.
168 \see senf::log::Target
172 std::string stream() const; ///< Stream to match
173 std::string area() const; ///< Area to match (empty of unspecified)
174 unsigned level() const; ///< Level to match (senf::log::NONE::value if unspecified)
175 action_t action() const; ///< Action to take
182 bool operator==(RoutingEntry const & other) const;
185 RoutingEntry(detail::StreamBase const * stream, detail::AreaBase const * area,
186 unsigned level, action_t action);
188 detail::StreamBase const * stream_;
189 detail::AreaBase const * area_;
197 typedef std::vector<RoutingEntry> RIB;
200 typedef RIB::const_iterator iterator; ///< Routing table iterator
201 typedef RIB::size_type size_type;
203 //-////////////////////////////////////////////////////////////////////////
204 ///\name Structors and default members
207 explicit Target(std::string const & name);
211 //-////////////////////////////////////////////////////////////////////////
217 template <class Stream, class Area, class Level> void route(
218 action_t action = ACCEPT, int index = -1); ///< Add route (static)
219 /**< Add a route for the given combination of \a Stream, \a
220 Area and \a Level. All parameters (\a Stream, \a Area
221 and \a Level) are optional (the template signature is
222 shown simplified here). So possible commands are:
225 target.route<SomeStream>();
226 target.route<SomeArea>();
227 target.route<SomeLevel>();
228 target.route<SomeStream, SomeArea>();
229 target.route<SomeStream, SomeLevel>();
230 target.route<SomeArea, SomeLevel>();
231 target.route<SomeStream, SomeArea, SomeLevel>();
234 See the class description for information on the \a
235 action and \a index parameters
237 \tparam Stream stream to match
238 \tparam Area area to match
239 \tparam Level level, matches messages with
240 at least the given level.
241 \param[in] action routing action to take
242 \param[in] index position of new route in the routing
247 void route(std::string const & stream, std::string const & area = "",
248 unsigned level = NONE::value, action_t action = ACCEPT, int index = -1);
249 ///< Add route (dynamic)
250 /**< Add a route for the given combination of \a stream, \a
251 area and \a level. All parameters (\a Stream, \a Area
252 and \a Level) are optional and may be omitted by
253 setting them to the empty string or the
254 senf::log::NONE::value respectively.
256 See the class description for information on the \a
257 action and \a index parameters
259 \throws InvalidStreamException if the given \a stream
260 is not found in the StreamRegistry
261 \throws InvalidAreaException if the given \a area is
262 not found in the AreaRegistry
264 \param[in] stream stream to match
265 \param[in] area area to match
266 \param[in] level level, matches messages with at least
268 \param[in] action routing action to take
269 \param[in] index position of new route in the routing
274 template <class Stream, class Area, class Level>
275 void unroute(action_t action = ACCEPT);
276 ///< Remove route (static)
277 /**< This member removes an arbitrary routing entry. The
278 template parameters are the same as for the
279 corresponding \ref route() call.
281 The routing table is searched for a route exactly
282 matching the given specification. If such a route is
283 found, it will be removed, otherwise the call will be
286 \tparam Stream stream to match
287 \tparam Area area to match
288 \tparam Level level, matches messages with
289 at least the given level.
290 \param[in] action routing action to take */
294 void unroute(std::string const & stream, std::string const & area = "",
295 unsigned level = NONE::value, action_t action = ACCEPT);
296 ///< Remove route (dynamic)
297 /**< This member removes an arbitrary routing entry. The \a
298 stream parameter is mandatory while either \a area or
299 \a level may be left unspecified by setting them to the
300 empty string or senf::log::NONE::value respectively.
302 The routing table is searched for a route exactly
303 matching the given specification. If such a route is
304 found, it will be removed, otherwise the call will be
307 \param[in] stream stream to match
308 \param[in] area area to match
309 \param[in] level level, matches messages with at least
311 \param[in] action routing action to take */
312 void unroute(int index=-1); ///< Remove route (indexed)
313 /**< This call will remove the route with the given index.
315 See the class documentation for more information on
318 \param[in] index index of routing entry to remove */
322 void route(action_t action = ACCEPT, int index = -1);
324 void route(action_t action = ACCEPT, int index = -1);
325 template <class A1, class A2>
326 void route(action_t action = ACCEPT, int index = -1);
327 template <class A1, class A2, class A3>
328 void route(action_t action = ACCEPT, int index = -1);
330 void unroute(action_t action = ACCEPT);
332 void unroute(action_t action = ACCEPT);
333 template <class A1, class A2>
334 void unroute(action_t action = ACCEPT);
335 template <class A1, class A2, class A3>
336 void unroute(action_t action = ACCEPT);
342 /** \brief Exception: Invalid stream */
343 struct InvalidStreamException : public senf::Exception
344 { InvalidStreamException()
345 : senf::Exception("senf::log::Target::InvalidStreamException") {} };
347 /** \brief Exception: Invalid area */
348 struct InvalidAreaException : public senf::Exception
349 { InvalidAreaException()
350 : senf::Exception("senf::log::Target::InvalidAreaException") {} };
352 iterator begin() const; ///< Iterator to beginning of routing table
353 iterator end() const; ///< Iterator past the end of routing table
355 RoutingEntry const & operator[](size_type i) const; ///< Access routing entry
357 size_type size() const; ///< Number of routing table entries
358 bool empty() const; ///< \c true, if routing table empty, \c false otherwise
360 void flush(); ///< Clear routing table
362 senf::console::ScopedDirectory<> & consoleDir(); ///< Get console/config directory
365 void route(detail::StreamBase const * stream, detail::AreaBase const * area,
366 unsigned level, action_t action, int index);
367 void unroute(detail::StreamBase const * stream, detail::AreaBase const * area,
368 unsigned level, action_t action);
370 void updateRoutingCache(detail::StreamBase const * stream, detail::AreaBase const * area);
372 void write(time_type timestamp, detail::StreamBase const & stream,
373 detail::AreaBase const & area, unsigned level, std::string const & message);
375 void consoleList(std::ostream & os);
376 void consoleRoute(int index, detail::LogParameters const & pm, action_t action);
377 void consoleUnroute(detail::LogParameters const & pm, action_t action);
383 virtual void v_write(time_type timestamp, std::string const & stream,
384 std::string const & area, unsigned level,
385 std::string const & message) = 0;
386 ///< Called to write out the routing message
387 /**< This member must be defined in the derived class to
388 somehow format and write the %log message.
390 Every %log message always possesses a complete set of
391 meta information (\a stream, \a area and \a level).
393 \note This member must \e not block since it may be
394 called from any unknown context. This prohibits
395 simple logging over NFS or many other network
398 \param[in] timestamp %log message timing information
399 \param[in] stream message stream
400 \param[in] area message area
401 \param[in] level message level
402 \param[in] message the message string */
410 console::LazyDirectory consoleDir_;
412 friend struct detail::AreaBase;
413 friend class detail::TargetRegistry;
416 /** \brief Write route action
419 std::ostream & operator<<(std::ostream & os, Target::action_t const & action);
423 //-/////////////////////////////////////////////////////////////////////////////////////////////////
424 #include "Target.cci"
425 //#include "Target.ct"
426 #include "Target.cti"
433 // comment-column: 40
434 // c-file-style: "senf"
435 // indent-tabs-mode: nil
436 // ispell-local-dictionary: "american"
437 // compile-command: "scons -u test"