diff --git a/Event/xAOD/xAODTriggerCnv/Root/TriggerMenuMetaDataTool.cxx b/Event/xAOD/xAODTriggerCnv/Root/TriggerMenuMetaDataTool.cxx
index d85d0c4dcb05be6bc33452e27f5f7d7fefe50c54..4cba2db61b869ff333f87ba2d5f0a1a16c6cfce7 100644
--- a/Event/xAOD/xAODTriggerCnv/Root/TriggerMenuMetaDataTool.cxx
+++ b/Event/xAOD/xAODTriggerCnv/Root/TriggerMenuMetaDataTool.cxx
@@ -36,6 +36,8 @@ namespace xAODMaker {
       declareProperty("OutputKey", m_outputKey = "TriggerMenu");
       declareProperty("InputKeyJSON_HLT", m_inputKeyJSON_HLT = "TriggerMenuJson_HLT");
       declareProperty("OutputKeyJSON_HLT", m_outputKeyJSON_HLT = "TriggerMenuJson_HLT");
+      declareProperty("InputKeyJSON_HLTMonitoring", m_inputKeyJSON_HLTMonitoring = "TriggerMenuJson_HLTMonitoring");
+      declareProperty("OutputKeyJSON_HLTMonitoring", m_outputKeyJSON_HLTMonitoring = "TriggerMenuJson_HLTMonitoring");
       declareProperty("InputKeyJSON_L1", m_inputKeyJSON_L1 = "TriggerMenuJson_L1");
       declareProperty("OutputKeyJSON_L1", m_outputKeyJSON_L1 = "TriggerMenuJson_L1");
       declareProperty("InputKeyJSON_HLTPS", m_inputKeyJSON_HLTPS = "TriggerMenuJson_HLTPS");
@@ -57,6 +59,8 @@ namespace xAODMaker {
       m_menuAux.reset();
       m_menuJSON_hlt.reset();
       m_menuJSON_hltAux.reset();
+      m_menuJSON_hltmonitoring.reset();
+      m_menuJSON_hltmonitoringAux.reset();
       m_menuJSON_l1.reset();
       m_menuJSON_l1Aux.reset();
       m_menuJSON_hltps.reset();
@@ -142,6 +146,7 @@ namespace xAODMaker {
 
    StatusCode TriggerMenuMetaDataTool::checkxAODTriggerMenuJson() {
       ATH_CHECK( checkCopyJson(m_inputKeyJSON_HLT, m_menuJSON_hlt, m_menuJSON_hltAux) );
+      ATH_CHECK( checkCopyJson(m_inputKeyJSON_HLTMonitoring, m_menuJSON_hltmonitoring, m_menuJSON_hltmonitoringAux) );
       ATH_CHECK( checkCopyJson(m_inputKeyJSON_L1, m_menuJSON_l1, m_menuJSON_l1Aux) );
       ATH_CHECK( checkCopyJson(m_inputKeyJSON_HLTPS, m_menuJSON_hltps, m_menuJSON_hltpsAux) );
       ATH_CHECK( checkCopyJson(m_inputKeyJSON_L1PS, m_menuJSON_l1ps, m_menuJSON_l1psAux) );
@@ -258,6 +263,7 @@ namespace xAODMaker {
 
    StatusCode TriggerMenuMetaDataTool::endxAODTriggerMenuJson() {
       ATH_CHECK( checkExportJson(m_outputKeyJSON_HLT, m_menuJSON_hlt, m_menuJSON_hltAux) );
+      ATH_CHECK( checkExportJson(m_outputKeyJSON_HLTMonitoring, m_menuJSON_hltmonitoring, m_menuJSON_hltmonitoringAux) );
       ATH_CHECK( checkExportJson(m_outputKeyJSON_L1, m_menuJSON_l1, m_menuJSON_l1Aux) );
       ATH_CHECK( checkExportJson(m_outputKeyJSON_HLTPS, m_menuJSON_hltps, m_menuJSON_hltpsAux) );
       ATH_CHECK( checkExportJson(m_outputKeyJSON_L1PS, m_menuJSON_l1ps, m_menuJSON_l1psAux) );
diff --git a/Event/xAOD/xAODTriggerCnv/xAODTriggerCnv/TriggerMenuMetaDataTool.h b/Event/xAOD/xAODTriggerCnv/xAODTriggerCnv/TriggerMenuMetaDataTool.h
index e42844ed9bb4a3e1f173d5e4e57cdf1630be69b6..a199aa4f82a99fe5efc401d81875963b7620e3b9 100644
--- a/Event/xAOD/xAODTriggerCnv/xAODTriggerCnv/TriggerMenuMetaDataTool.h
+++ b/Event/xAOD/xAODTriggerCnv/xAODTriggerCnv/TriggerMenuMetaDataTool.h
@@ -135,6 +135,9 @@ namespace xAODMaker {
       std::string m_inputKeyJSON_HLT;
       std::string m_outputKeyJSON_HLT;
 
+      std::string m_inputKeyJSON_HLTMonitoring;
+      std::string m_outputKeyJSON_HLTMonitoring;
+
       std::string m_inputKeyJSON_L1;
       std::string m_outputKeyJSON_L1;
 
@@ -150,6 +153,9 @@ namespace xAODMaker {
       std::unique_ptr< xAOD::TriggerMenuJsonContainer > m_menuJSON_hlt;
       std::unique_ptr< xAOD::TriggerMenuJsonAuxContainer > m_menuJSON_hltAux;
 
+      std::unique_ptr< xAOD::TriggerMenuJsonContainer > m_menuJSON_hltmonitoring;
+      std::unique_ptr< xAOD::TriggerMenuJsonAuxContainer > m_menuJSON_hltmonitoringAux;
+
       std::unique_ptr< xAOD::TriggerMenuJsonContainer > m_menuJSON_l1;
       std::unique_ptr< xAOD::TriggerMenuJsonAuxContainer > m_menuJSON_l1Aux;
 
diff --git a/Tools/PROCTools/data/master_q442_AOD_content.ref b/Tools/PROCTools/data/master_q442_AOD_content.ref
index 30709f980abe6d8cbb4ee32892f53b620d673557..c0be8265bc828ae42d693cb2106c351e07891130 100644
--- a/Tools/PROCTools/data/master_q442_AOD_content.ref
+++ b/Tools/PROCTools/data/master_q442_AOD_content.ref
@@ -1332,6 +1332,8 @@ TrigNavigation
 TrigNavigationAux.
 TriggerMenuJson_HLT
 TriggerMenuJson_HLTAux.
+TriggerMenuJson_HLTMonitoring
+TriggerMenuJson_HLTMonitoringAux.
 TriggerMenuJson_HLTPS
 TriggerMenuJson_HLTPSAux.
 TriggerMenuJson_L1
diff --git a/Tools/PyUtils/python/MetaReader.py b/Tools/PyUtils/python/MetaReader.py
index 23ae11f35ec36e7f0980207006c76e54d85ae42a..d760c41c8483a95fe94984835e082a23a92b5994 100644
--- a/Tools/PyUtils/python/MetaReader.py
+++ b/Tools/PyUtils/python/MetaReader.py
@@ -17,10 +17,10 @@ regexXAODEventFormat = re.compile(r'^xAOD::EventFormat(_v\d+)?$')
 regexXAODFileMetaData = re.compile(r'^xAOD::FileMetaData(_v\d+)?$')
 regexXAODFileMetaDataAux = re.compile(r'^xAOD::FileMetaDataAuxInfo(_v\d+)?$')
 regexXAODFileMetaDataAuxDyn = re.compile(r'^(xAOD::)?FileMetaData.*AuxDyn(\.[a-zA-Z0-9]+)?$')
-regexXAODTriggerMenu = re.compile(r'^DataVector<xAOD::TriggerMenu(_v\d+)?>$')
-regexXAODTriggerMenuAux = re.compile(r'^xAOD::TriggerMenuAuxContainer(_v\d+)?$')
-regexXAODTriggerMenuJson = re.compile(r'^DataVector<xAOD::TriggerMenuJson(_v\d+)?>$')
-regexXAODTriggerMenuJsonAux = re.compile(r'^xAOD::TriggerMenuJsonAuxContainer(_v\d+)?$')
+regexXAODTriggerMenu = re.compile(r'^DataVector<xAOD::TriggerMenu(_v\d+)?>$') # Run 2
+regexXAODTriggerMenuAux = re.compile(r'^xAOD::TriggerMenuAuxContainer(_v\d+)?$') # Run 2
+regexXAODTriggerMenuJson = re.compile(r'^DataVector<xAOD::TriggerMenuJson(_v\d+)?>$') # Run 3
+regexXAODTriggerMenuJsonAux = re.compile(r'^xAOD::TriggerMenuJsonAuxContainer(_v\d+)?$') # Run 3
 regex_cppname = re.compile(r'^([\w:]+)(<.*>)?$')
 # regex_persistent_class = re.compile(r'^([a-zA-Z]+_p\d+::)*[a-zA-Z]+_p\d+$')
 regex_persistent_class = re.compile(r'^([a-zA-Z]+(_[pv]\d+)?::)*[a-zA-Z]+_[pv]\d+$')
@@ -171,21 +171,25 @@ def read_metadata(filenames, file_type = None, mode = 'lite', promote = None, me
                         'xAOD::TriggerMenuAuxContainer_v1_TriggerMenuAux.': 'xAOD::TriggerMenuAuxContainer_v1',
                         'TriggerMenuJson_HLT': 'DataVector<xAOD::TriggerMenuJson_v1>', # R3 trigger metadata format AOD
                         'TriggerMenuJson_HLTAux.': 'xAOD::TriggerMenuJsonAuxContainer_v1',
+                        'TriggerMenuJson_HLTMonitoring': 'DataVector<xAOD::TriggerMenuJson_v1>', # R3 trigger metadata format AOD
+                        'TriggerMenuJson_HLTMonitoringAux.': 'xAOD::TriggerMenuJsonAuxContainer_v1',
                         'TriggerMenuJson_HLTPS': 'DataVector<xAOD::TriggerMenuJson_v1>', # R3 trigger metadata format AOD
                         'TriggerMenuJson_HLTPSAux.': 'xAOD::TriggerMenuJsonAuxContainer_v1',
-                        'TriggerMenuJson_L1': 'DataVector<xAOD::TriggerMenuJson_v1>',
+                        'TriggerMenuJson_L1': 'DataVector<xAOD::TriggerMenuJson_v1>', # R3 trigger metadata format AOD
                         'TriggerMenuJson_L1Aux.': 'xAOD::TriggerMenuJsonAuxContainer_v1',
-                        'TriggerMenuJson_L1PS': 'DataVector<xAOD::TriggerMenuJson_v1>',
+                        'TriggerMenuJson_L1PS': 'DataVector<xAOD::TriggerMenuJson_v1>', # R3 trigger metadata format AOD
                         'TriggerMenuJson_L1PSAux.': 'xAOD::TriggerMenuJsonAuxContainer_v1',
                         'FileMetaData': '*',
                         'FileMetaDataAux.': 'xAOD::FileMetaDataAuxInfo_v1',
                         'DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_HLT': 'DataVector<xAOD::TriggerMenuJson_v1>', # R3 trigger metadata format ESD
                         'xAOD::TriggerMenuJsonAuxContainer_v1_TriggerMenuJson_HLTAux.': 'xAOD::TriggerMenuJsonAuxContainer_v1',
+                        'DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_HLTMonitoring': 'DataVector<xAOD::TriggerMenuJson_v1>', # R3 trigger metadata format ESD
+                        'xAOD::TriggerMenuJsonAuxContainer_v1_TriggerMenuJson_HLTMonitoringAux.': 'xAOD::TriggerMenuJsonAuxContainer_v1',
                         'DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_HLTPS': 'DataVector<xAOD::TriggerMenuJson_v1>', # R3 trigger metadata format ESD
                         'xAOD::TriggerMenuJsonAuxContainer_v1_TriggerMenuJson_HLTPSAux.': 'xAOD::TriggerMenuJsonAuxContainer_v1',
-                        'DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_L1': 'DataVector<xAOD::TriggerMenuJson_v1>',
+                        'DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_L1': 'DataVector<xAOD::TriggerMenuJson_v1>', # R3 trigger metadata format ESD
                         'xAOD::TriggerMenuJsonAuxContainer_v1_TriggerMenuJson_L1Aux.': 'xAOD::TriggerMenuJsonAuxContainer_v1',
-                        'DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_L1PS': 'DataVector<xAOD::TriggerMenuJson_v1>',
+                        'DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_L1PS': 'DataVector<xAOD::TriggerMenuJson_v1>', # R3 trigger metadata format ESD
                         'xAOD::TriggerMenuJsonAuxContainer_v1_TriggerMenuJson_L1PSAux.': 'xAOD::TriggerMenuJsonAuxContainer_v1',
                         '*': 'EventStreamInfo_p*'
                     }
@@ -815,6 +819,8 @@ def _extract_fields_triggermenujson(interface, aux):
                 return result
             elif decoded['filetype'] == 'l1prescale':
                 return result
+            elif decoded['filetype'] == 'hltmonitoringsummary':
+                return result
 
             else:
                 msg.warn('Got an xAOD::TriggerMenuJson called {0} but only expecting hltmenu or l1menu'.format(decoded['filetype']))
diff --git a/Trigger/TrigConfiguration/TrigConfData/TrigConfData/HLTMonitoring.h b/Trigger/TrigConfiguration/TrigConfData/TrigConfData/HLTMonitoring.h
new file mode 100644
index 0000000000000000000000000000000000000000..2e737b6299f315470fd944b47ce446a118c66701
--- /dev/null
+++ b/Trigger/TrigConfiguration/TrigConfData/TrigConfData/HLTMonitoring.h
@@ -0,0 +1,77 @@
+/*
+  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGCONFDATA_HLTMONITORING_H
+#define TRIGCONFDATA_HLTMONITORING_H
+
+#include "TrigConfData/ConstIter.h"
+#include "TrigConfData/DataStructure.h"
+
+#include <map>
+
+namespace TrigConf {
+
+   /** 
+    * @brief HLT monitoring configuration
+    *
+    * Provides access to monitoring classifications corresponding to HLT chains.
+    *
+    * This file is primarily designed for python based access. This C++ wrapper remains minimalist
+    * for the time being. Data may still be queried via the wrapped ptree.
+    * 
+    * Further accessor helper functions may be added at a later date and would be backwards 
+    * compatible with existing files. 
+    */
+   class HLTMonitoring final : public DataStructure {
+   public:
+
+      /** Constructor */
+      HLTMonitoring();
+
+      /** Constructor initialized with configuration data 
+       * @param data The ptree containing the HLT monitoring structure 
+       */
+      HLTMonitoring(const ptree & data);
+      HLTMonitoring(const HLTMonitoring&) = default;
+      HLTMonitoring(HLTMonitoring&&) = default;
+
+      /** Destructor */
+      ~HLTMonitoring();
+
+      // class name
+      virtual std::string className() const override {
+         return "HLTMonitoring";
+      }
+
+      /** setter and getter for the supermasterkey */
+      unsigned int smk() const;
+      void setSMK(unsigned int psk);
+
+      /** Clearing the configuration data */
+      virtual void clear() override;
+
+   private:
+   
+      /** Update the internal data after modification of the data object */
+      virtual void update() override { load(); };
+      void load();
+
+      /** the supermasterkey */
+      unsigned int m_smk {0};
+   };
+}
+
+#ifndef TRIGCONF_STANDALONE
+#ifndef XAOD_STANDALONE
+
+#include "AthenaKernel/CLASS_DEF.h"
+CLASS_DEF( TrigConf::HLTMonitoring , 250972509, 1 )
+
+#include "AthenaKernel/CondCont.h"
+CONDCONT_DEF( TrigConf::HLTMonitoring , 50201204 );
+
+#endif
+#endif
+
+#endif
diff --git a/Trigger/TrigConfiguration/TrigConfData/src/HLTMonitoring.cxx b/Trigger/TrigConfiguration/TrigConfData/src/HLTMonitoring.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..46beff7f43fe533427c9925295584f458b3be5ca
--- /dev/null
+++ b/Trigger/TrigConfiguration/TrigConfData/src/HLTMonitoring.cxx
@@ -0,0 +1,46 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "TrigConfData/HLTMonitoring.h"
+
+using TV = boost::property_tree::ptree::value_type;  // tree-value type
+using namespace std;
+
+TrigConf::HLTMonitoring::HLTMonitoring()
+{}
+
+TrigConf::HLTMonitoring::HLTMonitoring(const boost::property_tree::ptree & data) 
+   : DataStructure(data)
+{
+   load();
+}
+
+TrigConf::HLTMonitoring::~HLTMonitoring()
+{}
+
+void
+TrigConf::HLTMonitoring::load()
+{
+   if(! isInitialized() || empty() ) {
+      return;
+   }
+   m_name = getAttribute("name");
+}
+
+void
+TrigConf::HLTMonitoring::clear()
+{
+   m_smk = 0;
+   m_name = "";
+}
+
+unsigned int
+TrigConf::HLTMonitoring::smk() const {
+   return m_smk;
+}
+
+void
+TrigConf::HLTMonitoring::setSMK(unsigned int smk) {
+   m_smk = smk;
+}
diff --git a/Trigger/TrigConfiguration/TrigConfInterfaces/TrigConfInterfaces/IIHLTConfigSvc.h b/Trigger/TrigConfiguration/TrigConfInterfaces/TrigConfInterfaces/IIHLTConfigSvc.h
index d40ac42ab108e4d19a6c229be419c0d76e1ee380..c80f2546547ebe361a36d48fec3c61c3b52a6a92 100644
--- a/Trigger/TrigConfiguration/TrigConfInterfaces/TrigConfInterfaces/IIHLTConfigSvc.h
+++ b/Trigger/TrigConfiguration/TrigConfInterfaces/TrigConfInterfaces/IIHLTConfigSvc.h
@@ -20,6 +20,7 @@ namespace TrigConf {
    class HLTChainList;
    class HLTSequenceList;
    class HLTMenu;
+   class HLTMonitoring;
    class HLTPrescalesSet;
 
    /**
@@ -50,6 +51,9 @@ namespace TrigConf {
       /// Returns the JSON configured HLTMenu ptree
       virtual const ::TrigConf::HLTMenu& hltMenu(const ::EventContext& ctx) const = 0;
 
+      /// Returns the JSON configured HLTMonitoring ptree
+      virtual const ::TrigConf::HLTMonitoring& hltMonitoring(const ::EventContext& ctx) const = 0;
+
       /// Returns the JSON configured HLT prescales ptree
       virtual const ::TrigConf::HLTPrescalesSet& hltPrescalesSet(const ::EventContext& ctx) const = 0;
 
diff --git a/Trigger/TrigConfiguration/TrigConfigSvc/python/TrigConfigSvcCfg.py b/Trigger/TrigConfiguration/TrigConfigSvc/python/TrigConfigSvcCfg.py
index b7b61a6f32e7e56d598451b0d04894711a2c2f33..bf6b55378aa280139775ccdbbf2341da4638e674 100644
--- a/Trigger/TrigConfiguration/TrigConfigSvc/python/TrigConfigSvcCfg.py
+++ b/Trigger/TrigConfiguration/TrigConfigSvc/python/TrigConfigSvcCfg.py
@@ -146,6 +146,12 @@ def getHLTMenuFileName( flags ):
     hltMenuFileName = hltMenuFileName.replace("_newJO","")
     return hltMenuFileName
 
+# HLT Monitoring set json file name
+def getHLTMonitoringFileName( flags ):
+    hltMonitoringFileName = 'HLTMonitoring'+_getMenuFileName(flags)+'.json'
+    hltMonitoringFileName = hltMonitoringFileName.replace("_newJO","")
+    return hltMonitoringFileName
+
 # L1 Prescales set json file name
 def getL1PrescalesSetFileName( flags ):
     return 'L1PrescalesSet'+_getMenuFileName(flags)+'.json'
@@ -154,10 +160,6 @@ def getL1PrescalesSetFileName( flags ):
 def getHLTPrescalesSetFileName( flags ):
     return 'HLTPrescalesSet'+_getMenuFileName(flags)+'.json'
 
-# HLT Monitoring set json file name
-def getHLTMonitoringFileName( flags ):
-    return 'HLTMonitoring'+_getMenuFileName(flags)+'.json'
-
 # L1 Bunchgroups set json file name
 def getBunchGroupSetFileName( flags ):
     return 'BunchGroupSet'+_getMenuFileName(flags)+'.json'
@@ -253,7 +255,9 @@ def HLTConfigSvcCfg( flags ):
 
         hltConfigSvc.InputType = "FILE"
         hltConfigSvc.JsonFileName = getHLTMenuFileName( flags )
-        log.info( "Configured HLTConfigSvc with InputType='FILE' and JsonFileName=%s", hltConfigSvc.JsonFileName )
+        hltConfigSvc.MonitoringJsonFileName = getHLTMonitoringFileName( flags )
+        log.info( "Configured HLTConfigSvc with InputType='FILE', JsonFileName=%s and MonitoringJsonFileName=%s",
+          hltConfigSvc.JsonFileName, hltConfigSvc.MonitoringJsonFileName )
     elif cfg["SOURCE"] == "DB":
         hltConfigSvc.InputType = "DB"
         hltConfigSvc.JsonFileName = ""
diff --git a/Trigger/TrigConfiguration/TrigConfigSvc/python/TriggerConfigAccess.py b/Trigger/TrigConfiguration/TrigConfigSvc/python/TriggerConfigAccess.py
index c20e6c1e34bee5d10539b5adbc5fcaa427c22567..8332bec80729e088cfd8c1f519ee612b965857ea 100644
--- a/Trigger/TrigConfiguration/TrigConfigSvc/python/TriggerConfigAccess.py
+++ b/Trigger/TrigConfiguration/TrigConfigSvc/python/TriggerConfigAccess.py
@@ -70,6 +70,23 @@ def getKeysFromCool(runNr, lbNr = 0):
 
     return d
 
+"""
+Returns a string-serialised JSON object from the metadata store.
+Checks AOD syntax first, then fully-qualified ESD syntax
+"""
+def _getJSONFromMetadata(flags, key):
+    from AthenaConfiguration.Enums import Format
+    if flags.Input.Format != Format.POOL:
+        raise RuntimeError("Cannot read trigger configuration (%s) from input type %s", key, flags.Input.Format)
+    from AthenaConfiguration.AutoConfigFlags import GetFileMD
+    metadata = GetFileMD(flags.Input.Files)
+    menu_json = metadata.get(key, None)
+    if menu_json is None:
+        menu_json = metadata.get('DataVector<xAOD::TriggerMenuJson_v1>_%s' % key, None)
+    if menu_json is None:
+        raise RuntimeError("Cannot read trigger configuration (%s) from input file metadata" % key)
+    return menu_json
+
 
 """
 
@@ -88,17 +105,7 @@ def getL1MenuAccess( flags = None ):
     elif tc["SOURCE"] == "DB":
         cfg = L1MenuAccess( dbalias = tc["dbconn"], smkey = tc["smk"] )
     elif tc["SOURCE"] == "INFILE":
-        from AthenaConfiguration.Enums import Format
-        if flags.Input.Format is not Format.POOL:
-            raise RuntimeError("Cannot read trigger configuration (L1 menu) from input type %s", flags.Input.Format )            
-        from AthenaConfiguration.AutoConfigFlags import GetFileMD
-        metadata = GetFileMD(flags.Input.Files)
-        menu_json = metadata.get ('TriggerMenuJson_L1', None)
-        if menu_json is None:
-            menu_json = metadata.get ('DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_L1', None)
-        if menu_json is None:
-            raise RuntimeError("Cannot read trigger configuration (TriggerMenuJson_L1) from input file metadata" )
-        cfg = L1MenuAccess(jsonString=menu_json)
+        cfg = L1MenuAccess(jsonString=_getJSONFromMetadata(flags, key='TriggerMenuJson_L1'))
     else:
         raise RuntimeError("Unknown source of trigger configuration: %s" % tc["SOURCE"])
     return cfg
@@ -116,17 +123,7 @@ def getL1PrescalesSetAccess( flags = None ):
     elif tc["SOURCE"] == "DB":
         cfg = L1PrescalesSetAccess( dbalias = tc["dbconn"], l1pskey = tc["l1psk"] )
     elif tc["SOURCE"] == "INFILE":
-        from AthenaConfiguration.Enums import Format
-        if flags.Input.Format is not Format.POOL:
-            raise RuntimeError("Cannot read trigger configuration (L1 prescales) from input type %s", flags.Input.Format )
-        from AthenaConfiguration.AutoConfigFlags import GetFileMD
-        metadata = GetFileMD(flags.Input.Files)
-        menu_json = metadata.get ('TriggerMenuJson_L1PS', None)
-        if menu_json is None:
-            menu_json = metadata.get ('DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_L1PS', None)
-        if menu_json is None:
-            raise RuntimeError("Cannot read trigger configuration (TriggerMenuJson_L1PS) from input file metadata" )
-        cfg = L1PrescalesSetAccess(jsonString=menu_json)
+        cfg = L1PrescalesSetAccess(jsonString=_getJSONFromMetadata(flags, key='TriggerMenuJson_L1PS'))
     else:
         raise RuntimeError("Unknown source of trigger configuration: %s" % tc["SOURCE"])
     return cfg
@@ -146,8 +143,8 @@ def getBunchGroupSetAccess( flags = None ):
     elif tc["SOURCE"] == "INFILE":
         from RecExConfig.InputFilePeeker import inputFileSummary as inpSum
         if inpSum["file_type"] != 'pool':
-            raise RuntimeError("Cannot read trigger configuration (HLT prescales) from input type %s" % inpSum["file_type"])
-        raise NotImplementedError("Python access to the trigger configuration (HLT prescales) from in-file metadata not yet implemented")
+            raise RuntimeError("Cannot read trigger configuration (Bunchgroup Set) from input type %s" % inpSum["file_type"])
+        raise NotImplementedError("Python access to the trigger configuration (Bunchgroup Set) from in-file metadata not yet implemented")
     else:
         raise RuntimeError("Unknown source of trigger configuration: %s" % tc["SOURCE"])
     return cfg
@@ -171,17 +168,7 @@ def getHLTMenuAccess( flags = None ):
     elif tc["SOURCE"] == "DB":
         cfg = HLTMenuAccess( dbalias = tc["dbconn"], smkey = tc["smk"] )
     elif tc["SOURCE"] == "INFILE":
-        from AthenaConfiguration.Enums import Format
-        if flags.Input.Format is not Format.POOL:
-            raise RuntimeError("Cannot read trigger configuration (HLT menu) from input type %s", flags.Input.Format )            
-        from AthenaConfiguration.AutoConfigFlags import GetFileMD
-        metadata = GetFileMD(flags.Input.Files)
-        menu_json = metadata.get ('TriggerMenuJson_HLT', None)
-        if menu_json is None:
-            menu_json = metadata.get ('DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_HLT', None)
-        if menu_json is None:
-            raise RuntimeError("Cannot read trigger configuration (TriggerMenuJson_HLT) from input file metadata" )
-        cfg = HLTMenuAccess(jsonString=menu_json)
+        cfg = HLTMenuAccess(jsonString=_getJSONFromMetadata(flags, key='TriggerMenuJson_HLT'))
     else:
         raise RuntimeError("Unknown source of trigger configuration: %s" % tc["SOURCE"])
     return cfg
@@ -199,17 +186,7 @@ def getHLTPrescalesSetAccess( flags = None ):
     elif tc["SOURCE"] == "DB":
         cfg = HLTPrescalesSetAccess( dbalias = tc["dbconn"], l1pskey = tc["hltpsk"] )
     elif tc["SOURCE"] == "INFILE":
-        from AthenaConfiguration.Enums import Format
-        if flags.Input.Format is not Format.POOL:
-            raise RuntimeError("Cannot read trigger configuration (HLT prescales) from input type %s", flags.Input.Format )            
-        from AthenaConfiguration.AutoConfigFlags import GetFileMD
-        metadata = GetFileMD(flags.Input.Files)
-        menu_json = metadata.get ('TriggerMenuJson_HLTPS', None)
-        if menu_json is None:
-            menu_json = metadata.get ('DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_HLTPS', None)
-        if menu_json is None:
-            raise RuntimeError("Cannot read trigger configuration (TriggerMenuJson_HLTPS) from input file metadata" )
-        cfg = HLTPrescalesSetAccess(jsonString=menu_json)
+        cfg = HLTPrescalesSetAccess(jsonString=_getJSONFromMetadata(flags, key='TriggerMenuJson_HLTPS'))
     else:
         raise RuntimeError("Unknown source of trigger configuration: %s" % tc["SOURCE"])
     return cfg
@@ -227,10 +204,7 @@ def getHLTJobOptionsAccess( flags = None ):
     elif tc["SOURCE"] == "DB":
         cfg = HLTJobOptionsAccess( dbalias = tc["dbconn"], smkey = tc["smk"] )
     elif tc["SOURCE"] == "INFILE":
-        from RecExConfig.InputFilePeeker import inputFileSummary as inpSum
-        if inpSum["file_type"] != 'pool':
-            raise RuntimeError("Cannot read trigger configuration (HLT menu) from input type %s" % inpSum["file_type"])
-        raise NotImplementedError("Python access to the trigger configuration (HLT menu) from in-file metadata not yet implemented")
+        raise NotImplementedError("Python access to the HLT Job Options configuration from in-file metadata is NOT SUPPORTED (this file is huge!)")
     else:
         raise RuntimeError("Unknown source of trigger configuration: %s" % tc["SOURCE"])
     return cfg
@@ -246,12 +220,7 @@ def getHLTMonitoringAccess( flags = None ):
         # TODO when database will be ready
         raise NotImplementedError("Python DB access to the HLT monitoring not yet implemented")
     elif tc["SOURCE"] == "INFILE":
-        # TODO when database metadata ready
-        filename = getHLTMonitoringFileName( flags )
-        from AthenaCommon.Logging import logging
-        logging.getLogger().info("Using  HLTMonitoringAccess from external file %s to be fixed once in file metadata contains relevant information",  filename)
-        cfg = HLTMonitoringAccess( filename = filename )
-
+        cfg = HLTMonitoringAccess(jsonString=_getJSONFromMetadata(flags, key='TriggerMenuJson_HLTMonitoring'))
     else:
         raise RuntimeError("Unknown source of trigger configuration: %s" % tc["SOURCE"])
     return cfg
diff --git a/Trigger/TrigConfiguration/TrigConfigSvc/src/HLTConfigSvc.cxx b/Trigger/TrigConfiguration/TrigConfigSvc/src/HLTConfigSvc.cxx
index 50c197f6a7ffe06983385e03a6a29de34e645e55..2b02e3b7523efdaf9485c3fcac8d41d7239534c2 100644
--- a/Trigger/TrigConfiguration/TrigConfigSvc/src/HLTConfigSvc.cxx
+++ b/Trigger/TrigConfiguration/TrigConfigSvc/src/HLTConfigSvc.cxx
@@ -6,6 +6,7 @@
 #include "StoreGate/StoreGateSvc.h"
 
 #include "TrigConfData/HLTMenu.h"
+#include "TrigConfData/HLTMonitoring.h"
 #include "TrigConfIO/JsonFileLoader.h"
 #include "TrigConfIO/TrigDBMenuLoader.h"
 #include "TrigConfInterfaces/IJobOptionsSvc.h"
@@ -20,7 +21,8 @@ TrigConf::HLTConfigSvc::HLTConfigSvc(const std::string& name, ISvcLocator* pSvcL
 
 StatusCode TrigConf::HLTConfigSvc::writeConfigToDetectorStore()
 {
-  auto hltmenu = std::make_unique<TrigConf::HLTMenu>();
+  std::unique_ptr<TrigConf::HLTMenu> hltmenu = std::make_unique<TrigConf::HLTMenu>();
+  std::unique_ptr<TrigConf::HLTMonitoring> monitoring;
 
   if (m_inputType == "DB") {
     // db menu loader
@@ -36,6 +38,22 @@ StatusCode TrigConf::HLTConfigSvc::writeConfigToDetectorStore()
 
     ATH_CHECK( fileLoader.loadFile(m_hltFileName, *hltmenu) );
     hltmenu->setSMK(m_smk);  // allow assigning a dummy SMK when running from FILE
+
+    if (!m_monitoringFileName.empty()) {
+      monitoring.reset( new TrigConf::HLTMonitoring() );
+      const bool success = fileLoader.loadFile(m_monitoringFileName, *monitoring);
+      if (not success) {
+        if (m_monitoringOptional) {
+          ATH_MSG_INFO("Unable to read " << m_monitoringFileName 
+            << ", but the monitoring collection is flagged as optional. Continuing.");
+          monitoring.reset(); // This smartpointer goes back from having Some to having None.
+        } else {
+          ATH_MSG_ERROR("Unable to read " << m_monitoringFileName 
+            << ", the monitoring collection flagged as non-optional in this job.");
+          return StatusCode::FAILURE;
+        }
+      }
+    }
   }
   else {
     ATH_MSG_ERROR("Unknown input type '" << m_inputType
@@ -48,6 +66,9 @@ StatusCode TrigConf::HLTConfigSvc::writeConfigToDetectorStore()
   if (detStore->record(std::move(hltmenu), "HLTTriggerMenu").isSuccess()) {
     ATH_MSG_INFO("Recorded HLT menu as 'HLTTriggerMenu' in detector store");
   }
+  if (monitoring and detStore->record(std::move(monitoring), "HLTMonitoringMenu").isSuccess()) {
+    ATH_MSG_INFO("Recorded HLT monitoring menu as 'HLTMonitoringMenu' in detector store");
+  }
 
   return StatusCode::SUCCESS;
 }
@@ -70,6 +91,7 @@ StatusCode TrigConf::HLTConfigSvc::initialize()
   ATH_MSG_INFO(m_inputType);
   if (m_inputType == "FILE") {
     ATH_MSG_INFO(m_hltFileName);
+    ATH_MSG_INFO(m_monitoringFileName);
   }
   else if (m_inputType == "DB") {
     ATH_MSG_INFO(m_dbConnection);
diff --git a/Trigger/TrigConfiguration/TrigConfigSvc/src/HLTConfigSvc.h b/Trigger/TrigConfiguration/TrigConfigSvc/src/HLTConfigSvc.h
index 0d2584b19bf4e6d2b484a4697f2348a51fc2cea3..1b9700e8c84d450474f81931f7027a682f7452b6 100644
--- a/Trigger/TrigConfiguration/TrigConfigSvc/src/HLTConfigSvc.h
+++ b/Trigger/TrigConfiguration/TrigConfigSvc/src/HLTConfigSvc.h
@@ -29,9 +29,15 @@ namespace TrigConf {
     Gaudi::Property<std::string> m_hltFileName{this, "JsonFileName", "HLTMenu.json",
       "file name of HLT json file, needed if InputType is FILE"};
 
+    Gaudi::Property<std::string> m_monitoringFileName{this, "MonitoringJsonFileName", "",
+      "file name of HLT monitoring json file, optional if InputType is FILE"};
+
     Gaudi::Property<std::string> m_dbConnection{this, "TriggerDB", "TRIGGERDB",
       "DB connection alias, needed if InputType is DB"};
 
+    Gaudi::Property<bool> m_monitoringOptional{this, "MonitoringJSONOptional", true,
+      "Flag to control if a JSON is required when MonitoringJsonFileName is supplied and InputType is FILE"};
+
     Gaudi::Property<unsigned int> m_smk{this, "SMK", 0,
       "DB smk, needed if InputType is DB (optional for file InputType)"};
   };
diff --git a/Trigger/TrigConfiguration/TrigConfxAOD/Root/xAODConfigTool.cxx b/Trigger/TrigConfiguration/TrigConfxAOD/Root/xAODConfigTool.cxx
index a3b97c4feccfdfba1495a39b249ba4ec32b8b7f5..36584431a97d9c7d0b8b1c8bb62d9d6c65180bf7 100644
--- a/Trigger/TrigConfiguration/TrigConfxAOD/Root/xAODConfigTool.cxx
+++ b/Trigger/TrigConfiguration/TrigConfxAOD/Root/xAODConfigTool.cxx
@@ -36,6 +36,8 @@ namespace TrigConf {
 
       /// The JSON decoded Run3 HLT menu
       HLTMenu m_currentHlt;
+      /// The JSON decoded Run3 HLT monitoring
+      HLTMonitoring m_currentHltmonitoring;
       /// The JSON decoded Run3 L1 menu
       L1Menu m_currentL1;
       /// The JSON decoded current HLT prescales set
@@ -49,10 +51,10 @@ namespace TrigConf {
    xAODConfigTool::xAODConfigTool( const std::string& name )
       : asg::AsgMetadataTool( name ),
         m_tmc( nullptr ),
-        m_hltJson( nullptr), m_l1Json( nullptr ),
+        m_hltJson( nullptr), m_hltmonitoringJson(nullptr), m_l1Json( nullptr ),
         m_hltpsJson( nullptr ), m_l1psJson( nullptr ), m_bgJson( nullptr ),
         m_menu( nullptr ),
-        m_currentHltJson( nullptr ), m_currentL1Json( nullptr ),
+        m_currentHltJson( nullptr ), m_currentHltmonitoringJson( nullptr ), m_currentL1Json( nullptr ),
         m_currentHltpsJson( nullptr ), m_currentL1psJson( nullptr ), m_currentBgJson( nullptr ),
         m_triggerMenuContainerAvailable(false),
         m_menuJSONContainerAvailable(false),
@@ -63,6 +65,7 @@ namespace TrigConf {
       declareProperty( "MetaObjectName", m_metaName_run2 = "TriggerMenu" );
 
       declareProperty( "JSONMetaObjectNameHLT", m_metaNameJSON_hlt = "TriggerMenuJson_HLT" );
+      declareProperty( "JSONMetaObjectNameHLTMonitoring", m_metaNameJSON_hltmonitoring = "TriggerMenuJson_HLTMonitoring" );
       declareProperty( "JSONMetaObjectNameL1", m_metaNameJSON_l1 = "TriggerMenuJson_L1" );
       declareProperty( "JSONMetaObjectNameHLTPS", m_metaNameJSON_hltps = "TriggerMenuJson_HLTPS" );
       declareProperty( "JSONMetaObjectNameL1PS", m_metaNameJSON_l1ps = "TriggerMenuJson_L1PS" );
@@ -82,6 +85,7 @@ namespace TrigConf {
       ATH_MSG_DEBUG( "MetaObjectName  = " << m_metaName_run2 );
       ATH_MSG_DEBUG( "-- Run 3 AOD Configuration Settings");
       ATH_MSG_DEBUG( "JSONMetaObjectNameHLT = " << m_metaNameJSON_hlt );
+      ATH_MSG_DEBUG( "JSONMetaObjectNameHLTMonitoring = " << m_metaNameJSON_hltmonitoring );
       ATH_MSG_DEBUG( "JSONMetaObjectNameL1 = " << m_metaNameJSON_l1 );
       ATH_MSG_DEBUG( "JSONMetaObjectNameHLTPS = " << m_metaNameJSON_hltps );
       ATH_MSG_DEBUG( "JSONMetaObjectNameL1PS = " << m_metaNameJSON_l1ps );
@@ -92,11 +96,13 @@ namespace TrigConf {
       m_menu = nullptr;
       //
       m_hltJson = nullptr;
+      m_hltmonitoringJson = nullptr;
       m_l1Json = nullptr;
       m_hltpsJson = nullptr;
       m_l1psJson = nullptr;
       m_bgJson = nullptr;
       m_currentHltJson = nullptr;
+      m_currentHltmonitoringJson = nullptr;
       m_currentL1Json = nullptr;
       m_currentHltpsJson = nullptr;
       m_currentL1psJson = nullptr;
@@ -215,6 +221,14 @@ namespace TrigConf {
       return m_impl->m_currentHlt;
    }
 
+   const HLTMonitoring& xAODConfigTool::hltMonitoring(const EventContext&) const {
+      if( ! m_menuJSONContainerAvailable ) {
+         ATH_MSG_FATAL( "Run 3 format Trigger menu not loaded" );
+         throw std::runtime_error( "Tool not initialised correctly" );
+      }
+      return m_impl->m_currentHltmonitoring;
+   }
+
    const L1Menu& xAODConfigTool::l1Menu(const EventContext&) const {
       if( ! m_menuJSONContainerAvailable ) {
          ATH_MSG_FATAL( "Run 3 format Trigger menu not loaded" );
@@ -263,6 +277,7 @@ namespace TrigConf {
 
       // Try to read the R3 metadata object:
       m_hltJson = nullptr;
+      m_hltmonitoringJson = nullptr;
       m_l1Json = nullptr;
       m_hltpsJson = nullptr;
       m_l1psJson = nullptr;
@@ -273,6 +288,12 @@ namespace TrigConf {
       {
          m_menuJSONContainerAvailable = false;
       }
+      if( !inputMetaStore()->contains<xAOD::TriggerMenuJsonContainer>(m_metaNameJSON_hltmonitoring)
+          or inputMetaStore()->retrieve( m_hltmonitoringJson, m_metaNameJSON_hltmonitoring ).isFailure() )
+      {
+         // m_menuJSONContainerAvailable = false;
+         // Currently planning on only storing these data in MC. Hence this has to be an optional input.
+      }
       if( !inputMetaStore()->contains<xAOD::TriggerMenuJsonContainer>(m_metaNameJSON_l1)
           or inputMetaStore()->retrieve( m_l1Json, m_metaNameJSON_l1 ).isFailure() )
       {
@@ -316,6 +337,9 @@ namespace TrigConf {
 
          // Load the first elements by default
          ATH_CHECK( m_hltJson->size() > 0 );
+         if (m_hltmonitoringJson) { // Optional
+            ATH_CHECK( m_hltmonitoringJson->size() > 0 );
+         }
          ATH_CHECK( m_l1Json->size() > 0 );
          ATH_CHECK( m_hltpsJson->size() > 0 );
          ATH_CHECK( m_l1psJson->size() > 0 );
@@ -324,6 +348,9 @@ namespace TrigConf {
          }
 
          m_currentHltJson = m_hltJson->at( 0 );
+         if (m_hltmonitoringJson) { // Optional
+            m_currentHltmonitoringJson = m_hltmonitoringJson->at( 0 );
+         }
          m_currentL1Json = m_l1Json->at( 0 );
          m_currentHltpsJson = m_hltpsJson->at( 0 );
          m_currentL1psJson = m_l1psJson->at( 0 );
@@ -335,10 +362,13 @@ namespace TrigConf {
 
          // Loading the payload doesn't additionally let the object know about its own key. We can load this in now too.
          m_impl->m_currentHlt.setSMK( m_currentHltJson->key() );
+         if (m_currentHltmonitoringJson) { // Optional
+            m_impl->m_currentHltmonitoring.setSMK( m_currentHltmonitoringJson->key() );
+         }
          m_impl->m_currentL1.setSMK( m_currentL1Json->key() );
          m_impl->m_currentHltps.setPSK( m_currentHltpsJson->key() );
          m_impl->m_currentL1ps.setPSK( m_currentL1psJson->key() );
-         if (m_bgJson) {
+         if (m_bgJson) { // Optional (for now)
             m_impl->m_currentBg.setBGSK( m_currentBgJson->key() );
          }
 
@@ -452,6 +482,7 @@ namespace TrigConf {
       if (m_currentHltJson->key() != keys->smk()) {
          validConfig = false;
       }
+      // m_currentHltminitoringJson is checked by the m_currentHltJson check
       if (m_currentL1Json->key() != keys->smk()) {
          validConfig = false;
       }
@@ -471,6 +502,9 @@ namespace TrigConf {
 
       // If not, load correct JSON menus from their respective containers, matching against the event's keys ...
       ATH_CHECK( loadJsonByKey("HLT Menu", m_hltJson, keys->smk(), m_currentHltJson) );
+      if (m_hltmonitoringJson) {
+         ATH_CHECK( loadJsonByKey("HLT Monitoring", m_hltmonitoringJson, keys->smk(), m_currentHltmonitoringJson) );
+      }
       ATH_CHECK( loadJsonByKey("L1 Menu", m_l1Json, keys->smk(), m_currentL1Json) );
       ATH_CHECK( loadJsonByKey("HLT Prescales", m_hltpsJson, keys->hltpsk(), m_currentHltpsJson) );
       ATH_CHECK( loadJsonByKey("L1 Prescales", m_l1psJson, keys->l1psk(), m_currentL1psJson) );
@@ -483,6 +517,9 @@ namespace TrigConf {
 
       // ... and set the keys of the objects in the objects (not part of the JSON pyaload) ...
       m_impl->m_currentHlt.setSMK( m_currentHltJson->key() );
+      if (m_currentHltmonitoringJson) {
+         m_impl->m_currentHltmonitoring.setSMK( m_currentHltmonitoringJson->key() );
+      }
       m_impl->m_currentL1.setSMK( m_currentL1Json->key() );
       m_impl->m_currentHltps.setPSK( m_currentHltpsJson->key() );
       m_impl->m_currentL1ps.setPSK( m_currentL1psJson->key() );
@@ -528,6 +565,9 @@ namespace TrigConf {
 
    StatusCode xAODConfigTool::loadPtrees() {
       ATH_CHECK( loadPtree("HLT Menu", m_currentHltJson, m_impl->m_currentHlt) );
+      if (m_currentHltmonitoringJson) {
+         ATH_CHECK( loadPtree("HLT Monitoring", m_currentHltmonitoringJson, m_impl->m_currentHltmonitoring) );
+      }
       ATH_CHECK( loadPtree("L1 Menu", m_currentL1Json, m_impl->m_currentL1) );
       ATH_CHECK( loadPtree("HLT Prescales", m_currentHltpsJson, m_impl->m_currentHltps) );
       ATH_CHECK( loadPtree("L1 Prescales", m_currentL1psJson, m_impl->m_currentL1ps) );
diff --git a/Trigger/TrigConfiguration/TrigConfxAOD/TrigConfxAOD/xAODConfigTool.h b/Trigger/TrigConfiguration/TrigConfxAOD/TrigConfxAOD/xAODConfigTool.h
index 5ebdc3ff696a01266809f8a0f1bafa7239037467..e8d2a11b116498a73283cb10650cffc5aa6e1bd6 100644
--- a/Trigger/TrigConfiguration/TrigConfxAOD/TrigConfxAOD/xAODConfigTool.h
+++ b/Trigger/TrigConfiguration/TrigConfxAOD/TrigConfxAOD/xAODConfigTool.h
@@ -19,6 +19,7 @@
 #include "TrigConfHLTData/HLTSequenceList.h"
 // Run 3 structures
 #include "TrigConfData/HLTMenu.h"
+#include "TrigConfData/HLTMonitoring.h"
 #include "TrigConfData/L1Menu.h"
 #include "TrigConfData/HLTPrescalesSet.h"
 #include "TrigConfData/L1PrescalesSet.h"
@@ -113,6 +114,9 @@ namespace TrigConf {
       /// Returns the JSON configured HLTMenu ptree
       virtual const HLTMenu& hltMenu(const EventContext& ctx = Gaudi::Hive::currentContext()) const override;
 
+      /// Returns the JSON configured HLTMonitoring ptree
+      virtual const HLTMonitoring& hltMonitoring(const EventContext& ctx = Gaudi::Hive::currentContext()) const override;
+
       /// Returns the JSON configured L1 ptree
       virtual const L1Menu& l1Menu(const EventContext& ctx = Gaudi::Hive::currentContext()) const override;
 
@@ -174,6 +178,7 @@ namespace TrigConf {
       std::string m_metaName_run2;
       /// Key for the trigger configuration metadata objects (Run 3)
       std::string m_metaNameJSON_hlt;
+      std::string m_metaNameJSON_hltmonitoring;
       std::string m_metaNameJSON_l1;
       std::string m_metaNameJSON_hltps;
       std::string m_metaNameJSON_l1ps;
@@ -183,6 +188,7 @@ namespace TrigConf {
       const xAOD::TriggerMenuContainer* m_tmc;
       /// The configuration object of the current input file (for Run3 AOD)
       const xAOD::TriggerMenuJsonContainer* m_hltJson;
+      const xAOD::TriggerMenuJsonContainer* m_hltmonitoringJson;
       const xAOD::TriggerMenuJsonContainer* m_l1Json;
       const xAOD::TriggerMenuJsonContainer* m_hltpsJson;
       const xAOD::TriggerMenuJsonContainer* m_l1psJson;
@@ -192,6 +198,7 @@ namespace TrigConf {
       const xAOD::TriggerMenu* m_menu;
       /// The active configuration for the current event (For Run3 AOD)
       const xAOD::TriggerMenuJson* m_currentHltJson;
+      const xAOD::TriggerMenuJson* m_currentHltmonitoringJson;
       const xAOD::TriggerMenuJson* m_currentL1Json;
       const xAOD::TriggerMenuJson* m_currentHltpsJson;
       const xAOD::TriggerMenuJson* m_currentL1psJson;
diff --git a/Trigger/TrigConfiguration/TrigConfxAOD/src/xAODConfigSvc.cxx b/Trigger/TrigConfiguration/TrigConfxAOD/src/xAODConfigSvc.cxx
index 07e14762fc0075131a308784846e99453b0b4534..eebe5b3fa3316845151ceb04858cae21ec61b214 100644
--- a/Trigger/TrigConfiguration/TrigConfxAOD/src/xAODConfigSvc.cxx
+++ b/Trigger/TrigConfiguration/TrigConfxAOD/src/xAODConfigSvc.cxx
@@ -68,6 +68,10 @@ namespace TrigConf {
         m_hltJson    = std::make_unique<xAOD::TriggerMenuJsonContainer>();
         m_hltJson->setStore( m_hltJsonAux.get() );
 
+        m_hltmonitoringJsonAux = std::make_unique<xAOD::TriggerMenuJsonAuxContainer>();
+        m_hltmonitoringJson    = std::make_unique<xAOD::TriggerMenuJsonContainer>();
+        m_hltmonitoringJson->setStore( m_hltmonitoringJsonAux.get() );
+
         m_l1JsonAux = std::make_unique<xAOD::TriggerMenuJsonAuxContainer>();
         m_l1Json    = std::make_unique<xAOD::TriggerMenuJsonContainer>();
         m_l1Json->setStore( m_l1JsonAux.get() );
@@ -293,6 +297,17 @@ namespace TrigConf {
       return *(m_currentHlt.get(ctx));
    }
 
+   const HLTMonitoring& xAODConfigSvc::hltMonitoring(const EventContext& ctx) const {
+      if (!m_menuJSONContainerAvailable) {
+         REPORT_MESSAGE( MSG::FATAL ) << "Run 3 hltMonitoring JSON not loaded." << endmsg;
+         throw GaudiException( "Service not initialised correctly",
+                               "TrigConf::xAODConfigSvc::hltMenu",
+                               StatusCode::FAILURE );
+      }
+      // Run3: From in-file JSON metadata
+      return *(m_currentHltmonitoring.get(ctx));
+   }
+
    const L1Menu& xAODConfigSvc::l1Menu(const EventContext& ctx) const {
       if (!m_useInFileMetadata) {
          SG::ReadHandle<L1Menu> l1MenuHandle(m_l1MenuName);  // No context - Detector Store
@@ -427,6 +442,7 @@ namespace TrigConf {
 
       // Read the R3 metadata object...
       const xAOD::TriggerMenuJsonContainer* input_hlt = nullptr;
+      const xAOD::TriggerMenuJsonContainer* input_hltmonitoring = nullptr;
       const xAOD::TriggerMenuJsonContainer* input_l1 = nullptr;
       const xAOD::TriggerMenuJsonContainer* input_hltps = nullptr;
       const xAOD::TriggerMenuJsonContainer* input_l1ps = nullptr;
@@ -436,6 +452,12 @@ namespace TrigConf {
       {
          m_menuJSONContainerAvailable = false;
       }
+      if( !m_metaStore->contains<xAOD::TriggerMenuJsonContainer>(m_metaNameJSON_hltmonitoring)
+          or m_metaStore->retrieve( input_hltmonitoring, m_metaNameJSON_hltmonitoring ).isFailure() )
+      {
+         // m_menuJSONContainerAvailable = false;
+         // Currently planning on only storing these data in MC. Hence this has to be an optional input.
+      }
       if( !m_metaStore->contains<xAOD::TriggerMenuJsonContainer>(m_metaNameJSON_l1)
           or m_metaStore->retrieve( input_l1, m_metaNameJSON_l1 ).isFailure() )
       {
@@ -515,6 +537,9 @@ namespace TrigConf {
       if (m_menuJSONContainerAvailable) {
 
          copyMetadataToPersonalStore(input_hlt, m_hltJson.get());
+         if (input_hltmonitoring) {
+            copyMetadataToPersonalStore(input_hltmonitoring, m_hltmonitoringJson.get());
+         }
          copyMetadataToPersonalStore(input_l1, m_l1Json.get());
          copyMetadataToPersonalStore(input_hltps, m_hltpsJson.get());
          copyMetadataToPersonalStore(input_l1ps, m_l1psJson.get());
@@ -806,6 +831,7 @@ namespace TrigConf {
       if (loadedHltJson == nullptr || loadedHltJson->key() != keys->smk()) {
          validConfig = false;
       }
+      // The check on loadedHltJson is good also for loadedHltmonitoringJson
       if (loadedL1Json == nullptr || loadedL1Json->key() != keys->smk()) {
          validConfig = false;
       }
@@ -832,30 +858,36 @@ namespace TrigConf {
       // but prevent the extension of m_hltJson et. al. from a BeginInputFile incident.
       std::shared_lock lockShared(m_sharedMutex);
 
-      TriggerMenuJsonPtrWrapper& currentHltJson   = *(m_currentHltJson.get(context));
-      TriggerMenuJsonPtrWrapper& currentL1Json    = *(m_currentL1Json.get(context));
+      TriggerMenuJsonPtrWrapper& currentHltJson = *(m_currentHltJson.get(context));
+      TriggerMenuJsonPtrWrapper& currentHltmonitoringJson = *(m_currentHltmonitoringJson.get(context));
+      TriggerMenuJsonPtrWrapper& currentL1Json = *(m_currentL1Json.get(context));
       TriggerMenuJsonPtrWrapper& currentHltpsJson = *(m_currentHltpsJson.get(context));
-      TriggerMenuJsonPtrWrapper& currentL1psJson  = *(m_currentL1psJson.get(context));
-      TriggerMenuJsonPtrWrapper& currentBgJson    = *(m_currentBgJson.get(context));
+      TriggerMenuJsonPtrWrapper& currentL1psJson = *(m_currentL1psJson.get(context));
+      TriggerMenuJsonPtrWrapper& currentBgJson = *(m_currentBgJson.get(context));
 
-      TrigConf::HLTMenu&         currentHlt   = *(m_currentHlt.get(context));
-      TrigConf::L1Menu&          currentL1    = *(m_currentL1.get(context));
+      TrigConf::HLTMenu& currentHlt = *(m_currentHlt.get(context));
+      TrigConf::HLTMonitoring& currentHltmonitoring = *(m_currentHltmonitoring.get(context));
+      TrigConf::L1Menu& currentL1 = *(m_currentL1.get(context));
       TrigConf::HLTPrescalesSet& currentHltps = *(m_currentHltps.get(context));
-      TrigConf::L1PrescalesSet&  currentL1ps  = *(m_currentL1ps.get(context));
-      TrigConf::L1BunchGroupSet& currentBg    = *(m_currentBg.get(context));
+      TrigConf::L1PrescalesSet& currentL1ps = *(m_currentL1ps.get(context));
+      TrigConf::L1BunchGroupSet& currentBg = *(m_currentBg.get(context));
 
-      ATH_CHECK( loadPtree("HLT Menu",      m_hltJson.get(),   keys->smk(),    currentHltJson,   currentHlt) );
-      ATH_CHECK( loadPtree("L1 Menu",       m_l1Json.get(),    keys->smk(),    currentL1Json,    currentL1) );
+      ATH_CHECK( loadPtree("HLT Menu", m_hltJson.get(), keys->smk(), currentHltJson, currentHlt) );
+      ATH_CHECK( loadPtree("HLT Monitoring", m_hltmonitoringJson.get(), keys->smk(), currentHltmonitoringJson, currentHltmonitoring, /*optional=*/true) );
+      ATH_CHECK( loadPtree("L1 Menu",  m_l1Json.get(), keys->smk(), currentL1Json, currentL1) );
       ATH_CHECK( loadPtree("HLT Prescales", m_hltpsJson.get(), keys->hltpsk(), currentHltpsJson, currentHltps) );
-      ATH_CHECK( loadPtree("L1 Prescales",  m_l1psJson.get(),  keys->l1psk(),  currentL1psJson,  currentL1ps) );
+      ATH_CHECK( loadPtree("L1 Prescales", m_l1psJson.get(), keys->l1psk(), currentL1psJson, currentL1ps) );
       if (bgKey) {
-         ATH_CHECK( loadPtree("Bunchgroups",   m_bgJson.get(),    bgKey->id(),           currentBgJson,    currentBg) );
+         ATH_CHECK( loadPtree("Bunchgroups", m_bgJson.get(), bgKey->id(), currentBgJson, currentBg) );
       }
 
       // Loading the payload doesn't additionally let the object know about its own key. We can load this in now too.
       // The current*Json objects were updated by loadPtree to point to the entry with the correct key.
       // We don't set this in loadPtree as the poperties are on the derived objects, not the base DataStructure.
       currentHlt.setSMK( currentHltJson.m_ptr->key() );
+      if (currentHltmonitoringJson.m_ptr) {
+         currentHltmonitoring.setSMK( currentHltmonitoringJson.m_ptr->key() );
+      }
       currentL1.setSMK( currentL1Json.m_ptr->key() );
       currentHltps.setPSK( currentHltpsJson.m_ptr->key() );
       currentL1ps.setPSK( currentL1psJson.m_ptr->key() );
@@ -898,10 +930,12 @@ namespace TrigConf {
                                        const xAOD::TriggerMenuJsonContainer* metaContainer,
                                        const uint32_t keyToCheck,
                                        TriggerMenuJsonPtrWrapper& cacheOfLoadedMenuPtr,
-                                       DataStructure& dataStructure) {
+                                       DataStructure& dataStructure,
+                                       const bool optional) {
       xAOD::TriggerMenuJsonContainer::const_iterator menu_itr = metaContainer->begin();
       xAOD::TriggerMenuJsonContainer::const_iterator menu_end = metaContainer->end();
       const xAOD::TriggerMenuJson* ptrToLocatedMenu = nullptr;
+      cacheOfLoadedMenuPtr.m_ptr = nullptr;
       for( ; menu_itr != menu_end; ++menu_itr ) {
          // Check if this is the menu we're looking for:
          if( keyToCheck != (*menu_itr)->key() ) continue;
@@ -923,7 +957,7 @@ namespace TrigConf {
          break;
       }
 
-      if (ptrToLocatedMenu == nullptr) {
+      if (not optional and ptrToLocatedMenu == nullptr) {
          REPORT_MESSAGE( MSG::FATAL )
             << "Couldn't find configuration for current event"
             << ", Requested key=" << keyToCheck
diff --git a/Trigger/TrigConfiguration/TrigConfxAOD/src/xAODConfigSvc.h b/Trigger/TrigConfiguration/TrigConfxAOD/src/xAODConfigSvc.h
index 93963db5e083416877294d6b85af94199bfedfa1..73fd7e4c7898bf0a18d0f9f7feb85f550e61b5c8 100644
--- a/Trigger/TrigConfiguration/TrigConfxAOD/src/xAODConfigSvc.h
+++ b/Trigger/TrigConfiguration/TrigConfxAOD/src/xAODConfigSvc.h
@@ -22,6 +22,7 @@
 #include "TrigConfHLTData/HLTSequenceList.h"
 
 #include "TrigConfData/HLTMenu.h"
+#include "TrigConfData/HLTMonitoring.h"
 #include "TrigConfData/L1Menu.h"
 #include "TrigConfData/HLTPrescalesSet.h"
 #include "TrigConfData/L1PrescalesSet.h"
@@ -134,6 +135,9 @@ namespace TrigConf {
       /// Returns the JSON configured HLTMenu ptree
       virtual const HLTMenu& hltMenu(const EventContext& ctx = Gaudi::Hive::currentContext()) const override;
 
+      /// Returns the JSON configured HLTMonitoring ptree
+      virtual const HLTMonitoring& hltMonitoring(const EventContext& ctx = Gaudi::Hive::currentContext()) const override;
+
       /// Returns the JSON configured L1 ptree
       virtual const L1Menu& l1Menu(const EventContext& ctx = Gaudi::Hive::currentContext()) const override;
 
@@ -179,11 +183,13 @@ namespace TrigConf {
       /// @param keyToCheck The key of the ptree to load
       /// @param cacheOfLoadedMenuPtr Slot's cache of the currently loaded TriggerMenuJson
       /// @param DataStructure dataStructure object to fill with the TriggerMenuJson's payload
+      /// @param optional Set to true if it is expected in some valid scenarios for the payload to be missing
       StatusCode loadPtree(const std::string& humanName, 
                            const xAOD::TriggerMenuJsonContainer* metaContainer, 
                            const uint32_t keyToCheck,
                            TriggerMenuJsonPtrWrapper& cacheOfLoadedMenuPtr,
-                           DataStructure& dataStructure);
+                           DataStructure& dataStructure,
+                           const bool optional = false);
 
       SG::ReadHandleKey<xAOD::TrigConfKeys> m_eventKey{this, "EventObjectName", "TrigConfKeys", 
         "Key for the event-level configuration identifier object"};
@@ -202,6 +208,9 @@ namespace TrigConf {
       Gaudi::Property< std::string > m_metaNameJSON_hlt {this, "JSONMetaObjectNameHLT", "TriggerMenuJson_HLT",
         "StoreGate key for the xAOD::TriggerMenuJson HLT configuration object"};
 
+      Gaudi::Property< std::string > m_metaNameJSON_hltmonitoring {this, "JSONMetaObjectNameHLTMonitoring", "TriggerMenuJson_HLTMonitoring",
+        "StoreGate key for the xAOD::TriggerMenuJson HLT monitoring configuration object"};
+
       Gaudi::Property< std::string > m_metaNameJSON_l1 {this, "JSONMetaObjectNameL1", "TriggerMenuJson_L1",
         "StoreGate key for the xAOD::TriggerMenuJson L1 configuration object"};
 
@@ -254,6 +263,8 @@ namespace TrigConf {
       /// @{
       std::unique_ptr<xAOD::TriggerMenuJsonAuxContainer> m_hltJsonAux;
       std::unique_ptr<xAOD::TriggerMenuJsonContainer> m_hltJson;
+      std::unique_ptr<xAOD::TriggerMenuJsonAuxContainer> m_hltmonitoringJsonAux;
+      std::unique_ptr<xAOD::TriggerMenuJsonContainer> m_hltmonitoringJson;
       std::unique_ptr<xAOD::TriggerMenuJsonAuxContainer> m_l1JsonAux;
       std::unique_ptr<xAOD::TriggerMenuJsonContainer> m_l1Json;
       std::unique_ptr<xAOD::TriggerMenuJsonAuxContainer> m_hltpsJsonAux;
@@ -265,6 +276,7 @@ namespace TrigConf {
 
       // The menu JSONs being used in the current event by each slot (wrapped 'const xAOD::TriggerMenuJson' ptr)
       SG::SlotSpecificObj<TriggerMenuJsonPtrWrapper> m_currentHltJson;
+      SG::SlotSpecificObj<TriggerMenuJsonPtrWrapper> m_currentHltmonitoringJson;
       SG::SlotSpecificObj<TriggerMenuJsonPtrWrapper> m_currentL1Json;
       SG::SlotSpecificObj<TriggerMenuJsonPtrWrapper> m_currentHltpsJson;
       SG::SlotSpecificObj<TriggerMenuJsonPtrWrapper> m_currentL1psJson;
@@ -272,6 +284,7 @@ namespace TrigConf {
 
       // The decoded menu JSON data stored in ptree objects
       SG::SlotSpecificObj<HLTMenu> m_currentHlt;
+      SG::SlotSpecificObj<HLTMonitoring> m_currentHltmonitoring;
       SG::SlotSpecificObj<L1Menu> m_currentL1;
       SG::SlotSpecificObj<HLTPrescalesSet> m_currentHltps;
       SG::SlotSpecificObj<L1PrescalesSet> m_currentL1ps;
diff --git a/Trigger/TrigConfiguration/TrigConfxAOD/src/xAODMenuWriterMT.cxx b/Trigger/TrigConfiguration/TrigConfxAOD/src/xAODMenuWriterMT.cxx
index cb0d3fdf52329f60a2c08e3e5eb41d7fec98b6fc..34ad23bbf5e0910227a2c172dc159cbe9dde7134 100644
--- a/Trigger/TrigConfiguration/TrigConfxAOD/src/xAODMenuWriterMT.cxx
+++ b/Trigger/TrigConfiguration/TrigConfxAOD/src/xAODMenuWriterMT.cxx
@@ -60,6 +60,8 @@ namespace TrigConf
 
       ATH_CHECK(m_HLTMenuKey.initialize());             // ReadHandleKey, but DetStore (so renounce)
       renounce(m_HLTMenuKey);
+      ATH_CHECK(m_HLTMonitoringKey.initialize());       // ReadHandleKey, but DetStore (so renounce)
+      renounce(m_HLTMonitoringKey);
       ATH_CHECK(m_HLTPrescaleSetInputKey.initialize()); // ReadCondHandleKey
 
       ATH_CHECK(m_L1MenuKey.initialize());             // ReadHandleKey, but DetStore (so renounce)
@@ -74,6 +76,14 @@ namespace TrigConf
       ATH_CHECK(m_metaStore->record(aux_hlt, m_metaNameJSON_hlt + "Aux."));
       ATH_CHECK(m_metaStore->record(m_menuJSON_hlt, m_metaNameJSON_hlt));
 
+      // HLT Monitoring JSON object - contains Monitoring groups for HLT menus
+      xAOD::TriggerMenuJsonAuxContainer *aux_hltmonitoring = new xAOD::TriggerMenuJsonAuxContainer();
+      m_menuJSON_hltmonitoring = new xAOD::TriggerMenuJsonContainer();
+      m_menuJSON_hltmonitoring->setStore(aux_hltmonitoring);
+
+      ATH_CHECK(m_metaStore->record(aux_hltmonitoring, m_metaNameJSON_hltmonitoring + "Aux."));
+      ATH_CHECK(m_metaStore->record(m_menuJSON_hltmonitoring, m_metaNameJSON_hltmonitoring));
+
       // L1 JSON object - contains L1 menus
       xAOD::TriggerMenuJsonAuxContainer *aux_l1 = new xAOD::TriggerMenuJsonAuxContainer();
       m_menuJSON_l1 = new xAOD::TriggerMenuJsonContainer();
@@ -127,7 +137,7 @@ namespace TrigConf
       if (!m_converted_smk.insert(ckeys.first).second) {
          ATH_MSG_VERBOSE("Already converted SMK: " << ckeys.first);
       } else {
-         ATH_MSG_DEBUG("Filling HLT information for SMK:" << ckeys.first);
+         ATH_MSG_DEBUG("Filling HLT Menu information for SMK:" << ckeys.first);
          SG::ReadHandle<TrigConf::HLTMenu> hltMenuHandle(m_HLTMenuKey, ctx);
          ATH_CHECK(hltMenuHandle.isValid());
          std::stringstream hltTriggerMenuJson;
@@ -138,6 +148,20 @@ namespace TrigConf
          hlt->setName(hltMenuHandle->name());
          hlt->setPayload(hltTriggerMenuJson.str());
          //////////////////////////////////////////////////////////////////////////////
+         ATH_MSG_DEBUG("Filling HLT Monitoring information for SMK:" << ckeys.first);
+         SG::ReadHandle<TrigConf::HLTMonitoring> hltMonitoringHandle(m_HLTMonitoringKey, ctx);
+         if (hltMonitoringHandle.isValid()) {
+            std::stringstream hltMonitoringJson;
+            hltMonitoringHandle->printRaw(hltMonitoringJson);
+            xAOD::TriggerMenuJson *hltmonitoring = new xAOD::TriggerMenuJson();
+            m_menuJSON_hltmonitoring->push_back(hltmonitoring); // Now owned by MetaDataStore
+            hltmonitoring->setKey(ckeys.first);
+            hltmonitoring->setName(hltMonitoringHandle->name());
+            hltmonitoring->setPayload(hltMonitoringJson.str());
+         } else {
+            ATH_MSG_DEBUG("No HLT Monitoring JSON available - skipping.");
+         }
+         //////////////////////////////////////////////////////////////////////////////
          ATH_MSG_DEBUG("Filling L1 information for SMK:" << ckeys.first);
          SG::ReadHandle<TrigConf::L1Menu> l1MenuHandle = SG::makeHandle(m_L1MenuKey, ctx);
          ATH_CHECK(l1MenuHandle.isValid());
diff --git a/Trigger/TrigConfiguration/TrigConfxAOD/src/xAODMenuWriterMT.h b/Trigger/TrigConfiguration/TrigConfxAOD/src/xAODMenuWriterMT.h
index ca869d0a59ccbde01dd4cdd0d8255887ed44f05c..40eefa96ba63f9f07ff362c4b93f29ed1787d736 100644
--- a/Trigger/TrigConfiguration/TrigConfxAOD/src/xAODMenuWriterMT.h
+++ b/Trigger/TrigConfiguration/TrigConfxAOD/src/xAODMenuWriterMT.h
@@ -24,6 +24,7 @@ extern "C" {
 
 // Trigger include(s):
 #include "TrigConfData/HLTMenu.h"
+#include "TrigConfData/HLTMonitoring.h"
 #include "TrigConfData/L1Menu.h"
 #include "TrigConfData/HLTPrescalesSet.h"
 #include "TrigConfData/L1PrescalesSet.h"
@@ -68,6 +69,9 @@ namespace TrigConf {
       SG::ReadHandleKey<TrigConf::HLTMenu> m_HLTMenuKey {this, "HLTTriggerMenu", "DetectorStore+HLTTriggerMenu",
         "HLT Menu key"};
 
+      SG::ReadHandleKey<TrigConf::HLTMonitoring> m_HLTMonitoringKey {this, "HLTMonitoringMenu", "DetectorStore+HLTMonitoringMenu",
+        "HLT Monitoring key"};
+
       SG::ReadHandleKey<TrigConf::L1Menu> m_L1MenuKey {this, "L1TriggerMenu", "DetectorStore+L1TriggerMenu",
         "L1 Menu key"};
 
@@ -80,6 +84,9 @@ namespace TrigConf {
       Gaudi::Property< std::string > m_metaNameJSON_hlt {this, "JSONMetaObjectNameHLT", "TriggerMenuJson_HLT",
         "StoreGate key for the xAOD::TriggerMenuJson HLT configuration object"};
 
+      Gaudi::Property< std::string > m_metaNameJSON_hltmonitoring {this, "JSONMetaObjectNameHLTMonitoring", "TriggerMenuJson_HLTMonitoring",
+        "StoreGate key for the xAOD::TriggerMenuJson HLT Monitoring configuration object"};
+
       Gaudi::Property< std::string > m_metaNameJSON_l1 {this, "JSONMetaObjectNameL1", "TriggerMenuJson_L1",
         "StoreGate key for the xAOD::TriggerMenuJson L1 configuration object"};
 
@@ -105,6 +112,7 @@ namespace TrigConf {
 
       //  The configuration objects that we are writing
       mutable xAOD::TriggerMenuJsonContainer* m_menuJSON_hlt ATLAS_THREAD_SAFE;
+      mutable xAOD::TriggerMenuJsonContainer* m_menuJSON_hltmonitoring ATLAS_THREAD_SAFE;
       mutable xAOD::TriggerMenuJsonContainer* m_menuJSON_l1 ATLAS_THREAD_SAFE;
       mutable xAOD::TriggerMenuJsonContainer* m_menuJSON_hltps ATLAS_THREAD_SAFE;
       mutable xAOD::TriggerMenuJsonContainer* m_menuJSON_l1ps ATLAS_THREAD_SAFE;