CMS 3D CMS Logo

L1TriggerJSONMonitoring.cc
Go to the documentation of this file.
1 
7 #include <atomic>
8 #include <fstream>
9 
10 #include <fmt/printf.h>
11 
33 
35  // special values for prescale index checks
36  static constexpr const int kPrescaleUndefined = -2;
37  static constexpr const int kPrescaleConflict = -1;
38  // variables accumulated event by event in each stream
39  struct stream {
40  unsigned int processed = 0; // number of events processed
41  std::vector<unsigned int> l1tAccept; // number of events accepted by each L1 trigger
42  std::vector<unsigned int> l1tAcceptPhysics; // number of "physics" events accepted by each L1 trigger
43  std::vector<unsigned int> l1tAcceptCalibration; // number of "calibration" events accepted by each L1 trigger
44  std::vector<unsigned int> l1tAcceptRandom; // number of "random" events accepted by each L1 trigger
45  std::vector<unsigned int> tcdsAccept; // number of "physics", "calibration", "random" and other event types
46  int prescaleIndex = kPrescaleUndefined; // prescale column index
47  };
48 
49  // variables initialised for each run
50  struct run {
53  std::string baseRunDir; // base directory from EvFDaqDirector
54  std::string jsdFileName; // definition file name for JSON with rates
55  };
56 
57  // variables accumulated over the whole lumisection
58  struct lumisection {
59  jsoncollector::HistoJ<unsigned int> processed; // number of events processed
60  jsoncollector::HistoJ<unsigned int> l1tAccept; // number of events accepted by each L1 trigger
61  jsoncollector::HistoJ<unsigned int> l1tAcceptPhysics; // number of "physics" events accepted by each L1 trigger
63  l1tAcceptCalibration; // number of "calibration" events accepted by each L1 trigger
64  jsoncollector::HistoJ<unsigned int> l1tAcceptRandom; // number of "random" events accepted by each L1 trigger
65  jsoncollector::HistoJ<unsigned int> tcdsAccept; // number of "physics", "calibration", "random" and other event types
66  int prescaleIndex = kPrescaleUndefined; // prescale column index
67  };
68 };
69 
71  // per-stream information
72  edm::StreamCache<L1TriggerJSONMonitoringData::stream>,
73  // per-run accounting
74  edm::RunCache<L1TriggerJSONMonitoringData::run>,
75  // accumulate per-lumisection statistics
76  edm::LuminosityBlockSummaryCache<L1TriggerJSONMonitoringData::lumisection> > {
77 public:
78  // constructor
80 
81  // destructor
82  ~L1TriggerJSONMonitoring() override = default;
83 
84  // validate the configuration and optionally fill the default values
85  static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
86 
87  // called for each Event
88  void analyze(edm::StreamID, edm::Event const&, edm::EventSetup const&) const override;
89 
90  // -- inherited from edm::StreamCache<L1TriggerJSONMonitoringData::stream>
91 
92  // called once for each Stream being used in the job to create the cache object that will be used for that particular Stream
93  std::unique_ptr<L1TriggerJSONMonitoringData::stream> beginStream(edm::StreamID) const override;
94 
95  // called when the Stream is switching from one LuminosityBlock to a new LuminosityBlock.
97 
98  // -- inherited from edm::RunCache<L1TriggerJSONMonitoringData::run>
99 
100  // called each time the Source sees a new Run, and guaranteed to finish before any Stream calls streamBeginRun for that same Run
101  std::shared_ptr<L1TriggerJSONMonitoringData::run> globalBeginRun(edm::Run const&,
102  edm::EventSetup const&) const override;
103 
104  // called after all Streams have finished processing a given Run (i.e. streamEndRun for all Streams have completed)
105  void globalEndRun(edm::Run const&, edm::EventSetup const&) const override;
106 
107  // -- inherited from edm::LuminosityBlockSummaryCache<L1TriggerJSONMonitoringData::lumisection>
108 
109  // called each time the Source sees a new LuminosityBlock
110  std::shared_ptr<L1TriggerJSONMonitoringData::lumisection> globalBeginLuminosityBlockSummary(
111  edm::LuminosityBlock const&, edm::EventSetup const&) const override;
112 
113  // called when a Stream has finished processing a LuminosityBlock, after streamEndLuminosityBlock
115  edm::LuminosityBlock const&,
116  edm::EventSetup const&,
118 
119  // called after the streamEndLuminosityBlockSummary method for all Streams have finished processing a given LuminosityBlock
121  edm::EventSetup const&,
123 
124 private:
125  // TCDS trigger types
126  // see https://twiki.cern.ch/twiki/bin/viewauth/CMS/TcdsEventRecord
127  static constexpr const std::array<const char*, 16> tcdsTriggerTypes_ = {{
128  "Error", // 0 - No trigger (DAQ error stream events may have this value)
129  "Physics", // 1 - GT trigger
130  "Calibration", // 2 - Sequence trigger (calibration)
131  "Random", // 3 - Random trigger
132  "Auxiliary", // 4 - Auxiliary (CPM front panel NIM input) trigger
133  "", // 5 - reserved
134  "", // 6 - reserved
135  "", // 7 - reserved
136  "Cyclic", // 8 - Cyclic trigger
137  "Bunch-pattern", // 9 - Bunch-pattern trigger
138  "Software", // 10 - Software trigger
139  "TTS", // 11 - TTS-sourced trigger
140  "", // 12 - reserved
141  "", // 13 - reserved
142  "", // 14 - reserved
143  "" // 15 - reserved
144  }};
145 
146  static constexpr const char* streamName_ = "streamL1Rates";
147 
149  static void writeIniFile(L1TriggerJSONMonitoringData::run const&, unsigned int, std::vector<std::string> const&);
150 
151  // configuration
152  const edm::InputTag level1Results_; // InputTag for L1 trigger results
155 };
156 
157 // instantiate static data members
158 constexpr const std::array<const char*, 16> L1TriggerJSONMonitoring::tcdsTriggerTypes_;
159 
160 // constructor
162  : level1Results_(config.getParameter<edm::InputTag>("L1Results")),
163  level1ResultsToken_(consumes<GlobalAlgBlkBxCollection>(level1Results_)),
164  l1tUtmTriggerMenuRcdToken_(esConsumes<edm::Transition::BeginRun>()) {
165  if (edm::Service<evf::EvFDaqDirector>().isAvailable()) {
166  //output initemp file. This lets hltd know number of streams early
167  std::string initFileName = edm::Service<evf::EvFDaqDirector>()->getInitTempFilePath("streamL1Rates");
168  std::ofstream file(initFileName);
169  if (!file)
170  throw cms::Exception("L1TriggerJsonMonitoring")
171  << "Cannot create INITEMP file: " << initFileName << " error: " << strerror(errno);
172  file.close();
173  }
174 }
175 
176 // validate the configuration and optionally fill the default values
179  desc.add<edm::InputTag>("L1Results", edm::InputTag("hltGtStage2Digis"));
180  descriptions.add("L1TriggerJSONMonitoring", desc);
181 }
182 
183 // called once for each Stream being used in the job to create the cache object that will be used for that particular Stream
184 std::unique_ptr<L1TriggerJSONMonitoringData::stream> L1TriggerJSONMonitoring::beginStream(edm::StreamID) const {
185  return std::make_unique<L1TriggerJSONMonitoringData::stream>();
186 }
187 
188 // called each time the Source sees a new Run, and guaranteed to finish before any Stream calls streamBeginRun for that same Run
189 std::shared_ptr<L1TriggerJSONMonitoringData::run> L1TriggerJSONMonitoring::globalBeginRun(
190  edm::Run const& run, edm::EventSetup const& setup) const {
191  auto rundata = std::make_shared<L1TriggerJSONMonitoringData::run>();
192 
193  // set the DAQ parameters
195  rundata->streamDestination = edm::Service<evf::EvFDaqDirector>()->getStreamDestinations(streamName_);
196  rundata->streamMergeType =
198  rundata->baseRunDir = edm::Service<evf::EvFDaqDirector>()->baseRunDir();
199  } else {
200  rundata->streamDestination = "";
201  rundata->streamMergeType = "";
202  rundata->baseRunDir = ".";
203  }
204 
205  // read the L1 trigger names from the EventSetup
206  std::vector<std::string> triggerNames(GlobalAlgBlk::maxPhysicsTriggers, ""s);
207  auto const& menuHandle = setup.getHandle(l1tUtmTriggerMenuRcdToken_);
208  if (menuHandle.isValid()) {
209  for (auto const& algo : menuHandle->getAlgorithmMap())
210  triggerNames[algo.second.getIndex()] = algo.first;
211  } else {
212  edm::LogWarning("L1TriggerJSONMonitoring") << "L1TUtmTriggerMenu not found in the EventSetup.\nThe Level 1 Trigger "
213  "rate monitoring will not include the trigger names.";
214  }
215 
216  // write the per-run .jsd file
217  rundata->jsdFileName = fmt::sprintf("run%06d_ls0000_streamL1Rates_pid%05d.jsd", run.run(), getpid());
218  writeJsdFile(*rundata);
219 
220  // write the per-run .ini file
221  //iniFileName = fmt::sprintf("run%06d_ls0000_streamL1Rates_pid%05d.ini", run.run(), getpid());
222  writeIniFile(*rundata, run.run(), triggerNames);
223 
224  return rundata;
225 }
226 
227 // called after all Streams have finished processing a given Run (i.e. streamEndRun for all Streams have completed)
229 
230 // called for each Event
232  auto& stream = *streamCache(sid);
233 
234  ++stream.processed;
235  unsigned int eventType = event.experimentType();
236  if (eventType < tcdsTriggerTypes_.size())
237  ++stream.tcdsAccept[eventType];
238  else
239  edm::LogWarning("L1TriggerJSONMonitoring") << "Unexpected event type " << eventType;
240 
241  // get hold of TriggerResults
243  if (not event.getByToken(level1ResultsToken_, handle) or not handle.isValid() or handle->isEmpty(0)) {
244  edm::LogError("L1TriggerJSONMonitoring")
245  << "L1 trigger results with label [" + level1Results_.encode() + "] not present or invalid";
246  return;
247  }
248 
249  // The GlobalAlgBlkBxCollection is a vector of vectors, but the second layer can only ever
250  // have one entry since there can't be more than one collection per bunch crossing.
251  // The first "0" here means BX = 0, while the second "0" is used to access the first and only element.
252  auto const& results = handle->at(0, 0);
253  auto const& decision = results.getAlgoDecisionFinal();
254  assert(decision.size() == GlobalAlgBlk::maxPhysicsTriggers);
255 
256  // check the results for each HLT path
257  for (unsigned int i = 0; i < decision.size(); ++i) {
258  if (decision[i]) {
259  ++stream.l1tAccept[i];
260  switch (eventType) {
262  ++stream.l1tAcceptPhysics[i];
263  break;
265  ++stream.l1tAcceptCalibration[i];
266  break;
268  ++stream.l1tAcceptRandom[i];
269  break;
270  default:
271  break;
272  }
273  }
274  }
275 
276  // check for conflicting values in the prescale column index, and store it
277  int prescaleIndex = results.getPreScColumn();
279  stream.prescaleIndex = prescaleIndex;
280  } else if (stream.prescaleIndex == L1TriggerJSONMonitoringData::kPrescaleConflict) {
281  // do nothing
282  } else if (stream.prescaleIndex != prescaleIndex) {
283  edm::LogWarning("L1TriggerJSONMonitoring") << "Prescale index changed from " << stream.prescaleIndex << " to "
284  << prescaleIndex << " inside lumisection " << event.luminosityBlock();
286  }
287 }
288 
289 // called each time the Source sees a new LuminosityBlock
290 std::shared_ptr<L1TriggerJSONMonitoringData::lumisection> L1TriggerJSONMonitoring::globalBeginLuminosityBlockSummary(
291  edm::LuminosityBlock const& lumi, edm::EventSetup const&) const {
292  // the API of jsoncollector::HistoJ does not really match our use case,
293  // but it is the only vector-like object available in JsonMonitorable.h
294  auto lumidata = std::make_shared<L1TriggerJSONMonitoringData::lumisection>(L1TriggerJSONMonitoringData::lumisection{
295  jsoncollector::HistoJ<unsigned int>(1), // processed
301  });
302  // repeated calls to `update` necessary to set the internal element counter
303  lumidata->processed.update(0);
304  for (unsigned int i = 0; i < GlobalAlgBlk::maxPhysicsTriggers; ++i)
305  lumidata->l1tAccept.update(0);
306  for (unsigned int i = 0; i < GlobalAlgBlk::maxPhysicsTriggers; ++i)
307  lumidata->l1tAcceptPhysics.update(0);
308  for (unsigned int i = 0; i < GlobalAlgBlk::maxPhysicsTriggers; ++i)
309  lumidata->l1tAcceptCalibration.update(0);
310  for (unsigned int i = 0; i < GlobalAlgBlk::maxPhysicsTriggers; ++i)
311  lumidata->l1tAcceptRandom.update(0);
312  for (unsigned int i = 0; i < tcdsTriggerTypes_.size(); ++i)
313  lumidata->tcdsAccept.update(0);
314  lumidata->prescaleIndex = L1TriggerJSONMonitoringData::kPrescaleUndefined;
315 
316  return lumidata;
317 }
318 
319 // called when the Stream is switching from one LuminosityBlock to a new LuminosityBlock.
321  edm::LuminosityBlock const& lumi,
322  edm::EventSetup const&) const {
323  auto& stream = *streamCache(sid);
324 
325  // reset the stream counters
326  stream.processed = 0;
327  stream.l1tAccept.assign(GlobalAlgBlk::maxPhysicsTriggers, 0);
328  stream.l1tAcceptPhysics.assign(GlobalAlgBlk::maxPhysicsTriggers, 0);
329  stream.l1tAcceptCalibration.assign(GlobalAlgBlk::maxPhysicsTriggers, 0);
330  stream.l1tAcceptRandom.assign(GlobalAlgBlk::maxPhysicsTriggers, 0);
331  stream.tcdsAccept.assign(tcdsTriggerTypes_.size(), 0);
333 }
334 
335 // called when a Stream has finished processing a LuminosityBlock, after streamEndLuminosityBlock
337  edm::LuminosityBlock const& lumi,
338  edm::EventSetup const&,
340  auto const& stream = *streamCache(sid);
341  lumidata->processed.value()[0] += stream.processed;
342 
343  for (unsigned int i = 0; i < GlobalAlgBlk::maxPhysicsTriggers; ++i) {
344  lumidata->l1tAccept.value()[i] += stream.l1tAccept[i];
345  lumidata->l1tAcceptPhysics.value()[i] += stream.l1tAcceptPhysics[i];
346  lumidata->l1tAcceptCalibration.value()[i] += stream.l1tAcceptCalibration[i];
347  lumidata->l1tAcceptRandom.value()[i] += stream.l1tAcceptRandom[i];
348  }
349  for (unsigned int i = 0; i < tcdsTriggerTypes_.size(); ++i)
350  lumidata->tcdsAccept.value()[i] += stream.tcdsAccept[i];
351 
352  // check for conflicting values in the prescale column index
354  lumidata->prescaleIndex = stream.prescaleIndex;
355  else if (lumidata->prescaleIndex != stream.prescaleIndex)
357 }
358 
359 // called after the streamEndLuminosityBlockSummary method for all Streams have finished processing a given LuminosityBlock
361  edm::EventSetup const&,
363  unsigned int ls = lumi.luminosityBlock();
364  unsigned int run = lumi.run();
365 
366  bool writeFiles = true;
367  if (edm::Service<evf::MicroStateService>().isAvailable()) {
370  if (fms)
371  writeFiles = fms->shouldWriteFiles(ls);
372  }
373  if (not writeFiles)
374  return;
375 
376  unsigned int processed = lumidata->processed.value().at(0);
377  auto const& rundata = *runCache(lumi.getRun().index());
379 
380  // [SIC]
381  char hostname[33];
382  gethostname(hostname, 32);
383  std::string sourceHost(hostname);
384 
385  // [SIC]
386  std::stringstream sOutDef;
387  sOutDef << rundata.baseRunDir << "/"
388  << "output_" << getpid() << ".jsd";
389 
390  std::string jsndataFileList = "";
391  unsigned int jsndataSize = 0;
392  unsigned int jsndataAdler32 = 1; // adler32 checksum for an empty file
393 
394  if (processed) {
395  // write the .jsndata files which contain the actual rates
396  Json::Value jsndata;
397  jsndata[jsoncollector::DataPoint::SOURCE] = sourceHost;
398  jsndata[jsoncollector::DataPoint::DEFINITION] = rundata.jsdFileName;
404 
405  // write only the number of "physics", "calibration" and "random" events
410  jsndata[jsoncollector::DataPoint::DATA].append(tcdsAccept.toJsonValue());
411  /* FIXME send information for all event types instead of only these three
412  jsndata[jsoncollector::DataPoint::DATA].append(lumidata->tcdsAccept.toJsonValue());
413  */
415 
416  auto jsndataFileName = fmt::sprintf("run%06d_ls%04d_streamL1Rates_pid%05d.jsndata", run, ls, getpid());
417 
418  std::string result = writer.write(jsndata);
419  std::ofstream jsndataFile(rundata.baseRunDir + "/" + jsndataFileName);
420  jsndataFile << result;
421  jsndataFile.close();
422 
423  jsndataFileList = jsndataFileName;
424  jsndataSize = result.size();
425  jsndataAdler32 = cms::Adler32(result.c_str(), result.size());
426  }
427 
428  // create a metadata json file for the "HLT rates" pseudo-stream
429  unsigned int jsnProcessed = processed;
430  unsigned int jsnAccepted = processed;
431  unsigned int jsnErrorEvents = 0;
432  unsigned int jsnRetCodeMask = 0;
433  std::string jsnInputFiles = "";
434  unsigned int jsnHLTErrorEvents = 0;
435 
436  Json::Value jsn;
437  jsn[jsoncollector::DataPoint::SOURCE] = sourceHost;
438  jsn[jsoncollector::DataPoint::DEFINITION] = sOutDef.str();
439  jsn[jsoncollector::DataPoint::DATA].append(jsnProcessed);
440  jsn[jsoncollector::DataPoint::DATA].append(jsnAccepted);
441  jsn[jsoncollector::DataPoint::DATA].append(jsnErrorEvents);
442  jsn[jsoncollector::DataPoint::DATA].append(jsnRetCodeMask);
443  jsn[jsoncollector::DataPoint::DATA].append(jsndataFileList);
444  jsn[jsoncollector::DataPoint::DATA].append(jsndataSize);
445  jsn[jsoncollector::DataPoint::DATA].append(jsnInputFiles);
446  jsn[jsoncollector::DataPoint::DATA].append(jsndataAdler32);
447  jsn[jsoncollector::DataPoint::DATA].append(rundata.streamDestination);
448  jsn[jsoncollector::DataPoint::DATA].append(rundata.streamMergeType);
449  jsn[jsoncollector::DataPoint::DATA].append(jsnHLTErrorEvents);
450 
451  auto jsnFileName = fmt::sprintf("run%06d_ls%04d_streamL1Rates_pid%05d.jsn", run, ls, getpid());
452  std::ofstream jsnFile(rundata.baseRunDir + "/" + jsnFileName);
453  jsnFile << writer.write(jsn);
454  jsnFile.close();
455 }
456 
458  std::ofstream file(rundata.baseRunDir + "/" + rundata.jsdFileName);
459  file << R"""({
460  "data" : [
461  { "name" : "Processed", "type" : "integer", "operation" : "histo"},
462  { "name" : "L1-AlgoAccepted", "type" : "integer", "operation" : "histo"},
463  { "name" : "L1-AlgoAccepted-Physics", "type" : "integer", "operation" : "histo"},
464  { "name" : "L1-AlgoAccepted-Calibration", "type" : "integer", "operation" : "histo"},
465  { "name" : "L1-AlgoAccepted-Random", "type" : "integer", "operation" : "histo"},
466  { "name" : "L1-Global", "type" : "integer", "operation" : "histo"},
467  { "name" : "Prescale-Index", "type" : "integer", "operation" : "sample"}
468  ]
469 })""";
470  file.close();
471 }
472 
474  unsigned int run,
475  std::vector<std::string> const& l1TriggerNames) {
477 
479  for (auto const& name : l1TriggerNames)
480  triggerNames.append(name);
481  content["L1-Algo-Names"] = triggerNames;
482 
487  /* FIXME send information for all event types instead of only these three
488  for (auto const& name : tcdsTriggerTypes_)
489  eventTypes.append(name);
490  */
491  content["Event-Type"] = eventTypes;
492 
493  std::string iniFileName = fmt::sprintf("run%06d_ls0000_streamL1Rates_pid%05d.ini", run, getpid());
494  std::ofstream file(rundata.baseRunDir + "/" + iniFileName);
496  file << writer.write(content);
497  file.close();
498 }
499 
500 // declare as a framework plugin
jsoncollector::HistoJ< unsigned int > l1tAcceptRandom
static constexpr const int kPrescaleConflict
static void writeJsdFile(L1TriggerJSONMonitoringData::run const &)
ESGetTokenH3DDVariant esConsumes(std::string const &Record, edm::ConsumesCollector &)
Definition: DeDxTools.cc:283
const edm::InputTag level1Results_
jsoncollector::HistoJ< unsigned int > l1tAccept
static const std::string SOURCE
Definition: DataPoint.h:116
std::vector< unsigned int > l1tAcceptPhysics
std::string encode() const
Definition: InputTag.cc:159
void globalEndLuminosityBlockSummary(edm::LuminosityBlock const &, edm::EventSetup const &, L1TriggerJSONMonitoringData::lumisection *) const override
Value & append(const Value &value)
Append value to array at the end.
jsoncollector::HistoJ< unsigned int > l1tAcceptCalibration
jsoncollector::HistoJ< unsigned int > processed
Definition: config.py:1
Represents a JSON value.
Definition: value.h:99
Log< level::Error, false > LogError
uint32_t T const *__restrict__ uint32_t const *__restrict__ int32_t int Histo::index_type cudaStream_t stream
assert(be >=bs)
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
std::vector< T > & value()
static const std::string DATA
Definition: DataPoint.h:118
jsoncollector::HistoJ< unsigned int > tcdsAccept
static void writeIniFile(L1TriggerJSONMonitoringData::run const &, unsigned int, std::vector< std::string > const &)
static constexpr const int kPrescaleUndefined
std::shared_ptr< L1TriggerJSONMonitoringData::lumisection > globalBeginLuminosityBlockSummary(edm::LuminosityBlock const &, edm::EventSetup const &) const override
std::vector< unsigned int > l1tAcceptRandom
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
Transition
Definition: Transition.h:12
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
jsoncollector::HistoJ< unsigned int > l1tAcceptPhysics
void Adler32(char const *data, size_t len, uint32_t &a, uint32_t &b)
def ls(path, rec=False)
Definition: eostools.py:349
virtual Json::Value toJsonValue() const
void globalEndRun(edm::Run const &, edm::EventSetup const &) const override
void add(std::string const &label, ParameterSetDescription const &psetDescription)
static constexpr const std::array< const char *, 16 > tcdsTriggerTypes_
const edm::ESGetToken< L1TUtmTriggerMenu, L1TUtmTriggerMenuRcd > l1tUtmTriggerMenuRcdToken_
void streamEndLuminosityBlockSummary(edm::StreamID, edm::LuminosityBlock const &, edm::EventSetup const &, L1TriggerJSONMonitoringData::lumisection *) const override
void streamBeginLuminosityBlock(edm::StreamID, edm::LuminosityBlock const &, edm::EventSetup const &) const override
void analyze(edm::StreamID, edm::Event const &, edm::EventSetup const &) const override
std::unique_ptr< L1TriggerJSONMonitoringData::stream > beginStream(edm::StreamID) const override
HLT enums.
L1TriggerJSONMonitoring(const edm::ParameterSet &)
std::vector< unsigned int > l1tAcceptCalibration
static constexpr unsigned int maxPhysicsTriggers
Definition: GlobalAlgBlk.h:52
std::shared_ptr< L1TriggerJSONMonitoringData::run > globalBeginRun(edm::Run const &, edm::EventSetup const &) const override
bool isAvailable() const
Definition: Service.h:40
Log< level::Warning, false > LogWarning
const edm::EDGetTokenT< GlobalAlgBlkBxCollection > level1ResultsToken_
Writes a Value in JSON format in a human friendly way.
Definition: writer.h:63
bool shouldWriteFiles(unsigned int lumi, unsigned int *proc=nullptr)
static const std::string DEFINITION
Definition: DataPoint.h:117
static constexpr const char * streamName_
~L1TriggerJSONMonitoring() override=default
Definition: event.py:1
Definition: Run.h:45
array value (ordered list)
Definition: value.h:30