CMS 3D CMS Logo

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

Generated on Tue Jun 9 17:34:42 2009 for CMSSW by  doxygen 1.5.4