00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef _logfile_h_
00030 #define _logfile_h_
00031
00032
00033 #define _NO_LOGGING
00034
00035 #include <fstream>
00036 #include <iostream>
00037
00038 #include <string.h>
00039 #include <pthread.h>
00040 #include <sys/time.h>
00041 #include <stdio.h>
00042 #include <unistd.h>
00043
00044 #include "protlib_types.h"
00045
00046 namespace protlib {
00047
00048 using namespace std;
00053 namespace log {
00054
00055 static const pthread_mutex_t initlogmutex=
00056 #ifdef _DEBUG
00057
00058 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
00059 #else // should be recursive mutex because sometimes error log output sometimes occurs
00060
00061 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
00062 #endif
00063
00064 #undef ERROR_LOG
00065 #undef WARNING_LOG
00066 #undef EVENT_LOG
00067 #undef INFO_LOG
00068 #undef DEBUG_LOG
00069 #undef LOG_TYPES
00070
00071 #undef LOG_ALL
00072 #undef LOG_EMERG
00073 #undef LOG_ALERT
00074 #undef LOG_CRIT
00075 #undef LOG_NORMAL
00076 #undef LOG_UNIMP
00077
00078
00079 enum logclass_t
00080 {
00081 ERROR_LOG= 0x10,
00082 WARNING_LOG= 0x20,
00083 EVENT_LOG= 0x30,
00084 INFO_LOG= 0x40,
00085 DEBUG_LOG= 0x50,
00086 EVERY_LOG= 0xF0,
00087 LOG_TYPES= 5
00088 };
00089
00090
00091 enum loglevel_t
00092 {
00093 LOG_EMERG= 0,
00094 LOG_ALERT= 1,
00095 LOG_CRIT= 2,
00096 LOG_NORMAL= 4,
00097 LOG_UNIMP= 8,
00098 LOG_ALL= 15
00099 };
00100
00101
00102
00103 enum color_t
00104 {
00105 clear,
00106 bold_on,
00107 italics_on,
00108 underline_on,
00109 inverse_on,
00110 strikethrough_on,
00111 bold_off,
00112 italics_off,
00113 underline_off,
00114 inverse_off,
00115 strikethrough_off,
00116 black,
00117 red,
00118 green,
00119 yellow,
00120 blue,
00121 magenta,
00122 cyan,
00123 white,
00124 fg_default,
00125 bg_black,
00126 bg_red,
00127 bg_green,
00128 bg_yellow,
00129 bg_blue,
00130 bg_magenta,
00131 bg_cyan,
00132 bg_white,
00133 bg_default,
00134 num_colors,
00135 off=0};
00136
00137 extern const char* color[];
00138 extern const char *const ANSIcolorcode[];
00139
00140
00141 #define ERRLog(mname, logstring) Log(ERROR_LOG, LOG_NORMAL, mname, logstring)
00142 #define ERRCLog(mname, logstring) Log(ERROR_LOG, LOG_CRIT, mname, logstring)
00143 #define EVLog(mname, logstring) Log(EVENT_LOG, LOG_NORMAL, mname, logstring)
00144 #define WLog(mname, logstring) Log(WARNING_LOG, LOG_NORMAL, mname, logstring)
00145 #define ILog(mname, logstring) Log(INFO_LOG, LOG_NORMAL, mname, logstring)
00146 #define DLog(mname, logstring) Log(DEBUG_LOG, LOG_NORMAL, mname, logstring)
00147
00148
00149 #ifndef _NO_LOGGING
00150
00151
00152
00153
00154 #define Log(lclass, llevel, mname, logstring) do { \
00155 if ( protlib::log::DefaultLog.should_log(lclass, llevel) ) { \
00156 using protlib::log::DefaultLog; \
00157 DefaultLog.logstart(lclass, llevel, mname) << logstring; \
00158 DefaultLog.logend(); \
00159 } \
00160 } while ( false )
00161
00162 #define LogS(lclass, llevel, mname, logstring) do { \
00163 if ( protlib::log::DefaultLog.should_log(lclass, llevel) ) { \
00164 protlib::log::DefaultLog.logstart(lclass, llevel, mname, \
00165 __FILE__, __FUNCTION__, __LINE__) << logstring; \
00166 protlib::log::DefaultLog.logend(); \
00167 } \
00168 } while ( false )
00169
00170 #else
00171
00172 #define Log(logclass, loglevel, mname, logstring)
00173 #define LogS(logclass, loglevel, mname, logstring)
00174
00175 #endif
00176
00177 class logfile
00178 {
00179 private:
00180 ostream* logstream;
00181 pthread_mutex_t logmutex;
00182
00183 unsigned char logfilter[LOG_TYPES];
00184
00185 bool usecolors;
00186 bool quiet_start;
00187
00188 const char* timenow();
00189
00190 public:
00191
00192 logfile(const char* filename="", bool usecolors= true, bool quietstart=false);
00193 ~logfile();
00194
00195 bool set_dest(const char* filename, bool quiet=false);
00196 void set_filter(logclass_t logclass, uint8 severitylevel);
00197 bool should_log(logclass_t logclass, loglevel_t severitylevel);
00198
00199
00200 ostream& logstart(logclass_t logclass, loglevel_t severity_level,
00201 const string& modname,
00202 const char* file="",
00203 const char* func="",
00204 int line=0);
00205 void coloron() { usecolors=true; for (int i= 0; i<num_colors; i++) {color[i]= ANSIcolorcode[i]; } }
00206 void coloroff() { usecolors=false; for (int i= 0; i<num_colors; i++) {color[i]= ""; } }
00207
00208 void logend();
00209 };
00210
00211 extern
00212
00213 inline
00214 logfile::logfile(const char* filename, bool usecolors, bool quietstart)
00215 : logstream(0),
00216 logmutex(initlogmutex),
00217 usecolors(usecolors),
00218 quiet_start(quietstart)
00219 {
00220 for (int i= 0; i< LOG_TYPES; i++)
00221 logfilter[i]= LOG_ALL;
00222
00223 if (strlen(filename))
00224 logstream= new(nothrow) ofstream(filename);
00225 else
00226 logstream= &cout;
00227
00228 if (!logstream)
00229 {
00230 cerr << "Could not open logfile " << filename << endl;
00231 }
00232 else
00233 {
00234 pthread_mutex_lock(&logmutex);
00235
00236
00237
00238 for (int i= 0; i<num_colors; i++)
00239 {
00240 color[i]= (usecolors ? ANSIcolorcode[i] : "");
00241 }
00242
00243 if (!quiet_start && logstream)
00244 {
00245
00246
00247
00248 }
00249 pthread_mutex_unlock(&logmutex);
00250 }
00251 }
00252
00253
00254 inline
00255 logfile::~logfile()
00256 {
00257 if (logstream)
00258 {
00259 pthread_mutex_lock(&logmutex);
00260
00261 if ( ! quiet_start )
00262
00263
00264
00265 pthread_mutex_unlock(&logmutex);
00266
00267
00268 pthread_mutex_destroy(&logmutex);
00269
00270
00271 if (logstream!= &cout)
00272 delete logstream;
00273
00274 logstream= 0;
00275 }
00276 }
00277
00278
00279
00280 inline
00281 void
00282 logfile::set_filter(logclass_t logclass, uint8 severity_level)
00283 {
00284 uint8 logclass_index= (logclass>>4)-1;
00285 if (logclass_index < LOG_TYPES)
00286 logfilter[logclass_index]= severity_level;
00287 }
00288
00289 inline
00290 bool
00291 logfile::should_log(logclass_t logclass, loglevel_t severity_level)
00292 {
00293 return severity_level <= logfilter[(logclass>>4)-1];
00294 }
00295
00296
00301 inline
00302 const char* logfile::timenow()
00303 {
00304 static time_t t;
00305 static struct timeval now;
00306 static char timestr[32]= "";
00307 static char msecstr[6];
00308
00309 gettimeofday(&now,NULL);
00310 t= now.tv_sec;
00311 strftime(timestr, sizeof(timestr)-sizeof(msecstr), "%Y-%m-%d %H:%M:%S.", localtime(&t));
00312 snprintf(msecstr,sizeof(msecstr),"%03lu",now.tv_usec/1000UL);
00313 strcat(timestr,msecstr);
00314 return timestr;
00315 }
00316
00317 inline
00318 void logfile::logend()
00319 {
00320 if (logstream)
00321 {
00322 (*logstream) << color[off] << endl;
00323 }
00324
00325 pthread_mutex_unlock(&logmutex);
00326 }
00327
00328
00329 extern logfile& DefaultLog;
00331
00332 }
00333
00334 }
00335
00336
00337
00338
00339
00344 inline
00345 const char* log_timenow(char* module, char* event)
00346 {
00347
00348
00349
00350
00351
00352
00353
00354
00355 static time_t t;
00356
00357 static char timestr[128]= "";
00358
00359
00360 struct timespec tp;
00361
00362 clock_gettime(CLOCK_REALTIME, &tp);
00363
00364
00365 t= tp.tv_sec;
00366
00367
00368
00369
00370
00371
00372
00373 sprintf(timestr, "%05ld%06ld - ", t % 3600, tp.tv_nsec/1000L);
00374
00375 strcat(timestr,module);
00376 strcat(timestr," - ");
00377 strcat(timestr,event);
00378
00379
00380
00381 return timestr;
00382 }
00383
00384
00385
00386 #endif