00001 // //////////////////////////////////////////////////////////////////// // 00002 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00003 // University of Southern California (USC) and the iLab at USC. // 00004 // See http://iLab.usc.edu for information about this project. // 00005 // //////////////////////////////////////////////////////////////////// // 00006 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00007 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00008 // in Visual Environments, and Applications'' by Christof Koch and // 00009 // Laurent Itti, California Institute of Technology, 2001 (patent // 00010 // pending; application number 09/912,225 filed July 23, 2001; see // 00011 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00012 // //////////////////////////////////////////////////////////////////// // 00013 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00014 // // 00015 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00016 // redistribute it and/or modify it under the terms of the GNU General // 00017 // Public License as published by the Free Software Foundation; either // 00018 // version 2 of the License, or (at your option) any later version. // 00019 // // 00020 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00021 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00022 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00023 // PURPOSE. See the GNU General Public License for more details. // 00024 // // 00025 // You should have received a copy of the GNU General Public License // 00026 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00027 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00028 // Boston, MA 02111-1307 USA. // 00029 // //////////////////////////////////////////////////////////////////// // 00030 // 00031 // Primary maintainer for this file: Laurent Itti <itti@usc.edu> 00032 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Util/log.H $ 00033 // $Id: log.H 11019 2009-03-11 20:57:11Z itti $ 00034 // 00035 00036 #ifndef LOG_H_DEFINED 00037 #define LOG_H_DEFINED 00038 00039 #include <exception> 00040 #include <syslog.h> 00041 #include <string.h> 00042 00043 /*! \file Util/log.H 00044 \brief Logging facility 00045 00046 This is a comprehensive logging facility. Use the functions 00047 provided below to display messages to the user and/or syslog. 00048 Never use printf() or std::cout<< in your code, use the functions 00049 provided here instead. 00050 00051 Basic function call is [ID | C][P]L<LOGLEV>("format", args, ...) 00052 00053 - Log levels are: DEBUG, INFO, ERROR, FATAL. 00054 - Prepend 'L' to call the function for a given level. 00055 - Prepend 'P' to have strerror(errno) appended to msg. 00056 - Prepend 'ID' to have integer value MYLOGID inserted at start of 00057 msg (see examples), OR, prepend 'C' to have the ModelComponent 00058 descriptive name used instead of the file name (see below), if 00059 you are inside a ModelComponent. The 'C' version will not work 00060 in any place where a descriptiveName() function is not 00061 available. To minimize confusion, the 'C' version will put the 00062 descriptive name in square brackets, so that it may be easily 00063 distinguished from a file name. 00064 - '#define DEBUG' in 'log.C' to get line numbers with function name. 00065 00066 Although macros, all functions are atomic, so 'if (bad) 00067 LERROR(bad);' is ok; also arguments that span several lines of 00068 source code are ok too. Using these functions in macros however is 00069 probably bogus: MACRO(LERROR("xx")). CAUTION: message size is 00070 limited to LBS chars (including final '\0'); longer messages will 00071 be cleanly truncated. 00072 00073 All log functions act like printf, so be careful when passing 00074 strings from outside directly as the format string for these 00075 functions, as outside strings may contain '%' signs which could 00076 segfault your program! so, use LERROR("%s", unknown_string) 00077 rather than LERROR(unknown_string). 00078 00079 DEBUG, INFO and ERROR simply report an error. FATAL also throws an 00080 exception of class "bug" (or exits; see implementation). 00081 00082 Log entries will look like: 00083 00084 \verbatim 00085 00086 >>>>>>>>>>>>>>>>>>>> LERROR("success! %d %s", 10, "bozo") 00087 Jan 11 07:21:26 jukebox dntwebcfgd: SockServ::check: success! 10 bozo 00088 ^^^^^^^^^^^^^^^ ^^^^^^^ ^^^^^^^^^^ ^^^^^^^^ ^^^^^ ^^^^^^^^^^^^^^^^ 00089 date/time machine program class funct message 00090 00091 >>>>>>>>>>>>>>>>>>>> PLERROR("Cannot open"); 00092 Jan 11 07:21:26 jukebox dntwebcfg: Cool::check: Cannot open (Bad descriptor) 00093 ^^^^^^^^^^^^^^^ ^^^^^^^ ^^^^^^^^^ ^^^^ ^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ 00094 date/time machine program class funct message errno in clear 00095 00096 >>>>>>>>>>>>>>>>>>>> IDLINFO("Connected"); 00097 with '#define MYLOGID fd' and current value of fd being 10 00098 Jan 11 07:21:26 jukebox dntwebcfgd: Cool::check:(10) Connected 00099 ^^^^^^^^^^^^^^^ ^^^^^^^ ^^^^^^^^^^ ^^^^ ^^^^^ ^^ ^^^^^^^^^ 00100 date/time machine program class funct ID message 00101 00102 >>>>>>>>>>>>>>>>>>>> IDPLFATAL("Abort"); 00103 with '#define MYLOGID fd' and current value of fd being 10 00104 Jan 11 07:21:26 jukebox dntwebcfgd: Cool::check:(10) Abort (Out of memory) 00105 ^^^^^^^^^^^^^^^ ^^^^^^^ ^^^^^^^^^^ ^^^^ ^^^^^ ^^ ^^^^^ ^^^^^^^^^^^^^ 00106 date/time machine program class funct ID mes errno in clear 00107 00108 >>>>>>>>>>>>>>>>>>>> CLERROR("success! %d %s", 10, "bozo") 00109 Jan 11 07:21:26 jukebox dntwebcfgd: [Gabor(45)]::check: success! 10 bozo 00110 ^^^^^^^^^^^^^^^ ^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^ ^^^^^^^^^^^^^^^^ 00111 date/time machine program ModelComponent funct message 00112 00113 \endverbatim 00114 00115 If the message starts with a '(', '[' or '{' char, no space is written 00116 between the colon following function name and the message 00117 00118 A last macro is provided, SHOWMEMORY(format, ...) which will display 00119 your message via LERROR, and append the total memory usage for the 00120 current process (as per the VmSize field in /proc/<pid>/status; this 00121 is useful to check for possible memory leaks). It only works under 00122 Linux and hence we have only defined it in the GNU C section here. 00123 */ 00124 00125 00126 /// Make LFATAL() throw a std::exception rather than abort()ing. 00127 /** This flag is on by default. */ 00128 const int LFATAL_THROWS = (1 << 0); 00129 /// Make LFATAL() print " -- ABORT" after each message. 00130 /** This flag is on by default. */ 00131 const int LFATAL_PRINTS_ABORT = (1 << 1); 00132 /// Make LFATAL() print its msg to stderr/syslog AND put it in the std::exception. 00133 /** This flag is on by default. Without it, LFATAL will only print its 00134 message to stderr or syslog if it will NOT be throwing a 00135 std::exception with that same message in 00136 std::exception::what(). */ 00137 const int LFATAL_XTRA_NOISY = (1 << 2); 00138 /// Whether to send log messages to stderr or to syslog. 00139 /*! Messages are sent to stderr if the LOG_FULLTRACE flag is set in 00140 LOG_FLAGS (this is the default), or are sent to syslog if the 00141 LOG_FULLTRACE flag is not set. Executables don't need to do 00142 anything special unless they need a non-default value. */ 00143 const int LOG_FULLTRACE = (1 << 3); 00144 00145 /// Bitwise-or'ed combination of above flags. 00146 extern int LOG_FLAGS; 00147 00148 00149 /*! Log verbosity (see <syslog.h> for possible values). Default value is 00150 LOG_DEBUG. Executables don't need to do anything special unless they need 00151 a non-default value. */ 00152 extern int MYLOGVERB; 00153 00154 /// Null by default, but if set to non-null this string will be prefixed to every log message. 00155 /*! This can be useful if you have multiple threads or multiple 00156 processes all writing to stdout, and you want to have some way to 00157 distinguish their log messages. */ 00158 extern const char* MYLOGPREFIX; 00159 00160 /// Type of exception that is thrown from LFATAL if (LOG_FLAGS&LFATAL_THROWS) 00161 /** The real type of the exception is a derived type that is hidden 00162 from this header file -- that's so that we can hide potentially 00163 expensive things in the real implementation, like using 00164 std::string or doing some other fancy message formatting. */ 00165 class lfatal_exception : public std::exception 00166 { 00167 protected: 00168 lfatal_exception() throw(); 00169 virtual ~lfatal_exception() throw(); 00170 00171 public: 00172 virtual const char* what() const throw() = 0; 00173 }; 00174 00175 // ###################################################################### 00176 // If using GNU C, these vararg macros provide a thread-safe facility 00177 // ###################################################################### 00178 #ifdef __GNUC__ 00179 00180 #define LDEBUG(f, x...) sendlog(LOG_DEBUG,__LINE__,__FILE__,__FUNCTION__,\ 00181 0,false,false, f , ## x) 00182 #define LINFO(f, x...) sendlog(LOG_INFO,__LINE__,__FILE__,__FUNCTION__,\ 00183 0,false,false, f , ## x) 00184 #define LERROR(f, x...) sendlog(LOG_ERR,__LINE__,__FILE__,__FUNCTION__,\ 00185 0,false,false,f ,## x) 00186 #define LFATAL(f, x...) sendlog(LOG_CRIT,__LINE__,__FILE__,__FUNCTION__,\ 00187 0,false,false, f , ## x) 00188 00189 #define PLDEBUG(f, x...) sendlog(LOG_DEBUG,__LINE__,__FILE__,__FUNCTION__,\ 00190 0,false,true, f , ## x) 00191 #define PLINFO(f, x...) sendlog(LOG_INFO,__LINE__,__FILE__,__FUNCTION__,\ 00192 0,false,true, f , ## x) 00193 #define PLERROR(f, x...) sendlog(LOG_ERR,__LINE__,__FILE__,__FUNCTION__,\ 00194 0,false,true, f , ## x) 00195 #define PLFATAL(f, x...) sendlog(LOG_CRIT,__LINE__,__FILE__,__FUNCTION__,\ 00196 0,false,true, f , ## x) 00197 00198 #define IDLDEBUG(f, x...) sendlog(LOG_DEBUG,__LINE__,__FILE__,__FUNCTION__,\ 00199 MYLOGID,true,false, f , ## x) 00200 #define IDLINFO(f, x...) sendlog(LOG_INFO,__LINE__,__FILE__,__FUNCTION__,\ 00201 MYLOGID,true,false, f , ## x) 00202 #define IDLERROR(f, x...) sendlog(LOG_ERR,__LINE__,__FILE__,__FUNCTION__,\ 00203 MYLOGID,true,false, f , ## x) 00204 #define IDLFATAL(f, x...) sendlog(LOG_CRIT,__LINE__,__FILE__,__FUNCTION__,\ 00205 MYLOGID,true,false, f , ## x) 00206 00207 #define IDPLDEBUG(f, x...) sendlog(LOG_DEBUG,__LINE__,__FILE__,__FUNCTION__,\ 00208 MYLOGID,true,true, f , ## x) 00209 #define IDPLINFO(f, x...) sendlog(LOG_INFO,__LINE__,__FILE__,__FUNCTION__,\ 00210 MYLOGID,true,true, f , ## x) 00211 #define IDPLERROR(f, x...) sendlog(LOG_ERR,__LINE__,__FILE__,__FUNCTION__,\ 00212 MYLOGID,true,true, f , ## x) 00213 #define IDPLFATAL(f, x...) sendlog(LOG_CRIT,__LINE__,__FILE__,__FUNCTION__,\ 00214 MYLOGID,true,true, f , ## x) 00215 00216 #define CLOGFILE ("[" + realm() + ":" + descriptiveName() + "]").c_str() 00217 00218 #define CLDEBUG(f, x...) sendlog(LOG_DEBUG,__LINE__,CLOGFILE,__FUNCTION__,\ 00219 0,false,false, f , ## x) 00220 #define CLINFO(f, x...) sendlog(LOG_INFO,__LINE__,CLOGFILE,__FUNCTION__,\ 00221 0,false,false, f , ## x) 00222 #define CLERROR(f, x...) sendlog(LOG_ERR,__LINE__,CLOGFILE,__FUNCTION__,\ 00223 0,false,false,f ,## x) 00224 #define CLFATAL(f, x...) sendlog(LOG_CRIT,__LINE__,CLOGFILE,__FUNCTION__,\ 00225 0,false,false, f , ## x) 00226 00227 #define CPLDEBUG(f, x...) sendlog(LOG_DEBUG,__LINE__,CLOGFILE,__FUNCTION__,\ 00228 0,false,true, f , ## x) 00229 #define CPLINFO(f, x...) sendlog(LOG_INFO,__LINE__,CLOGFILE,__FUNCTION__,\ 00230 0,false,true, f , ## x) 00231 #define CPLERROR(f, x...) sendlog(LOG_ERR,__LINE__,CLOGFILE,__FUNCTION__,\ 00232 0,false,true, f , ## x) 00233 #define CPLFATAL(f, x...) sendlog(LOG_CRIT,__LINE__,CLOGFILE,__FUNCTION__,\ 00234 0,false,true, f , ## x) 00235 00236 #define SHOWMEMORY(f, x...) showmemory(LOG_ERR,__LINE__,__FILE__,__FUNCTION__,\ 00237 0,false,false,f ,## x) 00238 00239 // NOTE: the __attribute__ tells gcc that it should issue printf-style 00240 // warnings when compiling calls to sendlog(), treating the 8th 00241 // argument (msg) as the format string, and the 9th and subsequent 00242 // arguments as the printf-style parameters 00243 00244 void sendlog(const int lev, const int line, const char *file, 00245 const char *func, const int idval, const bool useid, 00246 const bool usep, const char *msg, ...) 00247 __attribute__((format(__printf__,8,9))); 00248 00249 // NOTE: the __attribute__ tells gcc that it should issue printf-style 00250 // warnings when compiling calls to sendlog(), treating the 8th 00251 // argument (msg) as the format string, and the 9th and subsequent 00252 // arguments as the printf-style parameters 00253 00254 void showmemory(const int lev, const int line, const char *file, 00255 const char *func, const int idval, const bool useid, 00256 const bool usep, const char *msg, ...) 00257 __attribute__((format(__printf__,8,9))); 00258 00259 #else 00260 // ###################################################################### 00261 // If not using GNU C, these functions provide a thread-unsafe facility 00262 // ###################################################################### 00263 00264 //! max size of function or file name 00265 #define LBS2 64 00266 00267 // log functions 00268 #define SENDLOG MYLOG_USEID=false, MYLOG_USEP=false, sendlog 00269 #define SENDPLOG MYLOG_USEID=false, MYLOG_USEP=true, sendlog 00270 #define SENDIDLOG MYLOG_USEID=true, MYLOG_USEP=false, sendlog 00271 #define SENDIDPLOG MYLOG_USEID=true, MYLOG_USEP=true, sendlog 00272 00273 #define LDEBUG MYLOGLIN=__LINE__,strncpy(MYLOGFUN, __FUNCTION__, LBS2-1),\ 00274 strncpy(MYLOGFIL, __FILE__, LBS2-1),MYLOGLEV=LOG_DEBUG,SENDLOG 00275 #define LINFO MYLOGLIN=__LINE__,strncpy(MYLOGFUN, __FUNCTION__, LBS2-1),\ 00276 strncpy(MYLOGFIL, __FILE__, LBS2-1),MYLOGLEV=LOG_INFO,SENDLOG 00277 #define LERROR MYLOGLIN=__LINE__,strncpy(MYLOGFUN, __FUNCTION__, LBS2-1),\ 00278 strncpy(MYLOGFIL, __FILE__, LBS2-1),MYLOGLEV=LOG_ERR,SENDLOG 00279 #define LFATAL MYLOGLIN=__LINE__,strncpy(MYLOGFUN, __FUNCTION__, LBS2-1),\ 00280 strncpy(MYLOGFIL, __FILE__, LBS2-1),MYLOGLEV=LOG_CRIT,SENDLOG 00281 00282 #define PLDEBUG MYLOGLIN=__LINE__,strncpy(MYLOGFUN, __FUNCTION__, LBS2-1),\ 00283 strncpy(MYLOGFIL, __FILE__, LBS2-1),MYLOGLEV=LOG_DEBUG,SENDPLOG 00284 #define PLINFO MYLOGLIN=__LINE__,strncpy(MYLOGFUN, __FUNCTION__, LBS2-1),\ 00285 strncpy(MYLOGFIL, __FILE__, LBS2-1),MYLOGLEV=LOG_INFO,SENDPLOG 00286 #define PLERROR MYLOGLIN=__LINE__,strncpy(MYLOGFUN, __FUNCTION__, LBS2-1),\ 00287 strncpy(MYLOGFIL, __FILE__, LBS2-1),MYLOGLEV=LOG_ERR,SENDPLOG 00288 #define PLFATAL MYLOGLIN=__LINE__,strncpy(MYLOGFUN, __FUNCTION__, LBS2-1),\ 00289 strncpy(MYLOGFIL, __FILE__, LBS2-1),MYLOGLEV=LOG_CRIT,SENDPLOG 00290 00291 #define IDLDEBUG MYLOGLIN=__LINE__,strncpy(MYLOGFUN, __FUNCTION__, LBS2-1),\ 00292 MYLOGIDVAL=MYLOGID,strncpy(MYLOGFIL, __FILE__, LBS2-1),MYLOGLEV=LOG_DEBUG,\ 00293 SENDIDLOG 00294 #define IDLINFO MYLOGLIN=__LINE__,strncpy(MYLOGFUN, __FUNCTION__, LBS2-1),\ 00295 MYLOGIDVAL=MYLOGID,strncpy(MYLOGFIL, __FILE__, LBS2-1),MYLOGLEV=LOG_INFO,\ 00296 SENDIDLOG 00297 #define IDLERROR MYLOGLIN=__LINE__,strncpy(MYLOGFUN, __FUNCTION__, LBS2-1),\ 00298 MYLOGIDVAL=MYLOGID,strncpy(MYLOGFIL, __FILE__, LBS2-1),MYLOGLEV=LOG_ERR,\ 00299 SENDIDLOG 00300 #define IDLFATAL MYLOGLIN=__LINE__,strncpy(MYLOGFUN, __FUNCTION__, LBS2-1),\ 00301 MYLOGIDVAL=MYLOGID,strncpy(MYLOGFIL, __FILE__, LBS2-1),MYLOGLEV=LOG_CRIT,\ 00302 SENDIDLOG 00303 00304 #define IDPLDEBUG MYLOGLIN=__LINE__,strncpy(MYLOGFUN, __FUNCTION__, LBS2-1),\ 00305 MYLOGIDVAL=MYLOGID,strncpy(MYLOGFIL, __FILE__, LBS2-1),MYLOGLEV=LOG_DEBUG,\ 00306 SENDIDPLOG 00307 #define IDPLINFO MYLOGLIN=__LINE__,strncpy(MYLOGFUN, __FUNCTION__, LBS2-1),\ 00308 MYLOGIDVAL=MYLOGID,strncpy(MYLOGFIL, __FILE__, LBS2-1),MYLOGLEV=LOG_INFO,\ 00309 SENDIDPLOG 00310 #define IDPLERROR MYLOGLIN=__LINE__,strncpy(MYLOGFUN, __FUNCTION__, LBS2-1),\ 00311 MYLOGIDVAL=MYLOGID,strncpy(MYLOGFIL, __FILE__, LBS2-1),MYLOGLEV=LOG_ERR,\ 00312 SENDIDPLOG 00313 #define IDPLFATAL MYLOGLIN=__LINE__,strncpy(MYLOGFUN, __FUNCTION__, LBS2-1),\ 00314 MYLOGIDVAL=MYLOGID,strncpy(MYLOGFIL, __FILE__, LBS2-1),MYLOGLEV=LOG_CRIT,\ 00315 SENDIDPLOG 00316 00317 #define CLOGFILE ("[" + descriptiveName() + "]").c_str() 00318 00319 #define CLDEBUG MYLOGLIN=__LINE__,strncpy(MYLOGFUN, __FUNCTION__, LBS2-1),\ 00320 strncpy(MYLOGFIL, CLOGFILE, LBS2-1),MYLOGLEV=LOG_DEBUG,SENDLOG 00321 #define CLINFO MYLOGLIN=__LINE__,strncpy(MYLOGFUN, __FUNCTION__, LBS2-1),\ 00322 strncpy(MYLOGFIL, CLOGFILE, LBS2-1),MYLOGLEV=LOG_INFO,SENDLOG 00323 #define CLERROR MYLOGLIN=__LINE__,strncpy(MYLOGFUN, __FUNCTION__, LBS2-1),\ 00324 strncpy(MYLOGFIL, CLOGFILE, LBS2-1),MYLOGLEV=LOG_ERR,SENDLOG 00325 #define CLFATAL MYLOGLIN=__LINE__,strncpy(MYLOGFUN, __FUNCTION__, LBS2-1),\ 00326 strncpy(MYLOGFIL, CLOGFILE, LBS2-1),MYLOGLEV=LOG_CRIT,SENDLOG 00327 00328 #define CPLDEBUG MYLOGLIN=__LINE__,strncpy(MYLOGFUN, __FUNCTION__, LBS2-1),\ 00329 strncpy(MYLOGFIL, CLOGFILE, LBS2-1),MYLOGLEV=LOG_DEBUG,SENDPLOG 00330 #define CPLINFO MYLOGLIN=__LINE__,strncpy(MYLOGFUN, __FUNCTION__, LBS2-1),\ 00331 strncpy(MYLOGFIL, CLOGFILE, LBS2-1),MYLOGLEV=LOG_INFO,SENDPLOG 00332 #define CPLERROR MYLOGLIN=__LINE__,strncpy(MYLOGFUN, __FUNCTION__, LBS2-1),\ 00333 strncpy(MYLOGFIL, CLOGFILE, LBS2-1),MYLOGLEV=LOG_ERR,SENDPLOG 00334 #define CPLFATAL MYLOGLIN=__LINE__,strncpy(MYLOGFUN, __FUNCTION__, LBS2-1),\ 00335 strncpy(MYLOGFIL, CLOGFILE, LBS2-1),MYLOGLEV=LOG_CRIT,SENDPLOG 00336 00337 00338 // NOTE: the __attribute__ tells gcc that it should issue printf-style 00339 // warnings when compiling calls to sendlog(), treating the 1st 00340 // argument (msg) as the format string, and the 2nd and subsequent 00341 // arguments as the printf-style parameters. 00342 void sendlog(const char *msg, ...) 00343 __attribute__((format(__printf__, 1, 2))); 00344 00345 // defined in log.C: 00346 extern char MYLOGFUN[], MYLOGFIL[]; 00347 extern int MYLOGLIN, MYLOGLEV, MYLOGIDVAL; 00348 extern bool MYLOG_USEID, MYLOG_USEP; 00349 00350 #endif 00351 00352 /// Helper function for REPORT_CURRENT_EXCEPTION macro. 00353 void report_current_exception(const int line, const char* file) throw(); 00354 00355 /// Use this inside of a catch(...) to report info about the caught exception 00356 /** There MUST be a current exception object in order for this to work 00357 (i.e., you must be inside of a catch block when you call 00358 REPORT_CURRENT_EXCEPTION). */ 00359 #define REPORT_CURRENT_EXCEPTION \ 00360 report_current_exception(__LINE__, __FILE__) 00361 00362 #endif 00363 00364 // ###################################################################### 00365 /* So things look consistent in everyone's emacs... */ 00366 /* Local Variables: */ 00367 /* indent-tabs-mode: nil */ 00368 /* End: */