Log.h

Go to the documentation of this file.
00001 /*
00002  *    Copyright 2004-2006 Intel Corporation
00003  * 
00004  *    Licensed under the Apache License, Version 2.0 (the "License");
00005  *    you may not use this file except in compliance with the License.
00006  *    You may obtain a copy of the License at
00007  * 
00008  *        http://www.apache.org/licenses/LICENSE-2.0
00009  * 
00010  *    Unless required by applicable law or agreed to in writing, software
00011  *    distributed under the License is distributed on an "AS IS" BASIS,
00012  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  *    See the License for the specific language governing permissions and
00014  *    limitations under the License.
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,   // output the log path 
00336         OUTPUT_TIME      = 1<<1,   // output time in logs
00337         OUTPUT_LEVEL     = 1<<2,   // output level in logs
00338         OUTPUT_CLASSNAME = 1<<3,   // output the class name generating the log
00339         OUTPUT_OBJ       = 1<<4,   // output the obj generating the log
00340         OUTPUT_SHORT     = 1<<10,  // shorten prefix
00341         OUTPUT_COLOR     = 1<<11,  // colorific
00342         OUTPUT_WALLTIME  = 1<<12,  // output time as HH:MM:SS.mmm
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; } // XXX/bowei arghh..
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 } // namespace oasys
00431 
00450 // compile out all log_debug calls when not debugging
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 // Include Logger.h for simplicity.
00516 #include "Logger.h"
00517 
00518 #endif /* _OASYS_LOG_H_ */

Generated on Sat Sep 8 08:36:17 2007 for DTN Reference Implementation by  doxygen 1.5.3