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