From 201fcab9f0816e10c46a87be2dc5b9e257874536 Mon Sep 17 00:00:00 2001
From: Tim Martin <tim.martin@cern.ch>
Date: Fri, 2 Aug 2019 13:51:17 +0000
Subject: [PATCH] Addition of TrigCost python configuration. Modern CA
 configuration inside newJOtest.py -> TriggerConfig.py Old
 random-python-everywhere configuration inside full_menu.py

---
 .../python/ComponentAccumulator.py            |  6 ++-
 .../python/UnifyProperties.py                 |  1 +
 .../TrigCostAnalysis/src/TrigCostAnalysis.cxx |  5 +++
 .../TrigCostAnalysis/src/TrigCostAnalysis.h   |  2 +-
 .../TrigCostMonitorMT/CMakeLists.txt          |  2 +-
 .../python/TrigCostMonitorMTConfig.py         | 28 +++++++++++++
 .../TrigCostMonitorMT/src/AlgorithmPayload.h  |  1 +
 .../TrigCostMonitorMT/src/TrigCostMTSvc.cxx   | 41 +++++++++++++------
 .../TrigCostMonitorMT/src/TrigCostMTSvc.h     |  6 +--
 .../L1Decoder/python/L1DecoderConfig.py       |  9 +++-
 Trigger/TrigSteer/L1Decoder/src/L1Decoder.cxx |  4 +-
 Trigger/TrigSteer/L1Decoder/src/L1Decoder.h   |  2 +-
 .../src/DecisionSummaryMakerAlg.cxx           |  4 +-
 .../src/DecisionSummaryMakerAlg.h             |  4 +-
 .../TrigUpgradeTest/share/newJOtest.py        |  2 +
 .../TrigUpgradeTest/share/testHLT_MT.py       | 20 ++++++++-
 .../TrigValAlgs/src/TrigEDMChecker.cxx        |  2 +-
 .../TrigEDMConfig/python/TriggerEDMRun3.py    |  3 ++
 .../TriggerJobOpts/python/TriggerConfig.py    |  7 +++-
 .../python/TriggerConfigFlags.py              |  9 +++-
 Trigger/TriggerRelease/python/Modifiers.py    | 13 +++++-
 21 files changed, 136 insertions(+), 35 deletions(-)
 create mode 100644 Trigger/TrigMonitoring/TrigCostMonitorMT/python/TrigCostMonitorMTConfig.py

diff --git a/Control/AthenaConfiguration/python/ComponentAccumulator.py b/Control/AthenaConfiguration/python/ComponentAccumulator.py
index e4859ded180..88dff90a128 100644
--- a/Control/AthenaConfiguration/python/ComponentAccumulator.py
+++ b/Control/AthenaConfiguration/python/ComponentAccumulator.py
@@ -385,12 +385,14 @@ class ComponentAccumulator(object):
         if (overwrite or key not in (self._theAppProps)):
             self._theAppProps[key]=value
         else:
-            if isinstance(self._theAppProps[key],collections.Sequence) and not isinstance(self._theAppProps[key],str):
+            if self._theAppProps[key] == value:
+                self._msg.debug("ApplicationMgr property '%s' already set to '%s'.", key, value)
+            elif isinstance(self._theAppProps[key],collections.Sequence) and not isinstance(self._theAppProps[key],str):
                 value=unifySet(self._theAppProps[key],value)
                 self._msg.info("ApplicationMgr property '%s' already set to '%s'. Overwriting with %s", key, self._theAppProps[key], value)
                 self._theAppProps[key]=value
             else:
-                raise DeduplicationFailed("AppMgr property %s set twice: %s and %s",key,(self._theAppProps[key],value))
+                raise DeduplicationFailed("AppMgr property %s set twice: %s and %s" % (key, self._theAppProps[key], value))
 
 
         pass
diff --git a/Control/AthenaConfiguration/python/UnifyProperties.py b/Control/AthenaConfiguration/python/UnifyProperties.py
index bc5617ec562..91f07d1ed2b 100644
--- a/Control/AthenaConfiguration/python/UnifyProperties.py
+++ b/Control/AthenaConfiguration/python/UnifyProperties.py
@@ -78,6 +78,7 @@ _propsToUnify={"GeoModelSvc.DetectorTools":unifySet,
                "*.InputMakerInputDecisions": unifySet,
                "*.InputMakerOutputDecisions": unifySet,
                "AddressRemappingSvc.TypeKeyRenameMaps": unifySet,
+               "AuditorSvc.Auditors": unifySet,
                }
 
 def setUnificationFunction(key, function):
diff --git a/Trigger/TrigCost/TrigCostAnalysis/src/TrigCostAnalysis.cxx b/Trigger/TrigCost/TrigCostAnalysis/src/TrigCostAnalysis.cxx
index 630e75af10d..8f6495db64b 100644
--- a/Trigger/TrigCost/TrigCostAnalysis/src/TrigCostAnalysis.cxx
+++ b/Trigger/TrigCost/TrigCostAnalysis/src/TrigCostAnalysis.cxx
@@ -19,7 +19,9 @@ TrigCostAnalysis::TrigCostAnalysis( const std::string& name, ISvcLocator* pSvcLo
 StatusCode  TrigCostAnalysis::initialize() {
   ATH_MSG_VERBOSE("In initialize()");
 
+  ATH_MSG_DEBUG("Reading from " << m_costDataKey.key());
   ATH_CHECK( m_costDataKey.initialize() );
+
   if (!m_enhancedBiasTool.name().empty()) {
     ATH_CHECK( m_enhancedBiasTool.retrieve() );
   } else {
@@ -29,10 +31,12 @@ StatusCode  TrigCostAnalysis::initialize() {
       return StatusCode::FAILURE;
     }
   }
+
   ATH_CHECK( m_TimeRangeLengthLB > 0 );
   if (m_hashDictionaryFromFile) {
     TrigConf::HLTUtils::file2hashes();
   }
+  
   return StatusCode::SUCCESS;
 }
 
@@ -69,6 +73,7 @@ StatusCode TrigCostAnalysis::execute() {
     ATH_MSG_DEBUG("Monitoring event " << context.eventID().event_number() << " in range " << range->getName());
     
     SG::ReadHandle<xAOD::TrigCompositeContainer> costDataHandle(m_costDataKey, context);
+    ATH_CHECK( costDataHandle.isValid() );
 
     CostData costData;
     ATH_CHECK( costData.set(costDataHandle.get()) );
diff --git a/Trigger/TrigCost/TrigCostAnalysis/src/TrigCostAnalysis.h b/Trigger/TrigCost/TrigCostAnalysis/src/TrigCostAnalysis.h
index 302c3b3dd7a..ea3bfe6b1db 100644
--- a/Trigger/TrigCost/TrigCostAnalysis/src/TrigCostAnalysis.h
+++ b/Trigger/TrigCost/TrigCostAnalysis/src/TrigCostAnalysis.h
@@ -96,7 +96,7 @@ class TrigCostAnalysis: public ::AthHistogramAlgorithm {
     Gaudi::Property<float> m_baseEventWeight { this, "BaseEventWeight", true,
       "Base events weight, other weights may be multiplied on top of this one." };
 
-    SG::ReadHandleKey<xAOD::TrigCompositeContainer> m_costDataKey { this, "AlgorithmCostDataKey", "TrigCostContainer",
+    SG::ReadHandleKey<xAOD::TrigCompositeContainer> m_costDataKey { this, "CostReadHandleKey", "HLT_TrigCostContainer",
       "Trigger cost payload container for algorithms" };
 
     ToolHandle<IEnhancedBiasWeighter> m_enhancedBiasTool{this, "EnhancedBiasTool", "",
diff --git a/Trigger/TrigMonitoring/TrigCostMonitorMT/CMakeLists.txt b/Trigger/TrigMonitoring/TrigCostMonitorMT/CMakeLists.txt
index 062da07d079..ca3bed2bbfe 100644
--- a/Trigger/TrigMonitoring/TrigCostMonitorMT/CMakeLists.txt
+++ b/Trigger/TrigMonitoring/TrigCostMonitorMT/CMakeLists.txt
@@ -28,4 +28,4 @@ atlas_add_component( TrigCostMonitorMT
 
 # Install files from the package:
 atlas_install_headers( TrigCostMonitorMT )
-atlas_install_joboptions( share/*.py )
+atlas_install_python_modules( python/*.py)
diff --git a/Trigger/TrigMonitoring/TrigCostMonitorMT/python/TrigCostMonitorMTConfig.py b/Trigger/TrigMonitoring/TrigCostMonitorMT/python/TrigCostMonitorMTConfig.py
new file mode 100644
index 00000000000..3916e8fd1bf
--- /dev/null
+++ b/Trigger/TrigMonitoring/TrigCostMonitorMT/python/TrigCostMonitorMTConfig.py
@@ -0,0 +1,28 @@
+#
+#  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+#
+
+
+def TrigCostMonitorMTCfg(flags):
+    """
+    Component Accumulator based configuration of Trigger Cost MT Service and associated Auditor
+    """
+
+    from TrigCostMonitorMT.TrigCostMonitorMTConf import TrigCostMTAuditor, TrigCostMTSvc
+    from GaudiSvc.GaudiSvcConf import AuditorSvc
+    from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
+
+    acc = ComponentAccumulator()
+
+    if flags.Trigger.CostMonitoring.doCostMonitoring:
+      trigCostService = TrigCostMTSvc()
+      trigCostService.MonitorAllEvents = flags.Trigger.CostMonitoring.monitorAllEvents
+      trigCostService.SaveHashes = True # This option will go away once the TrigConfigSvc is fully up & running
+      acc.addService(trigCostService)
+
+      auditorService = AuditorSvc()
+      auditorService += TrigCostMTAuditor()
+      acc.addService(auditorService)
+      acc.setAppProperty("AuditAlgorithms", True)
+
+    return acc
diff --git a/Trigger/TrigMonitoring/TrigCostMonitorMT/src/AlgorithmPayload.h b/Trigger/TrigMonitoring/TrigCostMonitorMT/src/AlgorithmPayload.h
index 2de2c5fbc15..c67f6dc39c8 100644
--- a/Trigger/TrigMonitoring/TrigCostMonitorMT/src/AlgorithmPayload.h
+++ b/Trigger/TrigMonitoring/TrigCostMonitorMT/src/AlgorithmPayload.h
@@ -17,6 +17,7 @@ struct AlgorithmPayload {
   TrigTimeStamp m_algStartTime;
   std::thread::id m_algThreadID;
   int32_t m_algROIID;
+  uint32_t m_slot;
 };
 
 
diff --git a/Trigger/TrigMonitoring/TrigCostMonitorMT/src/TrigCostMTSvc.cxx b/Trigger/TrigMonitoring/TrigCostMonitorMT/src/TrigCostMTSvc.cxx
index 6c329d4fbed..45149908a77 100644
--- a/Trigger/TrigMonitoring/TrigCostMonitorMT/src/TrigCostMTSvc.cxx
+++ b/Trigger/TrigMonitoring/TrigCostMonitorMT/src/TrigCostMTSvc.cxx
@@ -31,10 +31,17 @@ TrigCostMTSvc::~TrigCostMTSvc() {
 
 StatusCode TrigCostMTSvc::initialize() {
   ATH_MSG_DEBUG("TrigCostMTSvc initialize()");
+  m_eventSlots = Gaudi::Concurrency::ConcurrencyFlags::numConcurrentEvents();
+  // TODO Remove this when the configuration is correctly propagated in config-then-run jobs
+  if (!m_eventSlots) {
+    ATH_MSG_WARNING("numConcurrentEvents() == 0. This is a misconfiguration, probably coming from running from pickle. "
+      "Setting local m_eventSlots to a 'large' number until this is fixed to allow the job to proceed.");
+    m_eventSlots = 100;
+  }
   ATH_MSG_INFO("Initializing TrigCostMTSvc with " << m_eventSlots << " event slots");
+
   // We cannot have a vector here as atomics are not movable nor copyable. Unique heap arrays are supported by C++
   m_eventMonitored = std::make_unique< std::atomic<bool>[] >( m_eventSlots );
-
   ATH_CHECK(m_algStartInfo.initialize(m_eventSlots));
   ATH_CHECK(m_algStopTime.initialize(m_eventSlots));
 
@@ -52,7 +59,7 @@ StatusCode TrigCostMTSvc::finalize() {
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 
 StatusCode TrigCostMTSvc::startEvent(const EventContext& context, const bool enableMonitoring) {
-  const bool monitoredEvent = (enableMonitoring || m_monitorAll);
+  const bool monitoredEvent = (enableMonitoring || m_monitorAllEvents);
   ATH_CHECK(checkSlot(context));
   m_eventMonitored[ context.slot() ] = monitoredEvent; 
   if (monitoredEvent) {
@@ -74,7 +81,13 @@ StatusCode TrigCostMTSvc::processAlg(const EventContext& context, const std::str
 
   if (type == AuditType::Before) {
 
-    AlgorithmPayload ap{TrigTimeStamp(), std::this_thread::get_id(), getROIID(context)};
+    AlgorithmPayload ap {
+      TrigTimeStamp(),
+      std::this_thread::get_id(),
+      getROIID(context),
+      static_cast<uint32_t>(context.slot())
+    };
+
     ATH_CHECK( m_algStartInfo.insert(ai, ap) );
 
     ATH_MSG_DEBUG("Caller '" << caller << "', '" << ai.m_store << "', began");
@@ -93,10 +106,10 @@ StatusCode TrigCostMTSvc::processAlg(const EventContext& context, const std::str
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 
 StatusCode TrigCostMTSvc::endEvent(const EventContext& context, SG::WriteHandle<xAOD::TrigCompositeContainer>& outputHandle) { 
+  ATH_CHECK(checkSlot(context));
   if (!isMonitoredEvent(context)) return StatusCode::SUCCESS;
 
   // Reset eventMonitored flag
-  ATH_CHECK(checkSlot(context));
   m_eventMonitored[ context.slot() ] = false;
   // Now that this atomic is set to FALSE, additional algs in this event which trigger this service will return on the 
   // second line of TrigCostMTSvc::processAlg. 
@@ -129,22 +142,24 @@ StatusCode TrigCostMTSvc::endEvent(const EventContext& context, SG::WriteHandle<
     result &= tc->setDetail("store", ai.storeHash());
     result &= tc->setDetail("view", ai.m_viewID);
     result &= tc->setDetail("thread", static_cast<uint32_t>( std::hash< std::thread::id >()(ap.m_algThreadID) ));
+    result &= tc->setDetail("slot", ap.m_slot);
     result &= tc->setDetail("roi", ap.m_algROIID);
     result &= tc->setDetail("start", ap.m_algStartTime.microsecondsSinceEpoch());
     result &= tc->setDetail("stop", stopTime.microsecondsSinceEpoch());
     if (!result) ATH_MSG_WARNING("Failed to append one or more details to trigger cost TC");
   }
 
-  if (m_printTimes && msg().level() <= MSG::INFO) {
+  if (msg().level() <= MSG::VERBOSE) {
     ATH_MSG_INFO("--- Trig Cost Event Summary ---");
     for ( const xAOD::TrigComposite* tc : *outputHandle ) {
-      ATH_MSG_INFO("Algorithm:'" << TrigConf::HLTUtils::hash2string( tc->getDetail<TrigConf::HLTHash>("alg"), "ALG") << "'");
-      ATH_MSG_INFO("  Store:'" << TrigConf::HLTUtils::hash2string( tc->getDetail<TrigConf::HLTHash>("store"), "STORE") << "'");
-      ATH_MSG_INFO("  View ID:" << tc->getDetail<int16_t>("view"));
-      ATH_MSG_INFO("  Thread ID Hash:" << tc->getDetail<uint32_t>("thread") );
-      ATH_MSG_INFO("  RoI ID Hash:" << tc->getDetail<int32_t>("roi") );
-      ATH_MSG_INFO("  Start Time:" << tc->getDetail<uint64_t>("start") << " mu s");
-      ATH_MSG_INFO("  Stop Time:" << tc->getDetail<uint64_t>("stop") << " mu s");
+      ATH_MSG_VERBOSE("Algorithm:'" << TrigConf::HLTUtils::hash2string( tc->getDetail<TrigConf::HLTHash>("alg"), "ALG") << "'");
+      ATH_MSG_VERBOSE("  Store:'" << TrigConf::HLTUtils::hash2string( tc->getDetail<TrigConf::HLTHash>("store"), "STORE") << "'");
+      ATH_MSG_VERBOSE("  View ID:" << tc->getDetail<int16_t>("view"));
+      ATH_MSG_VERBOSE("  Thread ID Hash:" << tc->getDetail<uint32_t>("thread") );
+      ATH_MSG_VERBOSE("  Slot:" << tc->getDetail<uint32_t>("slot") );
+      ATH_MSG_VERBOSE("  RoI ID Hash:" << tc->getDetail<int32_t>("roi") );
+      ATH_MSG_VERBOSE("  Start Time:" << tc->getDetail<uint64_t>("start") << " mu s");
+      ATH_MSG_VERBOSE("  Stop Time:" << tc->getDetail<uint64_t>("stop") << " mu s");
     }
   }
   
@@ -155,7 +170,7 @@ StatusCode TrigCostMTSvc::endEvent(const EventContext& context, SG::WriteHandle<
 
 StatusCode TrigCostMTSvc::checkSlot(const EventContext& context) const {
   if (context.slot() >= m_eventSlots) {
-    ATH_MSG_FATAL("Job is using more event slots (" << context.slot() << ") than we configured for, m_eventSlots = " << m_eventSlots);
+    ATH_MSG_FATAL("Job is using event slot #" << context.slot() << ", but we only reserved space for: " << m_eventSlots);
     return StatusCode::FAILURE;
   }
   return StatusCode::SUCCESS;
diff --git a/Trigger/TrigMonitoring/TrigCostMonitorMT/src/TrigCostMTSvc.h b/Trigger/TrigMonitoring/TrigCostMonitorMT/src/TrigCostMTSvc.h
index 356a8889e31..f8ef600ea0e 100644
--- a/Trigger/TrigMonitoring/TrigCostMonitorMT/src/TrigCostMTSvc.h
+++ b/Trigger/TrigMonitoring/TrigCostMonitorMT/src/TrigCostMTSvc.h
@@ -80,10 +80,10 @@ class TrigCostMTSvc : public extends <AthService, ITrigCostMTSvc> {
 
   private: 
 
-  Gaudi::Property<bool>      m_monitorAll{this, "MonitorAll", false, "Monitor every HLT event, e.g. for offline validation."};
-  Gaudi::Property<bool>      m_printTimes{this, "PrintTimes", false, "Sends per-algorithm timing to MSG::INFO."};
+  Gaudi::Property<bool>      m_monitorAllEvents{this, "MonitorAllEvents", false, "Monitor every HLT event, e.g. for offline validation."};
   Gaudi::Property<bool>      m_saveHashes{this, "SaveHashes", false, "Store a copy of the hash dictionary for easier debugging"};
-  Gaudi::Property<unsigned>  m_eventSlots{this, "EventSlots", 0,     "Number of concurrent processing slots."};
+  
+  size_t  m_eventSlots; //!< Number of concurrent processing slots. Cached from Gaudi
 
   /**
    * @return If the event is flagged as being monitored. Allows for a quick return if not
diff --git a/Trigger/TrigSteer/L1Decoder/python/L1DecoderConfig.py b/Trigger/TrigSteer/L1Decoder/python/L1DecoderConfig.py
index b95519f77b8..9ec4e69dc28 100644
--- a/Trigger/TrigSteer/L1Decoder/python/L1DecoderConfig.py
+++ b/Trigger/TrigSteer/L1Decoder/python/L1DecoderConfig.py
@@ -104,7 +104,11 @@ class L1Decoder(L1Decoder) :
             unpackers, rerunUnpackers = createMuonRoIUnpackers()
             self.roiUnpackers += unpackers
             self.rerunRoiUnpackers += rerunUnpackers
-            
+
+        from AthenaConfiguration.AllConfigFlags import ConfigFlags as flags
+        self.DoCostMonitoring = flags.Trigger.CostMonitoring.doCostMonitoring
+        self.CostMonitoringChain = flags.Trigger.CostMonitoring.chain
+
         self.L1DecoderSummaryKey = "L1DecoderSummary"
 
 
@@ -131,7 +135,8 @@ def L1DecoderCfg(flags):
     decoderAlg.roiUnpackers += unpackers
     decoderAlg.rerunRoiUnpackers += rerunUnpackers
 
-
+    decoderAlg.DoCostMonitoring = flags.Trigger.CostMonitoring.doCostMonitoring
+    decoderAlg.CostMonitoringChain = flags.Trigger.CostMonitoring.chain
 
     from TrigConfigSvc.TrigConfigSvcConfig import TrigConfigSvcCfg
     acc.merge( TrigConfigSvcCfg( flags ) )
diff --git a/Trigger/TrigSteer/L1Decoder/src/L1Decoder.cxx b/Trigger/TrigSteer/L1Decoder/src/L1Decoder.cxx
index 9fe4a63d129..2a7f60cbb3d 100644
--- a/Trigger/TrigSteer/L1Decoder/src/L1Decoder.cxx
+++ b/Trigger/TrigSteer/L1Decoder/src/L1Decoder.cxx
@@ -38,7 +38,7 @@ StatusCode L1Decoder::initialize() {
   incidentSvc->addListener(this,"BeginRun", 200);
   incidentSvc.release().ignore();
 
-  if (m_enableCostMonitoring) {
+  if (m_doCostMonitoring) {
     ATH_CHECK( m_trigCostSvcHandle.retrieve() );
   }
 
@@ -134,7 +134,7 @@ StatusCode L1Decoder::execute (const EventContext& ctx) const {
 
   }
   // Do cost monitoring, this utilises the HLT_costmonitor chain
-  if (m_enableCostMonitoring) {
+  if (m_doCostMonitoring) {
     const static HLT::Identifier costMonitorChain(m_costMonitoringChain);
     const auto activeCostMonIt = std::find(activeChains.begin(), activeChains.end(), costMonitorChain);
     const bool doCostMonitoring = (activeCostMonIt != activeChains.end());
diff --git a/Trigger/TrigSteer/L1Decoder/src/L1Decoder.h b/Trigger/TrigSteer/L1Decoder/src/L1Decoder.h
index 9423be14e99..804dd1352e9 100644
--- a/Trigger/TrigSteer/L1Decoder/src/L1Decoder.h
+++ b/Trigger/TrigSteer/L1Decoder/src/L1Decoder.h
@@ -60,7 +60,7 @@ private:
   SG::WriteHandleKey<TrigCompositeUtils::DecisionContainer> m_FSDecisions{
     this, "FSDecisions", "L1FS", "Name of the decisions container (suitable for filters) containing all unprescaled chains"};
 
-  Gaudi::Property<bool> m_enableCostMonitoring{this, "EnableCostMonitoring", false, 
+  Gaudi::Property<bool> m_doCostMonitoring{this, "DoCostMonitoring", false, 
     "Enables start-of-event cost monitoring behavior."};
 
   Gaudi::Property<std::string> m_costMonitoringChain{this, "CostMonitoringChain", "HLT_costmonitor", 
diff --git a/Trigger/TrigSteer/TrigOutputHandling/src/DecisionSummaryMakerAlg.cxx b/Trigger/TrigSteer/TrigOutputHandling/src/DecisionSummaryMakerAlg.cxx
index e3f91b0a20e..9b736d636cd 100644
--- a/Trigger/TrigSteer/TrigOutputHandling/src/DecisionSummaryMakerAlg.cxx
+++ b/Trigger/TrigSteer/TrigOutputHandling/src/DecisionSummaryMakerAlg.cxx
@@ -22,7 +22,7 @@ StatusCode DecisionSummaryMakerAlg::initialize() {
     ATH_MSG_DEBUG( "Final decision of the chain " << conf.chain << " will be read from " << conf.collection );
   }
 
-  if (m_enableCostMonitoring) {
+  if (m_doCostMonitoring) {
     CHECK( m_trigCostSvcHandle.retrieve() );
     CHECK( m_costWriteHandleKey.initialize() );
   }
@@ -139,7 +139,7 @@ StatusCode DecisionSummaryMakerAlg::execute(const EventContext& context) const {
         rerunIDs.begin(), rerunIDs.end() );
 
   // Do cost monitoring
-  if (m_enableCostMonitoring) {
+  if (m_doCostMonitoring) {
     SG::WriteHandle<xAOD::TrigCompositeContainer> costMonOutput = createAndStore(m_costWriteHandleKey, context);
     // Populate collection (assuming monitored event, otherwise collection will remain empty)
     ATH_CHECK(m_trigCostSvcHandle->endEvent(context, costMonOutput));
diff --git a/Trigger/TrigSteer/TrigOutputHandling/src/DecisionSummaryMakerAlg.h b/Trigger/TrigSteer/TrigOutputHandling/src/DecisionSummaryMakerAlg.h
index bb23b71d6e3..a54435d2038 100644
--- a/Trigger/TrigSteer/TrigOutputHandling/src/DecisionSummaryMakerAlg.h
+++ b/Trigger/TrigSteer/TrigOutputHandling/src/DecisionSummaryMakerAlg.h
@@ -32,7 +32,7 @@ private:
   SG::ReadHandleKeyArray<TrigCompositeUtils::DecisionContainer> m_finalDecisionKeys{ this, "FinalDecisionKeys", {}, 
       "Final stage of all decisions" };
 
-  SG::WriteHandleKey<xAOD::TrigCompositeContainer> m_costWriteHandleKey { this, "CostWriteHandleKey", "TrigCostContainer",
+  SG::WriteHandleKey<xAOD::TrigCompositeContainer> m_costWriteHandleKey { this, "CostWriteHandleKey", "HLT_TrigCostContainer",
     "Trig composite collections summarising the HLT execution" };
 
   SG::ReadHandleKey<xAOD::TrigCompositeContainer> m_l1SummaryKey { this, "L1DecoderSummaryKey", "L1DecoderSummary",
@@ -44,7 +44,7 @@ private:
   Gaudi::Property< std::map< std::string, std::string > > m_lastStepForChain{ this, "FinalStepDecisions", {}, 
     "The map of chain name to name of the collection in which the final decision is found" };
 
-  Gaudi::Property<bool> m_enableCostMonitoring{this, "EnableCostMonitoring", false, 
+  Gaudi::Property<bool> m_doCostMonitoring{this, "DoCostMonitoring", false, 
     "Enables end-of-event cost monitoring behavior."};
 
   std::map<std::string, TrigCompositeUtils::DecisionIDContainer> m_collectionFilter;
diff --git a/Trigger/TrigValidation/TrigUpgradeTest/share/newJOtest.py b/Trigger/TrigValidation/TrigUpgradeTest/share/newJOtest.py
index 4a6246eb529..3fa2cc321d8 100644
--- a/Trigger/TrigValidation/TrigUpgradeTest/share/newJOtest.py
+++ b/Trigger/TrigValidation/TrigUpgradeTest/share/newJOtest.py
@@ -24,6 +24,8 @@ flags.Detector.GeometryCSC   = True
 flags.Detector.GeometryRPC   = True     
 flags.Trigger.writeBS=True # switches on HLTResultMT creation
 
+flags.Trigger.CostMonitoring.doCostMonitoring = True
+
 
 import importlib
 setupMenuPath = "TriggerMenuMT.HLTMenuConfig.Menu."+flags.Trigger.triggerMenuSetup
diff --git a/Trigger/TrigValidation/TrigUpgradeTest/share/testHLT_MT.py b/Trigger/TrigValidation/TrigUpgradeTest/share/testHLT_MT.py
index 908e27c3998..157851cf75d 100644
--- a/Trigger/TrigValidation/TrigUpgradeTest/share/testHLT_MT.py
+++ b/Trigger/TrigValidation/TrigUpgradeTest/share/testHLT_MT.py
@@ -154,7 +154,7 @@ if opt.trigBase is not None:
 setModifiers = ['noLArCalibFolders',
                 'ForceMuonDataType',
                 'useNewRPCCabling',
-                #'enableCostMonitoring', 
+                'enableCostMonitoring',
                 #'enableCoherentPS',
                 'useOracle',
                 'enableHotIDMasking',
@@ -439,3 +439,21 @@ from AthenaConfiguration.AllConfigFlags import ConfigFlags
 ConfigFlags.lock()
 triggerIDCCacheCreatorsCfg(ConfigFlags).appendToGlobals()
 Configurable.configurableRun3Behavior=False
+
+#-------------------------------------------------------------
+# Non-ComponentAccumulator Cost Monitoring
+#-------------------------------------------------------------
+
+from AthenaCommon.AppMgr import ServiceMgr
+from GaudiSvc.GaudiSvcConf import AuditorSvc
+from TrigCostMonitorMT.TrigCostMonitorMTConf import TrigCostMTAuditor, TrigCostMTSvc
+
+# This should be temporary, it is doing the same job as TrigCostMonitorMTConfig but without using a ComponentAccumulator
+if ConfigFlags.Trigger.CostMonitoring.doCostMonitoring:
+    trigCostService = TrigCostMTSvc()
+    trigCostService.MonitorAllEvents = ConfigFlags.Trigger.CostMonitoring.monitorAllEvents
+    trigCostService.SaveHashes = True # This option will go away once the TrigConfigSvc is fully up & running
+    ServiceMgr += trigCostService
+    #
+    ServiceMgr.AuditorSvc += TrigCostMTAuditor()
+    theApp.AuditAlgorithms=True
diff --git a/Trigger/TrigValidation/TrigValAlgs/src/TrigEDMChecker.cxx b/Trigger/TrigValidation/TrigValAlgs/src/TrigEDMChecker.cxx
index 60230ba5bce..e846f8ef11c 100644
--- a/Trigger/TrigValidation/TrigValAlgs/src/TrigEDMChecker.cxx
+++ b/Trigger/TrigValidation/TrigValAlgs/src/TrigEDMChecker.cxx
@@ -4178,7 +4178,7 @@ StatusCode TrigEDMChecker::TrigCompositeNavigationToDot(std::string& returnValue
   ss << "  rankdir = BT" << std::endl;
 
   const std::vector<std::string> vetoList = { // Patterns to ignore when dumping all
-    "TrigCostContainer",
+    "HLT_TrigCostContainer",
     "L1DecoderSummary"
     };
 
diff --git a/Trigger/TriggerCommon/TrigEDMConfig/python/TriggerEDMRun3.py b/Trigger/TriggerCommon/TrigEDMConfig/python/TriggerEDMRun3.py
index 47e83ab6368..a4f8add7c4b 100644
--- a/Trigger/TriggerCommon/TrigEDMConfig/python/TriggerEDMRun3.py
+++ b/Trigger/TriggerCommon/TrigEDMConfig/python/TriggerEDMRun3.py
@@ -73,6 +73,9 @@ TriggerHLTListRun3 = [
     ('xAOD::TrigCompositeContainer#L1J',                     'BS ESD AODFULL AODSLIM', 'Steer'),
     ('xAOD::TrigCompositeAuxContainer#L1JAux.',              'BS ESD AODFULL AODSLIM', 'Steer'),
 
+    ('xAOD::TrigCompositeContainer#HLT_TrigCostContainer',   'BS ESD', 'Steer'),
+    ('xAOD::TrigCompositeAuxContainer#HLT_TrigCostContainerAux.alg.store.view.thread.slot.roi.start.stop.', 'BS ESD', 'Steer'),
+
     # Run-2 L1 (temporary)
     ('xAOD::MuonRoIContainer#LVL1MuonRoIs' ,                 'ESD AODFULL AODSLIM AODVERYSLIM AODBLSSLIM', 'L1'),
     ('xAOD::MuonRoIAuxContainer#LVL1MuonRoIsAux.' ,          'ESD AODFULL AODSLIM AODVERYSLIM AODBLSSLIM', 'L1'),
diff --git a/Trigger/TriggerCommon/TriggerJobOpts/python/TriggerConfig.py b/Trigger/TriggerCommon/TriggerJobOpts/python/TriggerConfig.py
index ac49f6b0250..8c4857c1d78 100644
--- a/Trigger/TriggerCommon/TriggerJobOpts/python/TriggerConfig.py
+++ b/Trigger/TriggerCommon/TriggerJobOpts/python/TriggerConfig.py
@@ -134,6 +134,7 @@ def triggerSummaryCfg(flags, hypos):
     """
     acc = ComponentAccumulator()
     from TrigOutputHandling.TrigOutputHandlingConf import DecisionSummaryMakerAlg
+    from TrigEDMConfig.TriggerEDMRun3 import recordable
     decisionSummaryAlg = DecisionSummaryMakerAlg()
     allChains = {}
     for stepName, stepHypos in sorted( hypos.items() ):
@@ -146,10 +147,11 @@ def triggerSummaryCfg(flags, hypos):
     decisionSummaryAlg.FinalDecisionKeys = list(set(allChains.values()))
     decisionSummaryAlg.FinalStepDecisions = allChains
     decisionSummaryAlg.DecisionsSummaryKey = "HLTNav_Summary" # Output
+    decisionSummaryAlg.DoCostMonitoring = flags.Trigger.CostMonitoring.doCostMonitoring
+    decisionSummaryAlg.CostWriteHandleKey = recordable(flags.Trigger.CostMonitoring.outputCollection)
     return acc, decisionSummaryAlg
 
 
-
 def triggerMonitoringCfg(flags, hypos, filters, l1Decoder):
     """
     Configures components needed for monitoring chains
@@ -379,6 +381,9 @@ def triggerRunCfg( flags, menu=None ):
     monitoringAcc, monitoringAlg = triggerMonitoringCfg( flags, hypos, filters, l1DecoderAlg )
     acc.merge( monitoringAcc )
 
+    from TrigCostMonitorMT.TrigCostMonitorMTConfig import TrigCostMonitorMTCfg
+    acc.merge( TrigCostMonitorMTCfg( flags ) )
+
     decObj = collectDecisionObjects( hypos, filters, l1DecoderAlg )
     __log.info( "Number of decision objects found in HLT CF %d", len( decObj ) )
     __log.info( str( decObj ) )
diff --git a/Trigger/TriggerCommon/TriggerJobOpts/python/TriggerConfigFlags.py b/Trigger/TriggerCommon/TriggerJobOpts/python/TriggerConfigFlags.py
index ef313a57857..f7ec638e4c9 100644
--- a/Trigger/TriggerCommon/TriggerJobOpts/python/TriggerConfigFlags.py
+++ b/Trigger/TriggerCommon/TriggerJobOpts/python/TriggerConfigFlags.py
@@ -33,7 +33,14 @@ def createTriggerFlags():
     flags.addFlag('Trigger.doTruth', False)
 
     # only enable services for analysis and BS -> ESD processing (we need better name)
-    flags.addFlag('Trigger.doTriggerConfigOnly', False)    
+    flags.addFlag('Trigger.doTriggerConfigOnly', False)
+
+    # Enables collection and export of detailed monitoring data of the HLT execution
+    flags.addFlag('Trigger.CostMonitoring.doCostMonitoring', False)
+    flags.addFlag('Trigger.CostMonitoring.chain', 'HLT_costmonitor')
+    flags.addFlag('Trigger.CostMonitoring.outputCollection', 'HLT_TrigCostContainer')
+    flags.addFlag('Trigger.CostMonitoring.monitorAllEvents', True) # Defaulting to "True" is temporary
+
 
     # enable Bcm inputs simulation
     flags.addFlag('Trigger.L1.doBcm', True)
diff --git a/Trigger/TriggerRelease/python/Modifiers.py b/Trigger/TriggerRelease/python/Modifiers.py
index 235cbba33b4..374c5a2e423 100644
--- a/Trigger/TriggerRelease/python/Modifiers.py
+++ b/Trigger/TriggerRelease/python/Modifiers.py
@@ -1421,10 +1421,16 @@ class enableCostMonitoring(_modifier):
     """
     def preSetup(self):
         TriggerFlags.enableMonitoring = TriggerFlags.enableMonitoring.get_Value()+['CostExecHLT']
+        # MT
+        from AthenaConfiguration.AllConfigFlags import ConfigFlags as flags
+        flags.Trigger.CostMonitoring.doCostMonitoring = True
 
     def postSetup(self):
-        from TrigCostMonitor.TrigCostMonitorConfig import postSetupOnlineCost
-        postSetupOnlineCost()
+        try:
+          from TrigCostMonitor.TrigCostMonitorConfig import postSetupOnlineCost
+          postSetupOnlineCost()
+        except:
+          print 'enableCostMonitoring (Run 2 style) post setup failed.'
 
 class enableCostForCAF(_modifier):
     """
@@ -1436,6 +1442,9 @@ class enableCostForCAF(_modifier):
             costConfig.preSetupCostForCAF()
         except AttributeError, msg:
             print '    TrigCostMonitor has not CAF preSetup option... OK to continue'
+        # MT
+        from AthenaConfiguration.AllConfigFlags import ConfigFlags as flags
+        flags.Trigger.CostMonitoring.monitorAllEvents = True
             
     def postSetup(self):
         try:
-- 
GitLab