CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_13_patch3/src/FWCore/MessageService/src/ELstatistics.cc

Go to the documentation of this file.
00001 //  ---------------------------------------------------------------------
00002 //
00003 // ELstatistics.cc
00004 //
00005 // History:
00006 //   7/8/98     mf      Created
00007 //   7/2/99     jv      Added noTerminationSummary() function
00008 //   6/7/00     web     Reflect consolidation of ELdestination/X;
00009 //                      consolidate ELstatistics/X
00010 //   6/14/00    web     Remove GNU relic code
00011 //   6/15/00    web     using -> USING
00012 //   10/4/00    mf      filterModule() and excludeModule()
00013 //   3/13/00    mf      statisticsMap()
00014 //    4/4/01    mf      Simplify filter/exclude logic by useing base class
00015 //                      method thisShouldBeIgnored().  Eliminate
00016 //                      moduleOfinterest and moduleToexclude.
00017 //  11/01/01    web     Remove last vestige of GNU relic code; reordered
00018 //                      initializers to correspond to order of member
00019 //                      declarations
00020 //   1/17/06    mf      summary() for use in MessageLogger
00021 //   8/16/07    mf      Changes to implement grouping of modules in specified 
00022 //                      categories
00023 //   6/19/08    mf      summaryForJobReport()
00024 //
00025 //  ---------------------------------------------------------------------
00026 
00027 
00028 #include "FWCore/MessageService/interface/ELstatistics.h"
00029 #include "FWCore/MessageService/interface/ELadministrator.h"
00030 #include "FWCore/MessageService/interface/ELcontextSupplier.h"
00031 
00032 #include "FWCore/MessageLogger/interface/ErrorObj.h"
00033 
00034 #include <iostream>
00035 #include <iomanip>
00036 #include <sstream>
00037 #include <ios>
00038 #include <cassert>
00039 
00040 // Possible Traces:
00041 // #define ELstatisticsCONSTRUCTOR_TRACE
00042 // #define ELstatsLOG_TRACE
00043 
00044 
00045 namespace edm {
00046 namespace service {
00047 
00048 
00049 
00050 // ----------------------------------------------------------------------
00051 // Constructors
00052 // ----------------------------------------------------------------------
00053 
00054 
00055 ELstatistics::ELstatistics()
00056 : ELdestination     (           )
00057 , tableLimit        ( -1        )
00058 , stats             (           )
00059 , updatedStats      ( false     )
00060 , termStream        ( std::cerr )
00061 , printAtTermination( true      )
00062 {
00063 
00064   #ifdef ELstatisticsCONSTRUCTOR_TRACE
00065     std::cerr << "Constructor for ELstatistics()\n";
00066   #endif
00067 
00068 }  // ELstatistics()
00069 
00070 
00071 ELstatistics::ELstatistics( std::ostream & osp )
00072 : ELdestination     (       )
00073 , tableLimit        ( -1    )
00074 , stats             (       )
00075 , updatedStats      ( false )
00076 , termStream        ( osp   )
00077 , printAtTermination( true  )
00078 {
00079 
00080   #ifdef ELstatisticsCONSTRUCTOR_TRACE
00081     std::cerr << "Constructor for ELstatistics(osp)\n";
00082   #endif
00083 
00084 }  // ELstatistics()
00085 
00086 
00087 ELstatistics::ELstatistics( int spaceLimit )
00088 : ELdestination     (            )
00089 , tableLimit        ( spaceLimit )
00090 , stats             (            )
00091 , updatedStats      ( false      )
00092 , termStream        ( std::cerr  )
00093 , printAtTermination( true       )
00094 {
00095 
00096   #ifdef ELstatisticsCONSTRUCTOR_TRACE
00097     std::cerr << "Constructor for ELstatistics(spaceLimit)\n";
00098   #endif
00099 
00100 }  // ELstatistics()
00101 
00102 
00103 ELstatistics::ELstatistics( int spaceLimit, std::ostream & osp )
00104 : ELdestination     (            )
00105 , tableLimit        ( spaceLimit )
00106 , stats             (            )
00107 , updatedStats      ( false      )
00108 , termStream        ( osp        )
00109 , printAtTermination( true       )
00110 {
00111 
00112   #ifdef ELstatisticsCONSTRUCTOR_TRACE
00113     std::cerr << "Constructor for ELstatistics(spaceLimit,osp)\n";
00114   #endif
00115 
00116 }  // ELstatistics()
00117 
00118 
00119 ELstatistics::ELstatistics( const ELstatistics & orig)
00120 : ELdestination     (                         )
00121 , tableLimit        ( orig.tableLimit         )
00122 , stats             ( orig.stats              )
00123 , updatedStats      ( orig.updatedStats       )
00124 , termStream        ( orig.termStream         )
00125 , printAtTermination( orig.printAtTermination )
00126 {
00127 
00128   #ifdef ELstatisticsCONSTRUCTOR_TRACE
00129     std::cerr << "Copy constructor for ELstatistics()\n";
00130   #endif
00131 
00132   ignoreMostModules    = orig.ignoreMostModules;
00133   respondToThese       = orig.respondToThese;
00134   respondToMostModules = orig.respondToMostModules;
00135   ignoreThese          = orig.ignoreThese;
00136 
00137 }  // ELstatistics()
00138 
00139 
00140 ELstatistics::~ELstatistics()  {
00141 
00142   #ifdef ELstatisticsCONSTRUCTOR_TRACE
00143     std::cerr << "Destructor for ELstatistics\n";
00144   #endif
00145 
00146   if ( updatedStats && printAtTermination )
00147     summary( termStream, "Termination Summary" );
00148 
00149 }  // ~ELstatistics()
00150 
00151 
00152 // ----------------------------------------------------------------------
00153 // Methods invoked by the ELadministrator
00154 // ----------------------------------------------------------------------
00155 
00156 ELstatistics *
00157 ELstatistics::clone() const  {
00158 
00159   return  new ELstatistics( *this );
00160 
00161 }  // clone()
00162 
00163 
00164 bool  ELstatistics::log( const edm::ErrorObj & msg )  {
00165 
00166   #ifdef ELstatsLOG_TRACE
00167     std::cerr << "  =:=:=: Log to an ELstatistics\n";
00168   #endif
00169 
00170   // See if this message is to be counted.
00171 
00172   if ( msg.xid().severity < threshold )        return false;
00173   if ( thisShouldBeIgnored(msg.xid().module) ) return false;
00174 
00175   // Account for this message, making a new table entry if needed:
00176   //
00177   ELmap_stats::iterator s = stats.find( msg.xid() );
00178   if ( s == stats.end() )  {
00179     if ( tableLimit < 0  ||  static_cast<int>(stats.size()) < tableLimit )  {
00180       stats[msg.xid()] = StatsCount();
00181       s = stats.find( msg.xid() );
00182     }
00183   }
00184   #ifdef ELstatsLOG_TRACE
00185     std::cerr << "    =:=:=: Message accounted for in stats \n";
00186   #endif
00187   if ( s != stats.end() )  {
00188     #ifdef ELstatsLOG_TRACE
00189         std::cerr << "    =:=:=: Message not last stats \n";
00190         std::cerr << "    =:=:=: getContextSupplier \n";
00191         const ELcontextSupplier & csup
00192           = ELadministrator::instance()->getContextSupplier();
00193         std::cerr << "    =:=:=: getContextSupplier \n";
00194         ELstring sumcon;
00195         std::cerr << "    =:=:=: summaryContext \n";
00196         sumcon = csup.summaryContext();
00197         std::cerr << "    =:=:=: summaryContext is: " << sumcon << "\n";
00198         (*s).second.add( sumcon, msg.reactedTo() );
00199         std::cerr << "    =:=:=: add worked. \n";
00200     #else
00201         (*s).second.add( ELadministrator::instance()->
00202                     getContextSupplier().summaryContext(), msg.reactedTo() );
00203     #endif
00204 
00205     updatedStats = true;
00206     #ifdef ELstatsLOG_TRACE
00207       std::cerr << "    =:=:=: Updated stats \n";
00208     #endif
00209   }
00210 
00211 
00212   // For the purposes of telling whether any log destination has reacted
00213   // to the message, the statistics destination does not count:
00214   //
00215 
00216   #ifdef ELstatsLOG_TRACE
00217     std::cerr << "  =:=:=: log(msg) done (stats) \n";
00218   #endif
00219 
00220   return false;
00221 
00222 
00223 }  // log()
00224 
00225 
00226 // ----------------------------------------------------------------------
00227 // Methods invoked through the ELdestControl handle
00228 // ----------------------------------------------------------------------
00229 
00230 void  ELstatistics::clearSummary()  {
00231 
00232   limits.zero();
00233   ELmap_stats::iterator s;
00234   for ( s = stats.begin();  s != stats.end();  ++s )  {
00235     (*s).second.n = 0;
00236     (*s).second.context1 = (*s).second.context2 = (*s).second.contextLast = "";
00237   }
00238 
00239 }  // clearSummary()
00240 
00241 
00242 void  ELstatistics::wipe()  {
00243 
00244   limits.wipe();
00245   stats.erase( stats.begin(), stats.end() );  //stats.clear();
00246 
00247 }  // wipe()
00248 
00249 
00250 void  ELstatistics::zero()  {
00251 
00252   limits.zero();
00253 
00254 }  // zero()
00255 
00256 
00257 ELstring  ELstatistics::formSummary( ELmap_stats & stats )  {
00258                         // Major changes 8/16/07 mf, including making this
00259                         // a static member function instead of a free function
00260                         
00261   using std::ios;       /* _base ? */
00262   using std::setw;
00263   using std::right;
00264   using std::left;
00265 
00266   std::ostringstream          s;
00267   int                         n = 0;
00268 
00269   // -----  Summary part I:
00270   //
00271   ELstring  lastProcess( "" );
00272   bool      ftnote( false );
00273 
00274   struct part3  {
00275     long n, t;
00276     part3() : n(0L), t(0L)  { ; }
00277   }  p3[ELseverityLevel::nLevels];
00278 
00279   std::set<std::string>::iterator gcEnd = groupedCategories.end(); 
00280   std::set<std::string> gCats = groupedCategories;  // TEMP FOR DEBUGGING SANITY
00281   for ( ELmap_stats::const_iterator i = stats.begin();  i != stats.end();  ++i )  {
00282 
00283      // If this is a grouped category, wait till later to output its stats
00284     std::string cat = (*i).first.id; 
00285     if ( groupedCategories.find(cat) != gcEnd )
00286     {                                                           // 8/16/07 mf
00287        continue; // We will process these categories later
00288     }
00289                                                         
00290     // -----  Emit new process and part I header, if needed:
00291     //
00292     if ( n == 0  || ! eq(lastProcess, (*i).first.process) ) {
00293       s << "\n";
00294       lastProcess = (*i).first.process;
00295       if ( lastProcess.size() > 0) {
00296         s << "Process " << (*i).first.process << '\n';
00297       }
00298       s << " type     category        sev    module        "
00299              "subroutine        count    total\n"
00300         << " ---- -------------------- -- ---------------- "
00301              "----------------  -----    -----\n"
00302         ;
00303     }
00304     // -----  Emit detailed message information:
00305     //
00306     s << right << std::setw( 5) << ++n                                     << ' '
00307       << left  << std::setw(20) << (*i).first.id.substr(0,20)              << ' '
00308       << left  << std::setw( 2) << (*i).first.severity.getSymbol()         << ' '
00309       << left  << std::setw(16) << (*i).first.module.substr(0,16)          << ' '
00310       << left  << std::setw(16) << (*i).first.subroutine.substr(0,16)
00311       << right << std::setw( 7) << (*i).second.n
00312       << left  << std::setw( 1) << ( (*i).second.ignoredFlag ? '*' : ' ' )
00313       << right << std::setw( 8) << (*i).second.aggregateN                  << '\n'
00314       ;
00315     ftnote = ftnote || (*i).second.ignoredFlag;
00316 
00317     // -----  Obtain information for Part III, below:
00318     //
00319     ELextendedID xid = (*i).first;
00320     p3[xid.severity.getLevel()].n += (*i).second.n;
00321     p3[xid.severity.getLevel()].t += (*i).second.aggregateN;
00322   }  // for i
00323 
00324   // ----- Part Ia:  The grouped categories
00325   for ( std::set<std::string>::iterator g = groupedCategories.begin(); g != gcEnd; ++g ) {
00326     int groupTotal = 0;
00327     int groupAggregateN = 0;
00328     ELseverityLevel severityLevel;
00329     bool groupIgnored = true;
00330     for ( ELmap_stats::const_iterator i = stats.begin();  i != stats.end();  ++i )  {
00331       if ( (*i).first.id == *g ) {
00332         if (groupTotal==0) severityLevel = (*i).first.severity;
00333         groupIgnored &= (*i).second.ignoredFlag;
00334         groupAggregateN += (*i).second.aggregateN;
00335         ++groupTotal;
00336       } 
00337     } // for i
00338     if (groupTotal > 0) {
00339       // -----  Emit detailed message information:
00340       //
00341       s << right << std::setw( 5) << ++n                                     << ' '
00342         << left  << std::setw(20) << (*g).substr(0,20)                       << ' '
00343         << left  << std::setw( 2) << severityLevel.getSymbol()               << ' '
00344         << left  << std::setw(16) << "  <Any Module>  "                      << ' '
00345         << left  << std::setw(16) << "<Any Function>"
00346         << right << std::setw( 7) << groupTotal
00347         << left  << std::setw( 1) << ( groupIgnored ? '*' : ' ' )
00348         << right << std::setw( 8) << groupAggregateN                  << '\n'
00349         ;
00350       ftnote = ftnote || groupIgnored;
00351 
00352       // -----  Obtain information for Part III, below:
00353       //
00354       int lev = severityLevel.getLevel();
00355       p3[lev].n += groupTotal;
00356       p3[lev].t += groupAggregateN;
00357     } // end if groupTotal>0
00358   }  // for g
00359 
00360   // -----  Provide footnote to part I, if needed:
00361   //
00362   if ( ftnote )
00363     s << "\n* Some occurrences of this message"
00364          " were suppressed in all logs, due to limits.\n"
00365       ;
00366 
00367   // -----  Summary part II:
00368   //
00369   n = 0;
00370   for ( ELmap_stats::const_iterator i = stats.begin();  i != stats.end();  ++i )  {
00371     std::string cat = (*i).first.id; 
00372     if ( groupedCategories.find(cat) != gcEnd )
00373     {                                                           // 8/16/07 mf
00374        continue; // We will process these categories later
00375     }
00376     if ( n ==  0 ) {
00377       s << '\n'
00378         << " type    category    Examples: "
00379            "run/evt        run/evt          run/evt\n"
00380         << " ---- -------------------- ----"
00381            "------------ ---------------- ----------------\n"
00382         ;
00383     }
00384     s << right << std::setw( 5) << ++n                             << ' '
00385       << left  << std::setw(20) << (*i).first.id.c_str()           << ' '
00386       << left  << std::setw(16) << (*i).second.context1.c_str()    << ' '
00387       << left  << std::setw(16) << (*i).second.context2.c_str()    << ' '
00388                            << (*i).second.contextLast.c_str() << '\n'
00389       ;
00390   }  // for
00391 
00392   // -----  Summary part III:
00393   //
00394   s << "\nSeverity    # Occurrences   Total Occurrences\n"
00395     <<   "--------    -------------   -----------------\n";
00396   for ( int k = 0;  k < ELseverityLevel::nLevels;  ++k )  {
00397     if ( p3[k].n != 0  ||  p3[k].t != 0 )  {
00398       s << left  << std::setw( 8) << ELseverityLevel( ELseverityLevel::ELsev_(k) ).getName().c_str()
00399         << right << std::setw(17) << p3[k].n
00400         << right << std::setw(20) << p3[k].t
00401                              << '\n'
00402         ;
00403     }
00404   }  // for
00405 
00406   return s.str();
00407 
00408 }  // formSummary()
00409 
00410 
00411 void  ELstatistics::summary( ELdestControl & dest, const ELstring & title )  {
00412 
00413   dest.summarization( title, formSummary(stats) );
00414   updatedStats = false;
00415 
00416 }  // summary()
00417 
00418 
00419 void  ELstatistics::summary( std::ostream & os, const ELstring & title )  {
00420 
00421   os << title << std::endl << formSummary(stats) << std::flush;
00422   updatedStats = false;
00423 
00424 }  // summary()
00425 
00426 void  ELstatistics::summary( )  {
00427 
00428   termStream << "\n=============================================\n\n"
00429              << "MessageLogger Summary" << std::endl << formSummary(stats) 
00430              << std::flush;
00431   updatedStats = false;
00432 
00433 }  // summary()
00434 
00435 
00436 void  ELstatistics::summary( ELstring & s, const ELstring & title )  {
00437 
00438   s = title + '\n' + formSummary(stats);
00439   updatedStats = false;
00440 
00441 }  // summary()
00442 
00443 
00444 void  ELstatistics::noTerminationSummary()  { printAtTermination = false; }
00445 
00446 std::map<ELextendedID , StatsCount> ELstatistics::statisticsMap() const {
00447   return std::map<ELextendedID , StatsCount> ( stats );
00448 }
00449 
00450 
00451                                                                 // 6/19/08 mf
00452 void  ELstatistics::summaryForJobReport (std::map<std::string, double> & sm) {
00453 
00454   struct part3  {
00455     long n, t;
00456     part3() : n(0L), t(0L)  { ; }
00457   }  p3[ELseverityLevel::nLevels];
00458 
00459   std::set<std::string>::iterator gcEnd = groupedCategories.end(); 
00460   std::set<std::string> gCats = groupedCategories;  // TEMP FOR DEBUGGING SANITY
00461 
00462   // ----- Part I:  The ungrouped categories
00463   for ( ELmap_stats::const_iterator i = stats.begin();  i != stats.end();  ++i )  {
00464 
00465      // If this is a grouped category, wait till later to output its stats
00466     std::string cat = (*i).first.id; 
00467     if ( groupedCategories.find(cat) != gcEnd )
00468     {                                                           
00469        continue; // We will process these categories later
00470     }
00471                                                         
00472     // -----  Emit detailed message information:
00473     //
00474     std::ostringstream s;
00475     s << "Category_";
00476     std::string sevSymbol = (*i).first.severity.getSymbol();
00477     if ( sevSymbol[0] == '-' ) sevSymbol = sevSymbol.substr(1);
00478     s << sevSymbol << "_" << (*i).first.id;
00479     int n = (*i).second.aggregateN;    
00480     std::string catstr = s.str();
00481     if (sm.find(catstr) != sm.end()) {
00482       sm[catstr] += n; 
00483     } else {
00484        sm[catstr] = n;
00485     } 
00486     // -----  Obtain information for Part III, below:
00487     //
00488     ELextendedID xid = (*i).first;
00489     p3[xid.severity.getLevel()].n += (*i).second.n;
00490     p3[xid.severity.getLevel()].t += (*i).second.aggregateN;
00491   }  // for i
00492 
00493   // ----- Part Ia:  The grouped categories
00494   for ( std::set<std::string>::iterator g = groupedCategories.begin(); g != gcEnd; ++g ) {
00495     int groupTotal = 0;
00496     int groupAggregateN = 0;
00497     ELseverityLevel severityLevel;
00498     for ( ELmap_stats::const_iterator i = stats.begin();  i != stats.end();  ++i )  {
00499       if ( (*i).first.id == *g ) {
00500         if (groupTotal==0) severityLevel = (*i).first.severity;
00501         groupAggregateN += (*i).second.aggregateN;
00502         ++groupTotal;
00503       } 
00504     } // for i
00505     if (groupTotal > 0) {
00506       // -----  Emit detailed message information:
00507       //
00508       std::ostringstream s;
00509       s << "Category_";
00510       std::string sevSymbol = severityLevel.getSymbol();
00511       if ( sevSymbol[0] == '-' ) sevSymbol = sevSymbol.substr(1);
00512       s << sevSymbol << "_" << *g;
00513       int n = groupAggregateN;    
00514       std::string catstr = s.str();
00515       if (sm.find(catstr) != sm.end()) {
00516         sm[catstr] += n; 
00517       } else {
00518          sm[catstr] = n;
00519       } 
00520 
00521       // -----  Obtain information for Part III, below:
00522       //
00523       int lev = severityLevel.getLevel();
00524       p3[lev].n += groupTotal;
00525       p3[lev].t += groupAggregateN;
00526     } // end if groupTotal>0
00527   }  // for g
00528 
00529   // part II (sample event numbers) does not exist for the job report.
00530 
00531   // -----  Summary part III:
00532   //
00533   for ( int k = 0;  k < ELseverityLevel::nLevels;  ++k )  {
00534     //if ( p3[k].t != 0 )  {
00535     if (true) {
00536       std::string sevName;
00537       sevName = ELseverityLevel( ELseverityLevel::ELsev_(k) ).getName();
00538       if (sevName == "Severe")  sevName = "System";
00539       if (sevName == "Success") sevName = "Debug";
00540       sevName = std::string("Log")+sevName;
00541       sevName = dualLogName(sevName);
00542       if (sevName != "UnusedSeverity") {
00543         sm[sevName] = p3[k].t;
00544       }
00545     }
00546   }  // for k
00547 
00548 } // summaryForJobReport()
00549 
00550 std::string ELstatistics::dualLogName (std::string const & s) 
00551 {
00552   if (s=="LogDebug")   return  "LogDebug_LogTrace";
00553   if (s=="LogInfo")    return  "LogInfo_LogVerbatim";
00554   if (s=="LogWarning") return  "LogWarnng_LogPrint";
00555   if (s=="LogError")   return  "LogError_LogProblem";
00556   if (s=="LogSystem")  return  "LogSystem_LogAbsolute";
00557   return "UnusedSeverity";
00558 }
00559 
00560 std::set<std::string> ELstatistics::groupedCategories; // 8/16/07 mf 
00561 
00562 void ELstatistics::noteGroupedCategory(std::string const & cat) {
00563   groupedCategories.insert(cat);
00564 }
00565   
00566 } // end of namespace service  
00567 } // end of namespace edm