1 /*
2  * Copyright (C) 2003, Tommi Maekitalo
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * As a special exception, you may use this file as part of a free
10  * software library without restriction. Specifically, if other files
11  * instantiate templates or use macros or inline functions from this
12  * file, or you compile this file and link it with other files to
13  * produce an executable, this file does not by itself cause the
14  * resulting executable to be covered by the GNU General Public
15  * License. This exception does not however invalidate any other
16  * reasons why the executable file might be covered by the GNU Library
17  * General Public License.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Lesser General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public
25  * License along with this library; if not, write to the Free Software
26  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
27  */
28 
29 #ifndef CXXTOOLS_LOG_CXXTOOLS_H
30 #define CXXTOOLS_LOG_CXXTOOLS_H
31 
32 #include <string>
33 #include <iostream>
34 
35 #define _cxxtools_log_enabled(level)   \
36   (getLogger() != 0 && getLogger()->isEnabled(::cxxtools::Logger::LOG_LEVEL_ ## level))
37 
38 #define _cxxtools_log(level, expr)   \
39   do { \
40     ::cxxtools::Logger* _cxxtools_logger = getLogger(); \
41     if (_cxxtools_logger != 0 && _cxxtools_logger->isEnabled(::cxxtools::Logger::LOG_LEVEL_ ## level)) \
42     { \
43       ::cxxtools::LogMessage _cxxtools_logMessage(_cxxtools_logger, #level); \
44       _cxxtools_logMessage.out() << expr; \
45       _cxxtools_logMessage.finish(); \
46     } \
47   } while (false)
48 
49 #define _cxxtools_log_if(level, cond, expr)   \
50   do { \
51     ::cxxtools::Logger* _cxxtools_logger = getLogger(); \
52     if (_cxxtools_logger != 0 && _cxxtools_logger->isEnabled(::cxxtools::Logger::LOG_LEVEL_ ## level) && (cond)) \
53     { \
54       ::cxxtools::LogMessage _cxxtools_logMessage(_cxxtools_logger, #level); \
55       _cxxtools_logMessage.out() << expr; \
56       _cxxtools_logMessage.finish(); \
57     } \
58   } while (false)
59 
60 #define log_fatal_enabled()     _cxxtools_log_enabled(FATAL)
61 #define log_error_enabled()     _cxxtools_log_enabled(ERROR)
62 #define log_warn_enabled()      _cxxtools_log_enabled(WARN)
63 #define log_info_enabled()      _cxxtools_log_enabled(INFO)
64 #define log_debug_enabled()     _cxxtools_log_enabled(DEBUG)
65 #define log_trace_enabled()     _cxxtools_log_enabled(TRACE)
66 
67 #define log_fatal(expr)     _cxxtools_log(FATAL, expr)
68 #define log_error(expr)     _cxxtools_log(ERROR, expr)
69 #define log_warn(expr)      _cxxtools_log(WARN, expr)
70 #define log_info(expr)      _cxxtools_log(INFO, expr)
71 #define log_debug(expr)     _cxxtools_log(DEBUG, expr)
72 
73 #define log_fatal_if(cond, expr)     _cxxtools_log_if(FATAL, cond, expr)
74 #define log_error_if(cond, expr)     _cxxtools_log_if(ERROR, cond, expr)
75 #define log_warn_if(cond, expr)      _cxxtools_log_if(WARN, cond, expr)
76 #define log_info_if(cond, expr)      _cxxtools_log_if(INFO, cond, expr)
77 #define log_debug_if(cond, expr)     _cxxtools_log_if(DEBUG, cond, expr)
78 
79 #define log_trace(expr)     \
80   ::cxxtools::LogTracer _cxxtools_tracer;  \
81   do { \
82     ::cxxtools::Logger* _cxxtools_logger = getLogger(); \
83     if (_cxxtools_logger != 0 && _cxxtools_logger->isEnabled(::cxxtools::Logger::LOG_LEVEL_TRACE)) \
84     { \
85       _cxxtools_tracer.setLogger(_cxxtools_logger); \
86       _cxxtools_tracer.out() << expr;  \
87       _cxxtools_tracer.enter();  \
88     } \
89   } while (false)
90 
91 #define log_define(category) \
92   static ::cxxtools::Logger* getLogger()   \
93   {  \
94     static cxxtools::Logger* logger = 0; \
95     if (!::cxxtools::LoggerManager::isEnabled()) \
96       return 0; \
97     if (logger == 0) \
98       logger = ::cxxtools::LoggerManager::getInstance().getLogger(category); \
99     return logger; \
100   }
101 
102 #define log_init_cxxtools  ::cxxtools::LoggerManager::logInit
103 #define log_init  log_init_cxxtools
104 
105 namespace cxxtools
106 {
107   class SerializationInfo;
108 
109   //////////////////////////////////////////////////////////////////////
110   //
111   class Logger
112   {
113     public:
114       typedef enum {
115         LOG_LEVEL_FATAL = 0,
116         LOG_LEVEL_ERROR = 100,
117         LOG_LEVEL_WARN  = 200,
118         LOG_LEVEL_INFO  = 300,
119         LOG_LEVEL_DEBUG = 400,
120         LOG_LEVEL_TRACE = 500
121       } log_level_type;
122 
123     private:
124       std::string category;
125       log_level_type level;
126 
127       Logger(const Logger&);
128       Logger& operator=(const Logger&);
129 
130     public:
Logger(const std::string & c,log_level_type l)131       Logger(const std::string& c, log_level_type l)
132         : category(c), level(l)
133         { }
134 
isEnabled(log_level_type l)135       bool isEnabled(log_level_type l) const
136         { return level >= l; }
getCategory()137       const std::string& getCategory() const
138         { return category; }
getLogLevel()139       log_level_type getLogLevel() const
140         { return level; }
141   };
142 
143   //////////////////////////////////////////////////////////////////////
144   //
145   class LoggerManagerConfiguration
146   {
147     public:
148       class Impl;
149 
150     private:
151       friend class Impl;
152       Impl* _impl;
153 
154     public:
155       LoggerManagerConfiguration();
156       LoggerManagerConfiguration(const LoggerManagerConfiguration&);
157       LoggerManagerConfiguration& operator=(const LoggerManagerConfiguration&);
158 
159       ~LoggerManagerConfiguration();
160 
impl()161       Impl* impl()             { return _impl; }
impl()162       const Impl* impl() const { return _impl; }
163 
164       Logger::log_level_type rootLevel() const;
165       Logger::log_level_type logLevel(const std::string& category) const;
166   };
167 
168   void operator>>= (const SerializationInfo& si, LoggerManagerConfiguration& loggerManagerConfiguration);
169 
170   //////////////////////////////////////////////////////////////////////
171   //
172   class LoggerManager
173   {
174     public:
175       class Impl;
176 
177       friend class Impl;
178 
179       Impl* _impl;
180       LoggerManager();
181       static bool _enabled;
182 
183       LoggerManager(const LoggerManager&);
184       LoggerManager& operator=(const LoggerManager&);
185 
186     public:
187       ~LoggerManager();
188 
impl()189       Impl* impl()              { return _impl; }
impl()190       const Impl* impl() const  { return _impl; }
191 
192       static LoggerManager& getInstance();
193       static void logInit();
194       static void logInit(const std::string& fname);
195       static void logInit(const cxxtools::SerializationInfo& si);
196 
197       void configure(const LoggerManagerConfiguration& config);
198       Logger* getLogger(const std::string& category);
isEnabled()199       static bool isEnabled()
200       { return _enabled; }
201 
202       Logger::log_level_type rootLevel() const;
203       Logger::log_level_type logLevel(const std::string& category) const;
204   };
205 
206   //////////////////////////////////////////////////////////////////////
207   //
208   class LogMessage
209   {
210     public:
211       class Impl;
212 
213     private:
214       Impl* _impl;
215 
216       LogMessage(const LogMessage&);
217       LogMessage& operator=(const LogMessage&);
218 
219     public:
220       LogMessage(Logger* logger, const char* level);
221       LogMessage(Logger* logger, Logger::log_level_type level);
222       ~LogMessage();
223 
impl()224       Impl* impl()             { return _impl; }
impl()225       const Impl* impl() const { return _impl; }
226 
227       std::ostream& out();
228       std::string str() const;
229 
230       void finish();
231   };
232 
233   //////////////////////////////////////////////////////////////////////
234   //
235   class LogTracer
236   {
237     public:
238       class Impl;
239 
240     private:
241       Impl* _impl;
242 
243       LogTracer(const LogTracer&);
244       LogTracer& operator=(const LogTracer&);
245 
246     public:
247       LogTracer();
248       ~LogTracer();
249 
impl()250       Impl* impl()             { return _impl; }
impl()251       const Impl* impl() const { return _impl; }
252 
253       void setLogger(Logger* l);
254       std::ostream& out();
255       void enter();
256       void exit();
257   };
258 
259 }
260 
261 #endif // LOG_CXXTOOLS_H
262