File indexing completed on 2024-09-07 04:36:25
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075 #include "FWCore/MessageService/src/ELoutput.h"
0076
0077 #include "FWCore/MessageLogger/interface/ErrorObj.h"
0078
0079 #include "FWCore/Utilities/interface/do_nothing_deleter.h"
0080
0081
0082
0083
0084
0085
0086 #include <iostream>
0087 #include <fstream>
0088 #include <cstring>
0089 #include <cassert>
0090
0091 namespace {
0092
0093
0094
0095
0096 std::string formatTime(const time_t t) {
0097
0098 constexpr char dummy[] = "dd-Mon-yyyy hh:mm:ss TZN ";
0099 char ts[sizeof(dummy)];
0100
0101 struct tm timebuf;
0102
0103 strftime(ts, sizeof(dummy), "%d-%b-%Y %H:%M:%S %Z", localtime_r(&t, &timebuf));
0104
0105
0106 #ifdef STRIP_TRAILING_BLANKS_IN_TIMEZONE
0107
0108
0109 unsigned int b = strlen(ts);
0110 while (ts[--b] == ' ') {
0111 ts[b] = 0;
0112 }
0113 #endif
0114
0115 return std::string(ts);
0116 }
0117 }
0118
0119 using namespace edm::messagelogger;
0120 namespace edm {
0121 namespace service {
0122
0123
0124
0125
0126 ELoutput::ELoutput()
0127 : ELdestination(),
0128 os(&std::cerr, do_nothing_deleter()),
0129 charsOnLine(0),
0130 xid(),
0131 wantTimestamp(true),
0132 wantModule(true),
0133 wantSubroutine(true),
0134 wantText(true),
0135 wantSomeContext(true),
0136 wantSerial(false),
0137 wantFullContext(false),
0138 wantTimeSeparate(false),
0139 wantEpilogueSeparate(false),
0140 preambleMode(true)
0141 {
0142 #ifdef ELoutputCONSTRUCTOR_TRACE
0143 std::cerr << "Constructor for ELoutput()\n";
0144 #endif
0145
0146 emitToken("\n=================================================", true);
0147 emitToken("\nMessage Log File written by MessageLogger service \n");
0148 emitToken("\n=================================================\n", true);
0149
0150 }
0151
0152 ELoutput::ELoutput(std::ostream& os_, bool emitAtStart)
0153 : ELdestination(),
0154 os(&os_, do_nothing_deleter()),
0155 charsOnLine(0),
0156 xid(),
0157 wantTimestamp(true),
0158 wantModule(true),
0159 wantSubroutine(true),
0160 wantText(true),
0161 wantSomeContext(true),
0162 wantSerial(false),
0163 wantFullContext(false),
0164 wantTimeSeparate(false),
0165 wantEpilogueSeparate(false),
0166 preambleMode(true)
0167 {
0168 #ifdef ELoutputCONSTRUCTOR_TRACE
0169 std::cerr << "Constructor for ELoutput( os )\n";
0170 #endif
0171
0172
0173 if (emitAtStart) {
0174 preambleMode = true;
0175 emitToken("\n=================================================", true);
0176 emitToken("\nMessage Log File written by MessageLogger service \n");
0177 emitToken("\n=================================================\n", true);
0178 }
0179
0180 }
0181
0182 ELoutput::ELoutput(const std::string& fileName, bool emitAtStart)
0183 : ELdestination(),
0184 os(new std::ofstream(fileName.c_str(), std::ios ::app), close_and_delete()),
0185 charsOnLine(0),
0186 xid(),
0187 wantTimestamp(true),
0188 wantModule(true),
0189 wantSubroutine(true),
0190 wantText(true),
0191 wantSomeContext(true),
0192 wantSerial(false),
0193 wantFullContext(false),
0194 wantTimeSeparate(false),
0195 wantEpilogueSeparate(false),
0196 preambleMode(true)
0197 {
0198 #ifdef ELoutputCONSTRUCTOR_TRACE
0199 std::cerr << "Constructor for ELoutput( " << fileName << " )\n";
0200 #endif
0201
0202 preambleMode = true;
0203 if (os && *os) {
0204 #ifdef ELoutputCONSTRUCTOR_TRACE
0205 std::cerr << " Testing if os is owned\n";
0206 #endif
0207 #ifdef ELoutputCONSTRUCTOR_TRACE
0208 std::cerr << " About to do first emit\n";
0209 #endif
0210
0211 if (emitAtStart) {
0212 emitToken("\n=======================================================", true);
0213 emitToken("\nError Log File ");
0214 emitToken(fileName);
0215 emitToken(" \n");
0216 }
0217 } else {
0218 #ifdef ELoutputCONSTRUCTOR_TRACE
0219 std::cerr << " Deleting os\n";
0220 #endif
0221 os.reset(&std::cerr, do_nothing_deleter());
0222 #ifdef ELoutputCONSTRUCTOR_TRACE
0223 std::cerr << " about to emit to cerr\n";
0224 #endif
0225 if (emitAtStart) {
0226 emitToken("\n=======================================================", true);
0227 emitToken("\n%MSG** Logging to cerr is being substituted");
0228 emitToken(" for specified log file \"");
0229 emitToken(fileName);
0230 emitToken("\" which could not be opened for write or append.\n");
0231 }
0232 }
0233 if (emitAtStart) {
0234 std::string const& ftime = formatTime(time(nullptr));
0235 emitToken(ftime, true);
0236 emitToken("\n=======================================================\n", true);
0237 }
0238
0239
0240 #ifdef ELoutputCONSTRUCTOR_TRACE
0241 std::cerr << "Constructor for ELoutput completed.\n";
0242 #endif
0243
0244 }
0245
0246 ELoutput::ELoutput(const ELoutput& orig)
0247 : ELdestination(),
0248 os(orig.os),
0249 charsOnLine(orig.charsOnLine),
0250 xid(orig.xid),
0251 wantTimestamp(orig.wantTimestamp),
0252 wantModule(orig.wantModule),
0253 wantSubroutine(orig.wantSubroutine),
0254 wantText(orig.wantText),
0255 wantSomeContext(orig.wantSomeContext),
0256 wantSerial(orig.wantSerial),
0257 wantFullContext(orig.wantFullContext),
0258 wantTimeSeparate(orig.wantTimeSeparate),
0259 wantEpilogueSeparate(orig.wantEpilogueSeparate),
0260 preambleMode(orig.preambleMode)
0261 {
0262 #ifdef ELoutputCONSTRUCTOR_TRACE
0263 std::cerr << "Copy constructor for ELoutput\n";
0264 #endif
0265
0266
0267 threshold = orig.threshold;
0268 traceThreshold = orig.traceThreshold;
0269 limits = orig.limits;
0270 preamble = orig.preamble;
0271 newline = orig.newline;
0272 indent = orig.indent;
0273 lineLength = orig.lineLength;
0274
0275 ignoreMostModules = orig.ignoreMostModules;
0276 respondToThese = orig.respondToThese;
0277 respondToMostModules = orig.respondToMostModules;
0278 ignoreThese = orig.ignoreThese;
0279
0280 }
0281
0282 ELoutput::~ELoutput() {
0283 #ifdef ELoutputCONSTRUCTOR_TRACE
0284 std::cerr << "Destructor for ELoutput\n";
0285 #endif
0286
0287 }
0288
0289
0290
0291
0292
0293
0294
0295
0296 bool ELoutput::log(const edm::ErrorObj& msg) {
0297 #ifdef ELoutputTRACE_LOG
0298 std::cerr << " =:=:=: Log to an ELoutput \n";
0299 #endif
0300
0301 xid = msg.xid();
0302
0303 #ifdef THRESHTRACE
0304 std::cerr << " =:=:=: Log to an ELoutput \n"
0305 << " severity = " << xid.severity << "\n"
0306 << " threshold = " << threshold << "\n"
0307 << " id = " << xid.id << "\n";
0308 #endif
0309
0310
0311
0312
0313 if (xid.severity < threshold)
0314 return false;
0315 if (thisShouldBeIgnored(xid.module) && (xid.severity < ELsevere) )
0316 return false;
0317 if (!limits.add(xid) && (xid.severity < ELsevere) )
0318 return false;
0319
0320 #ifdef ELoutputTRACE_LOG
0321 std::cerr << " =:=:=: Limits table work done \n";
0322 #endif
0323
0324
0325
0326 preambleMode = true;
0327
0328 if (!msg.is_verbatim()) {
0329 charsOnLine = 0;
0330 emitToken(preamble);
0331 emitToken(xid.severity.getSymbol());
0332 emitToken(" ");
0333 emitToken(xid.id);
0334 emitToken(msg.idOverflow());
0335 emitToken(": ");
0336 }
0337
0338 #ifdef ELoutputTRACE_LOG
0339 std::cerr << " =:=:=: Prologue done \n";
0340 #endif
0341
0342
0343 if (!msg.is_verbatim()) {
0344 if (wantSerial) {
0345 std::ostringstream s;
0346 s << msg.serial();
0347 emitToken("[serial #" + s.str() + "] ");
0348 }
0349 }
0350
0351 #ifdef OUTPUT_FORMATTED_ERROR_MESSAGES
0352
0353
0354 if (wantText) {
0355 ELlist_string::const_iterator it;
0356 for (it = msg.items().begin(); it != msg.items().end(); ++it) {
0357 #ifdef ELoutputTRACE_LOG
0358 std::cerr << " =:=:=: Item: " << *it << '\n';
0359 #endif
0360 emitToken(*it);
0361 }
0362 }
0363 #endif
0364
0365
0366
0367 bool needAspace = true;
0368 if (!msg.is_verbatim()) {
0369 if (wantEpilogueSeparate) {
0370 if (xid.module.length() + xid.subroutine.length() > 0) {
0371 emitToken("\n");
0372 needAspace = false;
0373 } else if (wantTimestamp && !wantTimeSeparate) {
0374 emitToken("\n");
0375 needAspace = false;
0376 }
0377 }
0378 if (wantModule && (xid.module.length() > 0)) {
0379 if (needAspace) {
0380 emitToken(" ");
0381 needAspace = false;
0382 }
0383 emitToken(xid.module + " ");
0384 }
0385 if (wantSubroutine && (xid.subroutine.length() > 0)) {
0386 if (needAspace) {
0387 emitToken(" ");
0388 needAspace = false;
0389 }
0390 emitToken(xid.subroutine + "() ");
0391 }
0392 }
0393
0394 #ifdef ELoutputTRACE_LOG
0395 std::cerr << " =:=:=: Module and Subroutine done \n";
0396 #endif
0397
0398
0399
0400 if (!msg.is_verbatim()) {
0401 if (wantTimestamp) {
0402 if (wantTimeSeparate) {
0403 emitToken("\n");
0404 needAspace = false;
0405 }
0406 if (needAspace) {
0407 emitToken(" ");
0408 needAspace = false;
0409 }
0410 std::string const& ftime = formatTime(msg.timestamp());
0411 emitToken(ftime + " ");
0412 }
0413 }
0414
0415 #ifdef ELoutputTRACE_LOG
0416 std::cerr << " =:=:=: TimeStamp done \n";
0417 #endif
0418
0419
0420
0421 if (!msg.is_verbatim()) {
0422 if (wantSomeContext) {
0423 if (needAspace) {
0424 emitToken(" ");
0425 needAspace = false;
0426 }
0427 assert(!needAspace);
0428 if (wantFullContext) {
0429 emitToken(msg.context());
0430 #ifdef ELoutputTRACE_LOG
0431 std::cerr << " =:=:=: fullContext done: \n";
0432 #endif
0433 } else {
0434 emitToken(msg.context());
0435 #ifdef ELoutputTRACE_LOG
0436 std::cerr << " =:=:=: Context done: \n";
0437 #endif
0438 }
0439 }
0440 }
0441
0442
0443
0444
0445 bool insertNewlineAfterHeader = (msg.xid().severity != ELdebug);
0446
0447
0448 if (!msg.is_verbatim()) {
0449 if (msg.xid().severity >= traceThreshold) {
0450 emitToken("\n", insertNewlineAfterHeader);
0451 } else {
0452 emitToken("", insertNewlineAfterHeader);
0453 }
0454 }
0455 #ifdef ELoutputTRACE_LOG
0456 std::cerr << " =:=:=: Trace routine done: \n";
0457 #endif
0458
0459 #ifndef OUTPUT_FORMATTED_ERROR_MESSAGES
0460
0461
0462 preambleMode = false;
0463 if (wantText) {
0464 ELlist_string::const_iterator it;
0465 int item_count = 0;
0466 for (it = msg.items().begin(); it != msg.items().end(); ++it) {
0467 #ifdef ELoutputTRACE_LOG
0468 std::cerr << " =:=:=: Item: " << *it << '\n';
0469 #endif
0470 ++item_count;
0471 if (!msg.is_verbatim()) {
0472 if (!insertNewlineAfterHeader && (item_count == 3)) {
0473
0474 emitToken(*it, true);
0475 } else {
0476 emitToken(*it);
0477 }
0478 } else {
0479 emitToken(*it);
0480 }
0481 }
0482 }
0483 #endif
0484
0485
0486
0487
0488 if (!msg.is_verbatim()) {
0489 emitToken("\n%MSG");
0490 }
0491
0492
0493
0494
0495 (*os) << newline;
0496 flush();
0497
0498 #ifdef ELoutputTRACE_LOG
0499 std::cerr << " =:=:=: log(msg) done: \n";
0500 #endif
0501
0502 return true;
0503
0504 }
0505
0506
0507
0508
0509
0510
0511
0512 void ELoutput::emitToken(std::string_view s, bool nl) {
0513 #ifdef ELoutput_EMIT_TRACE
0514 std::cerr << "[][][] in emit: charsOnLine is " << charsOnLine << '\n';
0515 std::cerr << "[][][] in emit: s.length() " << s.length() << '\n';
0516 std::cerr << "[][][] in emit: lineLength is " << lineLength << '\n';
0517 #endif
0518
0519 if (s.length() == 0) {
0520 if (nl) {
0521 (*os) << newline << std::flush;
0522 charsOnLine = 0;
0523 }
0524 return;
0525 }
0526
0527 char first = s[0];
0528 char second, last, last2;
0529 second = (s.length() < 2) ? '\0' : s[1];
0530 last = (s.length() < 2) ? '\0' : s[s.length() - 1];
0531 last2 = (s.length() < 3) ? '\0' : s[s.length() - 2];
0532
0533
0534
0535 if (preambleMode) {
0536
0537 if (first == '\n' || (charsOnLine + static_cast<int>(s.length())) > lineLength) {
0538 #ifdef ELoutput_EMIT_TRACE
0539 std::cerr << "[][][] in emit: about to << to *os \n";
0540 #endif
0541 #ifdef HEADERS_BROKEN_INTO_LINES_AND_INDENTED
0542
0543 (*os) << newline << indent;
0544 charsOnLine = indent.length();
0545 #else
0546 charsOnLine = 0;
0547 #endif
0548 if (second != ' ') {
0549 (*os) << ' ';
0550 charsOnLine++;
0551 }
0552 if (first == '\n') {
0553 (*os) << s.substr(1);
0554 } else {
0555 (*os) << s;
0556 }
0557 }
0558 #ifdef ELoutput_EMIT_TRACE
0559 std::cerr << "[][][] in emit: about to << s to *os: " << s << " \n";
0560 #endif
0561 else {
0562 (*os) << s;
0563 }
0564
0565 if (last == '\n' || last2 == '\n') {
0566 (*os) << indent;
0567 if (last != ' ')
0568 (*os) << ' ';
0569 charsOnLine = indent.length() + 1;
0570 }
0571
0572 if (nl) {
0573 (*os) << newline << std::flush;
0574 charsOnLine = 0;
0575 } else {
0576 charsOnLine += s.length();
0577 }
0578 }
0579
0580 if (!preambleMode) {
0581 (*os) << s;
0582 }
0583
0584 #ifdef ELoutput_EMIT_TRACE
0585 std::cerr << "[][][] in emit: completed \n";
0586 #endif
0587
0588 }
0589
0590
0591
0592
0593
0594 void ELoutput::includeTime() { wantTimestamp = true; }
0595 void ELoutput::suppressTime() { wantTimestamp = false; }
0596
0597 void ELoutput::includeModule() { wantModule = true; }
0598 void ELoutput::suppressModule() { wantModule = false; }
0599
0600 void ELoutput::includeSubroutine() { wantSubroutine = true; }
0601 void ELoutput::suppressSubroutine() { wantSubroutine = false; }
0602
0603 void ELoutput::includeText() { wantText = true; }
0604 void ELoutput::suppressText() { wantText = false; }
0605
0606 void ELoutput::includeContext() { wantSomeContext = true; }
0607 void ELoutput::suppressContext() { wantSomeContext = false; }
0608
0609 void ELoutput::suppressSerial() { wantSerial = false; }
0610 void ELoutput::includeSerial() { wantSerial = true; }
0611
0612 void ELoutput::useFullContext() { wantFullContext = true; }
0613 void ELoutput::useContext() { wantFullContext = false; }
0614
0615 void ELoutput::separateTime() { wantTimeSeparate = true; }
0616 void ELoutput::attachTime() { wantTimeSeparate = false; }
0617
0618 void ELoutput::separateEpilogue() { wantEpilogueSeparate = true; }
0619 void ELoutput::attachEpilogue() { wantEpilogueSeparate = false; }
0620
0621
0622
0623
0624
0625 void ELoutput::changeFile(std::ostream& os_) {
0626 os.reset(&os_, do_nothing_deleter());
0627 emitToken("\n=======================================================", true);
0628 emitToken("\nError Log changed to this stream\n");
0629 std::string const& ftime = formatTime(time(nullptr));
0630 emitToken(ftime, true);
0631 emitToken("\n=======================================================\n", true);
0632 }
0633
0634 void ELoutput::changeFile(const std::string& filename) {
0635 os.reset(new std::ofstream(filename.c_str(), std::ios ::app), close_and_delete());
0636 emitToken("\n=======================================================", true);
0637 emitToken("\nError Log changed to this file\n");
0638 std::string const& ftime = formatTime(time(nullptr));
0639 emitToken(ftime, true);
0640 emitToken("\n=======================================================\n", true);
0641 }
0642
0643 void ELoutput::flush() { os->flush(); }
0644
0645
0646
0647 }
0648 }