b4137d6db827249696c1a8c78460d8bcb4d74f80
[senf.git] / Utils / Logger / Target.hh
1 // $Id$
2 //
3 // Copyright (C) 2007 
4 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
5 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
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_Target_
27 #define HH_Target_ 1
28
29 // Custom includes
30 #include <set>
31 #include <boost/date_time/posix_time/posix_time.hpp>
32 #include <boost/utility.hpp>
33 #include <boost/type_traits/is_convertible.hpp>
34 #include "../singleton.hh"
35 #include "../mpl.hh"
36 #include "StreamRegistry.hh"
37 #include "AreaRegistry.hh"
38
39 //#include "Target.mpp"
40 ///////////////////////////////hh.p////////////////////////////////////////
41
42 namespace senf {
43 namespace log {
44
45     class TargetRegistry;
46
47     /** \brief Logging target base class
48
49         All enabled log messages are eventually routed to one or more logging targets. It is the
50         responsibility of the logging target to write the log messages somewhere: onto the console,
51         to a file, to mail them to the administrator or whatever. To this end, the logging target is
52         passed the log message and a complete set of logging parameters (\e stream, \e area and \e
53         level).
54
55         \fixme optionally Integrate with Scheduler / ClockService to reduce number of gettimeofday()
56             calls.
57       */
58     class Target : private boost::noncopyable
59     {
60     public:
61         ///////////////////////////////////////////////////////////////////////////
62         // Types
63
64         enum action_t { ACCEPT, REJECT };
65
66         struct RoutingEntry 
67         {
68             RoutingEntry();
69             bool operator==(RoutingEntry const & other);
70
71             std::string stream() const;
72             std::string area() const;
73             unsigned level() const;
74             action_t action() const;
75             
76         private:
77             RoutingEntry(detail::StreamBase const * stream, detail::AreaBase const * area, 
78                          unsigned level, action_t action);
79
80             detail::StreamBase const * stream_;
81             detail::AreaBase const * area_;
82             unsigned level_;
83             action_t action_;
84             
85             friend class Target;
86         };
87
88     private:
89         typedef std::vector<RoutingEntry> RIB;
90
91     public:
92         typedef RIB::const_iterator iterator;
93
94         ///////////////////////////////////////////////////////////////////////////
95         ///\name Structors and default members
96         ///@{
97
98         Target();
99         virtual ~Target();
100
101         ///@}
102
103         template <class Stream> void route(
104             action_t action = ACCEPT, int index = -1);
105         template <class Stream, class Level> void route(
106             action_t action = ACCEPT, int index = -1,
107             typename boost::enable_if< boost::is_convertible<Level*,
108                                                              detail::LevelBase *> >::type * = 0);
109         template <class Stream, class Area> void route(
110             action_t action = ACCEPT, int index = -1,
111             typename boost::enable_if< boost::is_convertible<Area*,
112                                                              detail::AreaBase *> >::type * = 0);
113         template <class Stream, class AreaClass> void route(
114             action_t action = ACCEPT, int index = -1,
115             typename boost::enable_if< boost::is_convertible<typename AreaClass::SENFLogArea *,
116                                                              detail::AreaBase *> >::type * = 0);
117         template <class Stream, class Area, class Level> void route(
118             action_t action = ACCEPT, int index = -1,
119             typename boost::enable_if< boost::is_convertible<Area *,
120                                                              detail::AreaBase *> >::type * = 0);
121         template <class Stream, class AreaClass, class Level> void route(
122             action_t action = ACCEPT, int index = -1,
123             typename boost::enable_if< boost::is_convertible<typename AreaClass::SENFLogArea *,
124                                                              detail::AreaBase *> >::type * = 0);
125
126         void route(std::string const & stream, std::string const & area = "", 
127                    unsigned level = NONE::value, action_t action = ACCEPT, int index = -1);
128
129         template <class Stream> void unroute(
130             action_t action = ACCEPT);
131         template <class Stream, class Level> void unroute(
132             action_t action = ACCEPT,
133             typename boost::enable_if< boost::is_convertible<Level*,
134                                                              detail::LevelBase *> >::type * = 0);
135         template <class Stream, class Area> void unroute(
136             action_t action = ACCEPT,
137             typename boost::enable_if< boost::is_convertible<Area*,
138                                                              detail::AreaBase *> >::type * = 0);
139         template <class Stream, class AreaClass> void unroute(
140             action_t action = ACCEPT,
141             typename boost::enable_if< boost::is_convertible<typename AreaClass::SENFLogArea *,
142                                                              detail::AreaBase *> >::type * = 0);
143         template <class Stream, class Area, class Level> void unroute(
144             action_t action = ACCEPT,
145             typename boost::enable_if< boost::is_convertible<Area*,
146                                                              detail::AreaBase *> >::type * = 0);
147         template <class Stream, class AreaClass, class Level> void unroute(
148             action_t action = ACCEPT,
149             typename boost::enable_if< boost::is_convertible<typename AreaClass::SENFLogArea *,
150                                                              detail::AreaBase *> >::type * = 0);
151
152         void unroute(std::string const & stream, std::string const & area = "", 
153                      unsigned level = NONE::value, action_t action = ACCEPT);
154         void unroute(int index);
155
156         struct InvalidStreamException : public std::exception
157         { virtual char const * what() const throw() 
158                 { return "senf::log::Target::InvalidStreamException"; } };
159         
160         struct InvalidAreaException : public std::exception
161         { virtual char const * what() const throw() 
162                 { return "senf::log::Target::InvalidAreaException"; } };
163
164         iterator begin() const;
165         iterator end() const;
166         
167     private:
168         void route(detail::StreamBase const * stream, detail::AreaBase const * area, 
169                    unsigned level, action_t action, int index);
170         void unroute(detail::StreamBase const * stream, detail::AreaBase const * area, 
171                      unsigned level, action_t action);
172
173         void updateRoutingCache(detail::StreamBase const * stream, detail::AreaBase const * area);
174
175         void write(boost::posix_time::ptime timestamp, detail::StreamBase const & stream,
176                    detail::AreaBase const & area, unsigned level, std::string const & message);
177
178 #   ifdef DOXYGEN
179     protected:
180 #   endif
181
182         virtual void v_write(boost::posix_time::ptime, std::string const & stream, 
183                              std::string const & area, unsigned level, 
184                              std::string const & message) = 0;
185
186 #   ifdef DOXYGEN
187     private:
188 #   endif
189
190         RIB rib_;
191         
192         friend class detail::AreaBase;
193     };
194
195     /** \brief Target registry
196
197         The TargetRegistry keeps a record of all existing targets. 
198       */
199     class TargetRegistry
200         : public senf::singleton<TargetRegistry>
201     {
202     public:
203         using senf::singleton<TargetRegistry>::instance;
204
205         void write(detail::StreamBase const & stream, detail::AreaBase const & area,
206                    unsigned level, std::string msg);
207
208     private:
209         void registerTarget(Target * target);
210         void unregisterTarget(Target * target);
211
212         typedef std::set<Target *> Targets;
213         Targets targets_;
214         
215         friend class Target;
216     };
217
218
219     template <class Stream, class Area, class Level>
220     void write(std::string msg);
221
222 }}
223
224 ///////////////////////////////hh.e////////////////////////////////////////
225 #include "Target.cci"
226 //#include "Target.ct"
227 #include "Target.cti"
228 #endif
229
230 \f
231 // Local Variables:
232 // mode: c++
233 // fill-column: 100
234 // comment-column: 40
235 // c-file-style: "senf"
236 // indent-tabs-mode: nil
237 // ispell-local-dictionary: "american"
238 // compile-command: "scons -u test"
239 // End: