Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

Logger.hpp

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file Logger.hpp
00003  */
00004 //----------------------------------------------------------------------------
00005 
00006 #ifndef HEXLOGGER_HPP
00007 #define HEXLOGGER_HPP
00008 
00009 #include <fstream>
00010 #include <iostream>
00011 #include <sstream>
00012 #include <vector>
00013 #include <map>
00014 #include <pthread.h>
00015 #include "Benzene.hpp"
00016 
00017 _BEGIN_BENZENE_NAMESPACE_
00018 
00019 //----------------------------------------------------------------------------
00020 
00021 /** Levels for messages to a Logger object. */
00022 enum LogLevel
00023 {
00024     /** All messages with levels higher than OFF are ignored. */
00025     LOG_LEVEL_OFF = 65536,
00026 
00027     /** Message level indicating a serious failure. 
00028         In general a severe message should describe events of considerable
00029         importance which will prevent normal program execution. 
00030     */
00031     LOG_LEVEL_SEVERE = 1000,
00032 
00033     /** Message level indicating a potential problem. 
00034         Should be used to describe events of interest to users and
00035         developers.
00036     */
00037     LOG_LEVEL_WARNING = 900,
00038 
00039     /** Message level for informational messages.
00040         Messages of this level or higher are typically output on the
00041         console.
00042     */
00043     LOG_LEVEL_INFO = 800,
00044     
00045     /** Message level for configuration purposes. 
00046         Should be used to provide a variety of static configuration
00047     information to assist in debugging.
00048     */
00049     LOG_LEVEL_CONFIG = 700,
00050 
00051     /** Message level providing tracing information. */
00052     LOG_LEVEL_FINE = 500,
00053 
00054     /** Message level providing more tracing information. */
00055     LOG_LEVEL_FINER = 300, 
00056 
00057     /** Special level indicating that all messages should be
00058         logged. */
00059     LOG_LEVEL_ALL = 0
00060 };
00061 
00062 /** Utilities on LogLevel. */
00063 namespace LogLevelUtil
00064 {
00065     /** Returns true if the given level is valid. */
00066     bool IsValidLevel(LogLevel level);
00067     
00068     /** Returns a string representation of the level. */
00069     std::string toString(LogLevel level);
00070 
00071     /** Converts a string to a LogLevel. */
00072     LogLevel fromString(std::string);
00073 }
00074 
00075 //----------------------------------------------------------------------------
00076 
00077 /** Logger supporting message levels and multiple output streams
00078     received from multiple threads.
00079 
00080     A Logger can have several streams. Each stream is assigned a level.
00081     When the Logger receives a message at level L, all streams with level 
00082     at least L will be sent a copy of the message.
00083 
00084     Logger handles messages coming from multiple threads internally. A
00085     LogLevel for each thread is maintained, and separate buffers are
00086     used for messages being formed simulataneously in different
00087     threads.  Blocking is used to grant a thread exclusive access to
00088     the streams when printing; this potentially could cause slowdown
00089     if several threads are dumping lots of text simultaneously.
00090 */
00091 class Logger
00092 {
00093 public:
00094 
00095     /** Creates a logger object. By default, log outputs to std::cerr
00096         at LOG_LEVEL_INFO. */
00097     Logger();
00098 
00099     /** Destructor. */
00100     ~Logger();
00101 
00102     /** Returns the global Logger object. */
00103     static Logger& Global();
00104 
00105     /** Adds a handler to this logger at the given level. */
00106     void AddStream(std::ostream& stream, LogLevel level);
00107 
00108     /** Removes all output streams. */
00109     void ClearStreams();
00110     
00111     /** Sets the level of all messages this logger receives from now
00112         on. */
00113     void SetLevel(LogLevel level);
00114 
00115     /** Flushes the log. */
00116     void Flush();
00117 
00118     /** Pipes text into the log. If text ends in a '\n', log is
00119         flushed. */
00120     template<typename TYPE>
00121     Logger& operator<<(const TYPE& type);
00122 
00123 private:
00124 
00125     /** Maximum number of threads handled at once. */
00126     static const int MAX_THREADS = 16;
00127 
00128     /** Buffer for a thread of execution. */
00129     struct ThreadBuffer
00130     {
00131         std::ostringstream buffer;
00132         pthread_t id;
00133     };
00134 
00135     /** Returns the buffer for the current thread. */
00136     ThreadBuffer& GetThreadBuffer();
00137 
00138     /** Returns the current loglevel for the thread. */
00139     LogLevel GetThreadLevel();
00140 
00141     /** Streams for this log. */
00142     std::vector<std::ostream*> m_streams;
00143 
00144     /** Level for each stream. */
00145     std::vector<LogLevel> m_levels;
00146    
00147     /** Threads must grab this mutex before modifying m_thread_buffer
00148         or printing output. */
00149     pthread_mutex_t m_buffer_mutex;
00150 
00151     /** Buffers for up to MAX_THREADS active threads. */
00152     ThreadBuffer m_thread_buffer[MAX_THREADS];
00153 
00154     /** Threads must grab this mutex before modifying
00155         m_thread_level. */
00156     pthread_mutex_t m_map_mutex;
00157 
00158     /** Current log level for each thread. */
00159     std::map<pthread_t, LogLevel> m_thread_level;
00160 };
00161 
00162 template<typename TYPE>
00163 Logger& Logger::operator<<(const TYPE& type)
00164 {
00165     ThreadBuffer& tb = GetThreadBuffer();
00166     tb.buffer << type;
00167     std::string str(tb.buffer.str());
00168     if (!str.empty() && str[str.size() - 1] == '\n')
00169         Flush();
00170     return *this;
00171 }
00172 
00173 //----------------------------------------------------------------------------
00174 
00175 /** Sets global logger to LOG_LEVEL_FINE. */
00176 inline Logger& LogFine()
00177 {
00178     Logger::Global().SetLevel(LOG_LEVEL_FINE);
00179     return Logger::Global();
00180 }
00181 
00182 /** Similar to LogFine() */
00183 inline Logger& LogConfig()
00184 {
00185     Logger::Global().SetLevel(LOG_LEVEL_CONFIG);
00186     return Logger::Global();
00187 }
00188 
00189 /** Similar to LogFine() */
00190 inline Logger& LogInfo()
00191 {
00192     Logger::Global().SetLevel(LOG_LEVEL_INFO);
00193     return Logger::Global();
00194 }
00195 
00196 /** Similar to LogFine() */
00197 inline Logger& LogWarning()
00198 {
00199     Logger::Global().SetLevel(LOG_LEVEL_WARNING);
00200     return Logger::Global();
00201 }
00202 
00203 /** Similar to LogFine() */
00204 inline Logger& LogSevere()
00205 {
00206     Logger::Global().SetLevel(LOG_LEVEL_SEVERE);
00207     return Logger::Global();
00208 }
00209 
00210 //----------------------------------------------------------------------------
00211 
00212 _END_BENZENE_NAMESPACE_
00213 
00214 #endif // LOGGER_HPP


6 Jan 2011 Doxygen 1.6.3