Log.h

Go to the documentation of this file.
00001 /*
00002  * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By
00003  * downloading, copying, installing or using the software you agree to
00004  * this license. If you do not agree to this license, do not download,
00005  * install, copy or use the software.
00006  * 
00007  * Intel Open Source License 
00008  * 
00009  * Copyright (c) 2004 Intel Corporation. All rights reserved. 
00010  * 
00011  * Redistribution and use in source and binary forms, with or without
00012  * modification, are permitted provided that the following conditions are
00013  * met:
00014  * 
00015  *   Redistributions of source code must retain the above copyright
00016  *   notice, this list of conditions and the following disclaimer.
00017  * 
00018  *   Redistributions in binary form must reproduce the above copyright
00019  *   notice, this list of conditions and the following disclaimer in the
00020  *   documentation and/or other materials provided with the distribution.
00021  * 
00022  *   Neither the name of the Intel Corporation nor the names of its
00023  *   contributors may be used to endorse or promote products derived from
00024  *   this software without specific prior written permission.
00025  *  
00026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00027  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00028  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00029  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR
00030  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00031  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00032  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00033  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00034  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00035  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00036  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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,   // output the log path 
00355         OUTPUT_TIME      = 1<<1,   // output time in logs
00356         OUTPUT_LEVEL     = 1<<2,   // output level in logs
00357         OUTPUT_CLASSNAME = 1<<3,   // output the class name generating the log
00358         OUTPUT_OBJ       = 1<<4,   // output the obj generating the log
00359         OUTPUT_SHORT     = 1<<10,  // shorten prefix
00360         OUTPUT_COLOR     = 1<<11,  // colorific
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; } // XXX/bowei arghh..
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 } // namespace oasys
00468 
00518 // compile out all log_debug calls when not debugging
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 // Include Logger.h for simplicity.
00582 #include "Logger.h"
00583 
00584 #endif /* _OASYS_LOG_H_ */

Generated on Fri Dec 22 14:47:59 2006 for DTN Reference Implementation by  doxygen 1.5.1