// Matt Wells, copyright Feb 2001 // . a great way to record errors encountered during // . we store the errorMsg, it's length, the type of message and time. // . when our buf gets full we dump half the messages to the log file (if any) // . netLogdb can send error msgs for you with it's sendError cmd // . sendError ( UdpSlot *slot , char *errFormat , ...); (also logs it) #ifndef GB_LOG_H #define GB_LOG_H #include <stdarg.h> #include <stdint.h> // THE TYPES OF LOG MESSAGES // logs information pertaining to more complicated procedures, like // the merging and dumping of data for the "db" component, or what urls are // being spidered for the "build" component. #define LOG_INFO 0x0001 // the default log message type. also logs slow performance. #define LOG_WARN 0x0004 // the default log message type. also logs slow performance. #define LOG_ERROR 0x0008 // programmer error. sanity check. always on. #define LOG_LOGIC 0x0010 // Reminders to fix the code. generally disabled. #define LOG_REMIND 0x0020 // for debugging. generally disabled. #define LOG_DEBUG 0x0040 // for tracing. generally disabled. Enabled for specific code // sections through config UI #define LOG_TRACE 0x0080 // times various subroutines for debugging performance. #define LOG_TIMING 0x0100 // initialization (and shutdown) information. also print routines. always on. #define LOG_INIT 0x0400 // if a url or link gets truncated, uses this in the "build" context. (Url.cpp // and Links.cpp) // also used if a document not added due to quota breech. (Msg16.cpp) // also used if too many nested tags to parse doc correctly (Xml.cpp) // in the "query" context for serps too big to be cached. (Msg17.cpp) #define LOG_LIMIT 0x2000 // It is convenient to divide everything into components and allow the admin // to toggle logging for various aspects, such as performance or timing // messages, of these components: // addurls related to adding urls // admin related to administrative things, sync file, collections // build related to indexing (high level) // conf configuration issues // disk disk reads and writes // dns dns networking // http http networking // loop // net network later: multicast pingserver. sits atop udpserver. // query related to querying (high level) // rdb generic rdb things // spcache related to determining what urls to spider next // speller query spell checking // thread calling threads // udp udp networking // example log: //456456454 0 INIT Gigablast Version 1.234 //454544444 0 INIT thread Allocated 435333 bytes for thread stacks. //123456789 0 WARN mem Failed to alloc 360000 bytes. //123456789 0 WARN query Failed to intersect lists. Out of memory. //123456789 0 WARN query Too many words. Query truncated. //234234324 0 REQST http 1.2.3.4 GET /index.html User-Agent //234234324 0 REPLY http 1.2.3.4 sent 34536 bytes //345989494 0 REQST build GET http://hohum.com/foobar.html //345989494 0 INFO build http://hohum.com/foobar.html ip=4.5.6.7 : Success //324234324 0 DEBUG build Skipping xxx.com, would hammer IP. #define MAX_LOG_MSGS 1024 // in memory // may also syslog and fprintf the msg. // ALWAYS returns FALSE (i.e. 0)!!!! so you can say return log.log(...) void log ( int32_t type , const char *formatString , ... ) __attribute__ ((format(printf, 2, 3))); // this defaults to type of LOG_WARN void log ( const char *formatString , ... ) __attribute__ ((format(printf, 1, 2))); // force it to be logged, even if off on log controls panel void logf ( int32_t type , const char *formatString , ... ) __attribute__ ((format(printf, 2, 3))); void loghex( int32_t type, void const *data, const unsigned int len, const char *formatString , ...) __attribute__ ((format(printf, 4, 5))); #define logError(msg, ...) \ logf(LOG_ERROR, "%s:%s:%d: " msg, __FILE__, __func__, __LINE__, ##__VA_ARGS__) #define logDebug(condition, ...) \ do { \ if (condition) { \ logf(LOG_DEBUG, __VA_ARGS__); \ } \ } while (0) #define logTrace(condition, msg, ...) \ do { \ if (condition) { \ logf(LOG_TRACE, "%s:%s:%d: " msg, __FILE__, __func__, __LINE__, ##__VA_ARGS__); \ } \ } while (0) #define logHexTrace(condition, data, len, msg, ...) \ do { \ if (condition) { \ loghex(LOG_TRACE, data, len, "%s:%s:%d: " msg, __FILE__, __func__, __LINE__, ##__VA_ARGS__); \ } \ } while (0) class Log { public: // just initialize with no file Log(); ~Log(); // returns true if opened log file successfully, otherwise false bool init(const char *filename); bool registerLogRotation(); // . log this msg // . "msg" must be NULL terminated // . now is the time of day in milliseconds since the epoch // . if "now" is 0 we insert the timestamp for you // . if "asterisk" is true we print an asterisk to indicate that // the msg was actually logged earlier but only printed now because // we were in a signal handler at the time bool logR(int64_t now, int32_t type, const char *msg, bool forced = false); // returns false if msg should not be logged, true if it should bool shouldLog(int32_t type, const char *msg); void reset(); // save before exiting void close() {} bool m_disabled; bool m_logTimestamps; bool m_logReadableTimestamps; bool m_logPrefix; private: bool makeNewLogFile(); static void rotateLog(int fd, void *state); const char *m_filename; int m_fd; }; extern class Log g_log; #endif // GB_LOG_H