CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/EventFilter/Message2log4cplus/src/ELlog4cplus.cc

Go to the documentation of this file.
00001 // ----------------------------------------------------------------------
00002 //
00003 // ELcontextSupplier.cc
00004 //
00005 //
00006 // 12/20/05   jm, mf    Created, based on ELoutput.
00007 //
00008 // ----------------------------------------------------------------------
00009 
00010 
00011 #include "EventFilter/Message2log4cplus/interface/ELlog4cplus.h"
00012 
00013 #include "FWCore/MessageLogger/interface/ErrorObj.h"
00014 #include "FWCore/MessageService/interface/ELadministrator.h"
00015 #include "FWCore/MessageService/interface/ELcontextSupplier.h"
00016 
00017 #include "log4cplus/logger.h"
00018 #include "log4cplus/fileappender.h"
00019 #include "log4cplus/loglevel.h"
00020 
00021 #include "xdaq/Application.h"
00022 #include <memory>
00023 
00024 // Possible Traces:
00025 // #define ELoutputCONSTRUCTOR_TRACE
00026 //#define ELlog4cplusTRACE_LOG
00027 //#define ELlog4cplus_EMIT_TRACE
00028 
00029 #include <iostream>
00030 #include <fstream>
00031 
00032 namespace edm
00033 {
00034 
00035 namespace {
00036   void makeFileAppender()
00037   {
00038     static bool iscalled = false;
00039     if(iscalled) return;
00040     iscalled=true;
00041 
00042     using namespace log4cplus;
00043     using namespace log4cplus::helpers;
00044 
00045     SharedAppenderPtr ap(new FileAppender("log4cplus.output"));
00046     ap->setName("Main");
00047     ap->setLayout(std::auto_ptr<Layout>(new log4cplus::TTCCLayout()) );
00048     Logger::getRoot().addAppender(ap);
00049   }
00050 }
00051 
00052 // ----------------------------------------------------------------------
00053 // Useful function:
00054 // ----------------------------------------------------------------------
00055 
00056 
00057 static char * formatTime( const time_t t )  {
00058 
00059 static char ts[] = "dd-Mon-yyyy hh:mm:ss XYZ";
00060 
00061 
00062 #ifdef ANALTERNATIVE
00063   char * c  = ctime( &t );                      // 6/14/99 mf Can't be static!
00064   strncpy( ts+ 0, c+ 8, 2 );  // dd
00065   strncpy( ts+ 3, c+ 4, 3 );  // Mon
00066   strncpy( ts+ 7, c+20, 4 );  // yyyy
00067   strncpy( ts+12, c+11, 8 );  // hh:mm:ss
00068   strncpy( ts+21, tzname[localtime(&t)->tm_isdst], 3 );  // CST
00069 #endif
00070 
00071   strftime( ts, strlen(ts)+1, "%d-%b-%Y %H:%M:%S %Z", localtime(&t) );
00072                 // mf 4-9-04
00073 
00074 
00075   return ts;
00076 
00077 }  // formatTime()
00078 
00079 
00080 // ----------------------------------------------------------------------
00081 // Constructors:
00082 // ----------------------------------------------------------------------
00083 
00084 ELlog4cplus::ELlog4cplus()
00085 : ELdestination       (            )
00086 , os                  ( &os_ )
00087 , osIsOwned           ( false      )
00088 , charsOnLine         ( 0          )
00089 , xid                 (            )
00090 , wantTimestamp       ( true       )
00091 , wantModule          ( true       )
00092 , wantSubroutine      ( true       )
00093 , wantText            ( true       )
00094 , wantSomeContext     ( true       )
00095 , wantSerial          ( false      )
00096 , wantFullContext     ( false      )
00097 , wantTimeSeparate    ( false      )
00098 , wantEpilogueSeparate( false      )
00099 , xxxxInt             ( 0          )
00100 , appl_               ( 0          )
00101 {
00102   //  makeFileAppender(); // this is not needed/wanted. An appender must be provided by the application itself
00103 
00104   #ifdef ELlog4cplusCONSTRUCTOR_TRACE
00105     std::cerr << "Constructor for ELlog4cplus()\n";
00106   #endif
00107 
00108   lineLength = 32000;
00109 
00110   emit( "\n=======================================================", true );
00111   emit( "\nMessageLogger service established\n" );
00112   emit( formatTime(time(0)), true );
00113   emit( "\n=======================================================\n", true );
00114 
00115 }  // ELlog4cplus()
00116 
00117 
00118 
00119 ELlog4cplus::ELlog4cplus( const ELlog4cplus & orig )
00120 : ELdestination       (                           )
00121 , os                  ( &os_                      )
00122 , osIsOwned           ( orig.osIsOwned            )
00123 , charsOnLine         ( orig.charsOnLine          )
00124 , xid                 ( orig.xid                  )
00125 , wantTimestamp       ( orig.wantTimestamp        )
00126 , wantModule          ( orig.wantModule           )
00127 , wantSubroutine      ( orig.wantSubroutine       )
00128 , wantText            ( orig.wantText             )
00129 , wantSomeContext     ( orig.wantSomeContext      )
00130 , wantSerial          ( orig.wantSerial           )
00131 , wantFullContext     ( orig.wantFullContext      )
00132 , wantTimeSeparate    ( orig.wantTimeSeparate     )
00133 , wantEpilogueSeparate( orig.wantEpilogueSeparate )
00134 , xxxxInt             ( orig.xxxxInt              )
00135 , appl_               ( orig.appl_                ) 
00136 {
00137 
00138   #ifdef ELlog4cplusCONSTRUCTOR_TRACE
00139     std::cerr << "Copy constructor for ELlog4cplus\n";
00140   #endif
00141 
00142   // mf 6/15/01 fix of Bug 005
00143   threshold             = orig.threshold;
00144   traceThreshold        = orig.traceThreshold;
00145 
00146   limits                = orig.limits;
00147   preamble              = orig.preamble;
00148   newline               = orig.newline;
00149   indent                = orig.indent;
00150   lineLength            = orig.lineLength;
00151 
00152   ignoreMostModules     = orig.ignoreMostModules;
00153   respondToThese        = orig.respondToThese;
00154   respondToMostModules  = orig.respondToMostModules;
00155   ignoreThese           = orig.ignoreThese;
00156 
00157   // ownership, if any, passes to new copy:
00158   const_cast<ELlog4cplus &>(orig).osIsOwned = false;
00159 
00160 }  // ELlog4cplus()
00161 
00162 
00163 ELlog4cplus::~ELlog4cplus()  {
00164 
00165   #ifdef ELlog4cplusCONSTRUCTOR_TRACE
00166     std::cerr << "Destructor for ELlog4cplus\n";
00167   #endif
00168 
00169   if ( osIsOwned )  { // we have an ofstream
00170     ((std::ofstream*)os)->close();
00171     delete os;
00172   }
00173 
00174 }  // ~ELlog4cplus()
00175 
00176 
00177 // ----------------------------------------------------------------------
00178 // Methods invoked by the ELadministrator:
00179 // ----------------------------------------------------------------------
00180 
00181 ELlog4cplus *
00182 ELlog4cplus::clone() const  {
00183 
00184   return new ELlog4cplus( *this );
00185 
00186 } // clone()
00187 
00188 
00189 bool ELlog4cplus::log( const ErrorObj & msg )  {
00190   os->str(std::string());
00191 
00192   #ifdef ELlog4cplusTRACE_LOG
00193     std::cerr << "    =:=:=: Log to an ELlog4cplus \n";
00194   #endif
00195 
00196   xid = msg.xid();      // Save the xid.
00197 
00198   // See if this message is to be acted upon, and add it to limits table
00199   // if it was not already present:
00200   //
00201   if ( msg.xid().severity < threshold  )  return false;
00202   if ( thisShouldBeIgnored(xid.module) )  return false;
00203   if ( ! limits.add( msg.xid() )       )  return false;
00204   
00205 #ifdef ELlog4cplusTRACE_LOG
00206   std::cerr << "    =:=:=: Limits table work done \n";
00207 #endif
00208   
00209   // get log4cplus logger and establish (log4cplus) context 
00210   bool mustPop = false;
00211 
00212   log4cplus::Logger loghere = appl_ ? appl_->getApplicationLogger() :
00213     log4cplus::Logger::getInstance(msg.xid().module.c_str());
00214   LOG4CPLUS_DEBUG(loghere,  "Message2log4cplus will use logger from appl_ ? " 
00215                  << (appl_ ? "yes" : "no"));
00216   if(appl_)
00217     {
00218       log4cplus::getNDC().push(msg.xid().module.c_str());
00219       mustPop = true;
00220     }
00221   log4cplus::getNDC().push(msg.context().c_str());
00222   
00223   // Output the prologue:
00224   //
00225   emit( preamble );
00226   emit( xid.severity.getSymbol() );
00227   emit( " " );
00228   emit( xid.id );
00229   emit( msg.idOverflow() );
00230   emit( ": " );
00231 
00232   #ifdef ELlog4cplusTRACE_LOG
00233     std::cerr << "    =:=:=: Prologue done \n";
00234   #endif
00235   // Output serial number of message:
00236   //
00237   if ( wantSerial )  {
00238     std::ostringstream s;
00239     s << msg.serial();
00240     emit( "[serial #" + s.str() + ELstring("] ") );
00241   }
00242 
00243   // Output each item in the message:
00244   //
00245   if ( wantText )  {
00246     ELlist_string::const_iterator it;
00247     for ( it = msg.items().begin();  it != msg.items().end();  ++it )  {
00248     #ifdef ELlog4cplusTRACE_LOG
00249       std::cerr << "      =:=:=: Item:  " << *it << '\n';
00250     #endif
00251       emit( *it );
00252     }
00253   }
00254 
00255   // Provide further identification:
00256   //
00257   bool needAspace = true;
00258   if ( wantEpilogueSeparate )  {
00259     if ( xid.module.length() + xid.subroutine.length() > 0 )  {
00260       emit("\n");
00261       needAspace = false;
00262     }
00263     else if ( wantTimestamp && !wantTimeSeparate )  {
00264       emit("\n");
00265       needAspace = false;
00266     }
00267   }
00268   if ( wantModule && (xid.module.length() > 0) )  {
00269     if (needAspace) { emit(ELstring(" ")); needAspace = false; }
00270     emit( xid.module + ELstring(" ") );
00271   }
00272   if ( wantSubroutine && (xid.subroutine.length() > 0) )  {
00273     if (needAspace) { emit(ELstring(" ")); needAspace = false; }
00274     emit( xid.subroutine + "()" + ELstring(" ") );
00275   }
00276 
00277   #ifdef ELlog4cplusTRACE_LOG
00278     std::cerr << "    =:=:=: Module and Subroutine done \n";
00279   #endif
00280 
00281   // Provide time stamp:
00282   //
00283   if ( wantTimestamp )  {
00284     if ( wantTimeSeparate )  {
00285       emit( ELstring("\n") );
00286       needAspace = false;
00287     }
00288     if (needAspace) { emit(ELstring(" ")); needAspace = false; }
00289     emit( formatTime(msg.timestamp()) + ELstring(" ") );
00290   }
00291 
00292   #ifdef ELlog4cplusTRACE_LOG
00293     std::cerr << "    =:=:=: TimeStamp done \n";
00294   #endif
00295 
00296   // Provide the context information:
00297   //
00298   if ( wantSomeContext )
00299     if (needAspace) { emit(ELstring(" ")); needAspace = false; }
00300     #ifdef ELlog4cplusTRACE_LOG
00301       std::cerr << "    =:=:=:>> context supplier is at 0x"
00302                 << std::hex
00303                 << &service::ELadministrator::instance()->getContextSupplier() << '\n';
00304       std::cerr << "    =:=:=:>> context is --- "
00305                 << service::ELadministrator::instance()->getContextSupplier().context()
00306                 << '\n';
00307     #endif
00308     if ( wantFullContext )  {
00309       emit( service::ELadministrator::instance()->getContextSupplier().fullContext());
00310     #ifdef ELlog4cplusTRACE_LOG
00311       std::cerr << "    =:=:=: fullContext done: \n";
00312     #endif
00313     } else  {
00314       emit( service::ELadministrator::instance()->getContextSupplier().context());
00315   #ifdef ELlog4cplusTRACE_LOG
00316     std::cerr << "    =:=:=: Context done: \n";
00317   #endif
00318     }
00319 
00320   // Provide traceback information:
00321   //
00322   if ( msg.xid().severity >= traceThreshold )  {
00323     emit( ELstring("\n")
00324           + service::ELadministrator::instance()->getContextSupplier().traceRoutine()
00325         , true );
00326   }
00327   else  {                                        //else statement added JV:1
00328     emit ("", true);
00329   }
00330   #ifdef ELlog4cplusTRACE_LOG
00331     std::cerr << "    =:=:=: Trace routine done: \n";
00332   #endif
00333 
00334   // Done; message has been fully processed:
00335   //
00336 
00337   #ifdef ELlog4cplusTRACE_LOG
00338     std::cerr << "  =:=:=: log(msg) done: \n";
00339   #endif
00340 
00341     // std::cout << os->str() << "\n";
00342 
00343     switch(msg.xid().severity.getLevel())
00344       {
00345       case edm::ELseverityLevel::ELsev_success:
00346         {
00347           // success is used for debug here
00348           LOG4CPLUS_DEBUG(loghere,os->str());
00349           break;
00350         }
00351       case edm::ELseverityLevel::ELsev_info:
00352         {
00353           LOG4CPLUS_INFO(loghere,os->str());
00354           break;
00355         }
00356       case edm::ELseverityLevel::ELsev_warning:
00357         {
00358           LOG4CPLUS_WARN(loghere,os->str());
00359           break;
00360         }
00361       case edm::ELseverityLevel::ELsev_error:
00362       default:
00363         {
00364           LOG4CPLUS_ERROR(loghere,os->str());
00365           break;
00366         }
00367       }
00368     if(mustPop) log4cplus::getNDC().pop();
00369     log4cplus::getNDC().pop();
00370   return true;
00371 
00372 }  // log()
00373 
00374 
00375 // Remainder are from base class.
00376 
00377 
00378 // ----------------------------------------------------------------------
00379 // Maintenance and test functionality:
00380 // ----------------------------------------------------------------------
00381 
00382 void ELlog4cplus::xxxxSet( int i )  {
00383   xxxxInt = i;
00384 }
00385 
00386 void ELlog4cplus::xxxxShout()  {
00387   std::cerr << "XXXX ELlog4cplus: " << xxxxInt << std::endl;
00388 }
00389 
00390 
00391 // ----------------------------------------------------------------------
00392 // Output methods:
00393 // ----------------------------------------------------------------------
00394 
00395 void ELlog4cplus::emit( const ELstring & s, bool nl )  {
00396 
00397   #ifdef ELlog4cplus_EMIT_TRACE
00398     std::cerr << "[][][] in emit:  charsOnLine is " << charsOnLine << '\n';
00399     std::cerr << "[][][] in emit:  s.length() " << s.length() << '\n';
00400     std::cerr << "[][][] in emit:  lineLength is " << lineLength << '\n';
00401   #endif
00402 
00403   if (s.length() == 0)  {
00404     if ( nl )  {
00405       (*os) << newline << std::flush;
00406       charsOnLine = 0;
00407     }
00408     return;
00409   }
00410 
00411   char first = s[0];
00412   char second,
00413        last,
00414        last2;
00415   second = (s.length() < 2) ? '\0' : s[1];
00416   last = (s.length() < 2) ? '\0' : s[s.length()-1];
00417   last2 = (s.length() < 3) ? '\0' : s[s.length()-2];
00418          //checking -2 because the very last char is sometimes a ' ' inserted
00419          //by ErrorLog::operator<<
00420 
00421                //Accounts for newline @ the beginning of the ELstring     JV:2
00422   if ( first == '\n'
00423   || (charsOnLine + static_cast<int>(s.length())) > lineLength )  {
00424     #ifdef ELlog4cplus_EMIT_TRACE
00425       std::cerr << "[][][] in emit: about to << to *os \n";
00426     #endif
00427     (*os) << newline << indent;
00428     charsOnLine = indent.length();
00429     if (second != ' ')  {
00430       (*os) << ' ';
00431       charsOnLine++;
00432     }
00433     if ( first == '\n' )  {
00434       (*os) << s.substr(1);
00435     }
00436     else  {
00437       (*os) << s;
00438     }
00439   }
00440 
00441   #ifdef ELlog4cplus_EMIT_TRACE
00442     std::cerr << "[][][] in emit: about to << s to *os: " << s << " \n";
00443   #endif
00444 
00445   else  {
00446     (*os) << s;
00447   }
00448 
00449   if (last == '\n' || last2 == '\n')  {  //accounts for newline @ end    $$ JV:2
00450     (*os) << indent;                    //of the ELstring
00451     if (last != ' ')
00452       (*os) << ' ';
00453     charsOnLine = indent.length() + 1;
00454   }
00455 
00456   if ( nl )  { (*os) << newline << std::flush; charsOnLine = 0;           }
00457   else       {                                 charsOnLine += s.length(); }
00458 
00459   #ifdef ELlog4cplus_EMIT_TRACE
00460     std::cerr << "[][][] in emit: completed \n";
00461   #endif
00462 
00463 }  // emit()
00464 
00465 
00466 // ----------------------------------------------------------------------
00467 // Methods controlling message formatting:
00468 // ----------------------------------------------------------------------
00469 
00470 void ELlog4cplus::includeTime()   { wantTimestamp = true;  }
00471 void ELlog4cplus::suppressTime()  { wantTimestamp = false; }
00472 
00473 void ELlog4cplus::includeModule()   { wantModule = true;  }
00474 void ELlog4cplus::suppressModule()  { wantModule = false; }
00475 
00476 void ELlog4cplus::includeSubroutine()   { wantSubroutine = true;  }
00477 void ELlog4cplus::suppressSubroutine()  { wantSubroutine = false; }
00478 
00479 void ELlog4cplus::includeText()   { wantText = true;  }
00480 void ELlog4cplus::suppressText()  { wantText = false; }
00481 
00482 void ELlog4cplus::includeContext()   { wantSomeContext = true;  }
00483 void ELlog4cplus::suppressContext()  { wantSomeContext = false; }
00484 
00485 void ELlog4cplus::suppressSerial()  { wantSerial = false; }
00486 void ELlog4cplus::includeSerial()   { wantSerial = true;  }
00487 
00488 void ELlog4cplus::useFullContext()  { wantFullContext = true;  }
00489 void ELlog4cplus::useContext()      { wantFullContext = false; }
00490 
00491 void ELlog4cplus::separateTime()  { wantTimeSeparate = true;  }
00492 void ELlog4cplus::attachTime()    { wantTimeSeparate = false; }
00493 
00494 void ELlog4cplus::separateEpilogue()  { wantEpilogueSeparate = true;  }
00495 void ELlog4cplus::attachEpilogue()    { wantEpilogueSeparate = false; }
00496 
00497 
00498 // ----------------------------------------------------------------------
00499 // Summary output:
00500 // ----------------------------------------------------------------------
00501 
00502 void ELlog4cplus::summarization(
00503   const ELstring & fullTitle
00504 , const ELstring & sumLines
00505 )  {
00506   const int titleMaxLength( 40 );
00507 
00508   // title:
00509   //
00510   ELstring title( fullTitle, 0, titleMaxLength );
00511   int q = (lineLength - title.length() - 2) / 2;
00512   ELstring line(q, '=');
00513   emit( "", true );
00514   emit( line );
00515   emit( " " );
00516   emit( title );
00517   emit( " " );
00518   emit( line, true );
00519 
00520   // body:
00521   //
00522   *os << sumLines;
00523 
00524   // finish:
00525   //
00526   emit( "", true );
00527   emit( ELstring(lineLength, '='), true );
00528 
00529 }  // summarization()
00530 
00531 void ELlog4cplus::setAppl(xdaq::Application *a)
00532 {
00533   std::cout << "setting application pointer in ELlog4cplus" << std::endl;
00534   appl_ = a;
00535 }
00536 
00537 // ----------------------------------------------------------------------
00538 
00539 
00540 } // end of namespace edm  */