rivet is hosted by Hepforge, IPPP Durham
Logging.hh
Go to the documentation of this file.
00001 #ifndef RIVET_LOGGING_HH
00002 #define RIVET_LOGGING_HH
00003 
00004 #include "Rivet/Rivet.hh"
00005 
00006 namespace Rivet {
00007 
00008 
00009   class Log {
00010   public:
00011 
00012     /// Log priority levels.
00013     enum Level {
00014       TRACE = 0, DEBUG = 10, INFO = 20, WARN = 30, WARNING = 30, ERROR = 40, CRITICAL = 50, ALWAYS = 50
00015     };
00016 
00017     /// Typedef for a collection of named logs.
00018     typedef std::map<std::string, Log*> LogMap;
00019 
00020     /// Typedef for a collection of named log levels.
00021     typedef std::map<std::string, int> LevelMap;
00022 
00023     /// Typedef for a collection of shell color codes, accessed by log level.
00024     typedef std::map<int, std::string> ColorCodes;
00025 
00026   private:
00027     /// A static map of existing logs: we don't make more loggers than necessary.
00028     static LogMap existingLogs;
00029 
00030     /// A static map of default log levels.
00031     static LevelMap defaultLevels;
00032 
00033     /// A static map of shell color codes for the log levels.
00034     static ColorCodes colorCodes;
00035 
00036     /// Shell color code for the end of the log levels.
00037     static std::string endColorCode;
00038 
00039     /// Show timestamp?
00040     static bool showTimestamp;
00041 
00042     /// Show log level?
00043     static bool showLogLevel;
00044 
00045     /// Show logger name?
00046     static bool showLoggerName;
00047 
00048     /// Use shell colour escape codes?
00049     static bool useShellColors;
00050 
00051   public:
00052     /// Set the log levels
00053     static void setLevel(const std::string& name, int level);
00054     static void setLevels(const LevelMap& logLevels);
00055 
00056     static void setShowTimestamp(bool showTime=true) {
00057       showTimestamp = showTime;
00058     }
00059 
00060     static void setShowLevel(bool showLevel=true) {
00061       showLogLevel = showLevel;
00062     }
00063 
00064     static void setShowLoggerName(bool showName=true) {
00065       showLoggerName = showName;
00066     }
00067 
00068     static void setUseColors(bool useColors=true) {
00069       useShellColors = useColors;
00070     }
00071 
00072   protected:
00073 
00074     /// @name Hidden constructors etc.
00075     //@{
00076 
00077     /// Constructor 1
00078     Log(const std::string& name);
00079 
00080     /// Constructor 2
00081     Log(const std::string& name, int level);
00082 
00083     //@}
00084 
00085     static std::string getColorCode(int level);
00086 
00087   public:
00088 
00089     /// Get a logger with the given name. The level will be taken from the
00090     /// "requestedLevels" static map or will be INFO by default.
00091     static Log& getLog(const std::string& name);
00092 
00093   public:
00094     /// Get the priority level of this logger.
00095     int getLevel() const {
00096       return _level;
00097     }
00098 
00099     /// Set the priority level of this logger.
00100     Log& setLevel(int level) {
00101       _level = level;
00102       return *this;
00103     }
00104 
00105     /// Get a log level enum from a string.
00106     static Level getLevelFromName(const std::string& level);
00107 
00108     /// Get the std::string representation of a log level.
00109     static std::string getLevelName(int level);
00110 
00111     /// Get the name of this logger.
00112     std::string getName() const {
00113       return _name;
00114     }
00115 
00116     /// Set the name of this logger.
00117     Log& setName(const std::string& name) {
00118       _name = name;
00119       return *this;
00120     }
00121 
00122     /// Will this log level produce output on this logger at the moment?
00123     bool isActive(int level) const {
00124       return (level >= _level);
00125     }
00126 
00127     /// @name Explicit log methods
00128     //@{
00129     void trace(const std::string& message) { log(TRACE, message); }
00130 
00131     void debug(const std::string& message) { log(DEBUG, message); }
00132 
00133     void info(const std::string& message) { log(INFO, message); }
00134 
00135     void warn(const std::string& message) { log(WARN, message); }
00136 
00137     void error(const std::string& message) { log(ERROR, message); }
00138     //@}
00139 
00140   private:
00141     /// This logger's name
00142     std::string _name;
00143 
00144     /// Threshold level for this logger.
00145     int _level;
00146 
00147   protected:
00148     /// Write a message at a particular level.
00149     void log(int level, const std::string& message);
00150 
00151     /// Turn a message string into the current log format.
00152     std::string formatMessage(int level, const std::string& message);
00153 
00154   public:
00155 
00156     /// A null output stream, used for piping discarded output to nowhere.
00157     /// @todo Hide this...
00158     std::ostream* const _nostream;
00159 
00160     /// The streaming operator can use Log's internals.
00161     friend std::ostream& operator<<(Log& log, int level);
00162 
00163   };
00164 
00165   /// Streaming output to a logger must have a Log::Level/int as its first argument.
00166   std::ostream& operator<<(Log& log, int level);
00167 
00168 }
00169 
00170 
00171 // Neat CPU-conserving logging macros. Use by preference!
00172 // NB. Only usable in classes where a getLog() method is provided
00173 #define MSG_LVL(lvl, x) \
00174   do { \
00175     if (getLog().isActive(lvl)) { \
00176       getLog() << lvl << x << endl;   \
00177     } \
00178   } while (0)
00179 
00180 #define MSG_TRACE(x)   MSG_LVL(Log::TRACE, x)
00181 #define MSG_DEBUG(x)   MSG_LVL(Log::DEBUG, x)
00182 #define MSG_INFO(x)    MSG_LVL(Log::INFO, x)
00183 #define MSG_WARNING(x) MSG_LVL(Log::WARNING, x)
00184 #define MSG_ERROR(x)   MSG_LVL(Log::ERROR, x)
00185 
00186 
00187 #endif