switch to new MPL based Fraunhofer FOKUS Public License
[senf.git] / senf / Utils / Logger / Config.hh
1 // $Id$
2 //
3 // Copyright (C) 2007
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 //
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
10 //
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.
14 //
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.
18 //
19 // The Original Code is Fraunhofer FOKUS code.
20 //
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.
24 //
25 // Contributor(s):
26 //   Stefan Bund <g0dil@berlios.de>
27
28 /** \file
29     \brief Config public header */
30
31 #ifndef HH_SENF_Utils_Logger_Config_
32 #define HH_SENF_Utils_Logger_Config_ 1
33
34 // Custom includes
35 #include "Levels.hh"
36
37 //#include "Config.mpp"
38 #include "Config.ih"
39 //-/////////////////////////////////////////////////////////////////////////////////////////////////
40
41 /** \defgroup config Configuration
42
43     The logger infrastructure provides for very fine-grained configuration of log messages. There
44     are two parts to this configuration: compile-time configuration and runtime configuration.
45
46     <em>Compile-time</em> configuration selects, which log statements will even be compiled. If
47     logging for a certain combination of stream, area and level is disabled at compile time, no code
48     will be generated for any such disabled log statement. This type of configuration is done using
49     \ref SENF_LOG_CONF.
50
51     <em>Runtime</em> configuration on the other hand deals with routing all those messages, which
52     are enabled at compile time to the logging targets. If a message is not routed, it will be
53     discarded. This allows to additionally disable messages at run-time. Message routing is managed
54     via the ::Target interface.
55
56     \section config_compile Compile time configuration
57
58     Compile time configuration is set on the compiler command line:
59     <pre>
60     g++ ... -DSENF_LOG_CONF="(( (senf)(log)(Debug),(_),DISABLED ))
61                              (( (senf)(log)(Debug),(foo)(SomeClass),VERBOSE ))
62                              (( (_),(_),NOTICE ))" ...
63     </pre>
64     The value is relatively complex; It's a Boost.Preprocessor style sequence of tuples, of which
65     the first and second elements are again sequences. What this boils down to, is that it allows to
66     configure compile time logging limits based on stream and optional area.
67
68     The above example disables all debug logging by setting the default log limit for all areas on
69     the \c senf::log::Debug stream to \c DISABLED. It enables debug logging only within the \c
70     foo::SomeClass area, where it is set to \c VERBOSE. Lastly, the global compile time limit is set
71     to \c NOTICE.
72
73     There are two standard uses for this configuration: Either to disable most logging in final
74     builds by changing the compile time limit to something like senf::log::IMPORTANT or to enable
75     senf::log::VERBOSE messages for some area:
76     <pre>
77     # Disable debug logging below 'IMPORTANT' level
78     g++ ... -DSENF_LOG_CONF="(( (senf)(log)(Debug), (_), IMPORTANT ))"
79
80     # Or enable verbose messages for the 'some::Area' area
81     g++ ... -DSENF_LOG_CONF="(( (senf)(log)(Verbose), (some)(Area), VERBOSE ))"
82     </pre>
83
84     All the entries specified via \c SENF_LOG_CONF are applied in a fixed order:
85
86     \li First the entries which have both a stream and an area specified are checked
87     \li next all entries with area but no stream given are checked
88     \li followed by all entries with a given stream but no area
89     \li and lastly if no match was found until now, a generic entry without stream and area is
90         checked
91     \li if no matching entry is found, the default compile time limit of the stream is used
92
93     So an area specification has precedence over a stream specification.
94
95     \warning Enabling a message at compile time does \e not ensure, the message is shown. You
96         additionally need to \e route the message (see next chapter). This is especially true for \c
97         VERBOSE messages, which are default disabled at runtime.
98
99     \see \ref SENF_LOG_CONF
100
101     \section config_runtime Runtime configuration
102
103     The runtime configuration is performed by routing messages to one or more logging targets:
104     \code
105     senf::log::ConsoleTarget & consoleLog (senf::log::ConsoleTarget::instance());
106     senf::log::FileTarget fileLog ("my.log");
107
108     consoleLog.route<senf::log::Debug>();
109     consoleLog.route<foo::Transactions, foo::SomeClass>(senf::log::Target::REJECT);
110     consoleLog.route<foo::Transactions, senf::log::IMPORTANT>();
111
112     fileLog.route<foo::Transactions>();
113     \endcode
114     Here we see an already relatively complex setup: All debug messages (that is, those, which are
115     not disabled at compile time) are routed to the console. We also route important transactions to
116     the console \e except transactions from the \c foo::SomeClass area. The \c fileLog simply
117     receives all transaction log messages.
118
119     The routing statements are processed by the targets in order, the first matching rule will
120     decide a log messages fate for that target.
121
122     \warning You can \e only route those messages at runtime which have been compile-time
123         enabled. By default, \c VERBOSE messages are \e disabled at compile time. They must be
124         enabled \e explicitly by setting \c SENF_LOG_CONF so they can be routed.
125
126     \section config_fallback Fallback routing
127
128     There are two cases, where this setup may lead to inadvertently lost log messages:
129     \li When using a library which does internally use the Logger but not initializing the logger in
130         your application.
131     \li When log messages are created during initialization of static objects.
132     Since no route is set up in these cases, the messages will be dropped.
133
134     To counter this problem, the logger is initially in <em>fallback routing</em> state. If any log
135     message arrives in this state, the message will be logged to the console if it is above the
136     default runtime limit of it's stream. The first routing statement on any target will take the
137     logger out of this state and normal routing will take place.
138
139     \see \ref senf::log::Target
140
141     \section config_timesource Log message timing
142
143     One auxiliary aspect of logging is message timing. Each message is stamped with a time-stamp
144     giving the exact time the message was created. How the current date/time value is created may be
145     changed by setting a \e TimeSource. A TimeSource is an instance derived from
146     senf::log::TimeSource which will return the current universal time (UTC) when called.
147
148     By default, the logging library will call gettimeofday() for each log message. To change the
149     time source, just pass the new class or instance to senf::log::timeSource:
150     \code
151     // Use senf::scheduler::eventTime() to time log messages
152     senf::log::timeSource<senf::scheduler::LogTimeSource>();
153     \endcode
154  */
155
156 namespace senf {
157 namespace log {
158
159     ///\ingroup config
160     //\{
161
162 #   ifdef DOXYGEN
163
164     /** \brief Compile time configuration
165
166         This define symbol sets the compile time logger configuration. This symbol should normally
167         be set on the compiler command line.
168
169         The formal syntax of this option is:
170
171         \par ""
172             <table class="ebnf">
173             <tr><td>conf</td>            <td>::= \e element \e element* \n</td></tr>
174             <tr><td>element</td>         <td>::= <tt>((</tt> \e optional_stream <tt>,</tt> \e optional_area <tt>,</tt> \e level <tt>))</tt> \n</td></tr>
175             <tr><td>optional_stream</td> <td>::= <tt>(_)</tt> | \e scope_seq \n</td></tr>
176             <tr><td>optional_area</td>   <td>::= <tt>(_)</tt> | \e scope_seq \n</td></tr>
177             <tr><td>level</td>           <td>::= \c VERBOSE | \c NOTICE | \c MESSAGE | \c IMPORTANT | \c CRITICAL | \c DISABLED \n</td></tr>
178             <tr><td>scope_seq</td>       <td>::= \e scope \e scope* \n</td></tr>
179             <tr><td>scope</td>           <td>::= <tt>(</tt> \e name <tt>)</tt> \n</td></tr>
180             <tr><td>name</td>            <td>::= arbitrary C++ identifier</td></tr>
181             </table>
182
183         \ref SENF_LOG_CONF is a Boost.Preprocessor style sequence of 3-tuples.
184
185         The first tuple element \e optional_stream specifies the stream to match. If this is
186         <tt>(_)</tt>, the entry will match any stream.
187
188         The next tuple element, \e optional_area optionally restricts the entry to match only the
189         given area. If set to <tt>(_)</tt>, the area is left unrestricted.
190
191         The last tuple element \e level defines the compile time log level. Messages with a level
192         below this are discarded at compile time.
193
194         Both \e optional_stream and \e optional_area are given as a \e scope_seq. A scope sequence
195         is a fully qualified C++ identifier placed into a sequence: <tt>foo::bar::baz</tt> is
196         represented by <tt>(foo)(bar)(baz)</tt>.
197      */
198 #   define SENF_LOG_CONF
199
200 #   endif
201
202     /** \brief Check, if logging is enabled for stream/area/level tuple
203
204         This is a template meta-function which will check, whether logging to the given combination
205         of parameters \a Stream, \a Area and \a Level is compile-time enabled. The logging might
206         still be disabled at runtime.
207         \code
208         if (senf::log::Enabled<senf::log::Debug,
209                                senf::log::DefaultArea,
210                                senf::log::VERBOSE>::value) {
211             // ...
212         }
213         \endcode
214
215         Since the \e value member is a compile time constant, the compiler will completely optimize
216         away this block of code when logging is disabled.
217      */
218     template <class Stream, class Area, class Level>
219     struct Enabled
220     {
221         static const bool value = (
222             (Level::value == NONE::value ? Stream::defaultLevel::value : Level::value)
223                 >= detail::Config<Stream,Area>::compileLimit::value );
224     };
225
226     //\}
227
228 }}
229
230 //-/////////////////////////////////////////////////////////////////////////////////////////////////
231 //#include "Config.cci"
232 //#include "Config.ct"
233 //#include "Config.cti"
234 #endif
235
236 \f
237 // Local Variables:
238 // mode: c++
239 // fill-column: 100
240 // comment-column: 40
241 // c-file-style: "senf"
242 // indent-tabs-mode: nil
243 // ispell-local-dictionary: "american"
244 // compile-command: "scons -u test"
245 // End: