![]() |
|
|
Generated: 18 Jul 2008 |
00001 #include "IssueLogger.h" 00002 00003 #include "GaudiKernel/SvcFactory.h" 00004 #include "GaudiKernel/ISvcLocator.h" 00005 #include "GaudiKernel/MsgStream.h" 00006 #include "GaudiKernel/Tokenizer.h" 00007 #include "GaudiKernel/System.h" 00008 00009 #include <sstream> 00010 #include <streambuf> 00011 #include <time.h> 00012 00013 #include "boost/bind.hpp" 00014 00015 using namespace std; 00016 00017 DECLARE_SERVICE_FACTORY(IssueLogger) 00018 00019 //*************************************************************************// 00020 inline void toupper(std::string &s) 00021 { 00022 std::string::iterator it=s.begin(); 00023 while(it != s.end()) 00024 { 00025 *it = toupper(*it); 00026 it++; 00027 } 00028 } 00029 00030 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00031 00032 IssueLogger::IssueLogger( const std::string& name, ISvcLocator* svc ) 00033 : Service(name, svc) { 00034 00035 declareProperty ("Output", m_outputfile ); 00036 declareProperty ("ReportLevel", m_reportLevelS="WARNING"); 00037 declareProperty ("TracebackLevel", m_traceLevelS="ERROR"); 00038 declareProperty ("ShowTime", m_showTime=false); 00039 00040 m_reportLevelS.declareUpdateHandler(&IssueLogger::setupLevels,this); 00041 m_traceLevelS.declareUpdateHandler(&IssueLogger::setupLevels,this); 00042 m_outputfile.declareUpdateHandler(&IssueLogger::setupStreams,this); 00043 00044 m_reportLevel = IssueSeverity::WARNING; 00045 m_traceLevel = IssueSeverity::ERROR; 00046 00047 for (int i=0; i<IssueSeverity::NUM_LEVELS; ++i) { 00048 m_logger[i] = 0; 00049 } 00050 00051 m_msgSevMap[MSG::NIL] = IssueSeverity::NIL; 00052 m_msgSevMap[MSG::VERBOSE] = IssueSeverity::VERBOSE; 00053 m_msgSevMap[MSG::DEBUG] = IssueSeverity::DEBUG; 00054 m_msgSevMap[MSG::INFO] = IssueSeverity::INFO; 00055 m_msgSevMap[MSG::WARNING] = IssueSeverity::WARNING; 00056 m_msgSevMap[MSG::ERROR] = IssueSeverity::ERROR; 00057 m_msgSevMap[MSG::FATAL] = IssueSeverity::FATAL; 00058 m_msgSevMap[MSG::ALWAYS] = IssueSeverity::ALWAYS; 00059 00060 m_sevMsgMap[IssueSeverity::NIL] = MSG::NIL; 00061 m_sevMsgMap[IssueSeverity::VERBOSE] = MSG::VERBOSE; 00062 m_sevMsgMap[IssueSeverity::DEBUG] = MSG::DEBUG; 00063 m_sevMsgMap[IssueSeverity::DEBUG1] = MSG::DEBUG; 00064 m_sevMsgMap[IssueSeverity::DEBUG2] = MSG::DEBUG; 00065 m_sevMsgMap[IssueSeverity::DEBUG3] = MSG::DEBUG; 00066 m_sevMsgMap[IssueSeverity::INFO] = MSG::INFO; 00067 m_sevMsgMap[IssueSeverity::WARNING] = MSG::WARNING; 00068 m_sevMsgMap[IssueSeverity::RECOVERABLE] = MSG::ERROR; 00069 m_sevMsgMap[IssueSeverity::ERROR] = MSG::ERROR; 00070 m_sevMsgMap[IssueSeverity::FATAL] = MSG::FATAL; 00071 m_sevMsgMap[IssueSeverity::ALWAYS] = MSG::ALWAYS; 00072 00073 m_levelTrans[IssueSeverity::VERBOSE] = "VERBOSE"; 00074 m_levelTrans[IssueSeverity::DEBUG] = "DEBUG"; 00075 m_levelTrans[IssueSeverity::DEBUG1] = "DEBUG1"; 00076 m_levelTrans[IssueSeverity::DEBUG2] = "DEBUG2"; 00077 m_levelTrans[IssueSeverity::DEBUG3] = "DEBUG3"; 00078 m_levelTrans[IssueSeverity::INFO] = "INFO"; 00079 m_levelTrans[IssueSeverity::WARNING] = "WARNING"; 00080 m_levelTrans[IssueSeverity::RECOVERABLE] = "RECOVERABLE"; 00081 m_levelTrans[IssueSeverity::ERROR] = "ERROR"; 00082 m_levelTrans[IssueSeverity::FATAL] = "FATAL"; 00083 m_levelTrans[IssueSeverity::ALWAYS] = "ALWAYS"; 00084 00085 m_levelSTrans["VERBOSE"] = IssueSeverity::VERBOSE; 00086 m_levelSTrans["DEBUG"] = IssueSeverity::DEBUG; 00087 m_levelSTrans["DEBUG1"] = IssueSeverity::DEBUG1; 00088 m_levelSTrans["DEBUG2"] = IssueSeverity::DEBUG2; 00089 m_levelSTrans["DEBUG3"] = IssueSeverity::DEBUG3; 00090 m_levelSTrans["INFO"] = IssueSeverity::INFO; 00091 m_levelSTrans["WARNING"] = IssueSeverity::WARNING; 00092 m_levelSTrans["RECOVERABLE"] = IssueSeverity::RECOVERABLE; 00093 m_levelSTrans["ERROR"] = IssueSeverity::ERROR; 00094 m_levelSTrans["FATAL"] = IssueSeverity::FATAL; 00095 m_levelSTrans["ALWAYS"] = IssueSeverity::ALWAYS; 00096 00097 00098 } 00099 00100 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00101 00102 IssueLogger::~IssueLogger() { 00103 00104 } 00105 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00106 00107 StatusCode IssueLogger::queryInterface( const InterfaceID& riid, 00108 void** ppvInterface ) { 00109 StatusCode sc = StatusCode::FAILURE; 00110 if ( ppvInterface ) { 00111 *ppvInterface = 0; 00112 00113 if ( IIssueLogger::interfaceID().versionMatch(riid) ) { 00114 *ppvInterface = static_cast<IIssueLogger*>(this); 00115 sc = StatusCode::SUCCESS; 00116 addRef(); 00117 } 00118 else 00119 sc = Service::queryInterface( riid, ppvInterface ); 00120 } 00121 return sc; 00122 } 00123 00124 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00125 00126 StatusCode 00127 IssueLogger::initialize() { 00128 00129 StatusCode st = Service::initialize(); 00130 if (st.isFailure()) { return st; } 00131 00132 setupDefaultLogger(); 00133 00134 return st; 00135 00136 } 00137 00138 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00139 00140 StatusCode 00141 IssueLogger::reinitialize() { 00142 00143 MsgStream log ( msgSvc(), name() ); 00144 log << MSG::WARNING << "reinitialize not implemented" << endreq; 00145 00146 00147 return StatusCode::SUCCESS; 00148 00149 } 00150 00151 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00152 00153 StatusCode 00154 IssueLogger::finalize() { 00155 00156 MsgStream log ( msgSvc(), name() ); 00157 log << MSG::DEBUG << "IssueLogger::finalize" << endreq; 00158 00159 for (int i=0; i<IssueSeverity::NUM_LEVELS; ++i) { 00160 IssueSeverity::Level j = IssueSeverity::Level (i); 00161 delete m_logger[j]; 00162 } 00163 00164 return Service::finalize(); 00165 } 00166 00167 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00168 00169 void 00170 IssueLogger::getTraceBack(std::string& stack) { 00171 00172 size_t depth = 21; 00173 void** addresses = 0 ; 00174 00175 addresses = (void**) malloc(depth*sizeof(void *)); 00176 00177 std::string fnc, lib; 00178 void *addr(0); 00179 00180 if ( (addresses != 0) && System::backTrace(addresses,depth)) { 00181 for (size_t i=7; i<depth; ++i) { 00182 addr = 0 ; 00183 00184 if (System::getStackLevel(addresses[i],addr,fnc,lib)) { 00185 std::ostringstream ost; 00186 ost << hex << addr << " " << fnc << " [" << lib << "]\n"; 00187 stack += ost.str(); 00188 } 00189 } 00190 free(addresses); 00191 } 00192 } 00193 00194 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00195 00196 StatusCode 00197 IssueLogger::connect(const std::string& ident) { 00198 00199 MsgStream log ( msgSvc(), name() ); 00200 Tokenizer tok(true); 00201 00202 string::size_type loc = ident.find(" "); 00203 string stream = ident.substr(0,loc); 00204 // typedef std::pair<std::string,std::string> Prop; 00205 // std::vector<Prop> props; 00206 string val,VAL,TAG,filename; 00207 00208 tok.analyse(ident.substr(loc+1,ident.length()), " ", "", "", "=", "'", "'"); 00209 00210 for ( Tokenizer::Items::iterator i = tok.items().begin(); 00211 i != tok.items().end(); i++) { 00212 const std::string& tag = (*i).tag(); 00213 TAG = tag; 00214 toupper(TAG); 00215 00216 val = (*i).value(); 00217 VAL = val; 00218 toupper(VAL); 00219 00220 IssueSeverity::Level level; 00221 00222 if (TAG == "DEBUG") { 00223 level = IssueSeverity::DEBUG; 00224 } else if ( TAG == "INFO") { 00225 level = IssueSeverity::INFO; 00226 } else if ( TAG == "WARNING") { 00227 level = IssueSeverity::WARNING; 00228 } else if ( TAG == "RECOVERABLE") { 00229 level = IssueSeverity::RECOVERABLE; 00230 } else if ( TAG == "ERROR") { 00231 level = IssueSeverity::ERROR; 00232 } else if ( TAG == "FATAL") { 00233 level = IssueSeverity::FATAL; 00234 } else { 00235 log << MSG::ERROR << "Unknown output level \"" << TAG << "\"" 00236 << endreq; 00237 continue; 00238 } 00239 00240 if (m_logger[level] != 0) { 00241 log << MSG::INFO << "closing stream " << m_logger[level]->name() 00242 << endreq; 00243 delete m_logger[level]; 00244 m_logger[level] = 0; 00245 } 00246 00247 if (val == "MsgSvc") { 00248 m_logger[level] = new StreamLogger(msgSvc(), m_sevMsgMap[level]); 00249 m_log[level] = 00250 boost::bind(&StreamLogger::WriteToMsgSvc, m_logger[level], 00251 _1); 00252 } else if (val == "STDERR") { 00253 m_logger[level] = new StreamLogger(std::cerr); 00254 m_log[level] = 00255 boost::bind(&StreamLogger::WriteToStream, m_logger[level], 00256 _1); 00257 } else if (val == "STDOUT") { 00258 m_logger[level] = new StreamLogger(std::cout); 00259 m_log[level] = 00260 boost::bind(&StreamLogger::WriteToStream, m_logger[level], 00261 _1); 00262 } else { // A file 00263 try { 00264 m_logger[level] = new StreamLogger(val.c_str()); 00265 } 00266 catch (std::exception&) { 00267 m_logger[level] = 0; 00268 log << MSG::ERROR << "Unable to open file \"" << VAL 00269 << "\" for writing issues at level " << TAG << endreq; 00270 return StatusCode::FAILURE; 00271 } 00272 m_log[level] = 00273 boost::bind(&StreamLogger::WriteToStream, m_logger[level], _1); 00274 } 00275 log << MSG::DEBUG << "Writing " << m_levelTrans[level] 00276 << " issues to " << m_logger[level]->name() << endreq; 00277 00278 } 00279 00280 return StatusCode::SUCCESS; 00281 } 00282 00283 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00284 00285 void 00286 IssueLogger::report(IssueSeverity::Level lev, const std::string& str, 00287 const std::string& org) { 00288 00289 if ( lev < m_reportLevel) return; 00290 00291 std::string msg = m_levelTrans[lev] + " " + org + " \"" + str + "\""; 00292 00293 if (m_showTime) { 00294 const time_t t = time( 0 ); 00295 tm *tt = localtime( &t ); 00296 00297 ostringstream os; 00298 os << (tt->tm_hour < 10 ? "0" : "" ) << tt->tm_hour << ":" 00299 << (tt->tm_min < 10 ? "0" : "" ) << tt->tm_min << ":" 00300 << (tt->tm_sec < 10 ? "0" : "" ) << tt->tm_sec << " " 00301 << tt->tm_year + 1900 << "/" 00302 << (tt->tm_mon < 9 ? "0" : "" ) << tt->tm_mon+1 << "/" 00303 << (tt->tm_mday < 10 ? "0" : "" ) << tt->tm_mday << " " 00304 #ifdef __linux 00305 << tt->tm_zone; 00306 #else 00307 << " " ; 00308 #endif 00309 00310 msg += " [" + os.str() +"]"; 00311 00312 } 00313 00314 if (lev >= m_traceLevel) { 00315 std::string stack; 00316 getTraceBack(stack); 00317 msg += "\n" + stack; 00318 } 00319 00320 00321 m_log[lev](msg); 00322 00323 00324 } 00325 00326 00327 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00328 00329 00330 void 00331 IssueLogger::report( const IssueSeverity &err ) { 00332 00333 report(err.getLevel(), err.getMsg(), err.getOrigin()); 00334 00335 } 00336 00337 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00338 00339 void 00340 IssueLogger::setupLevels(Property& prop) { 00341 00342 00343 StringProperty *sap = dynamic_cast<StringProperty*> (&prop); 00344 if (sap == 0) { 00345 MsgStream log ( msgSvc(), name() ); 00346 log << MSG::ERROR << "Could not convert " << prop.name() 00347 << "to a StringProperty (which it should be!)" << endreq; 00348 return; 00349 } 00350 00351 std::string val = sap->value(); 00352 00353 if (prop.name() == "ReportLevel") { 00354 if (m_levelSTrans.find(val) == m_levelSTrans.end()) { 00355 MsgStream log ( msgSvc(), name() ); 00356 log << MSG::ERROR 00357 << "Option ReportLevel: unknown Issue Severity level \"" 00358 << val << "\". Setting it WARNING" << endreq; 00359 m_reportLevel = IssueSeverity::WARNING; 00360 return; 00361 } else { 00362 m_reportLevel = m_levelSTrans[m_reportLevelS]; 00363 } 00364 } else if (prop.name() == "TracebackLevel") { 00365 if (m_levelSTrans.find(val) == m_levelSTrans.end()) { 00366 MsgStream log ( msgSvc(), name() ); 00367 log << MSG::ERROR 00368 << "Option TracebackLevel: unknown Issue Severity level \"" 00369 << val << "\". Setting it to ERROR" << endreq; 00370 m_traceLevel = IssueSeverity::ERROR; 00371 return; 00372 } else { 00373 m_traceLevel = m_levelSTrans[m_traceLevelS]; 00374 } 00375 } else { 00376 MsgStream log ( msgSvc(), name() ); 00377 log << MSG::ERROR << "setting up unknown property \"" << prop.name() 00378 << "\"" << endreq; 00379 return; 00380 } 00381 00382 } 00383 00384 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00385 00386 void 00387 IssueLogger::setupStreams(Property& prop) { 00388 00389 StringArrayProperty *sap = dynamic_cast<StringArrayProperty*>( &prop ); 00390 if (sap == 0) { 00391 MsgStream log ( msgSvc(), name() ); 00392 log << MSG::ERROR << "Could not convert " << prop.name() 00393 << "to a StringArrayProperty (which it should be!)" << endreq; 00394 return; 00395 } 00396 00397 vector<string>::const_iterator itr; 00398 for (itr = sap->value().begin(); itr != sap->value().end(); ++itr) { 00399 if (connect(*itr).isFailure()) { 00400 MsgStream log ( msgSvc(), name() ); 00401 log << MSG::ERROR << "Could not setup stream " << *itr << endreq; 00402 } 00403 } 00404 00405 return; 00406 00407 } 00408 00409 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00410 00411 void 00412 IssueLogger::setupDefaultLogger() { 00413 for (int i=1; i<IssueSeverity::NUM_LEVELS; ++i) { 00414 if (m_logger[i] == 0) { 00415 // default: dump to msgSvc 00416 IssueSeverity::Level j = IssueSeverity::Level (i); 00417 00418 m_logger[j] = new StreamLogger(msgSvc(), m_sevMsgMap[j]); 00419 m_log[j] = boost::bind(&StreamLogger::WriteToMsgSvc, m_logger[j], 00420 _1); 00421 00422 MsgStream log ( msgSvc(), name() ); 00423 log << MSG::DEBUG << "Writing " << m_levelTrans[j] 00424 << " issues to " << m_logger[j]->name() << endreq; 00425 00426 } 00427 } 00428 }