Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-05-23 23:00:38

0001 /** \class L1TriggerJSONMonitoring
0002  *
0003  *  Description: This class outputs JSON files with TCDS and L1T monitoring information.
0004  *
0005  */
0006 
0007 #include <atomic>
0008 #include <fstream>
0009 
0010 #include <fmt/printf.h>
0011 
0012 #include "CondFormats/DataRecord/interface/L1TUtmTriggerMenuRcd.h"
0013 #include "CondFormats/L1TObjects/interface/L1TUtmAlgorithm.h"
0014 #include "CondFormats/L1TObjects/interface/L1TUtmTriggerMenu.h"
0015 #include "DataFormats/Common/interface/Handle.h"
0016 #include "DataFormats/L1TGlobal/interface/GlobalAlgBlk.h"
0017 #include "DataFormats/L1TGlobal/interface/GlobalExtBlk.h"
0018 #include "EventFilter/Utilities/interface/EvFDaqDirector.h"
0019 #include "EventFilter/Utilities/interface/FastMonitor.h"
0020 #include "EventFilter/Utilities/interface/FastMonitoringService.h"
0021 #include "EventFilter/Utilities/interface/JSONSerializer.h"
0022 #include "EventFilter/Utilities/interface/JsonMonitorable.h"
0023 #include "FWCore/Framework/interface/Event.h"
0024 #include "FWCore/Framework/interface/EventSetup.h"
0025 #include "FWCore/Framework/interface/LuminosityBlock.h"
0026 #include "FWCore/Framework/interface/Run.h"
0027 #include "FWCore/Framework/interface/global/EDAnalyzer.h"
0028 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0029 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0030 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0031 #include "FWCore/ServiceRegistry/interface/Service.h"
0032 #include "FWCore/Utilities/interface/Adler32Calculator.h"
0033 
0034 struct L1TriggerJSONMonitoringData {
0035   // special values for prescale index checks
0036   static constexpr const int kPrescaleUndefined = -2;
0037   static constexpr const int kPrescaleConflict = -1;
0038   // variables accumulated event by event in each stream
0039   struct stream {
0040     unsigned int processed = 0;                      // number of events processed
0041     std::vector<unsigned int> l1tAccept;             // number of events accepted by each L1 trigger
0042     std::vector<unsigned int> l1tAcceptPhysics;      // number of "physics" events accepted by each L1 trigger
0043     std::vector<unsigned int> l1tAcceptCalibration;  // number of "calibration" events accepted by each L1 trigger
0044     std::vector<unsigned int> l1tAcceptRandom;       // number of "random" events accepted by each L1 trigger
0045     std::vector<unsigned int> tcdsAccept;    // number of "physics", "calibration", "random" and other event types
0046     int prescaleIndex = kPrescaleUndefined;  // prescale column index
0047   };
0048 
0049   // variables initialised for each run
0050   struct run {
0051     std::string streamDestination;
0052     std::string streamMergeType;
0053     std::string baseRunDir;   // base directory from EvFDaqDirector
0054     std::string jsdFileName;  // definition file name for JSON with rates
0055   };
0056 
0057   // variables accumulated over the whole lumisection
0058   struct lumisection {
0059     jsoncollector::HistoJ<unsigned int> processed;         // number of events processed
0060     jsoncollector::HistoJ<unsigned int> l1tAccept;         // number of events accepted by each L1 trigger
0061     jsoncollector::HistoJ<unsigned int> l1tAcceptPhysics;  // number of "physics" events accepted by each L1 trigger
0062     jsoncollector::HistoJ<unsigned int>
0063         l1tAcceptCalibration;                             // number of "calibration" events accepted by each L1 trigger
0064     jsoncollector::HistoJ<unsigned int> l1tAcceptRandom;  // number of "random" events accepted by each L1 trigger
0065     jsoncollector::HistoJ<unsigned int> tcdsAccept;  // number of "physics", "calibration", "random" and other event types
0066     int prescaleIndex = kPrescaleUndefined;          // prescale column index
0067   };
0068 };
0069 
0070 class L1TriggerJSONMonitoring : public edm::global::EDAnalyzer<
0071                                     // per-stream information
0072                                     edm::StreamCache<L1TriggerJSONMonitoringData::stream>,
0073                                     // per-run accounting
0074                                     edm::RunCache<L1TriggerJSONMonitoringData::run>,
0075                                     // accumulate per-lumisection statistics
0076                                     edm::LuminosityBlockSummaryCache<L1TriggerJSONMonitoringData::lumisection> > {
0077 public:
0078   // constructor
0079   explicit L1TriggerJSONMonitoring(const edm::ParameterSet&);
0080 
0081   // destructor
0082   ~L1TriggerJSONMonitoring() override = default;
0083 
0084   // validate the configuration and optionally fill the default values
0085   static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0086 
0087   // called for each Event
0088   void analyze(edm::StreamID, edm::Event const&, edm::EventSetup const&) const override;
0089 
0090   // -- inherited from edm::StreamCache<L1TriggerJSONMonitoringData::stream>
0091 
0092   // called once for each Stream being used in the job to create the cache object that will be used for that particular Stream
0093   std::unique_ptr<L1TriggerJSONMonitoringData::stream> beginStream(edm::StreamID) const override;
0094 
0095   // called when the Stream is switching from one LuminosityBlock to a new LuminosityBlock.
0096   void streamBeginLuminosityBlock(edm::StreamID, edm::LuminosityBlock const&, edm::EventSetup const&) const override;
0097 
0098   // -- inherited from edm::RunCache<L1TriggerJSONMonitoringData::run>
0099 
0100   // called each time the Source sees a new Run, and guaranteed to finish before any Stream calls streamBeginRun for that same Run
0101   std::shared_ptr<L1TriggerJSONMonitoringData::run> globalBeginRun(edm::Run const&,
0102                                                                    edm::EventSetup const&) const override;
0103 
0104   // called after all Streams have finished processing a given Run (i.e. streamEndRun for all Streams have completed)
0105   void globalEndRun(edm::Run const&, edm::EventSetup const&) const override;
0106 
0107   // -- inherited from edm::LuminosityBlockSummaryCache<L1TriggerJSONMonitoringData::lumisection>
0108 
0109   // called each time the Source sees a new LuminosityBlock
0110   std::shared_ptr<L1TriggerJSONMonitoringData::lumisection> globalBeginLuminosityBlockSummary(
0111       edm::LuminosityBlock const&, edm::EventSetup const&) const override;
0112 
0113   // called when a Stream has finished processing a LuminosityBlock, after streamEndLuminosityBlock
0114   void streamEndLuminosityBlockSummary(edm::StreamID,
0115                                        edm::LuminosityBlock const&,
0116                                        edm::EventSetup const&,
0117                                        L1TriggerJSONMonitoringData::lumisection*) const override;
0118 
0119   // called after the streamEndLuminosityBlockSummary method for all Streams have finished processing a given LuminosityBlock
0120   void globalEndLuminosityBlockSummary(edm::LuminosityBlock const&,
0121                                        edm::EventSetup const&,
0122                                        L1TriggerJSONMonitoringData::lumisection*) const override;
0123 
0124 private:
0125   // TCDS trigger types
0126   // see https://twiki.cern.ch/twiki/bin/viewauth/CMS/TcdsEventRecord
0127   static constexpr const std::array<const char*, 16> tcdsTriggerTypes_ = {{
0128       "Error",          //  0 - No trigger (DAQ error stream events may have this value)
0129       "Physics",        //  1 - GT trigger
0130       "Calibration",    //  2 - Sequence trigger (calibration)
0131       "Random",         //  3 - Random trigger
0132       "Auxiliary",      //  4 - Auxiliary (CPM front panel NIM input) trigger
0133       "",               //  5 - reserved
0134       "",               //  6 - reserved
0135       "",               //  7 - reserved
0136       "Cyclic",         //  8 - Cyclic trigger
0137       "Bunch-pattern",  //  9 - Bunch-pattern trigger
0138       "Software",       // 10 - Software trigger
0139       "TTS",            // 11 - TTS-sourced trigger
0140       "",               // 12 - reserved
0141       "",               // 13 - reserved
0142       "",               // 14 - reserved
0143       ""                // 15 - reserved
0144   }};
0145 
0146   static constexpr const char* streamName_ = "streamL1Rates";
0147 
0148   static void writeJsdFile(L1TriggerJSONMonitoringData::run const&);
0149   static void writeIniFile(L1TriggerJSONMonitoringData::run const&, unsigned int, std::vector<std::string> const&);
0150 
0151   // configuration
0152   const edm::InputTag level1Results_;                                    // InputTag for L1 trigger results
0153   const edm::EDGetTokenT<GlobalAlgBlkBxCollection> level1ResultsToken_;  // Token for L1 trigger results
0154   const edm::ESGetToken<L1TUtmTriggerMenu, L1TUtmTriggerMenuRcd> l1tUtmTriggerMenuRcdToken_;
0155 };
0156 
0157 // instantiate static data members
0158 constexpr const std::array<const char*, 16> L1TriggerJSONMonitoring::tcdsTriggerTypes_;
0159 
0160 // constructor
0161 L1TriggerJSONMonitoring::L1TriggerJSONMonitoring(edm::ParameterSet const& config)
0162     : level1Results_(config.getParameter<edm::InputTag>("L1Results")),
0163       level1ResultsToken_(consumes<GlobalAlgBlkBxCollection>(level1Results_)),
0164       l1tUtmTriggerMenuRcdToken_(esConsumes<edm::Transition::BeginRun>()) {}
0165 
0166 // validate the configuration and optionally fill the default values
0167 void L1TriggerJSONMonitoring::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0168   edm::ParameterSetDescription desc;
0169   desc.add<edm::InputTag>("L1Results", edm::InputTag("hltGtStage2Digis"));
0170   descriptions.add("L1TriggerJSONMonitoring", desc);
0171 }
0172 
0173 // called once for each Stream being used in the job to create the cache object that will be used for that particular Stream
0174 std::unique_ptr<L1TriggerJSONMonitoringData::stream> L1TriggerJSONMonitoring::beginStream(edm::StreamID) const {
0175   return std::make_unique<L1TriggerJSONMonitoringData::stream>();
0176 }
0177 
0178 // called each time the Source sees a new Run, and guaranteed to finish before any Stream calls streamBeginRun for that same Run
0179 std::shared_ptr<L1TriggerJSONMonitoringData::run> L1TriggerJSONMonitoring::globalBeginRun(
0180     edm::Run const& run, edm::EventSetup const& setup) const {
0181   auto rundata = std::make_shared<L1TriggerJSONMonitoringData::run>();
0182 
0183   // set the DAQ parameters
0184   if (edm::Service<evf::EvFDaqDirector>().isAvailable()) {
0185     rundata->streamDestination = edm::Service<evf::EvFDaqDirector>()->getStreamDestinations(streamName_);
0186     rundata->streamMergeType =
0187         edm::Service<evf::EvFDaqDirector>()->getStreamMergeType(streamName_, evf::MergeTypeJSNDATA);
0188     rundata->baseRunDir = edm::Service<evf::EvFDaqDirector>()->baseRunDir();
0189   } else {
0190     rundata->streamDestination = "";
0191     rundata->streamMergeType = "";
0192     rundata->baseRunDir = ".";
0193   }
0194 
0195   // read the L1 trigger names from the EventSetup
0196   std::vector<std::string> triggerNames(GlobalAlgBlk::maxPhysicsTriggers, ""s);
0197   auto const& menuHandle = setup.getHandle(l1tUtmTriggerMenuRcdToken_);
0198   if (menuHandle.isValid()) {
0199     for (auto const& algo : menuHandle->getAlgorithmMap())
0200       triggerNames[algo.second.getIndex()] = algo.first;
0201   } else {
0202     edm::LogWarning("L1TriggerJSONMonitoring") << "L1TUtmTriggerMenu not found in the EventSetup.\nThe Level 1 Trigger "
0203                                                   "rate monitoring will not include the trigger names.";
0204   }
0205 
0206   // write the per-run .jsd file
0207   rundata->jsdFileName = fmt::sprintf("run%06d_ls0000_streamL1Rates_pid%05d.jsd", run.run(), getpid());
0208   writeJsdFile(*rundata);
0209 
0210   // write the per-run .ini file
0211   //iniFileName = fmt::sprintf("run%06d_ls0000_streamL1Rates_pid%05d.ini", run.run(), getpid());
0212   writeIniFile(*rundata, run.run(), triggerNames);
0213 
0214   return rundata;
0215 }
0216 
0217 // called after all Streams have finished processing a given Run (i.e. streamEndRun for all Streams have completed)
0218 void L1TriggerJSONMonitoring::globalEndRun(edm::Run const&, edm::EventSetup const&) const {}
0219 
0220 // called for each Event
0221 void L1TriggerJSONMonitoring::analyze(edm::StreamID sid, edm::Event const& event, edm::EventSetup const&) const {
0222   auto& stream = *streamCache(sid);
0223 
0224   ++stream.processed;
0225   unsigned int eventType = event.experimentType();
0226   if (eventType < tcdsTriggerTypes_.size())
0227     ++stream.tcdsAccept[eventType];
0228   else
0229     edm::LogWarning("L1TriggerJSONMonitoring") << "Unexpected event type " << eventType;
0230 
0231   // get hold of TriggerResults
0232   edm::Handle<GlobalAlgBlkBxCollection> handle;
0233   if (not event.getByToken(level1ResultsToken_, handle) or not handle.isValid() or handle->isEmpty(0)) {
0234     edm::LogError("L1TriggerJSONMonitoring")
0235         << "L1 trigger results with label [" + level1Results_.encode() + "] not present or invalid";
0236     return;
0237   }
0238 
0239   // The GlobalAlgBlkBxCollection is a vector of vectors, but the second layer can only ever
0240   // have one entry since there can't be more than one collection per bunch crossing.
0241   // The first "0" here means BX = 0, while the second "0" is used to access the first and only element.
0242   auto const& results = handle->at(0, 0);
0243   auto const& decision = results.getAlgoDecisionFinal();
0244   assert(decision.size() == GlobalAlgBlk::maxPhysicsTriggers);
0245 
0246   // check the results for each HLT path
0247   for (unsigned int i = 0; i < decision.size(); ++i) {
0248     if (decision[i]) {
0249       ++stream.l1tAccept[i];
0250       switch (eventType) {
0251         case edm::EventAuxiliary::PhysicsTrigger:
0252           ++stream.l1tAcceptPhysics[i];
0253           break;
0254         case edm::EventAuxiliary::CalibrationTrigger:
0255           ++stream.l1tAcceptCalibration[i];
0256           break;
0257         case edm::EventAuxiliary::RandomTrigger:
0258           ++stream.l1tAcceptRandom[i];
0259           break;
0260         default:
0261           break;
0262       }
0263     }
0264   }
0265 
0266   // check for conflicting values in the prescale column index, and store it
0267   int prescaleIndex = results.getPreScColumn();
0268   if (stream.prescaleIndex == L1TriggerJSONMonitoringData::kPrescaleUndefined) {
0269     stream.prescaleIndex = prescaleIndex;
0270   } else if (stream.prescaleIndex == L1TriggerJSONMonitoringData::kPrescaleConflict) {
0271     // do nothing
0272   } else if (stream.prescaleIndex != prescaleIndex) {
0273     edm::LogWarning("L1TriggerJSONMonitoring") << "Prescale index changed from " << stream.prescaleIndex << " to "
0274                                                << prescaleIndex << " inside lumisection " << event.luminosityBlock();
0275     stream.prescaleIndex = L1TriggerJSONMonitoringData::kPrescaleConflict;
0276   }
0277 }
0278 
0279 // called each time the Source sees a new LuminosityBlock
0280 std::shared_ptr<L1TriggerJSONMonitoringData::lumisection> L1TriggerJSONMonitoring::globalBeginLuminosityBlockSummary(
0281     edm::LuminosityBlock const& lumi, edm::EventSetup const&) const {
0282   // the API of jsoncollector::HistoJ does not really match our use case,
0283   // but it is the only vector-like object available in JsonMonitorable.h
0284   auto lumidata = std::make_shared<L1TriggerJSONMonitoringData::lumisection>(L1TriggerJSONMonitoringData::lumisection{
0285       jsoncollector::HistoJ<unsigned int>(1),                                 // processed
0286       jsoncollector::HistoJ<unsigned int>(GlobalAlgBlk::maxPhysicsTriggers),  // l1tAccept
0287       jsoncollector::HistoJ<unsigned int>(GlobalAlgBlk::maxPhysicsTriggers),  // l1tAcceptPhysics
0288       jsoncollector::HistoJ<unsigned int>(GlobalAlgBlk::maxPhysicsTriggers),  // l1tAcceptCalibration
0289       jsoncollector::HistoJ<unsigned int>(GlobalAlgBlk::maxPhysicsTriggers),  // l1tAcceptRandom
0290       jsoncollector::HistoJ<unsigned int>(tcdsTriggerTypes_.size())           // tcdsAccept
0291   });
0292   // repeated calls to `update` necessary to set the internal element counter
0293   lumidata->processed.update(0);
0294   for (unsigned int i = 0; i < GlobalAlgBlk::maxPhysicsTriggers; ++i)
0295     lumidata->l1tAccept.update(0);
0296   for (unsigned int i = 0; i < GlobalAlgBlk::maxPhysicsTriggers; ++i)
0297     lumidata->l1tAcceptPhysics.update(0);
0298   for (unsigned int i = 0; i < GlobalAlgBlk::maxPhysicsTriggers; ++i)
0299     lumidata->l1tAcceptCalibration.update(0);
0300   for (unsigned int i = 0; i < GlobalAlgBlk::maxPhysicsTriggers; ++i)
0301     lumidata->l1tAcceptRandom.update(0);
0302   for (unsigned int i = 0; i < tcdsTriggerTypes_.size(); ++i)
0303     lumidata->tcdsAccept.update(0);
0304   lumidata->prescaleIndex = L1TriggerJSONMonitoringData::kPrescaleUndefined;
0305 
0306   return lumidata;
0307 }
0308 
0309 // called when the Stream is switching from one LuminosityBlock to a new LuminosityBlock.
0310 void L1TriggerJSONMonitoring::streamBeginLuminosityBlock(edm::StreamID sid,
0311                                                          edm::LuminosityBlock const& lumi,
0312                                                          edm::EventSetup const&) const {
0313   auto& stream = *streamCache(sid);
0314 
0315   // reset the stream counters
0316   stream.processed = 0;
0317   stream.l1tAccept.assign(GlobalAlgBlk::maxPhysicsTriggers, 0);
0318   stream.l1tAcceptPhysics.assign(GlobalAlgBlk::maxPhysicsTriggers, 0);
0319   stream.l1tAcceptCalibration.assign(GlobalAlgBlk::maxPhysicsTriggers, 0);
0320   stream.l1tAcceptRandom.assign(GlobalAlgBlk::maxPhysicsTriggers, 0);
0321   stream.tcdsAccept.assign(tcdsTriggerTypes_.size(), 0);
0322   stream.prescaleIndex = L1TriggerJSONMonitoringData::kPrescaleUndefined;
0323 }
0324 
0325 // called when a Stream has finished processing a LuminosityBlock, after streamEndLuminosityBlock
0326 void L1TriggerJSONMonitoring::streamEndLuminosityBlockSummary(edm::StreamID sid,
0327                                                               edm::LuminosityBlock const& lumi,
0328                                                               edm::EventSetup const&,
0329                                                               L1TriggerJSONMonitoringData::lumisection* lumidata) const {
0330   auto const& stream = *streamCache(sid);
0331   lumidata->processed.value()[0] += stream.processed;
0332 
0333   for (unsigned int i = 0; i < GlobalAlgBlk::maxPhysicsTriggers; ++i) {
0334     lumidata->l1tAccept.value()[i] += stream.l1tAccept[i];
0335     lumidata->l1tAcceptPhysics.value()[i] += stream.l1tAcceptPhysics[i];
0336     lumidata->l1tAcceptCalibration.value()[i] += stream.l1tAcceptCalibration[i];
0337     lumidata->l1tAcceptRandom.value()[i] += stream.l1tAcceptRandom[i];
0338   }
0339   for (unsigned int i = 0; i < tcdsTriggerTypes_.size(); ++i)
0340     lumidata->tcdsAccept.value()[i] += stream.tcdsAccept[i];
0341 
0342   // check for conflicting values in the prescale column index
0343   if (lumidata->prescaleIndex == L1TriggerJSONMonitoringData::kPrescaleUndefined)
0344     lumidata->prescaleIndex = stream.prescaleIndex;
0345   else if (lumidata->prescaleIndex != stream.prescaleIndex)
0346     lumidata->prescaleIndex = L1TriggerJSONMonitoringData::kPrescaleConflict;
0347 }
0348 
0349 // called after the streamEndLuminosityBlockSummary method for all Streams have finished processing a given LuminosityBlock
0350 void L1TriggerJSONMonitoring::globalEndLuminosityBlockSummary(edm::LuminosityBlock const& lumi,
0351                                                               edm::EventSetup const&,
0352                                                               L1TriggerJSONMonitoringData::lumisection* lumidata) const {
0353   unsigned int ls = lumi.luminosityBlock();
0354   unsigned int run = lumi.run();
0355 
0356   bool writeFiles = true;
0357   if (edm::Service<evf::MicroStateService>().isAvailable()) {
0358     evf::FastMonitoringService* fms =
0359         (evf::FastMonitoringService*)(edm::Service<evf::MicroStateService>().operator->());
0360     if (fms)
0361       writeFiles = fms->shouldWriteFiles(ls);
0362   }
0363   if (not writeFiles)
0364     return;
0365 
0366   unsigned int processed = lumidata->processed.value().at(0);
0367   auto const& rundata = *runCache(lumi.getRun().index());
0368   Json::StyledWriter writer;
0369 
0370   // [SIC]
0371   char hostname[33];
0372   gethostname(hostname, 32);
0373   std::string sourceHost(hostname);
0374 
0375   // [SIC]
0376   std::stringstream sOutDef;
0377   sOutDef << rundata.baseRunDir << "/"
0378           << "output_" << getpid() << ".jsd";
0379 
0380   std::string jsndataFileList = "";
0381   unsigned int jsndataSize = 0;
0382   unsigned int jsndataAdler32 = 1;  // adler32 checksum for an empty file
0383 
0384   if (processed) {
0385     // write the .jsndata files which contain the actual rates
0386     Json::Value jsndata;
0387     jsndata[jsoncollector::DataPoint::SOURCE] = sourceHost;
0388     jsndata[jsoncollector::DataPoint::DEFINITION] = rundata.jsdFileName;
0389     jsndata[jsoncollector::DataPoint::DATA].append(lumidata->processed.toJsonValue());
0390     jsndata[jsoncollector::DataPoint::DATA].append(lumidata->l1tAccept.toJsonValue());
0391     jsndata[jsoncollector::DataPoint::DATA].append(lumidata->l1tAcceptPhysics.toJsonValue());
0392     jsndata[jsoncollector::DataPoint::DATA].append(lumidata->l1tAcceptCalibration.toJsonValue());
0393     jsndata[jsoncollector::DataPoint::DATA].append(lumidata->l1tAcceptRandom.toJsonValue());
0394 
0395     // write only the number of "physics", "calibration" and "random" events
0396     jsoncollector::HistoJ<unsigned int> tcdsAccept;
0397     tcdsAccept.update(lumidata->tcdsAccept.value()[edm::EventAuxiliary::PhysicsTrigger]);
0398     tcdsAccept.update(lumidata->tcdsAccept.value()[edm::EventAuxiliary::CalibrationTrigger]);
0399     tcdsAccept.update(lumidata->tcdsAccept.value()[edm::EventAuxiliary::RandomTrigger]);
0400     jsndata[jsoncollector::DataPoint::DATA].append(tcdsAccept.toJsonValue());
0401     /* FIXME send information for all event types instead of only these three
0402     jsndata[jsoncollector::DataPoint::DATA].append(lumidata->tcdsAccept.toJsonValue());
0403     */
0404     jsndata[jsoncollector::DataPoint::DATA].append(lumidata->prescaleIndex);
0405 
0406     auto jsndataFileName = fmt::sprintf("run%06d_ls%04d_streamL1Rates_pid%05d.jsndata", run, ls, getpid());
0407 
0408     std::string result = writer.write(jsndata);
0409     std::ofstream jsndataFile(rundata.baseRunDir + "/" + jsndataFileName);
0410     jsndataFile << result;
0411     jsndataFile.close();
0412 
0413     jsndataFileList = jsndataFileName;
0414     jsndataSize = result.size();
0415     jsndataAdler32 = cms::Adler32(result.c_str(), result.size());
0416   }
0417 
0418   // create a metadata json file for the "HLT rates" pseudo-stream
0419   unsigned int jsnProcessed = processed;
0420   unsigned int jsnAccepted = processed;
0421   unsigned int jsnErrorEvents = 0;
0422   unsigned int jsnRetCodeMask = 0;
0423   std::string jsnInputFiles = "";
0424   unsigned int jsnHLTErrorEvents = 0;
0425 
0426   Json::Value jsn;
0427   jsn[jsoncollector::DataPoint::SOURCE] = sourceHost;
0428   jsn[jsoncollector::DataPoint::DEFINITION] = sOutDef.str();
0429   jsn[jsoncollector::DataPoint::DATA].append(jsnProcessed);
0430   jsn[jsoncollector::DataPoint::DATA].append(jsnAccepted);
0431   jsn[jsoncollector::DataPoint::DATA].append(jsnErrorEvents);
0432   jsn[jsoncollector::DataPoint::DATA].append(jsnRetCodeMask);
0433   jsn[jsoncollector::DataPoint::DATA].append(jsndataFileList);
0434   jsn[jsoncollector::DataPoint::DATA].append(jsndataSize);
0435   jsn[jsoncollector::DataPoint::DATA].append(jsnInputFiles);
0436   jsn[jsoncollector::DataPoint::DATA].append(jsndataAdler32);
0437   jsn[jsoncollector::DataPoint::DATA].append(rundata.streamDestination);
0438   jsn[jsoncollector::DataPoint::DATA].append(rundata.streamMergeType);
0439   jsn[jsoncollector::DataPoint::DATA].append(jsnHLTErrorEvents);
0440 
0441   auto jsnFileName = fmt::sprintf("run%06d_ls%04d_streamL1Rates_pid%05d.jsn", run, ls, getpid());
0442   std::ofstream jsnFile(rundata.baseRunDir + "/" + jsnFileName);
0443   jsnFile << writer.write(jsn);
0444   jsnFile.close();
0445 }
0446 
0447 void L1TriggerJSONMonitoring::writeJsdFile(L1TriggerJSONMonitoringData::run const& rundata) {
0448   std::ofstream file(rundata.baseRunDir + "/" + rundata.jsdFileName);
0449   file << R"""({
0450    "data" : [
0451       { "name" : "Processed", "type" : "integer", "operation" : "histo"},
0452       { "name" : "L1-AlgoAccepted", "type" : "integer", "operation" : "histo"},
0453       { "name" : "L1-AlgoAccepted-Physics", "type" : "integer", "operation" : "histo"},
0454       { "name" : "L1-AlgoAccepted-Calibration", "type" : "integer", "operation" : "histo"},
0455       { "name" : "L1-AlgoAccepted-Random", "type" : "integer", "operation" : "histo"},
0456       { "name" : "L1-Global", "type" : "integer", "operation" : "histo"},
0457       { "name" : "Prescale-Index", "type" : "integer", "operation" : "sample"}
0458    ]
0459 })""";
0460   file.close();
0461 }
0462 
0463 void L1TriggerJSONMonitoring::writeIniFile(L1TriggerJSONMonitoringData::run const& rundata,
0464                                            unsigned int run,
0465                                            std::vector<std::string> const& l1TriggerNames) {
0466   Json::Value content;
0467 
0468   Json::Value triggerNames(Json::arrayValue);
0469   for (auto const& name : l1TriggerNames)
0470     triggerNames.append(name);
0471   content["L1-Algo-Names"] = triggerNames;
0472 
0473   Json::Value eventTypes(Json::arrayValue);
0474   eventTypes.append(tcdsTriggerTypes_[edm::EventAuxiliary::PhysicsTrigger]);
0475   eventTypes.append(tcdsTriggerTypes_[edm::EventAuxiliary::CalibrationTrigger]);
0476   eventTypes.append(tcdsTriggerTypes_[edm::EventAuxiliary::RandomTrigger]);
0477   /* FIXME send information for all event types instead of only these three
0478   for (auto const& name : tcdsTriggerTypes_)
0479     eventTypes.append(name);
0480   */
0481   content["Event-Type"] = eventTypes;
0482 
0483   std::string iniFileName = fmt::sprintf("run%06d_ls0000_streamL1Rates_pid%05d.ini", run, getpid());
0484   std::ofstream file(rundata.baseRunDir + "/" + iniFileName);
0485   Json::StyledWriter writer;
0486   file << writer.write(content);
0487   file.close();
0488 }
0489 
0490 // declare as a framework plugin
0491 #include "FWCore/ServiceRegistry/interface/ServiceMaker.h"
0492 #include "FWCore/Framework/interface/MakerMacros.h"
0493 DEFINE_FWK_MODULE(L1TriggerJSONMonitoring);