00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "MsgLogger/MsgLoggerImpl.h"
00023
00024
00025
00026
00027 extern "C" {
00028 #include <stdlib.h>
00029 }
00030
00031
00032
00033
00034 #include <algorithm>
00035 #include <map>
00036 #include <sstream>
00037 #include <iostream>
00038 #include <boost/shared_ptr.hpp>
00039 #include <boost/thread/mutex.hpp>
00040 #if BOOST_VERSION>105200
00041 #include <boost/thread/lock_guard.hpp>
00042 #endif
00043
00044
00045
00046
00047 #include "MsgLogger/MsgHandler.h"
00048 #include "MsgLogger/MsgHandlerStdStreams.h"
00049 #include "MsgLogger/MsgLogRecord.h"
00050
00051
00052
00053
00054
00055 namespace {
00056
00057
00058 typedef std::map< std::string, boost::shared_ptr<MsgLogger::MsgLoggerImpl> > Name2ImplMap ;
00059 struct Name2Impl {
00060 Name2Impl () : map(), destroyed(false) {}
00061 ~Name2Impl () { destroyed = true ; }
00062 Name2ImplMap map ;
00063 bool destroyed ;
00064 } ;
00065 Name2Impl implementations ;
00066
00067
00068 std::string parentName ( const std::string& name ) {
00069 std::string::size_type n = name.rfind('.') ;
00070 if ( n == std::string::npos ) {
00071 return std::string() ;
00072 } else {
00073 return std::string( name, 0, n ) ;
00074 }
00075 }
00076
00077
00078 void initRoot ( MsgLogger::MsgLoggerImpl& root ) {
00079 root.addHandler ( new MsgLogger::MsgHandlerStdStreams ) ;
00080 }
00081
00082
00083 void readConfig() ;
00084
00085
00086 static boost::mutex newLoggerMutex ;
00087
00088 }
00089
00090 namespace MsgLogger {
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 MsgLoggerImpl::MsgLoggerImpl( const std::string& name )
00101 : _name(name)
00102 , _level( MsgLogLevel::defaultLevel() )
00103 , _propagate( ! name.empty() )
00104 , _parent(0)
00105 , _handlers()
00106 {
00107 }
00108
00109
00110 MsgLoggerImpl::~MsgLoggerImpl()
00111 {
00112
00113 for ( HandlerList::const_iterator it = _handlers.begin() ; it != _handlers.end() ; ++it ) {
00114 delete *it ;
00115 }
00116 }
00117
00118
00119
00120 void
00121 MsgLoggerImpl::addHandler ( MsgHandler* handler )
00122 {
00123 _handlers.push_back ( handler ) ;
00124 }
00125
00126
00127
00128 bool
00129 MsgLoggerImpl::logging ( MsgLogLevel level ) const
00130 {
00131
00132 if ( _name.empty() && _handlers.empty() ) {
00133 ::initRoot ( const_cast<MsgLoggerImpl&>(*this) ) ;
00134 }
00135
00136
00137 if ( level >= _level ) {
00138
00139 for ( HandlerList::const_iterator it = _handlers.begin() ; it != _handlers.end() ; ++it ) {
00140 if ( (*it)->logging(level) ) return true ;
00141 }
00142 }
00143
00144
00145 if ( _propagate ) {
00146 if ( ! _parent ) {
00147 _parent = getLogger( ::parentName (_name) ) ;
00148
00149 if ( ! _parent ) _propagate = false ;
00150 }
00151 if ( _parent ) {
00152 return _parent->logging(level) ;
00153 }
00154 }
00155
00156 return false ;
00157 }
00158
00159
00160 bool
00161 MsgLoggerImpl::log ( const MsgLogRecord& record ) const
00162 {
00163
00164 if ( _name.empty() && _handlers.empty() ) {
00165 ::initRoot ( const_cast<MsgLoggerImpl&>(*this) ) ;
00166 }
00167
00168 if ( record.level() >= _level ) {
00169
00170 for ( HandlerList::const_iterator it = _handlers.begin() ; it != _handlers.end() ; ++it ) {
00171 (*it)->log(record) ;
00172 }
00173 }
00174
00175
00176 if ( _propagate ) {
00177 if ( ! _parent ) {
00178 _parent = getLogger( ::parentName (_name) ) ;
00179
00180 if ( ! _parent ) _propagate = false ;
00181 }
00182 if ( _parent ) {
00183 _parent->log ( record ) ;
00184 }
00185 }
00186
00187 return true ;
00188 }
00189
00190 MsgLoggerImpl*
00191 MsgLoggerImpl::getLogger( const std::string& name )
00192 {
00193 if ( implementations.destroyed ) {
00194 return 0 ;
00195 }
00196
00197 boost::lock_guard<boost::mutex> lock(::newLoggerMutex);
00198
00199
00200 if ( implementations.map.empty() ) {
00201 try {
00202 ::readConfig() ;
00203 } catch ( const std::exception& e ) {
00204 std::cerr << "MsgLogger: Error while parsing MSGLOGCONFIG: " << e.what() << std::endl ;
00205 }
00206 }
00207
00208
00209 Name2ImplMap::const_iterator it = implementations.map.find ( name ) ;
00210 if ( it != implementations.map.end() ) {
00211 return it->second.get() ;
00212 }
00213
00214
00215 boost::shared_ptr<MsgLoggerImpl> logger ( new MsgLoggerImpl( name ) ) ;
00216 implementations.map.insert ( Name2ImplMap::value_type ( name, logger ) ) ;
00217
00218 return logger.get() ;
00219 }
00220
00221
00222 }
00223
00224 namespace {
00225
00226
00227 void makeLogger ( const std::string& name, const std::string& level, bool propagate )
00228 {
00229
00230 Name2ImplMap::const_iterator it = implementations.map.find ( name ) ;
00231 if ( it != implementations.map.end() ) {
00232 return ;
00233 }
00234
00235 MsgLogger::MsgLogLevel s ( level ) ;
00236
00237 boost::shared_ptr<MsgLogger::MsgLoggerImpl> logger ( new MsgLogger::MsgLoggerImpl( name ) ) ;
00238
00239
00240
00241 if ( ! name.empty() ) logger->addHandler ( new MsgLogger::MsgHandlerStdStreams ) ;
00242
00243 logger->setLevel ( s ) ;
00244 logger->propagate ( propagate ) ;
00245 implementations.map.insert ( Name2ImplMap::value_type ( name, logger ) ) ;
00246
00247 }
00248
00249
00250 void readConfig()
00251 {
00252 const char* env = getenv ( "MSGLOGCONFIG" ) ;
00253 if ( ! env ) return ;
00254
00255 const std::string configEnv(env) ;
00256
00257
00258
00259
00260
00261
00262 typedef std::string::const_iterator iter ;
00263 for ( iter i = configEnv.begin(), j ; i != configEnv.end() ; i = j ) {
00264
00265
00266 j = std::find ( i, configEnv.end(), ';' ) ;
00267
00268
00269 iter j1 = std::find ( i, j, '=' ) ;
00270 if ( j1 == j ) {
00271
00272 std::string level(i,j) ;
00273 ::makeLogger ( std::string(), level, false ) ;
00274 } else {
00275 bool propagate = *(j-1) != '-' ;
00276 std::string level( j1+1, *(j-1)=='-' ? j-1 : j ) ;
00277
00278 for ( iter i2 = i, j2 ; i2 != j1 ; i2 = j2 ) {
00279 j2 = std::find( i2, j1, ',') ;
00280 std::string name ( i2, j2 ) ;
00281 if ( j2 != j1 ) ++ j2 ;
00282 ::makeLogger ( name, level, propagate ) ;
00283 }
00284
00285 }
00286
00287
00288 if ( j != configEnv.end() ) ++ j ;
00289
00290 }
00291
00292 }
00293
00294
00295 }