Fix documentation build under maverick (doxygen 1.7.1)
[senf.git] / senf / Utils / Logger / Target.hh
1 // $Id$
2 //
3 // Copyright (C) 2007
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.de>
7 //
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.
12 //
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.
17 //
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.
22
23 /** \file
24     \brief Target public header */
25
26 #ifndef HH_SENF_Utils_Logger_Target_
27 #define HH_SENF_Utils_Logger_Target_ 1
28
29 // Custom includes
30 #include <set>
31 #include <vector>
32 #include <boost/utility.hpp>
33 #include <boost/type_traits/is_convertible.hpp>
34 #include <senf/Utils/singleton.hh>
35 #include <senf/Utils/mpl.hh>
36 #include "StreamRegistry.hh"
37 #include <senf/Utils/Exception.hh>
38 #include "TimeSource.hh"
39 #include <senf/Utils/Console/LazyDirectory.hh>
40
41 //#include "Target.mpp"
42 //-/////////////////////////////////////////////////////////////////////////////////////////////////
43
44 /** \defgroup targets Targets
45
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.
50
51     \see senf::log::Target
52  */
53
54 namespace senf {
55 namespace log {
56
57     namespace detail { class TargetRegistry; }
58     namespace detail { class AreaBase; }
59     namespace detail { struct LogParameters; }
60
61     /** \brief Logging target base class
62
63         Targets are the final destination of %log messages. Every message is eventually routed to
64         one or several targets.
65
66         \section target_routing Routing
67
68         Each target manages a routing table. The message meta-data (stream, area and level) is
69         matched against this table. If an entry matches, the action associated with this entry is
70         taken (either \c ACCEPT or \c REJECT).
71
72         Every target manages it's own routing table. Conceptually, every message will be routed to
73         every target where it will then be matched against each targets routing table (the
74         implementation is more efficient and utilizes a routing cache).
75
76         Each routing entry consists of the following parameters
77         \li (optional) \e stream. If specified, the entry will match only messages directed at that
78             stream
79         \li (optional) \e area. If the area is specified, only messages directed at that area are
80             matched, otherwise any area will be allowed
81         \li (optional) \e level. If the %log level is specified, messages will be accepted if their
82             level is at least that value. If the value is not specified, the limit will be taken
83             from the stream's default value.
84
85         Each parameter (stream, area and level) has two representations: A static (compile time
86         constant) representation, which is the representation also used in the %log statements, and a
87         dynamic (runtime) representation.
88
89         The static representation is used, when passing routing parameters via template arguments:
90         \code
91         target.route<foo::SomeStream, senf::log::NOTICE>(senf::log::Target::REJECT);
92         target.route<foo::SomeStream>();
93         target.route();
94         \endcode
95         The identical routing statements may be expressed using dynamic routing via:
96         \code
97         target.route("foo::SomeStream", "", senf::log::NOTICE::value, senf::log::Target::REJECT);
98         target.route("foo::SomeStream");
99         target.route();
100         \endcode
101         The static representation has the benefit of being compile-time type checked: Invalid
102         routing parameters will be caught while compiling the code. The dynamic representation is
103         more flexible as it allows to adjust routing from user input (e.g. configuration files).
104
105         The different object representations are:
106         \li The \e streams is statically represented by it's name, which is the name of a class
107             defined with \ref SENF_LOG_DEFINE_STREAM. The dynamic representation is a string
108             representation of this name.
109         \li The \e area is statically represented by it's name, which again is the name of a class
110             defined with \ref SENF_LOG_DEFINE_STREAM. The dynamic representation again is a string
111             representation of this class's name. The dynamic representation represents an absent
112             area with the empty string.
113         \li The \e level is statically represented by a level class from \ref
114             loglevels. Dynamically, it is represented by an unsigned integer number, the \c value
115             member of that class.
116
117         \subsection target_routing_processing Ordering routing entries and route processing
118
119         The routing table is processed from first route to last route, the first matching entry
120         determines the fate of a log messages. Therefore, the ordering of routing entries is
121         important.
122
123         If no position is explicitly specified, new routing entries are added to the end of the
124         routing table. All routing statements however take an index as optional argument to
125         explicitly specify the position of the new routing entry.
126
127         The index value starts from 0 for the first route. The value gives the position the new
128         routing entry will have after it has been added. An index of 0 will thus insert the new
129         routing entry at the beginning of the table. Negative values count from the back, -1 being
130         the last entry.
131
132         \section target_impl Implementing new targets
133
134         To implement a new target type, you need to derive from senf::log::Target and implement the
135         single \c v_write member. This member will be called whenever a message should be output.
136
137         The target may process the message in any arbitrary way: reformat it, write it into an SQL
138         DB, whatever can be envisioned. However, there is one important limitation: The \c v_write
139         call must \e not block. So for more complex scenarios, additional measures must be taken
140         (e.g. writing a %log backend daemon which receives the messages via UDP and processes
141         them). Of course, in rare cases messages might be lost but this cannot be avoided.
142
143         \see \ref targets
144       */
145     class Target : private boost::noncopyable
146     {
147     public:
148         //-////////////////////////////////////////////////////////////////////////
149         // Types
150
151         /** \brief Routing action
152
153             Every routing entry is associated with a routing action. This action is final (for this
154             target. Each target is processed independently).
155          */
156         enum action_t {
157             ACCEPT /** Output message */
158           , REJECT /** Suppress message output */
159         };
160
161         /** \brief Target routing entry
162
163             A single routing entry matches messages against their \e stream, \e area and \e
164             level. If the entry matches, the given \e action is performed.
165
166             \see senf::log::Target
167          */
168         struct RoutingEntry
169         {
170             std::string stream() const; ///< Stream to match
171             std::string area() const;   ///< Area to match (empty of unspecified)
172             unsigned level() const;     ///< Level to match (senf::log::NONE::value if unspecified)
173             action_t action() const;    ///< Action to take
174
175 #           ifdef DOXYGEN
176         private:
177 #           endif
178
179             RoutingEntry();
180             bool operator==(RoutingEntry const & other) const;
181
182         private:
183             RoutingEntry(detail::StreamBase const * stream, detail::AreaBase const * area,
184                          unsigned level, action_t action);
185
186             detail::StreamBase const * stream_;
187             detail::AreaBase const * area_;
188             unsigned level_;
189             action_t action_;
190
191             friend class Target;
192         };
193
194     private:
195         typedef std::vector<RoutingEntry> RIB;
196
197     public:
198         typedef RIB::const_iterator iterator; ///< Routing table iterator
199         typedef RIB::size_type size_type;
200
201         //-////////////////////////////////////////////////////////////////////////
202         ///\name Structors and default members
203         //\{
204
205         explicit Target(std::string const & name);
206         virtual ~Target();
207
208         //\}
209         //-////////////////////////////////////////////////////////////////////////
210         ///\name Routing
211         //\{
212
213 #       ifdef DOXYGEN
214
215         template <class Stream, class Area, class Level> void route(
216             action_t action = ACCEPT, int index = -1); ///< Add route (static)
217                                         /**< Add a route for the given combination of \a Stream, \a
218                                              Area and \a Level. All parameters (\a Stream, \a Area
219                                              and \a Level) are optional (the template signature is
220                                              shown simplified here). So possible commands are:
221                                              \code
222                                              target.route();
223                                              target.route<SomeStream>();
224                                              target.route<SomeArea>();
225                                              target.route<SomeLevel>();
226                                              target.route<SomeStream, SomeArea>();
227                                              target.route<SomeStream, SomeLevel>();
228                                              target.route<SomeArea, SomeLevel>();
229                                              target.route<SomeStream, SomeArea, SomeLevel>();
230                                              \endcode
231
232                                              See the class description for information on the \a
233                                              action and \a index parameters
234
235                                              \tparam Stream stream to match
236                                              \tparam Area area to match
237                                              \tparam Level level, matches messages with
238                                                  at least the given level.
239                                              \param[in] action routing action to take
240                                              \param[in] index position of new route in the routing
241                                                  table */
242
243 #       endif
244
245         void route(std::string const & stream, std::string const & area = "",
246                    unsigned level = NONE::value, action_t action = ACCEPT, int index = -1);
247                                         ///< Add route (dynamic)
248                                         /**< Add a route for the given combination of \a stream, \a
249                                              area and \a level. All parameters (\a Stream, \a Area
250                                              and \a Level) are optional and may be omitted by
251                                              setting them to the empty string or the
252                                              senf::log::NONE::value respectively.
253
254                                              See the class description for information on the \a
255                                              action and \a index parameters
256
257                                              \throws InvalidStreamException if the given \a stream
258                                                  is not found in the StreamRegistry
259                                              \throws InvalidAreaException if the given \a area is
260                                                  not found in the AreaRegistry
261
262                                              \param[in] stream stream to match
263                                              \param[in] area area to match
264                                              \param[in] level level, matches messages with at least
265                                                  the given level.
266                                              \param[in] action routing action to take
267                                              \param[in] index position of new route in the routing
268                                                  table */
269
270 #       ifdef DOXYGEN
271
272         template <class Stream, class Area, class Level>
273         void unroute(action_t action = ACCEPT);
274                                         ///< Remove route (static)
275                                         /**< This member removes an arbitrary routing entry. The
276                                              template parameters are the same as for the
277                                              corresponding \ref route() call.
278
279                                              The routing table is searched for a route exactly
280                                              matching the given specification. If such a route is
281                                              found, it will be removed, otherwise the call will be
282                                              ignored
283
284                                              \tparam Stream stream to match
285                                              \tparam Area area to match
286                                              \tparam Level level, matches messages with
287                                                  at least the given level.
288                                              \param[in] action routing action to take */
289
290 #       endif
291
292         void unroute(std::string const & stream, std::string const & area = "",
293                      unsigned level = NONE::value, action_t action = ACCEPT);
294                                         ///< Remove route (dynamic)
295                                         /**< This member removes an arbitrary routing entry. The \a
296                                              stream parameter is mandatory while either \a area or
297                                              \a level may be left unspecified by setting them to the
298                                              empty string or senf::log::NONE::value respectively.
299
300                                              The routing table is searched for a route exactly
301                                              matching the given specification. If such a route is
302                                              found, it will be removed, otherwise the call will be
303                                              ignored
304
305                                              \param[in] stream stream to match
306                                              \param[in] area area to match
307                                              \param[in] level level, matches messages with at least
308                                                  the given level.
309                                              \param[in] action routing action to take */
310         void unroute(int index=-1);     ///< Remove route (indexed)
311                                         /**< This call will remove the route with the given index.
312
313                                              See the class documentation for more information on
314                                              indexing.
315
316                                              \param[in] index index of routing entry to remove */
317
318 #       ifndef DOXYGEN
319
320         void route(action_t action = ACCEPT, int index = -1);
321         template <class A1>
322         void route(action_t action = ACCEPT, int index = -1);
323         template <class A1, class A2>
324         void route(action_t action = ACCEPT, int index = -1);
325         template <class A1, class A2, class A3>
326         void route(action_t action = ACCEPT, int index = -1);
327
328         void unroute(action_t action = ACCEPT);
329         template <class A1>
330         void unroute(action_t action = ACCEPT);
331         template <class A1, class A2>
332         void unroute(action_t action = ACCEPT);
333         template <class A1, class A2, class A3>
334         void unroute(action_t action = ACCEPT);
335
336 #       endif
337
338         //\}
339
340         /** \brief Exception: Invalid stream */
341         struct InvalidStreamException : public senf::Exception
342         { InvalidStreamException()
343               : senf::Exception("senf::log::Target::InvalidStreamException") {} };
344
345         /** \brief Exception: Invalid area */
346         struct InvalidAreaException : public senf::Exception
347         { InvalidAreaException()
348               : senf::Exception("senf::log::Target::InvalidAreaException") {} };
349
350         iterator begin() const;         ///< Iterator to beginning of routing table
351         iterator end() const;           ///< Iterator past the end of routing table
352
353         RoutingEntry const & operator[](size_type i) const; ///< Access routing entry
354
355         size_type size() const;         ///< Number of routing table entries
356         bool empty() const;             ///< \c true, if routing table empty, \c false otherwise
357
358         void flush();                   ///< Clear routing table
359
360         senf::console::ScopedDirectory<> & consoleDir(); ///< Get console/config directory
361
362     private:
363         void route(detail::StreamBase const * stream, detail::AreaBase const * area,
364                    unsigned level, action_t action, int index);
365         void unroute(detail::StreamBase const * stream, detail::AreaBase const * area,
366                      unsigned level, action_t action);
367
368         void updateRoutingCache(detail::StreamBase const * stream, detail::AreaBase const * area);
369
370         void write(time_type timestamp, detail::StreamBase const & stream,
371                    detail::AreaBase const & area, unsigned level, std::string const & message);
372
373         void consoleList(std::ostream & os);
374         void consoleRoute(int index, detail::LogParameters const & pm, action_t action);
375         void consoleUnroute(detail::LogParameters const & pm, action_t action);
376
377 #   ifdef DOXYGEN
378     protected:
379 #   endif
380
381         virtual void v_write(time_type timestamp, std::string const & stream,
382                              std::string const & area, unsigned level,
383                              std::string const & message) = 0;
384                                         ///< Called to write out the routing message
385                                         /**< This member must be defined in the derived class to
386                                              somehow format and write the %log message.
387
388                                              Every %log message always possesses a complete set of
389                                              meta information (\a stream, \a area and \a level).
390
391                                              \note This member must \e not block since it may be
392                                                  called from any unknown context. This prohibits
393                                                  simple logging over NFS or many other network
394                                                  protocols.
395
396                                              \param[in] timestamp %log message timing information
397                                              \param[in] stream message stream
398                                              \param[in] area message area
399                                              \param[in] level message level
400                                              \param[in] message the message string */
401
402 #   ifdef DOXYGEN
403     private:
404 #   endif
405
406         RIB rib_;
407
408         console::LazyDirectory consoleDir_;
409
410         friend class detail::AreaBase;
411         friend class detail::TargetRegistry;
412     };
413
414     /** \brief Write route action
415         \related Target
416      */
417     std::ostream & operator<<(std::ostream & os, Target::action_t const & action);
418
419 }}
420
421 //-/////////////////////////////////////////////////////////////////////////////////////////////////
422 #include "Target.cci"
423 //#include "Target.ct"
424 #include "Target.cti"
425 #endif
426
427 \f
428 // Local Variables:
429 // mode: c++
430 // fill-column: 100
431 // comment-column: 40
432 // c-file-style: "senf"
433 // indent-tabs-mode: nil
434 // ispell-local-dictionary: "american"
435 // compile-command: "scons -u test"
436 // End: