root/trunk/whisperlib/common/base/log.h

Revision 7, 9.7 kB (checked in by whispercastorg, 2 years ago)

version 0.2.0

Line 
1 // Copyright (c) 2009, Whispersoft s.r.l.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Whispersoft s.r.l. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Author: Cosmin Tudorache & Catalin Popescu
31
32 #ifndef __COMMON_BASE_LOG_H__
33 #define __COMMON_BASE_LOG_H__
34
35 #include <sstream>
36 #include <string>
37 #include <whisperlib/common/base/types.h>
38 #include <whisperlib/common/base/gflags.h>
39 #include <whisperlib/common/base/strutil.h>
40 #include <whisperlib/common/base/errno.h>
41
42 static const int LDEBUG    = 4;
43 static const int LINFO     = 3;
44 static const int LWARNING  = 2;
45 static const int LERROR    = 1;
46 static const int LFATAL    = 0;
47
48
49 //////////////////////////////////////////////////////////////////////
50
51 namespace synch {
52 class Mutex;
53 }
54
55 namespace log_internal {
56
57 class Log {
58  public:
59   Log(int level, const char* filename);
60   virtual ~Log();
61
62   int level() const { return level_; }
63
64   void Flush();
65
66   void OutputString(const string& s);
67  private:
68   // We synchronize log access w/ this guy
69   // (use * to not require including mutex.h)
70   // TODO(cpopescu): amazingly important !!! Make this reentrant !!!
71   synch::Mutex* mutex_;
72   // we log only under this level
73   const int level_;
74   // our log file - main stuff - everything goes here
75   FILE* log_file_;
76   // a tee - writes to logfile and cerr at the same time (if enabled w/
77   // --alsowritetostderr
78   FILE* tee_file_;
79
80   friend class LogLine;
81 };
82
83 class LogLine {
84  public:
85   LogLine(Log* log, int level);
86   ~LogLine();
87
88   std::ostream& stream() { return stream_; }
89
90  private:
91   Log* const log_;
92   std::ostringstream stream_;
93   const bool is_fatal_;
94 };
95
96 extern Log* gLogger;
97 }
98
99 //////////////////////////////////////////////////////////////////////
100
101 // Pure log macros
102
103 // The trick is to instantiate a LogLine w/ a scope of one C++ statement
104 #define LOG(log_level) \
105   if ( log_level <= log_internal::gLogger->level() ) \
106     log_internal::LogLine(log_internal::gLogger, log_level).stream()    \
107         << strutil::Basename(__FILE__) << ":" << __LINE__  << " : "
108 #ifdef _DEBUG
109 #define DLOG(log_level) LOG(log_level)
110 #else
111 #define DLOG(log_level) if (false) LOG(log_level)
112 #endif
113
114 #define LOG_INFO    LOG(LINFO)
115 #define LOG_DEBUG   LOG(LDEBUG)
116 #define LOG_WARNING LOG(LWARNING)
117 #define LOG_ERROR   LOG(LERROR)
118 #define LOG_FATAL   LOG(LFATAL)
119
120 #define LOG_FATAL_IF(cond) if ( cond ) LOG_FATAL
121 #define LOG_ERROR_IF(cond) if ( cond ) LOG_ERROR
122 #define LOG_INFO_IF(cond) if ( cond ) LOG_INFO
123
124 // Pure log macros, the same set as above
125 // but with the addition of the file name/line number
126 // as there are instances when we get those from somewhere else
127
128 // The trick is to instantiate a LogLine w/ a scope of one C++ statement
129 #define LOG_FILE_LINE(log_level, file, line)                            \
130   if ( log_level <= log_internal::gLogger->level() )                    \
131     log_internal::LogLine(log_internal::gLogger, log_level).stream()    \
132         << strutil::Basename(file) << ":" << (line) << " : "
133 #ifdef _DEBUG
134 #define LOG_FILE_LINE_DEBUG(file, line)         \
135   LOG_FILE_LINE(LDEBUG, file, line)
136 #else
137 #define LOG_FILE_LINE_DEBUG(file, line)         \
138   if (false) LOG_FILE_LINE(LDEBUG, file, line)
139 #endif
140
141 #define LOG_FILE_LINE_INFO(file, line)    LOG_FILE_LINE(LINFO, file, line)
142 #define LOG_FILE_LINE_WARNING(file, line) LOG_FILE_LINE(LWARNING, file, line)
143 #define LOG_FILE_LINE_ERROR(file, line)   LOG_FILE_LINE(LERROR, file, line)
144 #define LOG_FILE_LINE_FATAL(file, line)   LOG_FILE_LINE(LFATAL, file, line)
145
146 #define LOG_FILE_LINE_FATAL_IF(cond, file, line) \
147   if ( cond ) LOG_FILE_LINE_FATAL(file, line)
148 #define LOG_FILE_LINE_INFO_IF(cond, file, line) \
149   if ( cond ) LOG_FILE_LINE_INFO(file, line)
150
151 // Log the given value in hexadecimal with 0x prefix
152 #define LHEX(v) showbase << hex << v << dec << noshowbase
153
154
155 //////////////////////////////////////////////////////////////////////
156
157 // Conditional macros - a little better then ASSERTs
158 #define CHECK(cond)                                                     \
159   if ( cond );                                                          \
160   else                                                                  \
161     LOG_FATAL << #cond << " failed. "
162 #define CHECK_NOT_NULL(p)                                               \
163   if ( (p) != NULL );                                                   \
164   else                                                                  \
165     LOG_FATAL << " Pointer is NULL. "
166 #define CHECK_NULL(p)                                                   \
167   if ( (p) == NULL );                                                   \
168   else                                                                  \
169     LOG_FATAL << " Pointer " << #p << "(" << LHEX(p) << ") is not NULL. "
170 #define CHECK_OP(a, b, op)                                              \
171   if ( (a) op (b) );                                                    \
172   else                                                                  \
173     LOG_FATAL << "Check failed: " << (a) << " " #op " " << (b)
174 #define CHECK_EQ(a, b) CHECK_OP(a, b, ==)
175 #define CHECK_LT(a, b) CHECK_OP(a, b, <)
176 #define CHECK_LE(a, b) CHECK_OP(a, b, <=)
177 #define CHECK_GT(a, b) CHECK_OP(a, b, >)
178 #define CHECK_GE(a, b) CHECK_OP(a, b, >=)
179 #define CHECK_NE(a, b) CHECK_OP(a, b, !=)
180 #define CHECK_STREQ(a, b)                                               \
181   if ( 0 == strcmp((a), (b)) );                                         \
182   else                                                                  \
183     LOG_FATAL << (a) << " != " << (b)
184 #define CHECK_STRLT(a, b)                                               \
185   if ( -1 == strcmp((a), (b)) );                                        \
186   else                                                                  \
187     LOG_FATAL << (a) << " >= " << (b)
188 #define CHECK_STRGT(a, b)                                               \
189   if ( 1 == strcmp((a), (b)) );                                         \
190   else                                                                  \
191     LOG_FATAL << (a) << " <= " << (b)
192
193 #define CHECK_SYS_FUN(a, b)                                             \
194   do { int __tmp_res__ = a;                                             \
195     if ( __tmp_res__ != b ) {                                           \
196       LOG_FATAL << #a << " Failed w/ result: " << __tmp_res__           \
197                 << "(" << GetSystemErrorDescription(__tmp_res__) << ")" \
198                 << " expected: " << #b;                                 \
199     }                                                                   \
200   } while ( false );
201
202
203 //////////////////////////////////////////////////////////////////////
204
205 // What we have below is a compile time check helper
206 // that will trigger a compile error if the given constant
207 // expression evaluates to false.
208 template <bool>
209 struct CompileAssert {
210 };
211
212 #undef  COMPILE_ASSERT
213 #define COMPILE_ASSERT(expr, msg)                  \
214   typedef CompileAssert<(static_cast<bool>(expr))> \
215   msg[static_cast<bool>(expr) ? 1 : -1]
216
217
218 //////////////////////////////////////////////////////////////////////
219
220 #ifdef _DEBUG
221
222 #define DCHECK(cond)   CHECK(cond)
223 #define DCHECK_EQ(a, b) CHECK_EQ(a, b)
224 #define DCHECK_LT(a, b) CHECK_LT(a, b)
225 #define DCHECK_LE(a, b) CHECK_LE(a, b)
226 #define DCHECK_GT(a, b) CHECK_GT(a, b)
227 #define DCHECK_GE(a, b) CHECK_GE(a, b)
228 #define DCHECK_NE(a, b) CHECK_NE(a, b)
229
230 #define DLOG_DEBUG   LOG(LDEBUG)
231 #define DLOG_INFO    LOG(LINFO)
232 #define DLOG_WARNING LOG(LWARNING)
233 #define DLOG_ERROR   LOG(LERROR)
234 #define DLOG_FATAL   LOG(LFATAL)
235
236 #define DLOG_FATAL_IF(cond) if ( cond ) LOG_FATAL
237 #define DLOG_INFO_IF(cond) if ( cond ) LOG_INFO
238
239 #else
240 #define DCHECK(cond)    if ( false ) LOG(LDEBUG)
241 #define DCHECK_EQ(a, b) if ( false ) LOG(LDEBUG)
242 #define DCHECK_LT(a, b) if ( false ) LOG(LDEBUG)
243 #define DCHECK_LE(a, b) if ( false ) LOG(LDEBUG)
244 #define DCHECK_GT(a, b) if ( false ) LOG(LDEBUG)
245 #define DCHECK_GE(a, b) if ( false ) LOG(LDEBUG)
246 #define DCHECK_NE(a, b) if ( false ) LOG(LDEBUG)
247
248 #define DLOG_DEBUG   if ( false ) LOG(LDEBUG)
249 #define DLOG_INFO    if ( false ) LOG(LINFO)
250 #define DLOG_WARNING if ( false ) LOG(LWARNING)
251 #define DLOG_ERROR   if ( false ) LOG(LERROR)
252 #define DLOG_FATAL   if ( false ) LOG(LFATAL)
253
254 #define DLOG_FATAL_IF(cond) if (false) LOG_FATAL
255 #define DLOG_INFO_IF(cond) if ( false ) LOG_INFO
256
257 #endif
258
259
260 // Internal initialization/deinitialization functions -
261 // you should not call these
262 void InitLogger(int level, const char* filename);
263 void InitDefaultLogger(const char* progname);
264 void FlushLogger();
265
266 #endif    // __COMMON_BASE_LOG_H__
Note: See TracBrowser for help on using the browser.