diff --git a/reco/L1/CMakeLists.txt b/reco/L1/CMakeLists.txt
index 1564b7318a78a618cf330a75c7c03a624d3c0c94..080760aca90f84bb3e73d0f7a4182dd42cc32d9c 100644
--- a/reco/L1/CMakeLists.txt
+++ b/reco/L1/CMakeLists.txt
@@ -111,6 +111,7 @@ set(HEADERS
   L1Algo/L1EArray.h
   L1Algo/L1Undef.h
   L1Algo/utils/CaUvConverter.h
+  L1Algo/utils/CaMonitor.h
   catools/CaToolsWindowFinder.h
   catools/CaToolsLinkKey.h
   catools/CaToolsHitRecord.h
@@ -214,6 +215,7 @@ install(FILES CbmL1Counters.h
   utils/CbmCaIdealHitProducer.h
   utils/CbmCaIdealHitProducerDet.h
   L1Algo/utils/CaUvConverter.h
+  L1Algo/utils/CaMonitor.h
   qa/CbmCaInputQaBase.h
   DESTINATION include
 )
diff --git a/reco/L1/CbmCaMCModule.cxx b/reco/L1/CbmCaMCModule.cxx
index d70f501990a5b4a24dc3345d5a9119f2e859f12d..2e65dc8449572bf6c7000a457bab524be1c43dea 100644
--- a/reco/L1/CbmCaMCModule.cxx
+++ b/reco/L1/CbmCaMCModule.cxx
@@ -92,6 +92,19 @@ try {
   // Check initialization
   this->CheckInit();
 
+  // Init monitor
+  fMonitor.SetKeyName(EMonitorKey::kMcTrack, "N MC tracks");
+  fMonitor.SetKeyName(EMonitorKey::kMcTrackReconstructable, "N MC tracks rec-able");
+  fMonitor.SetKeyName(EMonitorKey::kMcPoint, "N MC points");
+  fMonitor.SetKeyName(EMonitorKey::kRecoNevents, "N reco events");
+  fMonitor.SetKeyName(EMonitorKey::kMissedMatchesMvd, "N missed MVD matches");
+  fMonitor.SetKeyName(EMonitorKey::kMissedMatchesSts, "N missed STS matches");
+  fMonitor.SetKeyName(EMonitorKey::kMissedMatchesMuch, "N missed MuCh matches");
+  fMonitor.SetKeyName(EMonitorKey::kMissedMatchesTrd, "N missed TRD matches");
+  fMonitor.SetKeyName(EMonitorKey::kMissedMatchesTof, "N missed TOF matches");
+  fMonitor.SetRatioKeys({EMonitorKey::kRecoNevents});
+
+
   LOG(info) << "CA MC Module: initializing CA tracking Monte-Carlo module... \033[1;32mDone!\033[0m";
   return true;
 }
@@ -125,12 +138,16 @@ void MCModule::InitEvent(CbmEvent* /*pEvent*/)
   fpMCData->Clear();
   this->ReadMCTracks();
   this->ReadMCPoints();
+  fMonitor.Increment(EMonitorKey::kMcTrack, fpMCData->GetNofPoints());
+  fMonitor.Increment(EMonitorKey::kMcPoint, fpMCData->GetNofTracks());
 
   // Prepare tracks: set point indexes and redefine indexes from external to internal containers
   for (auto& aTrk : fpMCData->GetTrackContainer()) {
     aTrk.SortPointIndexes(
       [&](const int& iPl, const int& iPr) { return fpMCData->GetPoint(iPl).GetZ() < fpMCData->GetPoint(iPr).GetZ(); });
   }
+
+  fMonitor.Increment(EMonitorKey::kRecoNevents);
 }
 
 // ---------------------------------------------------------------------------------------------------------------------
@@ -182,7 +199,7 @@ void MCModule::InitTrackInfo()
 
 // ---------------------------------------------------------------------------------------------------------------------
 //
-void MCModule::Finish() {}
+void MCModule::Finish() { LOG(info) << '\n' << fMonitor.ToString(); }
 
 
 // **********************************
@@ -200,6 +217,9 @@ void MCModule::MatchRecoAndMC()
   this->MatchPointsAndHits<L1DetectorID::kTof>();
   this->MatchRecoAndMCTracks();
   this->InitTrackInfo();
+  for (const auto& trkMC : fpMCData->GetTrackContainer()) {
+    if (trkMC.IsReconstructable()) { fMonitor.Increment(EMonitorKey::kMcTrackReconstructable); }
+  }
 }
 
 // ---------------------------------------------------------------------------------------------------------------------
diff --git a/reco/L1/CbmCaMCModule.h b/reco/L1/CbmCaMCModule.h
index af9ea9ef2cc51c8f1c3ac806d58394f92b61e42b..e51f7ed6ef2eb6a03c41862a34da793ff50f9f78 100644
--- a/reco/L1/CbmCaMCModule.h
+++ b/reco/L1/CbmCaMCModule.h
@@ -34,6 +34,7 @@
 #include <string_view>
 #include <type_traits>
 
+#include "CaMonitor.h"
 #include "CaToolsMCData.h"
 #include "CaToolsMCPoint.h"
 #include "L1Constants.h"
@@ -100,7 +101,7 @@ namespace cbm::ca
     /// This method finds a match for a given hit or matches for hits clusters (in case of STS), finds the best
     /// link in the match and returns the corresponding global ID of the MC points.
     template<L1DetectorID DetId>
-    int MatchHitWithMc(int iHitExt) const;
+    int MatchHitWithMc(int iHitExt);
 
     /// @brief Match reconstructed and MC data
     ///
@@ -202,6 +203,23 @@ namespace cbm::ca
     template<L1DetectorID DetID>
     std::optional<::ca::tools::MCPoint> FillMCPoint(int iExtId, int iEvent, int iFile);
 
+    /// @enum  EMonitorKey
+    /// @brief Monitor keys
+    enum class EMonitorKey
+    {
+      kMcTrack,                 ///< Number of MC tracks
+      kMcTrackReconstructable,  ///< Number of reconstructable MC tracks
+      kMcPoint,                 ///< Number of MC points
+      kRecoNevents,             ///< Number of events
+      kMissedMatchesMvd,        ///< Number of missed matches in MVD
+      kMissedMatchesSts,        ///< Number of missed matches in STS
+      kMissedMatchesMuch,       ///< Number of missed matches in MuCh
+      kMissedMatchesTrd,        ///< Number of missed matches in TRD
+      kMissedMatchesTof,        ///< Number of missed TOF matches
+      kEND
+    };
+    ::ca::Monitor<EMonitorKey> fMonitor {"CA MC Module"};  ///< Monitor
+
     // ------ Flags
     CbmCaDetIdArr_t<bool> fvbUseDet = {{false}};  ///< Flag: is detector subsystem used
     bool fbLegacyEventMode          = false;  ///< if tracking uses events instead of time-slices (back compatibility)
@@ -245,11 +263,27 @@ namespace cbm::ca
 // ---------------------------------------------------------------------------------------------------------------------
 //
 template<L1DetectorID DetID>
-int cbm::ca::MCModule::MatchHitWithMc(int iHitExt) const
+int cbm::ca::MCModule::MatchHitWithMc(int iHitExt)
 {
   int iPoint            = -1;
   const auto* pHitMatch = dynamic_cast<CbmMatch*>(fvpBrHitMatches[DetID]->At(iHitExt));
-  assert(pHitMatch);
+  if (!pHitMatch) {
+    LOG(warn) << "Hit match with index " << iHitExt << " is missing for " << kDetName[DetID];
+    if constexpr (L1DetectorID::kMvd == DetID) { fMonitor.Increment(EMonitorKey::kMissedMatchesMvd); }
+    else if constexpr (L1DetectorID::kSts == DetID) {
+      fMonitor.Increment(EMonitorKey::kMissedMatchesSts);
+    }
+    else if constexpr (L1DetectorID::kMuch == DetID) {
+      fMonitor.Increment(EMonitorKey::kMissedMatchesMuch);
+    }
+    else if constexpr (L1DetectorID::kTrd == DetID) {
+      fMonitor.Increment(EMonitorKey::kMissedMatchesTrd);
+    }
+    else if constexpr (L1DetectorID::kTof == DetID) {
+      fMonitor.Increment(EMonitorKey::kMissedMatchesTof);
+    }
+    return iPoint;
+  }
 
   if constexpr (L1DetectorID::kTof == DetID) {
     for (int iLink = 0; iLink < pHitMatch->GetNofLinks(); ++iLink) {
diff --git a/reco/L1/CbmL1.cxx b/reco/L1/CbmL1.cxx
index 56dac242b2851b495cc46631e819c4c59af55a89..bf0a7c1cdd5f357226fbb5d2b540c6cc263a6fae 100644
--- a/reco/L1/CbmL1.cxx
+++ b/reco/L1/CbmL1.cxx
@@ -659,9 +659,12 @@ InitStatus CbmL1::Init()
 
   DumpMaterialToFile("L1material.root");
 
-  // Initialize counters
-  fEventNo       = 0;
-  fNofRecoTracks = 0;
+  // Initialize monitor
+  fMonitor.SetKeyName(EMonitorKey::kEvent, "N events");
+  fMonitor.SetKeyName(EMonitorKey::kRecoTrack, "N reco tracks");
+  fMonitor.SetKeyName(EMonitorKey::kRecoHit, "N hits");
+  fMonitor.SetRatioKeys({EMonitorKey::kEvent, EMonitorKey::kRecoTrack});
+  fMonitor.Reset();
 
   return kSUCCESS;
 }
@@ -788,9 +791,10 @@ void CbmL1::Reconstruct(CbmEvent* event)
       t.Hits.push_back(cbmHitID);
     }
     fvRecoTracks.push_back(t);
+    fMonitor.Increment(EMonitorKey::kRecoHit, it->NHits);
   }
 
-  fNofRecoTracks += static_cast<int>(fpAlgo->fRecoTracks.size());
+  fMonitor.Increment(EMonitorKey::kRecoTrack, fvRecoTracks.size());
 
   LOG(debug) << "CA Track Finder: " << fpAlgo->fCaRecoTime << " s/sub-ts";
 
@@ -829,6 +833,7 @@ void CbmL1::Reconstruct(CbmEvent* event)
   }
 
   ++fEventNo;
+  fMonitor.Increment(EMonitorKey::kEvent);
 }
 
 // -----   Finish CbmStsFitPerformanceTask task   -----------------------------
@@ -836,9 +841,9 @@ void CbmL1::Finish()
 {
 
   // monitor the material
-  LOG(info) << "\033[31;1m ****************************\033[0m";
-  LOG(info) << "\033[31;1m **  CA Tracking monitore  **\033[0m";
-  LOG(info) << "\033[31;1m ****************************\033[0m";
+  LOG(info) << "\033[31;1m ***************************\033[0m";
+  LOG(info) << "\033[31;1m **  CA Tracking monitor  **\033[0m";
+  LOG(info) << "\033[31;1m ***************************\033[0m";
 
 
   LOG(info) << "\033[31;1m ----- Material budget -------------------------------------- \033[0m";
@@ -848,11 +853,7 @@ void CbmL1::Finish()
   LOG(info) << "\033[31;1m -------------------------------------------------------------\033[0m";
 
   // monitor of the reconstructed tracks
-  LOG(info) << "\033[31;1m ----- Counters ----------------------------------------------\033[0m";
-  LOG(info) << "\tNumber of analyzed events:                   " << fEventNo;
-  LOG(info) << "\tNumber of reconstructed tracks:              " << fNofRecoTracks;
-  LOG(info) << "\tNumber of reconstructed tracks per event/TS: " << static_cast<double>(fNofRecoTracks) / fEventNo;
-  LOG(info) << "\033[31;1m -------------------------------------------------------------\033[0m";
+  LOG(info) << '\n' << fMonitor.ToString();
 
   TDirectory* curr   = gDirectory;
   TFile* currentFile = gFile;
diff --git a/reco/L1/CbmL1.h b/reco/L1/CbmL1.h
index 0eb834827ca58a32e9e5cd28f9fc17954c4118f1..82358e36ef9de87618b9c55a7bd6374b1ed54818 100644
--- a/reco/L1/CbmL1.h
+++ b/reco/L1/CbmL1.h
@@ -53,6 +53,7 @@
 #include <unordered_map>
 #include <utility>
 
+#include "CaMonitor.h"
 #include "L1Algo/L1Algo.h"
 #include "L1Algo/L1Vector.h"
 #include "L1EventEfficiencies.h"
@@ -257,6 +258,17 @@ public:
   void SetMcbmMode() { fTrackingMode = L1Algo::TrackingMode::kMcbm; }
   void SetGlobalMode() { fTrackingMode = L1Algo::TrackingMode::kGlobal; }
 
+  // Tracking monitor (prototype)
+  enum class EMonitorKey
+  {
+    kEvent,
+    kRecoTrack,
+    kRecoHit,
+    kEND
+  };
+
+  ca::Monitor<EMonitorKey> fMonitor = {"CA Tracking"};  ///< Tracking monitor
+
 
   //   void SetTrackingLevel( Int_t iLevel ){ fTrackingLevel = iLevel; }
   //   void MomentumCutOff( Double_t cut ){ fMomentumCutOff = cut; }
diff --git a/reco/L1/L1Algo/utils/CaMonitor.h b/reco/L1/L1Algo/utils/CaMonitor.h
new file mode 100644
index 0000000000000000000000000000000000000000..70f908db614b018899956acd061a41c20a60d645
--- /dev/null
+++ b/reco/L1/L1Algo/utils/CaMonitor.h
@@ -0,0 +1,114 @@
+/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergei Zharko [committer] */
+
+/// @file   CaMonitor.h
+/// @brief  CA Tracking monitor class
+/// @since  25.08.2023
+/// @author S.Zharko <s.zharko@gsi.de>
+
+#ifndef CaMonitor_h
+#define CaMonitor_h 1
+
+#include <iomanip>
+#include <sstream>
+#include <string>
+
+#include "L1EArray.h"
+
+namespace ca
+{
+  /// @class  Monitor
+  /// @brief  Monitor class for CA tracking
+  /// @tparam EMonitorKey  A enum class, containing keys for monitorables
+  ///
+  template<class EMonitorKey>
+  class Monitor {
+  public:
+    /// @brief Alias to array, indexed by Monitorable enumeration
+    template<typename T>
+    using MonitorableArr_t = L1EArray<EMonitorKey, T>;
+
+    /// @brief Constructor
+    /// @param name Name of monitor
+    Monitor(const std::string& name) : fsName(name) {}
+
+    /// @brief Gets key name
+    /// @param key Monitorable key
+    const std::string& GetKeyName(EMonitorKey key) const { return faKeyNames[key]; }
+
+    /// @brief Gets counter value
+    /// @param key
+    int GetValue(EMonitorKey key) const { return faKeyCounters[key]; }
+
+    /// @brief Increments key counter by 1
+    /// @param key Monitorable key
+    void Increment(EMonitorKey key) { ++faKeyCounters[key]; };
+
+    /// @brief Increments key counter by a number
+    /// @param key  Monitorable key
+    /// @param num  Number to add
+    void Increment(EMonitorKey key, int num) { faKeyCounters[key] += num; }
+
+    /// @brief Resets the counters
+    void Reset() { faKeyCounters.fill(0); }
+
+    /// @brief Sets keys of monitorables, which are used as denominators for ratios
+    /// @param vKeys Vector of keys
+    void SetRatioKeys(const std::vector<EMonitorKey>& vKeys) { fvRatioKeys = vKeys; }
+
+    /// @brief Sets name of key
+    /// @param name  Name of monitoralble
+    void SetKeyName(EMonitorKey key, const char* name) { faKeyNames[key] = name; }
+
+    /// @brief Prints counters summary to string
+    std::string ToString() const;
+
+  private:
+    std::vector<EMonitorKey> fvRatioKeys {};      ///< List of keys, which are used as denominators in ratios
+    std::string fsName;                           ///< Name of the monitor
+    MonitorableArr_t<std::string> faKeyNames {};  ///< Names of keys
+    MonitorableArr_t<int> faKeyCounters {};       ///< Counters of keys
+  };
+}  // namespace ca
+
+// *****************************************
+// **  Template function implementations  **
+// *****************************************
+
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+template<class EMonitorKey>
+std::string ca::Monitor<EMonitorKey>::ToString() const
+{
+  using std::left;
+  using std::right;
+  using std::setfill;
+  using std::setw;
+  std::stringstream msg;
+  constexpr size_t width = 24;
+  size_t fillWidth       = (width + 2) * (1 + fvRatioKeys.size());
+  msg << "----- Monitor: " << fsName << ' ' << setw(fillWidth - fsName.size() - 16) << setfill('-') << '-' << '\n';
+  msg << setfill(' ');
+  msg << setw(width) << left << "Key" << ' ';
+  msg << setw(width) << left << "Total" << ' ';
+  for (auto key : fvRatioKeys) {
+    msg << setw(width) << left << std::string("per ") + faKeyNames[key] << ' ';
+  }
+  msg << '\n';
+  for (int iKey = 0; iKey < static_cast<int>(EMonitorKey::kEND); ++iKey) {
+    msg << setw(width) << left << faKeyNames[iKey] << ' ';
+    msg << setw(width) << right << faKeyCounters[iKey] << ' ';
+    for (auto keyDen : fvRatioKeys) {
+      auto ratio = static_cast<double>(faKeyCounters[iKey]) / faKeyCounters[keyDen];
+      msg << setw(width) << right << ratio << ' ';
+    }
+    msg << '\n';
+  }
+  msg << setw(fillWidth) << setfill('-') << '-' << '\n';
+  msg << setfill(' ');
+  return msg.str();
+}
+
+#endif  // CaToolsMonitor_h
diff --git a/reco/L1/qa/CbmCaOutputQa.cxx b/reco/L1/qa/CbmCaOutputQa.cxx
index d1d3b944fe1764d83383ed941090dcc1059b592b..121e8359885ebf416757747846f7774a5b438003 100644
--- a/reco/L1/qa/CbmCaOutputQa.cxx
+++ b/reco/L1/qa/CbmCaOutputQa.cxx
@@ -475,6 +475,14 @@ InitStatus OutputQa::InitDataBranches()
     if (!fpMCModule->InitRun()) { return kFATAL; }
   }
 
+  // Initialize monitor
+  fMonitor.SetKeyName(EMonitorKey::kEvent, "N events");
+  fMonitor.SetKeyName(EMonitorKey::kTrack, "N reco tracks");
+  fMonitor.SetKeyName(EMonitorKey::kHit, "N hits");
+  fMonitor.SetKeyName(EMonitorKey::kMcTrack, "N MC tracks");
+  fMonitor.SetKeyName(EMonitorKey::kMcPoint, "N MC points");
+  fMonitor.SetRatioKeys({EMonitorKey::kEvent, EMonitorKey::kTrack});
+
   return kSUCCESS;
 }
 
@@ -554,41 +562,44 @@ InitStatus OutputQa::InitHistograms()
 bool OutputQa::Check()
 {
   // Create summary table
-  int nRows = std::count_if(fvbTrackTypeOn.begin(), fvbTrackTypeOn.end(), [](const auto& f) { return f == true; });
-  CbmQaTable* aTable = MakeQaObject<CbmQaTable>("summary_table", "Tracking summary table", nRows + 1, 9);
-  int iRow                          = 0;
-  std::vector<std::string> colNames = {"Efficiency", "Killed", "Length",   "Fakes",     "Clones",
-                                       "Reco/Evt",   "MC/Evt", "Nst(hit)", "Nst(point)"};
-  aTable->SetNamesOfCols(colNames);
-  aTable->SetColWidth(14);
-  double nEvents = static_cast<double>(GetEventNumber());
-  LOG(info) << "Number of events: " << GetEventNumber();
-  for (int iTrType = 0; iTrType < static_cast<int>(fvpTrackHistograms.size()); ++iTrType) {
-    if (!fvbTrackTypeOn[iTrType] || !fvpTrackHistograms[iTrType]->IsMCUsed()) { continue; }
-    aTable->SetRowName(iRow, fvpTrackHistograms[iTrType]->GetTitle());
-    aTable->SetCell(iRow, 0, fvpTrackHistograms[iTrType]->GetIntegratedEff());
-    aTable->SetCell(iRow, 1, fvpTrackHistograms[iTrType]->GetKilledRate());
-    aTable->SetCell(iRow, 2, fvpTrackHistograms[iTrType]->GetAverageRecoLength());
-    aTable->SetCell(iRow, 3, fvpTrackHistograms[iTrType]->GetAverageFakeLength());
-    aTable->SetCell(iRow, 4, fvpTrackHistograms[iTrType]->GetClonesRate());
-    aTable->SetCell(iRow, 5, fvpTrackHistograms[iTrType]->GetNofRecoTracksMatched() / nEvents);
-    aTable->SetCell(iRow, 6, fvpTrackHistograms[iTrType]->GetNofMCTracks() / nEvents);
-    aTable->SetCell(iRow, 7, fvpTrackHistograms[iTrType]->GetAverageNofStationsWithHit());
-    aTable->SetCell(iRow, 8, fvpTrackHistograms[iTrType]->GetAverageNofStationsWithPoint());
-    ++iRow;
-  }
-  double nGhosts = 0.;
-  if (fvpTrackHistograms[ETrackType::kGhost] && fvpTrackHistograms[ETrackType::kAll]) {
-    nGhosts = fvpTrackHistograms[ETrackType::kGhost]->fph_reco_p->GetEntries();
-    aTable->SetRowName(iRow, "N ghosts");
-    aTable->SetCell(iRow, 0, nGhosts);
-    aTable->SetRowName(iRow + 1, "Ghost rate");
-    aTable->SetCell(iRow + 1, 0, nGhosts / fvpTrackHistograms[ETrackType::kAll]->GetNofMCTracks());
+  if (IsMCUsed()) {
+    fpMCModule->Finish();
+
+    int nRows = std::count_if(fvbTrackTypeOn.begin(), fvbTrackTypeOn.end(), [](const auto& f) { return f == true; });
+    CbmQaTable* aTable = MakeQaObject<CbmQaTable>("summary_table", "Tracking summary table", nRows + 1, 9);
+    int iRow           = 0;
+    std::vector<std::string> colNames = {"Efficiency", "Killed", "Length",   "Fakes",     "Clones",
+                                         "Reco/Evt",   "MC/Evt", "Nst(hit)", "Nst(point)"};
+    aTable->SetNamesOfCols(colNames);
+    aTable->SetColWidth(14);
+    double nEvents = static_cast<double>(GetEventNumber());
+    LOG(info) << "Number of events: " << GetEventNumber();
+    for (int iTrType = 0; iTrType < static_cast<int>(fvpTrackHistograms.size()); ++iTrType) {
+      if (!fvbTrackTypeOn[iTrType] || !fvpTrackHistograms[iTrType]->IsMCUsed()) { continue; }
+      aTable->SetRowName(iRow, fvpTrackHistograms[iTrType]->GetTitle());
+      aTable->SetCell(iRow, 0, fvpTrackHistograms[iTrType]->GetIntegratedEff());
+      aTable->SetCell(iRow, 1, fvpTrackHistograms[iTrType]->GetKilledRate());
+      aTable->SetCell(iRow, 2, fvpTrackHistograms[iTrType]->GetAverageRecoLength());
+      aTable->SetCell(iRow, 3, fvpTrackHistograms[iTrType]->GetAverageFakeLength());
+      aTable->SetCell(iRow, 4, fvpTrackHistograms[iTrType]->GetClonesRate());
+      aTable->SetCell(iRow, 5, fvpTrackHistograms[iTrType]->GetNofRecoTracksMatched() / nEvents);
+      aTable->SetCell(iRow, 6, fvpTrackHistograms[iTrType]->GetNofMCTracks() / nEvents);
+      aTable->SetCell(iRow, 7, fvpTrackHistograms[iTrType]->GetAverageNofStationsWithHit());
+      aTable->SetCell(iRow, 8, fvpTrackHistograms[iTrType]->GetAverageNofStationsWithPoint());
+      ++iRow;
+    }
+    double nGhosts = 0.;
+    if (fvpTrackHistograms[ETrackType::kGhost] && fvpTrackHistograms[ETrackType::kAll]) {
+      nGhosts = fvpTrackHistograms[ETrackType::kGhost]->fph_reco_p->GetEntries();
+      aTable->SetRowName(iRow, "N ghosts");
+      aTable->SetCell(iRow, 0, nGhosts);
+      aTable->SetRowName(iRow + 1, "Ghost rate");
+      aTable->SetCell(iRow + 1, 0, nGhosts / fvpTrackHistograms[ETrackType::kAll]->GetNofMCTracks());
+    }
+    LOG(info) << '\n' << aTable->ToString(3);
   }
 
 
-  LOG(info) << '\n' << aTable->ToString(3);
-
   return true;
 }
 
diff --git a/reco/L1/qa/CbmCaOutputQa.h b/reco/L1/qa/CbmCaOutputQa.h
index 582429ba85292fa894838b200ea0f6efc900897e..cabc82c0b8d852103c180e729664856671c22e79 100644
--- a/reco/L1/qa/CbmCaOutputQa.h
+++ b/reco/L1/qa/CbmCaOutputQa.h
@@ -21,6 +21,7 @@
 #include <array>
 #include <memory>
 
+#include "CaMonitor.h"
 #include "CaToolsDebugger.h"
 #include "L1Parameters.h"
 
@@ -245,6 +246,19 @@ namespace cbm::ca
     L1Vector<CbmL1Track> fvRecoTracks {"CbmCaOutputQa::fvRecoTracks"};
     ::ca::tools::MCData fMCData;  ///< Input MC data (points and tracks)
 
+    /// @enum  EMonitorKey
+    /// @brief QA monitor counters
+    enum class EMonitorKey
+    {
+      kEvent,
+      kTrack,
+      kHit,
+      kMcTrack,
+      kMcPoint,
+      kEND
+    };
+
+    ::ca::Monitor<EMonitorKey> fMonitor {"Output tracking QA"};
 
     // *************************
     // **  List of histograms **