File indexing completed on 2023-03-17 10:53:45
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include "FWCore/Framework/interface/global/EDFilter.h"
0013 #include "FWCore/Framework/interface/Event.h"
0014 #include "FWCore/Framework/interface/Run.h"
0015 #include "FWCore/Framework/interface/LuminosityBlock.h"
0016 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0017 #include "FWCore/Utilities/interface/InputTag.h"
0018
0019 #include "DataFormats/Common/interface/ErrorSummaryEntry.h"
0020
0021 #include <map>
0022 #include <set>
0023 #include <string>
0024 #include <iomanip>
0025 #include <iostream>
0026 #include <iterator>
0027
0028 namespace leef {
0029 using Error = edm::ErrorSummaryEntry;
0030 struct ErrorSort {
0031 bool operator()(const Error &e1, const Error &e2) const {
0032 if (e1.severity.getLevel() != e2.severity.getLevel())
0033 return e1.severity.getLevel() > e2.severity.getLevel();
0034 if (e1.module != e2.module)
0035 return e1.module < e2.module;
0036 if (e1.category != e2.category)
0037 return e1.category < e2.category;
0038 return false;
0039 }
0040 };
0041 using ErrorSet = std::set<edm::ErrorSummaryEntry, ErrorSort>;
0042
0043 struct RunErrors {
0044 RunErrors() : npass_{0}, nfail_{0}, collectionGuard_{false} {}
0045
0046
0047
0048 CMS_THREAD_GUARD(collectionGuard_) mutable ErrorSet errorCollection_;
0049 mutable std::atomic<size_t> npass_;
0050 mutable std::atomic<size_t> nfail_;
0051
0052 mutable std::atomic<bool> collectionGuard_;
0053 };
0054
0055 struct LumiErrors {
0056 LumiErrors() : npass_{0}, nfail_{0}, collectionGuard_{false} {}
0057
0058 CMS_THREAD_GUARD(collectionGuard_) mutable ErrorSet errorCollection_;
0059 mutable std::atomic<size_t> npass_;
0060 mutable std::atomic<size_t> nfail_;
0061
0062 mutable std::atomic<bool> collectionGuard_;
0063 };
0064 }
0065
0066 namespace {
0067
0068
0069 struct release {
0070 void operator()(std::atomic<bool> *b) const noexcept { b->store(false); }
0071 };
0072 std::unique_ptr<std::atomic<bool>, release> make_guard(std::atomic<bool> &b) noexcept {
0073 bool expected = false;
0074 while (not b.compare_exchange_strong(expected, true))
0075 ;
0076
0077 return std::unique_ptr<std::atomic<bool>, release>(&b, release());
0078 }
0079
0080 }
0081
0082 using namespace leef;
0083
0084 class LogErrorEventFilter : public edm::global::EDFilter<edm::RunCache<leef::RunErrors>,
0085 edm::LuminosityBlockCache<LumiErrors>,
0086 edm::EndLuminosityBlockProducer> {
0087 public:
0088 explicit LogErrorEventFilter(const edm::ParameterSet &iConfig);
0089 ~LogErrorEventFilter() override {}
0090
0091 bool filter(edm::StreamID, edm::Event &iEvent, const edm::EventSetup &iSetup) const override;
0092 std::shared_ptr<LumiErrors> globalBeginLuminosityBlock(const edm::LuminosityBlock &lumi,
0093 const edm::EventSetup &iSetup) const override;
0094 void globalEndLuminosityBlock(const edm::LuminosityBlock &lumi, const edm::EventSetup &iSetup) const override;
0095 void globalEndLuminosityBlockProduce(edm::LuminosityBlock &lumi, const edm::EventSetup &iSetup) const override;
0096 std::shared_ptr<RunErrors> globalBeginRun(const edm::Run &run, const edm::EventSetup &iSetup) const override;
0097 void globalEndRun(const edm::Run &run, const edm::EventSetup &iSetup) const override;
0098 void endJob() override;
0099
0100 private:
0101 typedef edm::ErrorSummaryEntry Error;
0102 typedef std::vector<edm::ErrorSummaryEntry> ErrorList;
0103
0104 edm::InputTag src_;
0105 edm::EDGetTokenT<ErrorList> srcT_;
0106 bool readSummaryMode_;
0107 std::set<std::string> modulesToWatch_;
0108 std::set<std::string> modulesToIgnore_;
0109 std::set<std::string> categoriesToWatch_;
0110 std::set<std::string> categoriesToIgnore_;
0111 CMS_THREAD_GUARD(statsGuard_)
0112 mutable std::map<std::pair<uint32_t, uint32_t>, std::pair<size_t, size_t> > statsPerLumi_;
0113 CMS_THREAD_GUARD(statsGuard_) mutable std::map<uint32_t, std::pair<size_t, size_t> > statsPerRun_;
0114 CMS_THREAD_GUARD(statsGuard_) mutable ErrorSet errorCollectionAll_;
0115 double thresholdPerLumi_, thresholdPerRun_;
0116 size_t maxSavedEventsPerLumi_;
0117 bool verbose_, veryVerbose_;
0118 bool taggedMode_, forcedValue_;
0119 mutable std::atomic<bool> statsGuard_;
0120
0121 template <typename Collection>
0122 static void increment(ErrorSet &scoreboard, Collection &list);
0123 template <typename Collection>
0124 static void print(const Collection &errors);
0125
0126 static std::unique_ptr<ErrorList> serialize(const ErrorSet &set) {
0127 return std::make_unique<ErrorList>(set.begin(), set.end());
0128 }
0129 };
0130
0131 LogErrorEventFilter::LogErrorEventFilter(const edm::ParameterSet &iConfig)
0132 : src_(iConfig.getParameter<edm::InputTag>("src")),
0133 srcT_(consumes<ErrorList>(iConfig.getParameter<edm::InputTag>("src"))),
0134 readSummaryMode_(iConfig.existsAs<bool>("readSummaryMode") ? iConfig.getParameter<bool>("readSummaryMode")
0135 : false),
0136 thresholdPerLumi_(iConfig.getParameter<double>("maxErrorFractionInLumi")),
0137 thresholdPerRun_(iConfig.getParameter<double>("maxErrorFractionInRun")),
0138 maxSavedEventsPerLumi_(iConfig.getParameter<uint32_t>("maxSavedEventsPerLumiAndError")),
0139 verbose_(iConfig.getUntrackedParameter<bool>("verbose", false)),
0140 veryVerbose_(iConfig.getUntrackedParameter<bool>("veryVerbose", false)),
0141 taggedMode_(iConfig.getUntrackedParameter<bool>("taggedMode", false)),
0142 forcedValue_(iConfig.getUntrackedParameter<bool>("forcedValue", true)) {
0143 produces<ErrorList, edm::Transition::EndLuminosityBlock>();
0144 produces<int, edm::Transition::EndLuminosityBlock>("pass");
0145 produces<int, edm::Transition::EndLuminosityBlock>("fail");
0146
0147 produces<bool>();
0148
0149 if (iConfig.existsAs<std::vector<std::string> >("modulesToWatch")) {
0150 std::vector<std::string> modules = iConfig.getParameter<std::vector<std::string> >("modulesToWatch");
0151 if (!(modules.size() == 1 && modules[0] == "*")) {
0152 modulesToWatch_.insert(modules.begin(), modules.end());
0153 }
0154 }
0155 if (iConfig.existsAs<std::vector<std::string> >("modulesToIgnore")) {
0156 std::vector<std::string> modules = iConfig.getParameter<std::vector<std::string> >("modulesToIgnore");
0157 if (!(modules.size() == 1 && modules[0] == "*")) {
0158 modulesToIgnore_.insert(modules.begin(), modules.end());
0159 }
0160 }
0161 if (iConfig.existsAs<std::vector<std::string> >("categoriesToWatch")) {
0162 std::vector<std::string> categories = iConfig.getParameter<std::vector<std::string> >("categoriesToWatch");
0163 if (!(categories.size() == 1 && categories[0] == "*")) {
0164 categoriesToWatch_.insert(categories.begin(), categories.end());
0165 }
0166 }
0167 if (iConfig.existsAs<std::vector<std::string> >("categoriesToIgnore")) {
0168 std::vector<std::string> categories = iConfig.getParameter<std::vector<std::string> >("categoriesToIgnore");
0169 if (!(categories.size() == 1 && categories[0] == "*")) {
0170 categoriesToIgnore_.insert(categories.begin(), categories.end());
0171 }
0172 }
0173
0174
0175
0176
0177
0178
0179 }
0180
0181 std::shared_ptr<LumiErrors> LogErrorEventFilter::globalBeginLuminosityBlock(const edm::LuminosityBlock &lumi,
0182 const edm::EventSetup &iSetup) const {
0183 auto ret = std::make_shared<LumiErrors>();
0184 if (readSummaryMode_) {
0185 edm::Handle<ErrorList> handle;
0186 edm::Handle<int> hpass, hfail;
0187 lumi.getByLabel(src_, handle);
0188 lumi.getByLabel(edm::InputTag(src_.label(), "pass", src_.process()), hpass);
0189 lumi.getByLabel(edm::InputTag(src_.label(), "fail", src_.process()), hfail);
0190 increment(ret->errorCollection_, *handle);
0191 ret->npass_ = *hpass;
0192 ret->nfail_ = *hfail;
0193
0194 auto runC = runCache(lumi.getRun().index());
0195 runC->npass_ += *hpass;
0196 runC->nfail_ += *hfail;
0197 }
0198 return ret;
0199 }
0200 void LogErrorEventFilter::globalEndLuminosityBlock(edm::LuminosityBlock const &lumi,
0201 const edm::EventSetup &iSetup) const {
0202 auto lumiC = luminosityBlockCache(lumi.index());
0203 auto nfail = lumiC->nfail_.load();
0204 auto npass = lumiC->npass_.load();
0205 {
0206 auto guard = make_guard(statsGuard_);
0207 statsPerLumi_[std::pair<uint32_t, uint32_t>(lumi.run(), lumi.luminosityBlock())] =
0208 std::pair<size_t, size_t>(npass, nfail);
0209 }
0210 {
0211
0212 auto guard = make_guard(lumiC->collectionGuard_);
0213
0214 {
0215 if (nfail < thresholdPerLumi_ * (npass + nfail)) {
0216
0217 auto runC = runCache(lumi.getRun().index());
0218 auto guard = make_guard(runC->collectionGuard_);
0219 increment(runC->errorCollection_, lumiC->errorCollection_);
0220 }
0221 }
0222 if (verbose_) {
0223 if (!lumiC->errorCollection_.empty()) {
0224 std::cout << "\n === REPORT FOR RUN " << lumi.run() << " LUMI " << lumi.luminosityBlock()
0225 << " === " << std::endl;
0226 print(lumiC->errorCollection_);
0227 }
0228 }
0229 }
0230 }
0231
0232 void LogErrorEventFilter::globalEndLuminosityBlockProduce(edm::LuminosityBlock &lumi,
0233 const edm::EventSetup &iSetup) const {
0234 auto lumiC = luminosityBlockCache(lumi.index());
0235 {
0236
0237 auto guard = make_guard(lumiC->collectionGuard_);
0238 lumi.put(serialize(lumiC->errorCollection_));
0239 }
0240 lumi.put(std::make_unique<int>(lumiC->npass_.load()), "pass");
0241 lumi.put(std::make_unique<int>(lumiC->nfail_.load()), "fail");
0242 }
0243
0244 std::shared_ptr<RunErrors> LogErrorEventFilter::globalBeginRun(const edm::Run &run,
0245 const edm::EventSetup &iSetup) const {
0246 return std::make_shared<RunErrors>();
0247 }
0248
0249 void LogErrorEventFilter::globalEndRun(const edm::Run &run, const edm::EventSetup &iSetup) const {
0250 auto runC = runCache(run.index());
0251 auto npass = runC->npass_.load();
0252 auto nfail = runC->nfail_.load();
0253 {
0254 auto guard = make_guard(statsGuard_);
0255 statsPerRun_[run.run()] = std::pair<size_t, size_t>(npass, nfail);
0256 }
0257 {
0258
0259 auto guard = make_guard(runC->collectionGuard_);
0260 if (nfail < thresholdPerRun_ * (npass + nfail)) {
0261 auto guard = make_guard(statsGuard_);
0262 increment(errorCollectionAll_, runC->errorCollection_);
0263 }
0264 if (verbose_) {
0265 if (!runC->errorCollection_.empty()) {
0266 std::cout << "\n === REPORT FOR RUN " << run.run() << " === " << std::endl;
0267 print(runC->errorCollection_);
0268 }
0269 }
0270 }
0271 }
0272
0273 void LogErrorEventFilter::endJob() {
0274 if (verbose_) {
0275 std::cout << "\n === REPORT FOR JOB === " << std::endl;
0276
0277 auto guard = make_guard(statsGuard_);
0278 print(errorCollectionAll_);
0279
0280 typedef std::pair<size_t, size_t> counter;
0281
0282 std::cout << "\n === SCOREBOARD PER RUN === " << std::endl;
0283 typedef std::pair<uint32_t, counter> hitRun;
0284 for (auto const &hit : statsPerRun_) {
0285 double fract = hit.second.second / double(hit.second.first + hit.second.second);
0286 printf("run %6d: fail %7zu, pass %7zu, fraction %7.3f%%%s\n",
0287 hit.first,
0288 hit.second.second,
0289 hit.second.first,
0290 fract * 100.,
0291 (fract >= thresholdPerRun_ ? " (run excluded from summary list)" : ""));
0292 }
0293
0294 std::cout << "\n === SCOREBOARD PER LUMI === " << std::endl;
0295 typedef std::pair<std::pair<uint32_t, uint32_t>, counter> hitLumi;
0296 for (auto const &hit : statsPerLumi_) {
0297 double fract = hit.second.second / double(hit.second.first + hit.second.second);
0298 printf("run %6d, lumi %4d: fail %zu, pass %zu, fraction %7.3f%%%s\n",
0299 hit.first.first,
0300 hit.first.second,
0301 hit.second.second,
0302 hit.second.first,
0303 fract * 100.,
0304 (fract >= thresholdPerLumi_ ? " (lumi excluded from run list)" : ""));
0305 }
0306 }
0307 }
0308
0309 bool LogErrorEventFilter::filter(edm::StreamID, edm::Event &iEvent, const edm::EventSetup &iSetup) const {
0310 if (readSummaryMode_)
0311 return true;
0312
0313 bool fail = false, save = false;
0314
0315 edm::Handle<ErrorList> errors;
0316 iEvent.getByToken(srcT_, errors);
0317
0318 auto runC = runCache(iEvent.getRun().index());
0319 auto lumiC = luminosityBlockCache(iEvent.getLuminosityBlock().index());
0320
0321 if (errors->empty()) {
0322 ++(runC->npass_);
0323 ++(lumiC->npass_);
0324 iEvent.put(std::make_unique<bool>(false));
0325
0326 if (taggedMode_)
0327 return forcedValue_;
0328 return false;
0329 }
0330
0331 for (auto const &err : *errors) {
0332 if (!modulesToWatch_.empty() && (modulesToWatch_.count(err.module) == 0))
0333 continue;
0334 if (!categoriesToWatch_.empty() && (categoriesToWatch_.count(err.category) == 0))
0335 continue;
0336 if (!modulesToIgnore_.empty() && (modulesToIgnore_.count(err.module) != 0))
0337 continue;
0338 if (!categoriesToIgnore_.empty() && (categoriesToIgnore_.count(err.category) != 0))
0339 continue;
0340
0341 fail = true;
0342
0343
0344 auto guard = make_guard(lumiC->collectionGuard_);
0345
0346 std::pair<ErrorSet::iterator, bool> result = lumiC->errorCollection_.insert(err);
0347 if (!result.second) {
0348
0349 const_cast<unsigned int &>(result.first->count) += err.count;
0350 if (result.first->count < maxSavedEventsPerLumi_)
0351 save = true;
0352 } else {
0353 save = true;
0354 }
0355 }
0356 if (save && veryVerbose_) {
0357 std::cout << "\n === REPORT FOR EVENT " << iEvent.id().event() << " RUN " << iEvent.run() << " LUMI "
0358 << iEvent.luminosityBlock() << " === " << std::endl;
0359 print(*errors);
0360 }
0361
0362 if (fail) {
0363 ++(lumiC->nfail_);
0364 ++(runC->nfail_);
0365 } else {
0366 ++(runC->npass_);
0367 ++(lumiC->npass_);
0368 }
0369 iEvent.put(std::make_unique<bool>(fail));
0370
0371 if (taggedMode_)
0372 return forcedValue_;
0373 return save;
0374 }
0375
0376 template <typename Collection>
0377 void LogErrorEventFilter::increment(ErrorSet &scoreboard, Collection &list) {
0378 for (auto const &err : list) {
0379 std::pair<ErrorSet::iterator, bool> result = scoreboard.insert(err);
0380
0381 if (!result.second)
0382 const_cast<unsigned int &>(result.first->count) += err.count;
0383 }
0384 }
0385
0386 template <typename Collection>
0387 void LogErrorEventFilter::print(const Collection &errors) {
0388 using namespace std;
0389 cout << setw(40) << left << "Category"
0390 << " " << setw(60) << left << "Module"
0391 << " " << setw(10) << left << "Level"
0392 << " " << setw(9) << right << "Count"
0393 << "\n";
0394 cout << setw(40) << left << "----------------------------------------"
0395 << " " << setw(60) << left << "------------------------------------------------------------"
0396 << " " << setw(10) << left << "----------"
0397 << " " << setw(9) << right << "---------"
0398 << "\n";
0399 for (auto const &err : errors) {
0400 cout << setw(40) << left << err.category << " " << setw(60) << left << err.module << " " << setw(10) << left
0401 << err.severity.getName() << " " << setw(9) << right << err.count << "\n";
0402 }
0403 cout << flush;
0404 }
0405
0406 #include "FWCore/Framework/interface/MakerMacros.h"
0407 DEFINE_FWK_MODULE(LogErrorEventFilter);