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 
76 
78 
80 
81 // Possible Traces:
82 // #define ELoutputCONSTRUCTOR_TRACE
83 // #define ELoutputTRACE_LOG
84 // #define ELoutput_EMIT_TRACE
85 
86 #include <iostream>
87 #include <fstream>
88 #include <cstring>
89 #include <cassert>
90 
91 namespace {
92  // ----------------------------------------------------------------------
93  // Useful function:
94  // ----------------------------------------------------------------------
95 
96  std::string formatTime(const time_t t) { // Change log 7
97 
98  constexpr char dummy[] = "dd-Mon-yyyy hh:mm:ss TZN "; // Change log 7 for length only
99  char ts[sizeof(dummy)]; // Change log 7
100 
101  struct tm timebuf; // Change log 7
102 
103  strftime(ts, sizeof(dummy), "%d-%b-%Y %H:%M:%S %Z", localtime_r(&t, &timebuf)); // Change log 7
104  // mf 4-9-04
105 
106 #ifdef STRIP_TRAILING_BLANKS_IN_TIMEZONE
107  // strip trailing blanks that would come when the time zone is not as
108  // long as the maximum allowed - probably not worth the time
109  unsigned int b = strlen(ts);
110  while (ts[--b] == ' ') {
111  ts[b] = 0;
112  }
113 #endif
114 
115  return std::string(ts); // Change log 7
116  } // formatTime()
117 } // namespace
118 
119 using namespace edm::messagelogger;
120 namespace edm {
121  namespace service {
122  // ----------------------------------------------------------------------
123  // Constructors:
124  // ----------------------------------------------------------------------
125 
126  ELoutput::ELoutput()
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 #ifdef ELoutputCONSTRUCTOR_TRACE
143  std::cerr << "Constructor for ELoutput()\n";
144 #endif
145 
146  emitToken("\n=================================================", true);
147  emitToken("\nMessage Log File written by MessageLogger service \n");
148  emitToken("\n=================================================\n", true);
149 
150  } // ELoutput()
151 
152  ELoutput::ELoutput(std::ostream& os_, bool emitAtStart)
153  : ELdestination(),
154  os(&os_, do_nothing_deleter()),
155  charsOnLine(0),
156  xid(),
157  wantTimestamp(true),
158  wantModule(true),
159  wantSubroutine(true),
160  wantText(true),
161  wantSomeContext(true),
162  wantSerial(false),
163  wantFullContext(false),
164  wantTimeSeparate(false),
165  wantEpilogueSeparate(false),
166  preambleMode(true) // 006 9/2/10 mf
167  {
168 #ifdef ELoutputCONSTRUCTOR_TRACE
169  std::cerr << "Constructor for ELoutput( os )\n";
170 #endif
171 
172  // Enh 001 2/13/01 mf
173  if (emitAtStart) {
174  preambleMode = true;
175  emitToken("\n=================================================", true);
176  emitToken("\nMessage Log File written by MessageLogger service \n");
177  emitToken("\n=================================================\n", true);
178  }
179 
180  } // ELoutput()
181 
182  ELoutput::ELoutput(const std::string& fileName, bool emitAtStart)
183  : ELdestination(),
184  os(new std::ofstream(fileName.c_str(), std::ios /*_base*/ ::app), close_and_delete()),
185  charsOnLine(0),
186  xid(),
187  wantTimestamp(true),
188  wantModule(true),
189  wantSubroutine(true),
190  wantText(true),
191  wantSomeContext(true),
192  wantSerial(false),
193  wantFullContext(false),
194  wantTimeSeparate(false),
195  wantEpilogueSeparate(false),
196  preambleMode(true) // 006 9/2/10 mf
197  {
198 #ifdef ELoutputCONSTRUCTOR_TRACE
199  std::cerr << "Constructor for ELoutput( " << fileName << " )\n";
200 #endif
201 
202  preambleMode = true;
203  if (os && *os) {
204 #ifdef ELoutputCONSTRUCTOR_TRACE
205  std::cerr << " Testing if os is owned\n";
206 #endif
207 #ifdef ELoutputCONSTRUCTOR_TRACE
208  std::cerr << " About to do first emit\n";
209 #endif
210  // Enh 001 2/13/01 mf
211  if (emitAtStart) {
212  emitToken("\n=======================================================", true);
213  emitToken("\nError Log File ");
215  emitToken(" \n");
216  }
217  } else {
218 #ifdef ELoutputCONSTRUCTOR_TRACE
219  std::cerr << " Deleting os\n";
220 #endif
221  os.reset(&std::cerr, do_nothing_deleter());
222 #ifdef ELoutputCONSTRUCTOR_TRACE
223  std::cerr << " about to emit to cerr\n";
224 #endif
225  if (emitAtStart) {
226  emitToken("\n=======================================================", true);
227  emitToken("\n%MSG** Logging to cerr is being substituted");
228  emitToken(" for specified log file \"");
230  emitToken("\" which could not be opened for write or append.\n");
231  }
232  }
233  if (emitAtStart) {
234  std::string const& ftime = formatTime(time(nullptr)); // Change log 7
235  emitToken(ftime, true);
236  emitToken("\n=======================================================\n", true);
237  }
238  // preambleMode = tprm; removed 9/2/10 mf see change log 6
239 
240 #ifdef ELoutputCONSTRUCTOR_TRACE
241  std::cerr << "Constructor for ELoutput completed.\n";
242 #endif
243 
244  } // ELoutput()
245 
247  : ELdestination(),
248  os(orig.os),
249  charsOnLine(orig.charsOnLine),
250  xid(orig.xid),
251  wantTimestamp(orig.wantTimestamp),
252  wantModule(orig.wantModule),
253  wantSubroutine(orig.wantSubroutine),
254  wantText(orig.wantText),
255  wantSomeContext(orig.wantSomeContext),
256  wantSerial(orig.wantSerial),
257  wantFullContext(orig.wantFullContext),
258  wantTimeSeparate(orig.wantTimeSeparate),
259  wantEpilogueSeparate(orig.wantEpilogueSeparate),
260  preambleMode(orig.preambleMode) // 006 9/2/10 mf
261  {
262 #ifdef ELoutputCONSTRUCTOR_TRACE
263  std::cerr << "Copy constructor for ELoutput\n";
264 #endif
265 
266  // mf 6/15/01 fix of Bug 005
267  threshold = orig.threshold;
268  traceThreshold = orig.traceThreshold;
269  limits = orig.limits;
270  preamble = orig.preamble;
271  newline = orig.newline;
272  indent = orig.indent;
273  lineLength = orig.lineLength;
274 
275  ignoreMostModules = orig.ignoreMostModules;
276  respondToThese = orig.respondToThese;
277  respondToMostModules = orig.respondToMostModules;
278  ignoreThese = orig.ignoreThese;
279 
280  } // ELoutput()
281 
283 #ifdef ELoutputCONSTRUCTOR_TRACE
284  std::cerr << "Destructor for ELoutput\n";
285 #endif
286 
287  } // ~ELoutput()
288 
289  // ----------------------------------------------------------------------
290  // Methods invoked by the ELadministrator:
291  // ----------------------------------------------------------------------
292 
293  //#define THRESHTRACE
294  //#define ELoutputTRACE_LOG
295 
297 #ifdef ELoutputTRACE_LOG
298  std::cerr << " =:=:=: Log to an ELoutput \n";
299 #endif
300 
301  xid = msg.xid(); // Save the xid.
302 
303 #ifdef THRESHTRACE
304  std::cerr << " =:=:=: Log to an ELoutput \n"
305  << " severity = " << xid.severity << "\n"
306  << " threshold = " << threshold << "\n"
307  << " id = " << xid.id << "\n";
308 #endif
309 
310  // See if this message is to be acted upon, and add it to limits table
311  // if it was not already present:
312  //
313  if (xid.severity < threshold)
314  return false;
315  if (thisShouldBeIgnored(xid.module) && (xid.severity < ELsevere) /* change log 2 */)
316  return false;
317  if (!limits.add(xid) && (xid.severity < ELsevere) /* change log 2 */)
318  return false;
319 
320 #ifdef ELoutputTRACE_LOG
321  std::cerr << " =:=:=: Limits table work done \n";
322 #endif
323 
324  // Output the prologue:
325  //
326  preambleMode = true;
327 
328  if (!msg.is_verbatim()) {
329  charsOnLine = 0; // Change log 5
332  emitToken(" ");
333  emitToken(xid.id);
334  emitToken(msg.idOverflow());
335  emitToken(": ");
336  }
337 
338 #ifdef ELoutputTRACE_LOG
339  std::cerr << " =:=:=: Prologue done \n";
340 #endif
341  // Output serial number of message:
342  //
343  if (!msg.is_verbatim()) {
344  if (wantSerial) {
345  std::ostringstream s;
346  s << msg.serial();
347  emitToken("[serial #" + s.str() + "] ");
348  }
349  }
350 
351 #ifdef OUTPUT_FORMATTED_ERROR_MESSAGES
352  // Output each item in the message (before the epilogue):
353  //
354  if (wantText) {
355  ELlist_string::const_iterator it;
356  for (it = msg.items().begin(); it != msg.items().end(); ++it) {
357 #ifdef ELoutputTRACE_LOG
358  std::cerr << " =:=:=: Item: " << *it << '\n';
359 #endif
360  emitToken(*it);
361  }
362  }
363 #endif
364 
365  // Provide further identification:
366  //
367  bool needAspace = true;
368  if (!msg.is_verbatim()) {
369  if (wantEpilogueSeparate) {
370  if (xid.module.length() + xid.subroutine.length() > 0) {
371  emitToken("\n");
372  needAspace = false;
373  } else if (wantTimestamp && !wantTimeSeparate) {
374  emitToken("\n");
375  needAspace = false;
376  }
377  }
378  if (wantModule && (xid.module.length() > 0)) {
379  if (needAspace) {
380  emitToken(" ");
381  needAspace = false;
382  }
383  emitToken(xid.module + " ");
384  }
385  if (wantSubroutine && (xid.subroutine.length() > 0)) {
386  if (needAspace) {
387  emitToken(" ");
388  needAspace = false;
389  }
390  emitToken(xid.subroutine + "() ");
391  }
392  }
393 
394 #ifdef ELoutputTRACE_LOG
395  std::cerr << " =:=:=: Module and Subroutine done \n";
396 #endif
397 
398  // Provide time stamp:
399  //
400  if (!msg.is_verbatim()) {
401  if (wantTimestamp) {
402  if (wantTimeSeparate) {
403  emitToken("\n");
404  needAspace = false;
405  }
406  if (needAspace) {
407  emitToken(" ");
408  needAspace = false;
409  }
410  std::string const& ftime = formatTime(msg.timestamp()); // Change log 7
411  emitToken(ftime + " ");
412  }
413  }
414 
415 #ifdef ELoutputTRACE_LOG
416  std::cerr << " =:=:=: TimeStamp done \n";
417 #endif
418 
419  // Provide the context information:
420  //
421  if (!msg.is_verbatim()) {
422  if (wantSomeContext) {
423  if (needAspace) {
424  emitToken(" ");
425  needAspace = false;
426  }
427  assert(!needAspace);
428  if (wantFullContext) {
429  emitToken(msg.context());
430 #ifdef ELoutputTRACE_LOG
431  std::cerr << " =:=:=: fullContext done: \n";
432 #endif
433  } else {
434  emitToken(msg.context());
435 #ifdef ELoutputTRACE_LOG
436  std::cerr << " =:=:=: Context done: \n";
437 #endif
438  }
439  }
440  }
441 
442  // Provide traceback information:
443  //
444 
445  bool insertNewlineAfterHeader = (msg.xid().severity != ELdebug);
446  // ELdebug is what LogDebug issues
447 
448  if (!msg.is_verbatim()) {
449  if (msg.xid().severity >= traceThreshold) {
450  emitToken("\n", insertNewlineAfterHeader);
451  } else { //else statement added JV:1
452  emitToken("", insertNewlineAfterHeader);
453  }
454  }
455 #ifdef ELoutputTRACE_LOG
456  std::cerr << " =:=:=: Trace routine done: \n";
457 #endif
458 
459 #ifndef OUTPUT_FORMATTED_ERROR_MESSAGES
460  // Finally, output each item in the message:
461  //
462  preambleMode = false;
463  if (wantText) {
464  ELlist_string::const_iterator it;
465  int item_count = 0;
466  for (it = msg.items().begin(); it != msg.items().end(); ++it) {
467 #ifdef ELoutputTRACE_LOG
468  std::cerr << " =:=:=: Item: " << *it << '\n';
469 #endif
470  ++item_count;
471  if (!msg.is_verbatim()) {
472  if (!insertNewlineAfterHeader && (item_count == 3)) {
473  // in a LogDebug message, the first 3 items are FILE, :, and LINE
474  emitToken(*it, true);
475  } else {
476  emitToken(*it);
477  }
478  } else {
479  emitToken(*it);
480  }
481  }
482  }
483 #endif
484 
485  // And after the message, add a %MSG on its own line
486  // Change log 4 6/11/07 mf
487 
488  if (!msg.is_verbatim()) {
489  emitToken("\n%MSG");
490  }
491 
492  // Done; message has been fully processed; separate, flush, and leave
493  //
494 
495  (*os) << newline;
496  flush();
497 
498 #ifdef ELoutputTRACE_LOG
499  std::cerr << " =:=:=: log(msg) done: \n";
500 #endif
501 
502  return true;
503 
504  } // log()
505 
506  // Remainder are from base class.
507 
508  // ----------------------------------------------------------------------
509  // Output methods:
510  // ----------------------------------------------------------------------
511 
512  void ELoutput::emitToken(std::string_view s, bool nl) {
513 #ifdef ELoutput_EMIT_TRACE
514  std::cerr << "[][][] in emit: charsOnLine is " << charsOnLine << '\n';
515  std::cerr << "[][][] in emit: s.length() " << s.length() << '\n';
516  std::cerr << "[][][] in emit: lineLength is " << lineLength << '\n';
517 #endif
518 
519  if (s.length() == 0) {
520  if (nl) {
521  (*os) << newline << std::flush;
522  charsOnLine = 0;
523  }
524  return;
525  }
526 
527  char first = s[0];
528  char second, last, last2;
529  second = (s.length() < 2) ? '\0' : s[1];
530  last = (s.length() < 2) ? '\0' : s[s.length() - 1];
531  last2 = (s.length() < 3) ? '\0' : s[s.length() - 2];
532  //checking -2 because the very last char is sometimes a ' ' inserted
533  //by ErrorLog::operator<<
534 
535  if (preambleMode) {
536  //Accounts for newline @ the beginning of the ELstring JV:2
537  if (first == '\n' || (charsOnLine + static_cast<int>(s.length())) > lineLength) {
538 #ifdef ELoutput_EMIT_TRACE
539  std::cerr << "[][][] in emit: about to << to *os \n";
540 #endif
541 #ifdef HEADERS_BROKEN_INTO_LINES_AND_INDENTED
542  // Change log 3: Removed this code 6/11/07 mf
543  (*os) << newline << indent;
544  charsOnLine = indent.length();
545 #else
546  charsOnLine = 0; // Change log 5
547 #endif
548  if (second != ' ') {
549  (*os) << ' ';
550  charsOnLine++;
551  }
552  if (first == '\n') {
553  (*os) << s.substr(1);
554  } else {
555  (*os) << s;
556  }
557  }
558 #ifdef ELoutput_EMIT_TRACE
559  std::cerr << "[][][] in emit: about to << s to *os: " << s << " \n";
560 #endif
561  else {
562  (*os) << s;
563  }
564 
565  if (last == '\n' || last2 == '\n') { //accounts for newline @ end $$ JV:2
566  (*os) << indent; //of the ELstring
567  if (last != ' ')
568  (*os) << ' ';
569  charsOnLine = indent.length() + 1;
570  }
571 
572  if (nl) {
573  (*os) << newline << std::flush;
574  charsOnLine = 0;
575  } else {
576  charsOnLine += s.length();
577  }
578  }
579 
580  if (!preambleMode) {
581  (*os) << s;
582  }
583 
584 #ifdef ELoutput_EMIT_TRACE
585  std::cerr << "[][][] in emit: completed \n";
586 #endif
587 
588  } // emitToken()
589 
590  // ----------------------------------------------------------------------
591  // Methods controlling message formatting:
592  // ----------------------------------------------------------------------
593 
596 
599 
602 
603  void ELoutput::includeText() { wantText = true; }
604  void ELoutput::suppressText() { wantText = false; }
605 
608 
611 
614 
617 
620 
621  // ----------------------------------------------------------------------
622  // Changing ostream:
623  // ----------------------------------------------------------------------
624 
625  void ELoutput::changeFile(std::ostream& os_) {
626  os.reset(&os_, do_nothing_deleter());
627  emitToken("\n=======================================================", true);
628  emitToken("\nError Log changed to this stream\n");
629  std::string const& ftime = formatTime(time(nullptr)); // Change log 7
630  emitToken(ftime, true);
631  emitToken("\n=======================================================\n", true);
632  }
633 
635  os.reset(new std::ofstream(filename.c_str(), std::ios /*_base*/ ::app), close_and_delete());
636  emitToken("\n=======================================================", true);
637  emitToken("\nError Log changed to this file\n");
638  std::string const& ftime = formatTime(time(nullptr)); // Change log 7
639  emitToken(ftime, true);
640  emitToken("\n=======================================================\n", true);
641  }
642 
643  void ELoutput::flush() { os->flush(); }
644 
645  // ----------------------------------------------------------------------
646 
647  } // end of namespace service
648 } // end of namespace edm
messagelogger::ELseverityLevel severity
Definition: ELextendedID.h:30
std::unordered_set< std::string > ignoreThese
void suppressText() override
Definition: ELoutput.cc:604
~ELoutput() override
Definition: ELoutput.cc:282
void separateEpilogue() override
Definition: ELoutput.cc:618
assert(be >=bs)
edm::ELextendedID xid
Definition: ELoutput.h:97
constexpr const ELseverityLevel ELsevere
U second(std::pair< T, U > const &p)
std::string module
Definition: ELextendedID.h:31
void flush() override
Definition: ELoutput.cc:643
void includeModule() override
Definition: ELoutput.cc:597
void includeSubroutine() override
Definition: ELoutput.cc:600
bool add(const ELextendedID &xid)
void includeContext() override
Definition: ELoutput.cc:606
void attachEpilogue() override
Definition: ELoutput.cc:619
void suppressSerial() override
Definition: ELoutput.cc:609
std::unordered_set< std::string > respondToThese
void emitToken(std::string_view s, bool nl=false)
Definition: ELoutput.cc:512
void separateTime() override
Definition: ELoutput.cc:615
void suppressTime() override
Definition: ELoutput.cc:595
std::shared_ptr< std::ostream > os
Definition: ELoutput.h:95
std::string id
Definition: ELextendedID.h:29
void useFullContext() override
Definition: ELoutput.cc:612
void includeSerial() override
Definition: ELoutput.cc:610
double b
Definition: hdecay.h:118
void attachTime() override
Definition: ELoutput.cc:616
void suppressModule() override
Definition: ELoutput.cc:598
tuple msg
Definition: mps_check.py:285
std::string subroutine
Definition: ELextendedID.h:32
void includeTime() override
Definition: ELoutput.cc:594
void useContext() override
Definition: ELoutput.cc:613
HLT enums.
bool log(const edm::ErrorObj &msg) override
Definition: ELoutput.cc:296
virtual bool thisShouldBeIgnored(std::string const &s) const
messagelogger::ELseverityLevel traceThreshold
messagelogger::ELseverityLevel threshold
T first(std::pair< T, U > const &p)
void suppressContext() override
Definition: ELoutput.cc:607
constexpr const ELseverityLevel ELdebug
void changeFile(std::ostream &os) override
Definition: ELoutput.cc:625
void includeText() override
Definition: ELoutput.cc:603
void suppressSubroutine() override
Definition: ELoutput.cc:601
const std::string & getSymbol() const