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