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
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #ifndef _OASYS_LOG_H_
00040 #define _OASYS_LOG_H_
00041
00111 #include <stdarg.h>
00112 #include <stdio.h>
00113 #include <string.h>
00114 #include <unistd.h>
00115 #include <sys/time.h>
00116 #include <string>
00117 #include <vector>
00118
00119 #if defined(__GNUC__)
00120 # define PRINTFLIKE(fmt, arg) __attribute__((format (printf, fmt, arg)))
00121 #else
00122 # define PRINTFLIKE(a, b)
00123 #endif
00124
00125 namespace oasys {
00126
00127 #define LOG_DEFAULT_THRESHOLD oasys::LOG_INFO
00128 #define LOG_DEFAULT_DBGFILE "~/.debug"
00129
00130 #define LOG_MAX_PATHLEN (64)
00131 #define LOG_MAX_LINELEN (256)
00132
00133 typedef enum {
00134 LOG_INVALID = -1,
00135 LOG_DEBUG = 1,
00136 LOG_INFO = 2,
00137 LOG_NOTICE = 3,
00138 LOG_WARN = 4,
00139 LOG_ERR = 5,
00140 LOG_CRIT = 6,
00141 LOG_ALWAYS = 7
00142 } log_level_t;
00143
00144 #ifndef DOXYGEN
00145 struct level2str_t {
00146 const char* str;
00147 log_level_t level;
00148 };
00149
00150 extern level2str_t log_levelnames[];
00151
00152 #endif
00153
00154 inline const char *level2str(log_level_t level) {
00155 for (int i = 0; log_levelnames[i].str != 0; i++) {
00156 if (log_levelnames[i].level == level) {
00157 return log_levelnames[i].str;
00158 }
00159 }
00160
00161 return "(unknown level)";
00162 }
00163
00164 inline log_level_t str2level(const char *level)
00165 {
00166 for (int i = 0; log_levelnames[i].str && i < 20; i++) {
00167 if (strcasecmp(log_levelnames[i].str, level) == 0) {
00168 return log_levelnames[i].level;
00169 }
00170 }
00171
00172 return LOG_INVALID;
00173 }
00174
00175 void __log_assert(bool x, const char* what, const char* file, int line);
00176
00177 class SpinLock;
00178 class StringBuffer;
00179
00180 class Log {
00181 public:
00187 static Log *instance() {
00188 __log_assert(instance_ != 0, "Log::init not called yet",
00189 __FILE__, __LINE__);
00190 return instance_;
00191 }
00192
00196 static void init(const char* logfile = "-",
00197 log_level_t defaultlvl = LOG_DEFAULT_THRESHOLD,
00198 const char *prefix = NULL,
00199 const char *debug_path = LOG_DEFAULT_DBGFILE);
00200
00204 static void init(log_level_t defaultlvl)
00205 {
00206 init("-", defaultlvl);
00207 }
00208
00212 static bool initialized()
00213 {
00214 return inited_;
00215 }
00216
00220 static void shutdown();
00221
00225 virtual void getlogtime(struct timeval* tv);
00226
00232 int vlogf(const char *path, log_level_t level,
00233 const char* classname, const void* obj,
00234 const char *fmt, va_list ap);
00235
00241 int log_multiline(const char* path, log_level_t level,
00242 const char* classname, const void* obj,
00243 const char* msg);
00244
00248 log_level_t log_level(const char *path);
00249
00255 void parse_debug_file(const char* debug_path = NULL);
00256
00260 void set_prefix(const char* prefix)
00261 {
00262 prefix_.assign(prefix);
00263 }
00264
00268 void rotate();
00269
00274 void add_rotate_handler(int sig);
00275
00280 void add_reparse_handler(int sig);
00281
00285 void dump_rules(StringBuffer* buf);
00286
00292 void redirect_stdio();
00293
00298 static bool __debug_no_panic_on_overflow;
00299
00300 protected:
00301 friend class LogCommand;
00302
00303 Log();
00304 virtual ~Log();
00305
00310 void do_init(const char* logfile, log_level_t defaultlvl,
00311 const char* prefix, const char* debug_path);
00312
00316 static Log* instance_;
00317
00318 private:
00323 struct Rule {
00324 Rule(const char* path, log_level_t level)
00325 : path_(path), level_(level) {}
00326
00327 Rule(const Rule& rule)
00328 : path_(rule.path_), level_(rule.level_) {}
00329
00330 std::string path_;
00331 log_level_t level_;
00332 };
00333
00334
00335
00343 static bool rule_compare(const Rule& rule1, const Rule& rule2);
00344
00348 typedef std::vector<Rule> RuleList;
00349
00353 enum {
00354 OUTPUT_PATH = 1<<0,
00355 OUTPUT_TIME = 1<<1,
00356 OUTPUT_LEVEL = 1<<2,
00357 OUTPUT_CLASSNAME = 1<<3,
00358 OUTPUT_OBJ = 1<<4,
00359 OUTPUT_SHORT = 1<<10,
00360 OUTPUT_COLOR = 1<<11,
00361 };
00362
00366 int output_flags_;
00367
00373 size_t gen_prefix(char* buf, size_t buflen,
00374 const char* path, log_level_t level,
00375 const char* classname, const void* obj);
00376
00380 Rule *find_rule(const char *path);
00381
00385 static void sort_rules(RuleList* rule_list);
00386
00387 static bool inited_;
00388 std::string logfile_;
00389 int logfd_;
00390 bool stdio_redirected_;
00391 RuleList* rule_list_;
00392 RuleList rule_lists_[2];
00393 SpinLock* output_lock_;
00394 std::string debug_path_;
00395 std::string prefix_;
00396 log_level_t default_threshold_;
00397 };
00398
00402 inline int
00403 vlogf(const char *path, log_level_t level,
00404 const char *fmt, va_list ap)
00405 {
00406 if (path == 0) { return -1; }
00407 return Log::instance()->vlogf(path, level, NULL, NULL, fmt, ap);
00408 }
00409
00413 inline int
00414 logf(const char *path, log_level_t level, const char *fmt, ...)
00415 PRINTFLIKE(3, 4);
00416
00417 inline int
00418 logf(const char *path, log_level_t level, const char *fmt, ...)
00419 {
00420 if (!path) return -1;
00421 va_list ap;
00422 va_start(ap, fmt);
00423 int ret = Log::instance()->vlogf(path, level, NULL, NULL, fmt, ap);
00424 va_end(ap);
00425 return ret;
00426 }
00427
00431 inline int
00432 log_multiline(const char* path, log_level_t level, const char* msg)
00433 {
00434 return Log::instance()->log_multiline(path, level, NULL, NULL, msg);
00435 }
00436
00441 inline int
00442 __logf(log_level_t level, const char *path, const char *fmt, ...)
00443 PRINTFLIKE(3, 4);
00444
00445 inline int
00446 __logf(log_level_t level, const char *path, const char *fmt, ...)
00447 {
00448 if (!path) return -1;
00449 va_list ap;
00450 va_start(ap, fmt);
00451 int ret = vlogf(path, level, fmt, ap);
00452 va_end(ap);
00453 return ret;
00454 }
00455
00460 inline bool
00461 __log_enabled(log_level_t level, const char* path)
00462 {
00463 log_level_t threshold = oasys::Log::instance()->log_level(path);
00464 return (level >= threshold);
00465 }
00466
00467 }
00468
00518
00519 #ifdef NDEBUG
00520 inline int log_nop() { return 0; }
00521 #define log_debug(args...) log_nop()
00522 #define __log_debug(args...) log_nop()
00523 #else
00524 #define log_debug(p, args...) \
00525 ((__log_enabled(oasys::LOG_DEBUG, (p))) ? \
00526 __logf(oasys::LOG_DEBUG, (p) , ## args) : 0)
00527
00528 #define __log_debug(p, args...) \
00529 ((oasys::__log_enabled(oasys::LOG_DEBUG, (p))) ? \
00530 oasys::__logf(oasys::LOG_DEBUG, (p) , ## args) : 0)
00531 #endif // NDEBUG
00532
00533 #define log_info(p, args...) \
00534 ((__log_enabled(oasys::LOG_INFO, (p))) ? \
00535 __logf(oasys::LOG_INFO, (p) , ## args) : 0)
00536
00537 #define __log_info(p, args...) \
00538 ((oasys::__log_enabled(oasys::LOG_INFO, (p))) ? \
00539 oasys::__logf(oasys::LOG_INFO, (p) , ## args) : 0)
00540
00541 #define log_notice(p, args...) \
00542 ((__log_enabled(oasys::LOG_NOTICE, (p))) ? \
00543 __logf(oasys::LOG_NOTICE, (p) , ## args) : 0)
00544
00545 #define __log_notice(p, args...) \
00546 ((oasys::__log_enabled(oasys::LOG_NOTICE, (p))) ? \
00547 oasys::__logf(oasys::LOG_NOTICE, (p) , ## args) : 0)
00548
00549 #define log_warn(p, args...) \
00550 ((__log_enabled(oasys::LOG_WARN, (p))) ? \
00551 __logf(oasys::LOG_WARN, (p) , ## args) : 0)
00552
00553 #define __log_warn(p, args...) \
00554 ((oasys::__log_enabled(oasys::LOG_WARN, (p))) ? \
00555 oasys::__logf(oasys::LOG_WARN, (p) , ## args) : 0)
00556
00557 #define log_err(p, args...) \
00558 ((__log_enabled(oasys::LOG_ERR, (p))) ? \
00559 __logf(oasys::LOG_ERR, (p) , ## args) : 0)
00560
00561 #define __log_err(p, args...) \
00562 ((oasys::__log_enabled(oasys::LOG_ERR, (p))) ? \
00563 oasys::__logf(oasys::LOG_ERR, (p) , ## args) : 0)
00564
00565 #define log_crit(p, args...) \
00566 ((__log_enabled(oasys::LOG_CRIT, (p))) ? \
00567 __logf(oasys::LOG_CRIT, (p) , ## args) : 0)
00568
00569 #define __log_crit(p, args...) \
00570 ((oasys::__log_enabled(oasys::LOG_CRIT, (p))) ? \
00571 oasys::__logf(oasys::LOG_CRIT, (p) , ## args) : 0)
00572
00573 #define log_always(p, args...) \
00574 ((__log_enabled(oasys::LOG_ALWAYS, (p))) ? \
00575 __logf(oasys::LOG_ALWAYS, (p) , ## args) : 0)
00576
00577 #define __log_always(p, args...) \
00578 ((oasys::__log_enabled(oasys::LOG_ALWAYS, (p))) ? \
00579 oasys::__logf(oasys::LOG_ALWAYS, (p) , ## args) : 0)
00580
00581
00582 #include "Logger.h"
00583
00584 #endif