CMS 3D CMS Logo

ELoutput.cc
Go to the documentation of this file.
1 // ----------------------------------------------------------------------
2 //
3 // ELoutput.cc
4 //
5 //
6 // 7/8/98 mf Created
7 // 6/10/99 jv JV:1 puts a \n after each log using suppressContext()
8 // 6/11/99 jv JV:2 accounts for newline at the beginning and end of
9 // an emitted ELstring
10 // 6/14/99 mf Made the static char* in formatTime into auto so that
11 // ctime(&t) is called each time - corrects the bug of
12 // never changing the first timestamp.
13 // 6/15/99 mf Inserted operator<<(void (*f)(ErrorLog&) to avoid
14 // mystery characters being inserted when users <<
15 // endmsg to an ErrorObj.
16 // 7/2/99 jv Added separate/attachTime, Epilogue, and Serial options
17 // 8/2/99 jv Modified handling of newline in an emmitted ELstring
18 // 2/22/00 mf Changed usage of myDestX to myOutputX. Added
19 // constructor of ELoutput from ELoutputX * to allow for
20 // inheritance.
21 // 6/7/00 web Reflect consolidation of ELdestination/X; consolidate
22 // ELoutput/X; add filterModule() and query logic
23 // 10/4/00 mf excludeModule()
24 // 1/15/01 mf line length control: changed ELoutputLineLen to
25 // the base class lineLen (no longer static const)
26 // 2/13/01 mf Added emitAtStart argument to two constructors
27 // { Enh 001 }.
28 // 4/4/01 mf Simplify filter/exclude logic by useing base class
29 // method thisShouldBeIgnored(). Eliminate
30 // moduleOfinterest and moduleToexclude.
31 // 6/15/01 mf Repaired Bug 005 by explicitly setting all
32 // ELdestination member data appropriately.
33 //10/18/01 mf When epilogue not on separate line, preceed by space
34 // 6/23/03 mf changeFile(), flush()
35 // 4/09/04 mf Add 1 to length in strftime call in formatTime, to
36 // correctly provide the time zone. Had been providing
37 // CST every time.
38 //
39 // 12/xx/06 mf Tailoring to CMS MessageLogger
40 // 1/11/06 mf Eliminate time stamp from starting message
41 // 3/20/06 mf Major formatting change to do no formatting
42 // except the header and line separation.
43 // 4/04/06 mf Move the line feed between header and text
44 // till after the first 3 items (FILE:LINE) for
45 // debug messages.
46 // 6/06/06 mf Verbatim
47 // 6/12/06 mf Set preambleMode true when printing the header
48 //
49 // Change Log
50 //
51 // 1 10/18/06 mf In format_time(): Initialized ts[] with 5 extra
52 // spaces, to cover cases where time zone is more than
53 // 3 characters long
54 //
55 // 2 10/30/06 mf In log(): if severity indicated is SEVERE, do not
56 // impose limits. This is to implement the LogSystem
57 // feature: Those messages are never to be ignored.
58 //
59 // 3 6/11/07 mf In emitToken(): In preamble mode, do not break and indent
60 // even if exceeding nominal line length.
61 //
62 // 4 6/11/07 mf In log(): After the message, add a %MSG on its own line
63 //
64 // 5 3/27/09 mf Properly treat charsOnLine, which had been fouled due to
65 // change 3. In log() and emitToken().
66 //
67 // 6 9/2/10 mf Initialize preambleMode in each ctor, and remove the
68 // unnecessary use of tprm which was preserving a moot
69 // initial value.
70 //
71 // 7 9/30/10 wmtan make formatTime() thread safe by not using statics.
72 //
73 // ----------------------------------------------------------------------
74 
75 
77 
79 
81 
82 // Possible Traces:
83 // #define ELoutputCONSTRUCTOR_TRACE
84 // #define ELoutputTRACE_LOG
85 // #define ELoutput_EMIT_TRACE
86 
87 #include <iostream>
88 #include <fstream>
89 #include <cstring>
90 #include <cassert>
91 
92 namespace edm {
93 namespace service {
94 
95 // ----------------------------------------------------------------------
96 // Useful function:
97 // ----------------------------------------------------------------------
98 
99 
100 static ELstring formatTime( const time_t t ) { // Change log 7
101 
102  static char const dummy[] = "dd-Mon-yyyy hh:mm:ss TZN "; // Change log 7 for length only
103  char ts[sizeof(dummy)]; // Change log 7
104 
105  struct tm timebuf; // Change log 7
106 
107  strftime( ts, sizeof(dummy), "%d-%b-%Y %H:%M:%S %Z", localtime_r(&t, &timebuf) ); // Change log 7
108  // mf 4-9-04
109 
110 #ifdef STRIP_TRAILING_BLANKS_IN_TIMEZONE
111  // strip trailing blanks that would come when the time zone is not as
112  // long as the maximum allowed - probably not worth the time
113  unsigned int b = strlen(ts);
114  while (ts[--b] == ' ') {ts[b] = 0;}
115 #endif
116 
117  ELstring result(ts); // Change log 7
118  return result; // Change log 7
119 } // formatTime()
120 
121 
122 // ----------------------------------------------------------------------
123 // Constructors:
124 // ----------------------------------------------------------------------
125 
127 : ELdestination ( )
128 , os ( &std::cerr, do_nothing_deleter() )
129 , charsOnLine ( 0 )
130 , xid ( )
131 , wantTimestamp ( true )
132 , wantModule ( true )
133 , wantSubroutine ( true )
134 , wantText ( true )
135 , wantSomeContext ( true )
136 , wantSerial ( false )
137 , wantFullContext ( false )
138 , wantTimeSeparate ( false )
139 , wantEpilogueSeparate( false )
140 , preambleMode ( true ) // 006 9/2/10 mf
141 {
142 
143  #ifdef ELoutputCONSTRUCTOR_TRACE
144  std::cerr << "Constructor for ELoutput()\n";
145  #endif
146 
147  emitToken( "\n=================================================", true );
148  emitToken( "\nMessage Log File written by MessageLogger service \n" );
149  emitToken( "\n=================================================\n", true );
150 
151 } // ELoutput()
152 
153 
154 ELoutput::ELoutput( std::ostream & os_ , bool emitAtStart )
155 : ELdestination ( )
156 , os ( &os_, do_nothing_deleter() )
157 , charsOnLine ( 0 )
158 , xid ( )
159 , wantTimestamp ( true )
160 , wantModule ( true )
161 , wantSubroutine ( true )
162 , wantText ( true )
163 , wantSomeContext ( true )
164 , wantSerial ( false )
168 , preambleMode ( true ) // 006 9/2/10 mf
169 {
170 
171  #ifdef ELoutputCONSTRUCTOR_TRACE
172  std::cerr << "Constructor for ELoutput( os )\n";
173  #endif
174 
175  // Enh 001 2/13/01 mf
176  if (emitAtStart) {
177  preambleMode = true;
178  emitToken( "\n=================================================", true );
179  emitToken( "\nMessage Log File written by MessageLogger service \n" );
180  emitToken( "\n=================================================\n", true );
181  }
182 
183 } // ELoutput()
184 
185 
186 ELoutput::ELoutput( const ELstring & fileName, bool emitAtStart )
187 : ELdestination ( )
188 , os ( new std::ofstream( fileName.c_str() , std::ios/*_base*/::app), close_and_delete())
189 , charsOnLine ( 0 )
190 , xid ( )
191 , wantTimestamp ( true )
192 , wantModule ( true )
193 , wantSubroutine ( true )
194 , wantText ( true )
195 , wantSomeContext ( true )
196 , wantSerial ( false )
200 , preambleMode ( true ) // 006 9/2/10 mf
201 {
202 
203  #ifdef ELoutputCONSTRUCTOR_TRACE
204  std::cerr << "Constructor for ELoutput( " << fileName << " )\n";
205  #endif
206 
207  preambleMode = true;
208  if ( os && *os ) {
209  #ifdef ELoutputCONSTRUCTOR_TRACE
210  std::cerr << " Testing if os is owned\n";
211  #endif
212  #ifdef ELoutputCONSTRUCTOR_TRACE
213  std::cerr << " About to do first emit\n";
214  #endif
215  // Enh 001 2/13/01 mf
216  if (emitAtStart) {
217  emitToken( "\n=======================================================",
218  true );
219  emitToken( "\nError Log File " );
220  emitToken( fileName );
221  emitToken( " \n" );
222  }
223  }
224  else {
225  #ifdef ELoutputCONSTRUCTOR_TRACE
226  std::cerr << " Deleting os\n";
227  #endif
228  os.reset(&std::cerr, do_nothing_deleter());
229  #ifdef ELoutputCONSTRUCTOR_TRACE
230  std::cerr << " about to emit to cerr\n";
231  #endif
232  if (emitAtStart) {
233  emitToken( "\n=======================================================",
234  true );
235  emitToken( "\n%MSG** Logging to cerr is being substituted" );
236  emitToken( " for specified log file \"" );
237  emitToken( fileName );
238  emitToken( "\" which could not be opened for write or append.\n" );
239  }
240  }
241  if (emitAtStart) {
242  ELstring const& ftime = formatTime(time(0)); // Change log 7
243  emitToken( ftime, true );
244  emitToken( "\n=======================================================\n",
245  true );
246  }
247  // preambleMode = tprm; removed 9/2/10 mf see change log 6
248 
249  #ifdef ELoutputCONSTRUCTOR_TRACE
250  std::cerr << "Constructor for ELoutput completed.\n";
251  #endif
252 
253 } // ELoutput()
254 
255 
257 : ELdestination ( )
258 , os ( orig.os )
259 , charsOnLine ( orig.charsOnLine )
260 , xid ( orig.xid )
261 , wantTimestamp ( orig.wantTimestamp )
262 , wantModule ( orig.wantModule )
264 , wantText ( orig.wantText )
266 , wantSerial ( orig.wantSerial )
270 , preambleMode ( orig.preambleMode ) // 006 9/2/10 mf
271 {
272 
273  #ifdef ELoutputCONSTRUCTOR_TRACE
274  std::cerr << "Copy constructor for ELoutput\n";
275  #endif
276 
277  // mf 6/15/01 fix of Bug 005
278  threshold = orig.threshold;
280  limits = orig.limits;
281  preamble = orig.preamble;
282  newline = orig.newline;
283  indent = orig.indent;
284  lineLength = orig.lineLength;
285 
289  ignoreThese = orig.ignoreThese;
290 
291 } // ELoutput()
292 
293 
295 
296  #ifdef ELoutputCONSTRUCTOR_TRACE
297  std::cerr << "Destructor for ELoutput\n";
298  #endif
299 
300 } // ~ELoutput()
301 
302 
303 // ----------------------------------------------------------------------
304 // Methods invoked by the ELadministrator:
305 // ----------------------------------------------------------------------
306 
307 //#define THRESHTRACE
308 //#define ELoutputTRACE_LOG
309 
310 bool ELoutput::log( const edm::ErrorObj & msg ) {
311 
312  #ifdef ELoutputTRACE_LOG
313  std::cerr << " =:=:=: Log to an ELoutput \n";
314  #endif
315 
316  xid = msg.xid(); // Save the xid.
317 
318 #ifdef THRESHTRACE
319  std::cerr << " =:=:=: Log to an ELoutput \n"
320  << " severity = " << xid.severity << "\n"
321  << " threshold = " << threshold << "\n"
322  << " id = " << xid.id << "\n";
323 #endif
324 
325  // See if this message is to be acted upon, and add it to limits table
326  // if it was not already present:
327  //
328  if ( xid.severity < threshold ) return false;
330  && (xid.severity < ELsevere) /* change log 2 */ )
331  return false;
332  if ( ! limits.add( xid )
333  && (xid.severity < ELsevere) /* change log 2 */ )
334  return false;
335 
336  #ifdef ELoutputTRACE_LOG
337  std::cerr << " =:=:=: Limits table work done \n";
338  #endif
339 
340  // Output the prologue:
341  //
342  preambleMode = true;
343 
344  if ( !msg.is_verbatim() ) {
345  charsOnLine = 0; // Change log 5
346  emitToken( preamble );
348  emitToken( " " );
349  emitToken( xid.id );
350  emitToken( msg.idOverflow() );
351  emitToken( ": " );
352  }
353 
354  #ifdef ELoutputTRACE_LOG
355  std::cerr << " =:=:=: Prologue done \n";
356  #endif
357  // Output serial number of message:
358  //
359  if ( !msg.is_verbatim() )
360  {
361  if ( wantSerial ) {
362  std::ostringstream s;
363  s << msg.serial();
364  emitToken( "[serial #" + s.str() + ELstring("] ") );
365  }
366  }
367 
368 #ifdef OUTPUT_FORMATTED_ERROR_MESSAGES
369  // Output each item in the message (before the epilogue):
370  //
371  if ( wantText ) {
372  ELlist_string::const_iterator it;
373  for ( it = msg.items().begin(); it != msg.items().end(); ++it ) {
374  #ifdef ELoutputTRACE_LOG
375  std::cerr << " =:=:=: Item: " << *it << '\n';
376  #endif
377  emitToken( *it );
378  }
379  }
380 #endif
381 
382  // Provide further identification:
383  //
384  bool needAspace = true;
385  if ( !msg.is_verbatim() )
386  {
387  if ( wantEpilogueSeparate ) {
388  if ( xid.module.length() + xid.subroutine.length() > 0 ) {
389  emitToken("\n");
390  needAspace = false;
391  }
392  else if ( wantTimestamp && !wantTimeSeparate ) {
393  emitToken("\n");
394  needAspace = false;
395  }
396  }
397  if ( wantModule && (xid.module.length() > 0) ) {
398  if (needAspace) { emitToken(ELstring(" ")); needAspace = false; }
399  emitToken( xid.module + ELstring(" ") );
400  }
401  if ( wantSubroutine && (xid.subroutine.length() > 0) ) {
402  if (needAspace) { emitToken(ELstring(" ")); needAspace = false; }
403  emitToken( xid.subroutine + "()" + ELstring(" ") );
404  }
405  }
406 
407  #ifdef ELoutputTRACE_LOG
408  std::cerr << " =:=:=: Module and Subroutine done \n";
409  #endif
410 
411  // Provide time stamp:
412  //
413  if ( !msg.is_verbatim() )
414  {
415  if ( wantTimestamp ) {
416  if ( wantTimeSeparate ) {
417  emitToken( ELstring("\n") );
418  needAspace = false;
419  }
420  if (needAspace) { emitToken(ELstring(" ")); needAspace = false; }
421  ELstring const& ftime = formatTime(msg.timestamp()); // Change log 7
422  emitToken( ftime + ELstring(" ") );
423  }
424  }
425 
426  #ifdef ELoutputTRACE_LOG
427  std::cerr << " =:=:=: TimeStamp done \n";
428  #endif
429 
430  // Provide the context information:
431  //
432  if ( !msg.is_verbatim() )
433  {
434  if ( wantSomeContext ) {
435  if (needAspace) { emitToken(ELstring(" ")); needAspace = false; }
436  assert(!needAspace);
437  if ( wantFullContext ) {
438  emitToken( msg.context());
439  #ifdef ELoutputTRACE_LOG
440  std::cerr << " =:=:=: fullContext done: \n";
441  #endif
442  } else {
443  emitToken( msg.context());
444  #ifdef ELoutputTRACE_LOG
445  std::cerr << " =:=:=: Context done: \n";
446  #endif
447  }
448  }
449  }
450 
451  // Provide traceback information:
452  //
453 
454  bool insertNewlineAfterHeader = ( msg.xid().severity != ELdebug );
455  // ELdebug is what LogDebug issues
456 
457  if ( !msg.is_verbatim() )
458  {
459  if ( msg.xid().severity >= traceThreshold ) {
460  emitToken( ELstring("\n")
461  , insertNewlineAfterHeader );
462  }
463  else { //else statement added JV:1
464  emitToken("", insertNewlineAfterHeader);
465  }
466  }
467  #ifdef ELoutputTRACE_LOG
468  std::cerr << " =:=:=: Trace routine done: \n";
469  #endif
470 
471 #ifndef OUTPUT_FORMATTED_ERROR_MESSAGES
472  // Finally, output each item in the message:
473  //
474  preambleMode = false;
475  if ( wantText ) {
476  ELlist_string::const_iterator it;
477  int item_count = 0;
478  for ( it = msg.items().begin(); it != msg.items().end(); ++it ) {
479  #ifdef ELoutputTRACE_LOG
480  std::cerr << " =:=:=: Item: " << *it << '\n';
481  #endif
482  ++item_count;
483  if ( !msg.is_verbatim() ) {
484  if ( !insertNewlineAfterHeader && (item_count == 3) ) {
485  // in a LogDebug message, the first 3 items are FILE, :, and LINE
486  emitToken( *it, true );
487  } else {
488  emitToken( *it );
489  }
490  } else {
491  emitToken( *it );
492  }
493  }
494  }
495 #endif
496 
497  // And after the message, add a %MSG on its own line
498  // Change log 4 6/11/07 mf
499 
500  if ( !msg.is_verbatim() )
501  {
502  emitToken("\n%MSG");
503  }
504 
505 
506  // Done; message has been fully processed; separate, flush, and leave
507  //
508 
509  (*os) << newline;
510  flush();
511 
512 
513  #ifdef ELoutputTRACE_LOG
514  std::cerr << " =:=:=: log(msg) done: \n";
515  #endif
516 
517  return true;
518 
519 } // log()
520 
521 
522 // Remainder are from base class.
523 
524 // ----------------------------------------------------------------------
525 // Output methods:
526 // ----------------------------------------------------------------------
527 
528 void ELoutput::emitToken( const ELstring & s, bool nl ) {
529 
530  #ifdef ELoutput_EMIT_TRACE
531  std::cerr << "[][][] in emit: charsOnLine is " << charsOnLine << '\n';
532  std::cerr << "[][][] in emit: s.length() " << s.length() << '\n';
533  std::cerr << "[][][] in emit: lineLength is " << lineLength << '\n';
534  #endif
535 
536  if (s.length() == 0) {
537  if ( nl ) {
538  (*os) << newline << std::flush;
539  charsOnLine = 0;
540  }
541  return;
542  }
543 
544  char first = s[0];
545  char second,
546  last,
547  last2;
548  second = (s.length() < 2) ? '\0' : s[1];
549  last = (s.length() < 2) ? '\0' : s[s.length()-1];
550  last2 = (s.length() < 3) ? '\0' : s[s.length()-2];
551  //checking -2 because the very last char is sometimes a ' ' inserted
552  //by ErrorLog::operator<<
553 
554  if (preambleMode) {
555  //Accounts for newline @ the beginning of the ELstring JV:2
556  if ( first == '\n'
557  || (charsOnLine + static_cast<int>(s.length())) > lineLength ) {
558  #ifdef ELoutput_EMIT_TRACE
559  std::cerr << "[][][] in emit: about to << to *os \n";
560  #endif
561  #ifdef HEADERS_BROKEN_INTO_LINES_AND_INDENTED
562  // Change log 3: Removed this code 6/11/07 mf
563  (*os) << newline << indent;
564  charsOnLine = indent.length();
565  #else
566  charsOnLine = 0; // Change log 5
567  #endif
568  if (second != ' ') {
569  (*os) << ' ';
570  charsOnLine++;
571  }
572  if ( first == '\n' ) {
573  (*os) << s.substr(1);
574  }
575  else {
576  (*os) << s;
577  }
578  }
579  #ifdef ELoutput_EMIT_TRACE
580  std::cerr << "[][][] in emit: about to << s to *os: " << s << " \n";
581  #endif
582  else {
583  (*os) << s;
584  }
585 
586  if (last == '\n' || last2 == '\n') { //accounts for newline @ end $$ JV:2
587  (*os) << indent; //of the ELstring
588  if (last != ' ')
589  (*os) << ' ';
590  charsOnLine = indent.length() + 1;
591  }
592 
593  if ( nl ) { (*os) << newline << std::flush; charsOnLine = 0; }
594  else { charsOnLine += s.length(); }
595 }
596 
597  if (!preambleMode) {
598  (*os) << s;
599  }
600 
601  #ifdef ELoutput_EMIT_TRACE
602  std::cerr << "[][][] in emit: completed \n";
603  #endif
604 
605 } // emitToken()
606 
607 
608 // ----------------------------------------------------------------------
609 // Methods controlling message formatting:
610 // ----------------------------------------------------------------------
611 
614 
617 
620 
621 void ELoutput::includeText() { wantText = true; }
622 void ELoutput::suppressText() { wantText = false; }
623 
626 
629 
632 
635 
638 
639 
640 // ----------------------------------------------------------------------
641 // Changing ostream:
642 // ----------------------------------------------------------------------
643 
644 void ELoutput::changeFile (std::ostream & os_) {
645  os.reset(&os_, do_nothing_deleter());
646  emitToken( "\n=======================================================", true );
647  emitToken( "\nError Log changed to this stream\n" );
648  ELstring const& ftime = formatTime(time(0)); // Change log 7
649  emitToken( ftime, true );
650  emitToken( "\n=======================================================\n", true );
651 }
652 
654  os.reset(new std::ofstream( filename.c_str(), std::ios/*_base*/::app), close_and_delete());
655  emitToken( "\n=======================================================", true );
656  emitToken( "\nError Log changed to this file\n" );
657  ELstring const& ftime = formatTime(time(0)); // Change log 7
658  emitToken( ftime, true );
659  emitToken( "\n=======================================================\n", true );
660 }
661 
663  os->flush();
664 }
665 
666 
667 // ----------------------------------------------------------------------
668 
669 
670 } // end of namespace service
671 } // end of namespace edm
ELslProxy< ELdebugGen > const ELdebug
ELseverityLevel traceThreshold
ELseverityLevel severity
Definition: ELextendedID.h:35
const ELstring & idOverflow() const
Definition: ErrorObj.cc:148
std::unordered_set< std::string > ignoreThese
virtual void suppressText() override
Definition: ELoutput.cc:622
time_t timestamp() const
Definition: ErrorObj.cc:149
virtual bool thisShouldBeIgnored(const ELstring &s) const
virtual void separateEpilogue() override
Definition: ELoutput.cc:636
edm::ELextendedID xid
Definition: ELoutput.h:103
U second(std::pair< T, U > const &p)
const ELstring getSymbol() const
static ELstring formatTime(const time_t t)
Definition: ELoutput.cc:100
const ELextendedID & xid() const
Definition: ErrorObj.cc:147
virtual void flush() override
Definition: ELoutput.cc:662
virtual void includeModule() override
Definition: ELoutput.cc:615
virtual void includeSubroutine() override
Definition: ELoutput.cc:618
bool add(const ELextendedID &xid)
virtual void includeContext() override
Definition: ELoutput.cc:624
virtual void attachEpilogue() override
Definition: ELoutput.cc:637
virtual void suppressSerial() override
Definition: ELoutput.cc:627
int serial() const
Definition: ErrorObj.cc:146
std::unordered_set< std::string > respondToThese
ELstring subroutine
Definition: ELextendedID.h:37
virtual void separateTime() override
Definition: ELoutput.cc:633
virtual void suppressTime() override
Definition: ELoutput.cc:613
std::shared_ptr< std::ostream > os
Definition: ELoutput.h:101
const ELlist_string & items() const
Definition: ErrorObj.cc:150
ELslProxy< ELsevereGen > const ELsevere
virtual void useFullContext() override
Definition: ELoutput.cc:630
virtual void includeSerial() override
Definition: ELoutput.cc:628
void emitToken(const ELstring &s, bool nl=false)
Definition: ELoutput.cc:528
double b
Definition: hdecay.h:120
virtual void attachTime() override
Definition: ELoutput.cc:634
virtual void suppressModule() override
Definition: ELoutput.cc:616
virtual void includeTime() override
Definition: ELoutput.cc:612
virtual void useContext() override
Definition: ELoutput.cc:631
HLT enums.
virtual bool log(const edm::ErrorObj &msg) override
Definition: ELoutput.cc:310
T first(std::pair< T, U > const &p)
bool is_verbatim() const
Definition: ErrorObj.cc:152
virtual void suppressContext() override
Definition: ELoutput.cc:625
std::string ELstring
Definition: ELstring.h:26
virtual void changeFile(std::ostream &os) override
Definition: ELoutput.cc:644
ELstring context() const
Definition: ErrorObj.cc:154
virtual void includeText() override
Definition: ELoutput.cc:621
virtual void suppressSubroutine() override
Definition: ELoutput.cc:619