00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 #include "FWCore/MessageService/interface/ELoutput.h"
00077 #include "FWCore/MessageService/interface/ELadministrator.h"
00078 #include "FWCore/MessageService/interface/ELcontextSupplier.h"
00079
00080 #include "FWCore/MessageLogger/interface/ErrorObj.h"
00081
00082 #include "FWCore/Utilities/interface/do_nothing_deleter.h"
00083
00084
00085
00086
00087
00088
00089 #include <iostream>
00090 #include <fstream>
00091 #include <cstring>
00092 #include <cassert>
00093
00094 namespace edm {
00095 namespace service {
00096
00097
00098
00099
00100
00101
00102 static ELstring formatTime( const time_t t ) {
00103
00104 static char const dummy[] = "dd-Mon-yyyy hh:mm:ss TZN ";
00105 char ts[sizeof(dummy)];
00106
00107 struct tm timebuf;
00108
00109 strftime( ts, sizeof(dummy), "%d-%b-%Y %H:%M:%S %Z", localtime_r(&t, &timebuf) );
00110
00111
00112 #ifdef STRIP_TRAILING_BLANKS_IN_TIMEZONE
00113
00114
00115 unsigned int b = strlen(ts);
00116 while (ts[--b] == ' ') {ts[b] = 0;}
00117 #endif
00118
00119 ELstring result(ts);
00120 return result;
00121 }
00122
00123
00124
00125
00126
00127
00128 ELoutput::ELoutput()
00129 : ELdestination ( )
00130 , os ( &std::cerr, do_nothing_deleter() )
00131 , charsOnLine ( 0 )
00132 , xid ( )
00133 , wantTimestamp ( true )
00134 , wantModule ( true )
00135 , wantSubroutine ( true )
00136 , wantText ( true )
00137 , wantSomeContext ( true )
00138 , wantSerial ( false )
00139 , wantFullContext ( false )
00140 , wantTimeSeparate ( false )
00141 , wantEpilogueSeparate( false )
00142 , preambleMode ( true )
00143 {
00144
00145 #ifdef ELoutputCONSTRUCTOR_TRACE
00146 std::cerr << "Constructor for ELoutput()\n";
00147 #endif
00148
00149 emitToken( "\n=================================================", true );
00150 emitToken( "\nMessage Log File written by MessageLogger service \n" );
00151 emitToken( "\n=================================================\n", true );
00152
00153 }
00154
00155
00156 ELoutput::ELoutput( std::ostream & os_ , bool emitAtStart )
00157 : ELdestination ( )
00158 , os ( &os_, do_nothing_deleter() )
00159 , charsOnLine ( 0 )
00160 , xid ( )
00161 , wantTimestamp ( true )
00162 , wantModule ( true )
00163 , wantSubroutine ( true )
00164 , wantText ( true )
00165 , wantSomeContext ( true )
00166 , wantSerial ( false )
00167 , wantFullContext ( false )
00168 , wantTimeSeparate ( false )
00169 , wantEpilogueSeparate( false )
00170 , preambleMode ( true )
00171 {
00172
00173 #ifdef ELoutputCONSTRUCTOR_TRACE
00174 std::cerr << "Constructor for ELoutput( os )\n";
00175 #endif
00176
00177
00178 if (emitAtStart) {
00179 preambleMode = true;
00180 emitToken( "\n=================================================", true );
00181 emitToken( "\nMessage Log File written by MessageLogger service \n" );
00182 emitToken( "\n=================================================\n", true );
00183 }
00184
00185 }
00186
00187
00188 ELoutput::ELoutput( const ELstring & fileName, bool emitAtStart )
00189 : ELdestination ( )
00190 , os ( new std::ofstream( fileName.c_str() , std::ios::app), close_and_delete())
00191 , charsOnLine ( 0 )
00192 , xid ( )
00193 , wantTimestamp ( true )
00194 , wantModule ( true )
00195 , wantSubroutine ( true )
00196 , wantText ( true )
00197 , wantSomeContext ( true )
00198 , wantSerial ( false )
00199 , wantFullContext ( false )
00200 , wantTimeSeparate ( false )
00201 , wantEpilogueSeparate( false )
00202 , preambleMode ( true )
00203 {
00204
00205 #ifdef ELoutputCONSTRUCTOR_TRACE
00206 std::cerr << "Constructor for ELoutput( " << fileName << " )\n";
00207 #endif
00208
00209 preambleMode = true;
00210 if ( os && *os ) {
00211 #ifdef ELoutputCONSTRUCTOR_TRACE
00212 std::cerr << " Testing if os is owned\n";
00213 #endif
00214 #ifdef ELoutputCONSTRUCTOR_TRACE
00215 std::cerr << " About to do first emit\n";
00216 #endif
00217
00218 if (emitAtStart) {
00219 emitToken( "\n=======================================================",
00220 true );
00221 emitToken( "\nError Log File " );
00222 emitToken( fileName );
00223 emitToken( " \n" );
00224 }
00225 }
00226 else {
00227 #ifdef ELoutputCONSTRUCTOR_TRACE
00228 std::cerr << " Deleting os\n";
00229 #endif
00230 os.reset(&std::cerr, do_nothing_deleter());
00231 #ifdef ELoutputCONSTRUCTOR_TRACE
00232 std::cerr << " about to emit to cerr\n";
00233 #endif
00234 if (emitAtStart) {
00235 emitToken( "\n=======================================================",
00236 true );
00237 emitToken( "\n%MSG** Logging to cerr is being substituted" );
00238 emitToken( " for specified log file \"" );
00239 emitToken( fileName );
00240 emitToken( "\" which could not be opened for write or append.\n" );
00241 }
00242 }
00243 if (emitAtStart) {
00244 ELstring const& ftime = formatTime(time(0));
00245 emitToken( ftime, true );
00246 emitToken( "\n=======================================================\n",
00247 true );
00248 }
00249
00250
00251 #ifdef ELoutputCONSTRUCTOR_TRACE
00252 std::cerr << "Constructor for ELoutput completed.\n";
00253 #endif
00254
00255 }
00256
00257
00258 ELoutput::ELoutput( const ELoutput & orig )
00259 : ELdestination ( )
00260 , os ( orig.os )
00261 , charsOnLine ( orig.charsOnLine )
00262 , xid ( orig.xid )
00263 , wantTimestamp ( orig.wantTimestamp )
00264 , wantModule ( orig.wantModule )
00265 , wantSubroutine ( orig.wantSubroutine )
00266 , wantText ( orig.wantText )
00267 , wantSomeContext ( orig.wantSomeContext )
00268 , wantSerial ( orig.wantSerial )
00269 , wantFullContext ( orig.wantFullContext )
00270 , wantTimeSeparate ( orig.wantTimeSeparate )
00271 , wantEpilogueSeparate( orig.wantEpilogueSeparate )
00272 , preambleMode ( orig.preambleMode )
00273 {
00274
00275 #ifdef ELoutputCONSTRUCTOR_TRACE
00276 std::cerr << "Copy constructor for ELoutput\n";
00277 #endif
00278
00279
00280 threshold = orig.threshold;
00281 traceThreshold = orig.traceThreshold;
00282 limits = orig.limits;
00283 preamble = orig.preamble;
00284 newline = orig.newline;
00285 indent = orig.indent;
00286 lineLength = orig.lineLength;
00287
00288 ignoreMostModules = orig.ignoreMostModules;
00289 respondToThese = orig.respondToThese;
00290 respondToMostModules = orig.respondToMostModules;
00291 ignoreThese = orig.ignoreThese;
00292
00293 }
00294
00295
00296 ELoutput::~ELoutput() {
00297
00298 #ifdef ELoutputCONSTRUCTOR_TRACE
00299 std::cerr << "Destructor for ELoutput\n";
00300 #endif
00301
00302 }
00303
00304
00305
00306
00307
00308
00309 ELoutput *
00310 ELoutput::clone() const {
00311
00312 return new ELoutput( *this );
00313
00314 }
00315
00316
00317
00318
00319 bool ELoutput::log( const edm::ErrorObj & msg ) {
00320
00321 #ifdef ELoutputTRACE_LOG
00322 std::cerr << " =:=:=: Log to an ELoutput \n";
00323 #endif
00324
00325 xid = msg.xid();
00326
00327 #ifdef THRESHTRACE
00328 std::cerr << " =:=:=: Log to an ELoutput \n"
00329 << " severity = " << xid.severity << "\n"
00330 << " threshold = " << threshold << "\n"
00331 << " id = " << xid.id << "\n";
00332 #endif
00333
00334
00335
00336
00337 if ( xid.severity < threshold ) return false;
00338 if ( thisShouldBeIgnored(xid.module)
00339 && (xid.severity < ELsevere) )
00340 return false;
00341 if ( ! limits.add( xid )
00342 && (xid.severity < ELsevere) )
00343 return false;
00344
00345 #ifdef ELoutputTRACE_LOG
00346 std::cerr << " =:=:=: Limits table work done \n";
00347 #endif
00348
00349
00350
00351 preambleMode = true;
00352
00353 if ( !msg.is_verbatim() ) {
00354 charsOnLine = 0;
00355 emitToken( preamble );
00356 emitToken( xid.severity.getSymbol() );
00357 emitToken( " " );
00358 emitToken( xid.id );
00359 emitToken( msg.idOverflow() );
00360 emitToken( ": " );
00361 }
00362
00363 #ifdef ELoutputTRACE_LOG
00364 std::cerr << " =:=:=: Prologue done \n";
00365 #endif
00366
00367
00368 if ( !msg.is_verbatim() )
00369 {
00370 if ( wantSerial ) {
00371 std::ostringstream s;
00372 s << msg.serial();
00373 emitToken( "[serial #" + s.str() + ELstring("] ") );
00374 }
00375 }
00376
00377 #ifdef OUTPUT_FORMATTED_ERROR_MESSAGES
00378
00379
00380 if ( wantText ) {
00381 ELlist_string::const_iterator it;
00382 for ( it = msg.items().begin(); it != msg.items().end(); ++it ) {
00383 #ifdef ELoutputTRACE_LOG
00384 std::cerr << " =:=:=: Item: " << *it << '\n';
00385 #endif
00386 emitToken( *it );
00387 }
00388 }
00389 #endif
00390
00391
00392
00393 bool needAspace = true;
00394 if ( !msg.is_verbatim() )
00395 {
00396 if ( wantEpilogueSeparate ) {
00397 if ( xid.module.length() + xid.subroutine.length() > 0 ) {
00398 emitToken("\n");
00399 needAspace = false;
00400 }
00401 else if ( wantTimestamp && !wantTimeSeparate ) {
00402 emitToken("\n");
00403 needAspace = false;
00404 }
00405 }
00406 if ( wantModule && (xid.module.length() > 0) ) {
00407 if (needAspace) { emitToken(ELstring(" ")); needAspace = false; }
00408 emitToken( xid.module + ELstring(" ") );
00409 }
00410 if ( wantSubroutine && (xid.subroutine.length() > 0) ) {
00411 if (needAspace) { emitToken(ELstring(" ")); needAspace = false; }
00412 emitToken( xid.subroutine + "()" + ELstring(" ") );
00413 }
00414 }
00415
00416 #ifdef ELoutputTRACE_LOG
00417 std::cerr << " =:=:=: Module and Subroutine done \n";
00418 #endif
00419
00420
00421
00422 if ( !msg.is_verbatim() )
00423 {
00424 if ( wantTimestamp ) {
00425 if ( wantTimeSeparate ) {
00426 emitToken( ELstring("\n") );
00427 needAspace = false;
00428 }
00429 if (needAspace) { emitToken(ELstring(" ")); needAspace = false; }
00430 ELstring const& ftime = formatTime(msg.timestamp());
00431 emitToken( ftime + ELstring(" ") );
00432 }
00433 }
00434
00435 #ifdef ELoutputTRACE_LOG
00436 std::cerr << " =:=:=: TimeStamp done \n";
00437 #endif
00438
00439
00440
00441 if ( !msg.is_verbatim() )
00442 {
00443 if ( wantSomeContext ) {
00444 if (needAspace) { emitToken(ELstring(" ")); needAspace = false; }
00445 assert(!needAspace);
00446 #ifdef ELoutputTRACE_LOG
00447 std::cerr << " =:=:=:>> context supplier is at 0x"
00448 << std::hex
00449 << &ELadministrator::instance()->getContextSupplier() << '\n';
00450 std::cerr << " =:=:=:>> context is --- "
00451 << ELadministrator::instance()->getContextSupplier().context()
00452 << '\n';
00453 #endif
00454 if ( wantFullContext ) {
00455 emitToken( ELadministrator::instance()->getContextSupplier().fullContext());
00456 #ifdef ELoutputTRACE_LOG
00457 std::cerr << " =:=:=: fullContext done: \n";
00458 #endif
00459 } else {
00460 emitToken( ELadministrator::instance()->getContextSupplier().context());
00461 #ifdef ELoutputTRACE_LOG
00462 std::cerr << " =:=:=: Context done: \n";
00463 #endif
00464 }
00465 }
00466 }
00467
00468
00469
00470
00471 bool insertNewlineAfterHeader = ( msg.xid().severity != ELsuccess );
00472
00473
00474 if ( !msg.is_verbatim() )
00475 {
00476 if ( msg.xid().severity >= traceThreshold ) {
00477 emitToken( ELstring("\n")
00478 + ELadministrator::instance()->getContextSupplier().traceRoutine()
00479 , insertNewlineAfterHeader );
00480 }
00481 else {
00482 emitToken("", insertNewlineAfterHeader);
00483 }
00484 }
00485 #ifdef ELoutputTRACE_LOG
00486 std::cerr << " =:=:=: Trace routine done: \n";
00487 #endif
00488
00489 #ifndef OUTPUT_FORMATTED_ERROR_MESSAGES
00490
00491
00492 preambleMode = false;
00493 if ( wantText ) {
00494 ELlist_string::const_iterator it;
00495 int item_count = 0;
00496 for ( it = msg.items().begin(); it != msg.items().end(); ++it ) {
00497 #ifdef ELoutputTRACE_LOG
00498 std::cerr << " =:=:=: Item: " << *it << '\n';
00499 #endif
00500 ++item_count;
00501 if ( !msg.is_verbatim() ) {
00502 if ( !insertNewlineAfterHeader && (item_count == 3) ) {
00503
00504 emitToken( *it, true );
00505 } else {
00506 emitToken( *it );
00507 }
00508 } else {
00509 emitToken( *it );
00510 }
00511 }
00512 }
00513 #endif
00514
00515
00516
00517
00518 if ( !msg.is_verbatim() )
00519 {
00520 emitToken("\n%MSG");
00521 }
00522
00523
00524
00525
00526
00527 (*os) << newline;
00528 flush();
00529
00530
00531 #ifdef ELoutputTRACE_LOG
00532 std::cerr << " =:=:=: log(msg) done: \n";
00533 #endif
00534
00535 return true;
00536
00537 }
00538
00539
00540
00541
00542
00543
00544
00545
00546 void ELoutput::emitToken( const ELstring & s, bool nl ) {
00547
00548 #ifdef ELoutput_EMIT_TRACE
00549 std::cerr << "[][][] in emit: charsOnLine is " << charsOnLine << '\n';
00550 std::cerr << "[][][] in emit: s.length() " << s.length() << '\n';
00551 std::cerr << "[][][] in emit: lineLength is " << lineLength << '\n';
00552 #endif
00553
00554 if (s.length() == 0) {
00555 if ( nl ) {
00556 (*os) << newline << std::flush;
00557 charsOnLine = 0;
00558 }
00559 return;
00560 }
00561
00562 char first = s[0];
00563 char second,
00564 last,
00565 last2;
00566 second = (s.length() < 2) ? '\0' : s[1];
00567 last = (s.length() < 2) ? '\0' : s[s.length()-1];
00568 last2 = (s.length() < 3) ? '\0' : s[s.length()-2];
00569
00570
00571
00572 if (preambleMode) {
00573
00574 if ( first == '\n'
00575 || (charsOnLine + static_cast<int>(s.length())) > lineLength ) {
00576 #ifdef ELoutput_EMIT_TRACE
00577 std::cerr << "[][][] in emit: about to << to *os \n";
00578 #endif
00579 #ifdef HEADERS_BROKEN_INTO_LINES_AND_INDENTED
00580
00581 (*os) << newline << indent;
00582 charsOnLine = indent.length();
00583 #else
00584 charsOnLine = 0;
00585 #endif
00586 if (second != ' ') {
00587 (*os) << ' ';
00588 charsOnLine++;
00589 }
00590 if ( first == '\n' ) {
00591 (*os) << s.substr(1);
00592 }
00593 else {
00594 (*os) << s;
00595 }
00596 }
00597 #ifdef ELoutput_EMIT_TRACE
00598 std::cerr << "[][][] in emit: about to << s to *os: " << s << " \n";
00599 #endif
00600 else {
00601 (*os) << s;
00602 }
00603
00604 if (last == '\n' || last2 == '\n') {
00605 (*os) << indent;
00606 if (last != ' ')
00607 (*os) << ' ';
00608 charsOnLine = indent.length() + 1;
00609 }
00610
00611 if ( nl ) { (*os) << newline << std::flush; charsOnLine = 0; }
00612 else { charsOnLine += s.length(); }
00613 }
00614
00615 if (!preambleMode) {
00616 (*os) << s;
00617 }
00618
00619 #ifdef ELoutput_EMIT_TRACE
00620 std::cerr << "[][][] in emit: completed \n";
00621 #endif
00622
00623 }
00624
00625
00626
00627
00628
00629
00630 void ELoutput::includeTime() { wantTimestamp = true; }
00631 void ELoutput::suppressTime() { wantTimestamp = false; }
00632
00633 void ELoutput::includeModule() { wantModule = true; }
00634 void ELoutput::suppressModule() { wantModule = false; }
00635
00636 void ELoutput::includeSubroutine() { wantSubroutine = true; }
00637 void ELoutput::suppressSubroutine() { wantSubroutine = false; }
00638
00639 void ELoutput::includeText() { wantText = true; }
00640 void ELoutput::suppressText() { wantText = false; }
00641
00642 void ELoutput::includeContext() { wantSomeContext = true; }
00643 void ELoutput::suppressContext() { wantSomeContext = false; }
00644
00645 void ELoutput::suppressSerial() { wantSerial = false; }
00646 void ELoutput::includeSerial() { wantSerial = true; }
00647
00648 void ELoutput::useFullContext() { wantFullContext = true; }
00649 void ELoutput::useContext() { wantFullContext = false; }
00650
00651 void ELoutput::separateTime() { wantTimeSeparate = true; }
00652 void ELoutput::attachTime() { wantTimeSeparate = false; }
00653
00654 void ELoutput::separateEpilogue() { wantEpilogueSeparate = true; }
00655 void ELoutput::attachEpilogue() { wantEpilogueSeparate = false; }
00656
00657
00658
00659
00660
00661
00662 void ELoutput::summarization(
00663 const ELstring & fullTitle
00664 , const ELstring & sumLines
00665 ) {
00666 const int titleMaxLength( 40 );
00667
00668
00669
00670 ELstring title( fullTitle, 0, titleMaxLength );
00671 int q = (lineLength - title.length() - 2) / 2;
00672 ELstring line(q, '=');
00673 emitToken( "", true );
00674 emitToken( line );
00675 emitToken( " " );
00676 emitToken( title );
00677 emitToken( " " );
00678 emitToken( line, true );
00679
00680
00681
00682 *os << sumLines;
00683
00684
00685
00686 emitToken( "", true );
00687 emitToken( ELstring(lineLength, '='), true );
00688
00689 }
00690
00691
00692
00693
00694
00695
00696 void ELoutput::changeFile (std::ostream & os_) {
00697 os.reset(&os_, do_nothing_deleter());
00698 emitToken( "\n=======================================================", true );
00699 emitToken( "\nError Log changed to this stream\n" );
00700 ELstring const& ftime = formatTime(time(0));
00701 emitToken( ftime, true );
00702 emitToken( "\n=======================================================\n", true );
00703 }
00704
00705 void ELoutput::changeFile (const ELstring & filename) {
00706 os.reset(new std::ofstream( filename.c_str(), std::ios::app), close_and_delete());
00707 emitToken( "\n=======================================================", true );
00708 emitToken( "\nError Log changed to this file\n" );
00709 ELstring const& ftime = formatTime(time(0));
00710 emitToken( ftime, true );
00711 emitToken( "\n=======================================================\n", true );
00712 }
00713
00714 void ELoutput::flush() {
00715 os->flush();
00716 }
00717
00718
00719
00720
00721
00722 }
00723 }