log.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <pthread.h>
00019
00020 #include "log.h"
00021 #include "perThread.h"
00022 #include "thread.h"
00023
00024 using namespace std;
00025
00026 #ifdef WIN32_VC
00027 # define atoll _atoi64
00028 #endif
00029
00030
00031 namespace eq
00032 {
00033 namespace base
00034 {
00035
00036 static int getLogLevel();
00037 static unsigned getLogTopics();
00038
00039 namespace
00040 {
00041 class LogTable
00042 {
00043 public:
00044 LogTable( const LogLevel _level, const string& _name )
00045 : level( _level ), name( _name ) {}
00046
00047 LogLevel level;
00048 string name;
00049 };
00050
00051 #define LOG_TABLE_ENTRY( name ) LogTable( LOG_ ## name, string( #name ))
00052 #define LOG_TABLE_SIZE (5)
00053
00054 static LogTable _logTable[ LOG_TABLE_SIZE ] =
00055 {
00056 LOG_TABLE_ENTRY( ERROR ),
00057 LOG_TABLE_ENTRY( WARN ),
00058 LOG_TABLE_ENTRY( INFO ),
00059 LOG_TABLE_ENTRY( VERB ),
00060 LOG_TABLE_ENTRY( ALL )
00061 };
00062 }
00063
00064 int Log::level = getLogLevel();
00065 unsigned Log::topics = getLogTopics();
00066 Clock _defaultClock;
00067 Clock* _clock = &_defaultClock;
00068
00069 static PerThread< Log > _logInstance;
00070
00071 #ifdef NDEBUG
00072 static std::ostream* _logStream = &std::cout;
00073 #else
00074 static std::ostream* _logStream = &std::cerr;
00075 #endif
00076
00077 int getLogLevel()
00078 {
00079 const char *env = getenv("EQ_LOG_LEVEL");
00080 if( env )
00081 {
00082 const int level = atoi( env );
00083 if( level )
00084 return level;
00085
00086 const string envString( env );
00087 for( uint32_t i=0; i<LOG_TABLE_SIZE; ++i )
00088 if( _logTable[i].name == envString )
00089 return _logTable[i].level;
00090 }
00091
00092 #ifdef NDEBUG
00093 return LOG_WARN;
00094 #else
00095 return LOG_INFO;
00096 #endif
00097 }
00098
00099 std::string& Log::getLogLevelString()
00100 {
00101 for( uint32_t i=0; i<LOG_TABLE_SIZE; ++i )
00102 if( _logTable[i].level == level )
00103 return _logTable[i].name;
00104
00105 return _logTable[0].name;
00106 }
00107
00108 unsigned getLogTopics()
00109 {
00110 const char *env = getenv("EQ_LOG_TOPICS");
00111 if( env )
00112 return atoll(env);
00113
00114 if( getLogLevel() == LOG_ALL )
00115 return 0xffffffffu;
00116
00117 return 0;
00118 }
00119
00120 Log& Log::instance( const char* subdir, const char* file,
00121 const int line )
00122 {
00123 Log* log = _logInstance.get();
00124 if( !log )
00125 {
00126 log = new Log();
00127 _logInstance = log;
00128 }
00129
00130 log->setLogInfo( subdir, file, line );
00131 return *log;
00132 }
00133
00134 void Log::exit()
00135 {
00136 Log* log = _logInstance.get();
00137 _logInstance = 0;
00138 delete log;
00139 }
00140
00141 void Log::setOutput( std::ostream& stream )
00142 {
00143 _logStream = &stream;
00144 exit();
00145 }
00146
00147 void Log::setClock( Clock* clock )
00148 {
00149 if( clock )
00150 _clock = clock;
00151 else
00152 _clock = &_defaultClock;
00153 }
00154
00155 std::ostream& Log::getOutput()
00156 {
00157 return *_logStream;
00158 }
00159
00160
00161 LogBuffer::int_type LogBuffer::overflow( LogBuffer::int_type c )
00162 {
00163 if( c == EOF )
00164 return EOF;
00165
00166 if( _newLine )
00167 {
00168 if( !_noHeader )
00169 {
00170 _stringStream << getpid() << " "
00171 << eq::base::Thread::getSelfThreadID()
00172 << " " << _file << ":" << _line << " ";
00173
00174 const int prec = _stringStream.precision();
00175
00176 _stringStream.precision( 5 );
00177 _stringStream << std::setw(5) << (_clock->getTime64() % 100000)
00178 << " ";
00179 _stringStream.precision( prec );
00180 }
00181
00182 for( int i=0; i<_indent; ++i )
00183 _stringStream << " ";
00184 _newLine = false;
00185 }
00186
00187 _stringStream << (char)c;
00188 return c;
00189 }
00190
00191
00192 std::ostream& indent( std::ostream& os )
00193 {
00194 Log* log = dynamic_cast<Log*>(&os);
00195 if( log )
00196 log->indent();
00197 return os;
00198 }
00199 std::ostream& exdent( std::ostream& os )
00200 {
00201 Log* log = dynamic_cast<Log*>(&os);
00202 if( log )
00203 log->exdent();
00204 return os;
00205 }
00206
00207 std::ostream& disableFlush( std::ostream& os )
00208 {
00209 Log* log = dynamic_cast<Log*>(&os);
00210 if( log )
00211 log->disableFlush();
00212 return os;
00213 }
00214 std::ostream& enableFlush( std::ostream& os )
00215 {
00216 Log* log = dynamic_cast<Log*>(&os);
00217 if( log )
00218 log->enableFlush();
00219 return os;
00220 }
00221 std::ostream& forceFlush( std::ostream& os )
00222 {
00223 Log* log = dynamic_cast<Log*>(&os);
00224 if( log )
00225 log->forceFlush();
00226 return os;
00227 }
00228
00229 std::ostream& disableHeader( std::ostream& os )
00230 {
00231 Log* log = dynamic_cast<Log*>(&os);
00232 if( log )
00233 log->disableHeader();
00234 return os;
00235 }
00236 std::ostream& enableHeader( std::ostream& os )
00237 {
00238 Log* log = dynamic_cast<Log*>(&os);
00239 if( log )
00240 log->enableHeader();
00241 return os;
00242 }
00243
00244 }
00245 }