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 : base_class(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
00108 StatusCode
00109 IssueLogger::initialize() {
00110
00111 StatusCode st = Service::initialize();
00112 if (st.isFailure()) { return st; }
00113
00114 setupDefaultLogger();
00115
00116 return st;
00117
00118 }
00119
00120
00121
00122 StatusCode
00123 IssueLogger::reinitialize() {
00124
00125 MsgStream log ( msgSvc(), name() );
00126 log << MSG::WARNING << "reinitialize not implemented" << endmsg;
00127
00128
00129 return StatusCode::SUCCESS;
00130
00131 }
00132
00133
00134
00135 StatusCode
00136 IssueLogger::finalize() {
00137
00138 MsgStream log ( msgSvc(), name() );
00139 log << MSG::DEBUG << "IssueLogger::finalize" << endmsg;
00140
00141 for (int i=0; i<IssueSeverity::NUM_LEVELS; ++i) {
00142 IssueSeverity::Level j = IssueSeverity::Level (i);
00143 delete m_logger[j];
00144 }
00145
00146 return Service::finalize();
00147 }
00148
00149
00150
00151 void
00152 IssueLogger::getTraceBack(std::string& stack) {
00153 const int depth = 30;
00154 const int offset = 5;
00155 System::backTrace(stack, depth, offset);
00156 }
00157
00158
00159
00160 StatusCode
00161 IssueLogger::connect(const std::string& ident) {
00162
00163 MsgStream log ( msgSvc(), name() );
00164 Tokenizer tok(true);
00165
00166 string::size_type loc = ident.find(" ");
00167 string stream = ident.substr(0,loc);
00168
00169
00170 string val,VAL,TAG,filename;
00171
00172 tok.analyse(ident.substr(loc+1,ident.length()), " ", "", "", "=", "'", "'");
00173
00174 for ( Tokenizer::Items::iterator i = tok.items().begin();
00175 i != tok.items().end(); i++) {
00176 const std::string& tag = (*i).tag();
00177 TAG = tag;
00178 toupper(TAG);
00179
00180 val = (*i).value();
00181 VAL = val;
00182 toupper(VAL);
00183
00184 IssueSeverity::Level level;
00185
00186 if (TAG == "DEBUG") {
00187 level = IssueSeverity::DEBUG;
00188 } else if ( TAG == "INFO") {
00189 level = IssueSeverity::INFO;
00190 } else if ( TAG == "WARNING") {
00191 level = IssueSeverity::WARNING;
00192 } else if ( TAG == "RECOVERABLE") {
00193 level = IssueSeverity::RECOVERABLE;
00194 } else if ( TAG == "ERROR") {
00195 level = IssueSeverity::ERROR;
00196 } else if ( TAG == "FATAL") {
00197 level = IssueSeverity::FATAL;
00198 } else {
00199 log << MSG::ERROR << "Unknown output level \"" << TAG << "\""
00200 << endmsg;
00201 continue;
00202 }
00203
00204 if (m_logger[level] != 0) {
00205 log << MSG::INFO << "closing stream " << m_logger[level]->name()
00206 << endmsg;
00207 delete m_logger[level];
00208 m_logger[level] = 0;
00209 }
00210
00211 if (val == "MsgSvc") {
00212 m_logger[level] = new StreamLogger(msgSvc(), m_sevMsgMap[level]);
00213 m_log[level] =
00214 boost::bind(&StreamLogger::WriteToMsgSvc, m_logger[level],
00215 _1);
00216 } else if (val == "STDERR") {
00217 m_logger[level] = new StreamLogger(std::cerr);
00218 m_log[level] =
00219 boost::bind(&StreamLogger::WriteToStream, m_logger[level],
00220 _1);
00221 } else if (val == "STDOUT") {
00222 m_logger[level] = new StreamLogger(std::cout);
00223 m_log[level] =
00224 boost::bind(&StreamLogger::WriteToStream, m_logger[level],
00225 _1);
00226 } else {
00227 try {
00228 m_logger[level] = new StreamLogger(val.c_str());
00229 }
00230 catch (std::exception&) {
00231 m_logger[level] = 0;
00232 log << MSG::ERROR << "Unable to open file \"" << VAL
00233 << "\" for writing issues at level " << TAG << endmsg;
00234 return StatusCode::FAILURE;
00235 }
00236 m_log[level] =
00237 boost::bind(&StreamLogger::WriteToStream, m_logger[level], _1);
00238 }
00239 log << MSG::DEBUG << "Writing " << m_levelTrans[level]
00240 << " issues to " << m_logger[level]->name() << endmsg;
00241
00242 }
00243
00244 return StatusCode::SUCCESS;
00245 }
00246
00247
00248
00249 void
00250 IssueLogger::report(IssueSeverity::Level lev, const std::string& str,
00251 const std::string& org) {
00252
00253 if ( lev < m_reportLevel) return;
00254
00255 std::string msg = m_levelTrans[lev] + " " + org + " \"" + str + "\"";
00256
00257 if (m_showTime) {
00258 const time_t t = time( 0 );
00259 tm *tt = localtime( &t );
00260
00261 ostringstream os;
00262 os << (tt->tm_hour < 10 ? "0" : "" ) << tt->tm_hour << ":"
00263 << (tt->tm_min < 10 ? "0" : "" ) << tt->tm_min << ":"
00264 << (tt->tm_sec < 10 ? "0" : "" ) << tt->tm_sec << " "
00265 << tt->tm_year + 1900 << "/"
00266 << (tt->tm_mon < 9 ? "0" : "" ) << tt->tm_mon+1 << "/"
00267 << (tt->tm_mday < 10 ? "0" : "" ) << tt->tm_mday << " "
00268 #ifdef __linux
00269 << tt->tm_zone;
00270 #else
00271 << " " ;
00272 #endif
00273
00274 msg += " [" + os.str() +"]";
00275
00276 }
00277
00278 if (lev >= m_traceLevel) {
00279 std::string stack;
00280 getTraceBack(stack);
00281 msg += "\n" + stack;
00282 }
00283
00284
00285 m_log[lev](msg);
00286
00287
00288 }
00289
00290
00291
00292
00293
00294 void
00295 IssueLogger::report( const IssueSeverity &err ) {
00296
00297 report(err.getLevel(), err.getMsg(), err.getOrigin());
00298
00299 }
00300
00301
00302
00303 void
00304 IssueLogger::setupLevels(Property& prop) {
00305
00306
00307 StringProperty *sap = dynamic_cast<StringProperty*> (&prop);
00308 if (sap == 0) {
00309 MsgStream log ( msgSvc(), name() );
00310 log << MSG::ERROR << "Could not convert " << prop.name()
00311 << "to a StringProperty (which it should be!)" << endmsg;
00312 return;
00313 }
00314
00315 std::string val = sap->value();
00316
00317 if (prop.name() == "ReportLevel") {
00318 if (m_levelSTrans.find(val) == m_levelSTrans.end()) {
00319 MsgStream log ( msgSvc(), name() );
00320 log << MSG::ERROR
00321 << "Option ReportLevel: unknown Issue Severity level \""
00322 << val << "\". Setting it WARNING" << endmsg;
00323 m_reportLevel = IssueSeverity::WARNING;
00324 return;
00325 } else {
00326 m_reportLevel = m_levelSTrans[m_reportLevelS];
00327 }
00328 } else if (prop.name() == "TracebackLevel") {
00329 if (m_levelSTrans.find(val) == m_levelSTrans.end()) {
00330 MsgStream log ( msgSvc(), name() );
00331 log << MSG::ERROR
00332 << "Option TracebackLevel: unknown Issue Severity level \""
00333 << val << "\". Setting it to ERROR" << endmsg;
00334 m_traceLevel = IssueSeverity::ERROR;
00335 return;
00336 } else {
00337 m_traceLevel = m_levelSTrans[m_traceLevelS];
00338 }
00339 } else {
00340 MsgStream log ( msgSvc(), name() );
00341 log << MSG::ERROR << "setting up unknown property \"" << prop.name()
00342 << "\"" << endmsg;
00343 return;
00344 }
00345
00346 }
00347
00348
00349
00350 void
00351 IssueLogger::setupStreams(Property& prop) {
00352
00353 StringArrayProperty *sap = dynamic_cast<StringArrayProperty*>( &prop );
00354 if (sap == 0) {
00355 MsgStream log ( msgSvc(), name() );
00356 log << MSG::ERROR << "Could not convert " << prop.name()
00357 << "to a StringArrayProperty (which it should be!)" << endmsg;
00358 return;
00359 }
00360
00361 vector<string>::const_iterator itr;
00362 for (itr = sap->value().begin(); itr != sap->value().end(); ++itr) {
00363 if (connect(*itr).isFailure()) {
00364 MsgStream log ( msgSvc(), name() );
00365 log << MSG::ERROR << "Could not setup stream " << *itr << endmsg;
00366 }
00367 }
00368
00369 return;
00370
00371 }
00372
00373
00374
00375 void
00376 IssueLogger::setupDefaultLogger() {
00377 for (int i=1; i<IssueSeverity::NUM_LEVELS; ++i) {
00378 if (m_logger[i] == 0) {
00379
00380 IssueSeverity::Level j = IssueSeverity::Level (i);
00381
00382 m_logger[j] = new StreamLogger(msgSvc(), m_sevMsgMap[j]);
00383 m_log[j] = boost::bind(&StreamLogger::WriteToMsgSvc, m_logger[j],
00384 _1);
00385
00386 MsgStream log ( msgSvc(), name() );
00387 log << MSG::DEBUG << "Writing " << m_levelTrans[j]
00388 << " issues to " << m_logger[j]->name() << endmsg;
00389
00390 }
00391 }
00392 }