00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef _OASYS_LOG_H_
00019 #define _OASYS_LOG_H_
00020
00092 #include <stdarg.h>
00093 #include <stdio.h>
00094 #include <string.h>
00095 #include <unistd.h>
00096 #include <sys/time.h>
00097 #include <string>
00098 #include <vector>
00099
00100 #if defined(__GNUC__)
00101 # define PRINTFLIKE(fmt, arg) __attribute__((format (printf, fmt, arg)))
00102 #else
00103 # define PRINTFLIKE(a, b)
00104 #endif
00105
00106 namespace oasys {
00107
00108 #define LOG_DEFAULT_THRESHOLD oasys::LOG_INFO
00109 #define LOG_DEFAULT_DBGFILE "~/.debug"
00110
00111 #define LOG_MAX_PATHLEN (64)
00112 #define LOG_MAX_LINELEN (512)
00113
00114 typedef enum {
00115 LOG_INVALID = -1,
00116 LOG_DEBUG = 1,
00117 LOG_INFO = 2,
00118 LOG_NOTICE = 3,
00119 LOG_WARN = 4,
00120 LOG_ERR = 5,
00121 LOG_CRIT = 6,
00122 LOG_ALWAYS = 7
00123 } log_level_t;
00124
00125 #ifndef DOXYGEN
00126 struct level2str_t {
00127 const char* str;
00128 log_level_t level;
00129 };
00130
00131 extern level2str_t log_levelnames[];
00132
00133 #endif
00134
00135 inline const char *level2str(log_level_t level) {
00136 for (int i = 0; log_levelnames[i].str != 0; i++) {
00137 if (log_levelnames[i].level == level) {
00138 return log_levelnames[i].str;
00139 }
00140 }
00141
00142 return "(unknown level)";
00143 }
00144
00145 inline log_level_t str2level(const char *level)
00146 {
00147 for (int i = 0; log_levelnames[i].str && i < 20; i++) {
00148 if (strcasecmp(log_levelnames[i].str, level) == 0) {
00149 return log_levelnames[i].level;
00150 }
00151 }
00152
00153 return LOG_INVALID;
00154 }
00155
00156 void __log_assert(bool x, const char* what, const char* file, int line);
00157
00158 class SpinLock;
00159 class StringBuffer;
00160
00161 class Log {
00162 public:
00168 static Log *instance() {
00169 __log_assert(instance_ != 0, "Log::init not called yet",
00170 __FILE__, __LINE__);
00171 return instance_;
00172 }
00173
00177 static void init(const char* logfile = "-",
00178 log_level_t defaultlvl = LOG_DEFAULT_THRESHOLD,
00179 const char *prefix = NULL,
00180 const char *debug_path = LOG_DEFAULT_DBGFILE);
00181
00185 static void init(log_level_t defaultlvl)
00186 {
00187 init("-", defaultlvl);
00188 }
00189
00193 static bool initialized()
00194 {
00195 return inited_;
00196 }
00197
00201 static void shutdown();
00202
00206 virtual void getlogtime(struct timeval* tv);
00207
00213 int vlogf(const char *path, log_level_t level,
00214 const char* classname, const void* obj,
00215 const char *fmt, va_list ap);
00216
00222 int log_multiline(const char* path, log_level_t level,
00223 const char* classname, const void* obj,
00224 const char* msg);
00225
00229 log_level_t log_level(const char *path);
00230
00236 void parse_debug_file(const char* debug_path = NULL);
00237
00241 void set_prefix(const char* prefix)
00242 {
00243 prefix_.assign(prefix);
00244 }
00245
00249 void rotate();
00250
00255 void add_rotate_handler(int sig);
00256
00261 void add_reparse_handler(int sig);
00262
00266 void dump_rules(StringBuffer* buf);
00267
00273 void redirect_stdio();
00274
00279 static bool __debug_no_panic_on_overflow;
00280
00281 protected:
00282 friend class LogCommand;
00283
00284 Log();
00285 virtual ~Log();
00286
00291 void do_init(const char* logfile, log_level_t defaultlvl,
00292 const char* prefix, const char* debug_path);
00293
00297 static Log* instance_;
00298
00299 private:
00304 struct Rule {
00305 Rule(const char* path, log_level_t level)
00306 : path_(path), level_(level) {}
00307
00308 Rule(const Rule& rule)
00309 : path_(rule.path_), level_(rule.level_) {}
00310
00311 std::string path_;
00312 log_level_t level_;
00313 };
00314
00315
00316
00324 static bool rule_compare(const Rule& rule1, const Rule& rule2);
00325
00329 typedef std::vector<Rule> RuleList;
00330
00334 enum {
00335 OUTPUT_PATH = 1<<0,
00336 OUTPUT_TIME = 1<<1,
00337 OUTPUT_LEVEL = 1<<2,
00338 OUTPUT_CLASSNAME = 1<<3,
00339 OUTPUT_OBJ = 1<<4,
00340 OUTPUT_SHORT = 1<<10,
00341 OUTPUT_COLOR = 1<<11,
00342 OUTPUT_WALLTIME = 1<<12,
00343 };
00344
00348 int output_flags_;
00349
00355 size_t gen_prefix(char* buf, size_t buflen,
00356 const char* path, log_level_t level,
00357 const char* classname, const void* obj);
00358
00362 Rule *find_rule(const char *path);
00363
00367 static void sort_rules(RuleList* rule_list);
00368
00369 static bool inited_;
00370 std::string logfile_;
00371 int logfd_;
00372 bool stdio_redirected_;
00373 RuleList* rule_list_;
00374 RuleList rule_lists_[2];
00375 SpinLock* output_lock_;
00376 std::string debug_path_;
00377 std::string prefix_;
00378 log_level_t default_threshold_;
00379 };
00380
00384 inline int
00385 vlogf(const char *path, log_level_t level,
00386 const char *fmt, va_list ap)
00387 {
00388 if (path == 0) { return -1; }
00389 return Log::instance()->vlogf(path, level, NULL, NULL, fmt, ap);
00390 }
00391
00395 inline int
00396 logf(const char *path, log_level_t level, const char *fmt, ...)
00397 PRINTFLIKE(3, 4);
00398
00399 inline int
00400 logf(const char *path, log_level_t level, const char *fmt, ...)
00401 {
00402 if (!path) return -1;
00403 va_list ap;
00404 va_start(ap, fmt);
00405 int ret = Log::instance()->vlogf(path, level, NULL, NULL, fmt, ap);
00406 va_end(ap);
00407 return ret;
00408 }
00409
00413 inline int
00414 log_multiline(const char* path, log_level_t level, const char* msg)
00415 {
00416 return Log::instance()->log_multiline(path, level, NULL, NULL, msg);
00417 }
00418
00423 inline bool
00424 log_enabled(log_level_t level, const char* path)
00425 {
00426 log_level_t threshold = oasys::Log::instance()->log_level(path);
00427 return (level >= threshold);
00428 }
00429
00430 }
00431
00450
00451 #ifdef NDEBUG
00452 inline int log_nop() { return 0; }
00453 #define log_debug(args...) log_nop()
00454 #define log_debug_p(args...) log_nop()
00455 #else
00456 #define log_debug(args...) \
00457 (this->log_enabled((Can_Only_Be_Called_By_A_Logger)oasys::LOG_DEBUG) ? \
00458 this->logf(oasys::LOG_DEBUG, ## args) : 0)
00459
00460 #define log_debug_p(p, args...) \
00461 ((oasys::log_enabled(oasys::LOG_DEBUG, (p))) ? \
00462 oasys::logf((p), oasys::LOG_DEBUG, ## args) : 0)
00463
00464 #endif // NDEBUG
00465
00466 #define log_info(args...) \
00467 (this->log_enabled((Can_Only_Be_Called_By_A_Logger)oasys::LOG_INFO) ? \
00468 this->logf(oasys::LOG_INFO, ## args) : 0)
00469
00470 #define log_info_p(p, args...) \
00471 ((oasys::log_enabled(oasys::LOG_INFO, (p))) ? \
00472 oasys::logf((p), oasys::LOG_INFO, ## args) : 0)
00473
00474 #define log_notice(args...) \
00475 (this->log_enabled((Can_Only_Be_Called_By_A_Logger)oasys::LOG_NOTICE) ? \
00476 this->logf(oasys::LOG_NOTICE, ## args) : 0)
00477
00478 #define log_notice_p(p, args...) \
00479 ((oasys::log_enabled(oasys::LOG_NOTICE, (p))) ? \
00480 oasys::logf((p), oasys::LOG_NOTICE, ## args) : 0)
00481
00482 #define log_warn(args...) \
00483 (this->log_enabled((Can_Only_Be_Called_By_A_Logger)oasys::LOG_WARN) ? \
00484 this->logf(oasys::LOG_WARN, ## args) : 0)
00485
00486 #define log_warn_p(p, args...) \
00487 ((oasys::log_enabled(oasys::LOG_WARN, (p))) ? \
00488 oasys::logf((p), oasys::LOG_WARN, ## args) : 0)
00489
00490 #define log_err(args...) \
00491 (this->log_enabled((Can_Only_Be_Called_By_A_Logger)oasys::LOG_ERR) ? \
00492 this->logf(oasys::LOG_ERR, ## args) : 0)
00493
00494 #define log_err_p(p, args...) \
00495 ((oasys::log_enabled(oasys::LOG_ERR, (p))) ? \
00496 oasys::logf((p), oasys::LOG_ERR, ## args) : 0)
00497
00498 #define log_crit(args...) \
00499 (this->log_enabled((Can_Only_Be_Called_By_A_Logger)oasys::LOG_CRIT) ? \
00500 this->logf(oasys::LOG_CRIT, ## args) : 0)
00501
00502 #define log_crit_p(p, args...) \
00503 ((oasys::log_enabled(oasys::LOG_CRIT, (p))) ? \
00504 oasys::logf((p), oasys::LOG_CRIT, ## args) : 0)
00505
00506 #define log_always(args...) \
00507 (this->log_enabled((Can_Only_Be_Called_By_A_Logger)oasys::LOG_ALWAYS) ? \
00508 this->logf(oasys::LOG_ALWAYS, ## args) : 0)
00509
00510 #define log_always_p(p, args...) \
00511 ((oasys::log_enabled(oasys::LOG_ALWAYS, (p))) ? \
00512 oasys::logf((p), oasys::LOG_ALWAYS, ## args) : 0)
00513
00514
00515
00516 #include "Logger.h"
00517
00518 #endif