diff --git a/algo/ca/core/tracking/CaFramework.cxx b/algo/ca/core/tracking/CaFramework.cxx
index a63ddae336587894b484d06a9a9a195f296285f5..82326d6755b56ad8ca96676310f96f0d1abb05d8 100644
--- a/algo/ca/core/tracking/CaFramework.cxx
+++ b/algo/ca/core/tracking/CaFramework.cxx
@@ -31,9 +31,10 @@ void Framework::Init(const TrackingMode mode)
   fTrackingMode = mode;
   for (int iThread = 0; iThread < fNofThreads; ++iThread) {
     fvWData.emplace_back();
+    fvMonitorDataThread.emplace_back();
   }
   for (int iThread = 0; iThread < fNofThreads; ++iThread) {
-    fvTrackFinderWindow.emplace_back(*this, fvWData[iThread]);
+    fvTrackFinderWindow.emplace_back(*this, fvWData[iThread], fvMonitorDataThread[iThread]);
   }
   fTrackFinder.Init();
 }
diff --git a/algo/ca/core/tracking/CaFramework.h b/algo/ca/core/tracking/CaFramework.h
index deb9b164b7f700e824b10348dff0b62d99a49a2f..5f8ca1ae09906e7056065913e45963baa1af28e1 100644
--- a/algo/ca/core/tracking/CaFramework.h
+++ b/algo/ca/core/tracking/CaFramework.h
@@ -223,7 +223,8 @@ namespace cbm::algo::ca
     Vector<unsigned char> fvHitKeyFlags{
       "Framework::fvHitKeyFlags"};  ///< List of key flags: has been this hit or cluster already used
 
-    TrackingMonitorData fMonitorData{};  ///< Tracking monitor data (statistics per call)
+    TrackingMonitorData fMonitorData{};                    ///< Tracking monitor data (statistics per call)
+    std::vector<TrackingMonitorData> fvMonitorDataThread;  ///< Tracking monitor data per thread
 
     int fNofThreads = 1;  ///< Number of threads to execute the track-finder
 
diff --git a/algo/ca/core/tracking/CaTrackFinder.cxx b/algo/ca/core/tracking/CaTrackFinder.cxx
index b40cef2c67c758227cccacc875eb078298253256..cc3ce2f23170334c7ddc568a87f0e1a76531cae1 100644
--- a/algo/ca/core/tracking/CaTrackFinder.cxx
+++ b/algo/ca/core/tracking/CaTrackFinder.cxx
@@ -256,6 +256,12 @@ void TrackFinder::FindTracks()
   auto timerEnd      = std::chrono::high_resolution_clock::now();
   frAlgo.fCaRecoTime = (double) (std::chrono::duration<double>(timerEnd - timerStart).count());
 
+  // Add thread monitors to the main monitor
+  for (auto& monitor : frAlgo.fvMonitorDataThread) {
+    frAlgo.fMonitorData.AddMonitorData(monitor);
+    monitor.Reset();
+  }
+
   int statNhitsProcessedTotal = 0;
   int statNwindowsTotal       = 0;
   for (int iThread = 0; iThread < frAlgo.GetNofThreads(); ++iThread) {
@@ -278,7 +284,7 @@ void TrackFinder::FindTracks()
 void TrackFinder::FindTracksThread(int iThread)
 {
   LOG(info) << "---- CA: searching for tracks on thread " << iThread;
-  frAlgo.fMonitorData.StartTimer(ETimer::FindTracksThread);
+  frAlgo.fvMonitorDataThread[iThread].StartTimer(ETimer::FindTracksThread);
 
   const int nDataStreams    = frAlgo.fInputData.GetNdataStreams();
   bool areUntouchedDataLeft = true;  // is the whole TS processed
@@ -312,7 +318,7 @@ void TrackFinder::FindTracksThread(int iThread)
   int statLastLogTimeChunk = -1;
 
   while (areUntouchedDataLeft) {
-    frAlgo.fMonitorData.IncrementCounter(ECounter::SubTS);
+    frAlgo.fvMonitorDataThread[iThread].IncrementCounter(ECounter::SubTS);
     // select the sub-slice hits
     for (int iS = 0; iS < frAlgo.GetParameters().GetNstationsActive(); ++iS) {
       frAlgo.fvWData[iThread].TsHitIndices(iS).clear();
@@ -326,7 +332,7 @@ void TrackFinder::FindTracksThread(int iThread)
 
     int statNwindowHits = 0;
 
-    frAlgo.fMonitorData.StartTimer(ETimer::PrepareHitsWindow);
+    frAlgo.fvMonitorDataThread[iThread].StartTimer(ETimer::PrepareHitsWindow);
     for (int iStream = 0; iStream < nDataStreams; ++iStream) {
       for (ca::HitIndex_t caHitId = sliceFirstHit[iStream]; caHitId < sliceLastHit[iStream]; ++caHitId) {
         const CaHitTimeInfo& info = frAlgo.fHitTimeInfo[caHitId];
@@ -356,7 +362,7 @@ void TrackFinder::FindTracksThread(int iThread)
       }
     }
     fvStatNhitsProcessed[iThread] += statNwindowHits;
-    frAlgo.fMonitorData.StopTimer(ETimer::PrepareHitsWindow);
+    frAlgo.fvMonitorDataThread[iThread].StopTimer(ETimer::PrepareHitsWindow);
 
     // print the LOG for every 10 ms of data processed
     {
@@ -387,9 +393,9 @@ void TrackFinder::FindTracksThread(int iThread)
       }
     }
 
-    frAlgo.fMonitorData.StartTimer(ETimer::TrackFinderWindow);
+    frAlgo.fvMonitorDataThread[iThread].StartTimer(ETimer::TrackFinderWindow);
     frAlgo.fvTrackFinderWindow[iThread].CaTrackFinderSlice();
-    frAlgo.fMonitorData.StopTimer(ETimer::TrackFinderWindow);
+    frAlgo.fvMonitorDataThread[iThread].StopTimer(ETimer::TrackFinderWindow);
 
     // save reconstructed tracks with no hits in the overlap region
     //if (fvWindowStartThread[iThread] > 13.23e6 && fvWindowStartThread[iThread] < 13.26e6) {
@@ -398,7 +404,7 @@ void TrackFinder::FindTracksThread(int iThread)
     // we do it in a simple way by extending the tsStartNew
     // TODO: only add those hits from the region before tsStartNew that belong to the not stored tracks
 
-    frAlgo.fMonitorData.StartTimer(ETimer::StoreTracksWindow);
+    frAlgo.fvMonitorDataThread[iThread].StartTimer(ETimer::StoreTracksWindow);
     int trackFirstHit = 0;
     for (const auto& track : frAlgo.fvWData[iThread].RecoTracks()) {
       bool isTrackCompletelyInOverlap = true;
@@ -441,7 +447,7 @@ void TrackFinder::FindTracksThread(int iThread)
       }
       trackFirstHit += track.fNofHits;
     }  // sub-timeslice tracks
-    frAlgo.fMonitorData.StopTimer(ETimer::StoreTracksWindow);
+    frAlgo.fvMonitorDataThread[iThread].StopTimer(ETimer::StoreTracksWindow);
 
     if (fvWindowStartThread[iThread] > fvWindowEndThread[iThread]) {
       break;
@@ -450,7 +456,7 @@ void TrackFinder::FindTracksThread(int iThread)
       fvWindowStartThread[iThread] -= 5;  // do 5 ns margin
     }
   }
-  frAlgo.fMonitorData.StopTimer(ETimer::FindTracksThread);
+  frAlgo.fvMonitorDataThread[iThread].StopTimer(ETimer::FindTracksThread);
 }
 
 // ---------------------------------------------------------------------------------------------------------------------
diff --git a/algo/ca/core/tracking/CaTrackFinderWindow.cxx b/algo/ca/core/tracking/CaTrackFinderWindow.cxx
index d73d7de5fac2550486036f26eb21122c8164bf66..de1582fb929d9dac07a452747fcdbbc4d3134644 100644
--- a/algo/ca/core/tracking/CaTrackFinderWindow.cxx
+++ b/algo/ca/core/tracking/CaTrackFinderWindow.cxx
@@ -46,9 +46,10 @@ using namespace cbm::algo::ca;
 
 // ---------------------------------------------------------------------------------------------------------------------
 //
-TrackFinderWindow::TrackFinderWindow(ca::Framework& algo, ca::WindowData& wData)
+TrackFinderWindow::TrackFinderWindow(ca::Framework& algo, ca::WindowData& wData, ca::TrackingMonitorData& monitorData)
   : frAlgo(algo)
   , frWData(wData)
+  , frMonitorData(monitorData)
   , fTrackExtender(frAlgo, frWData)
   , fCloneMerger(frAlgo)
   , fTrackFitter(frAlgo, frWData)
@@ -309,7 +310,7 @@ void TrackFinderWindow::CaTrackFinderSlice()
 
     ///   stage for triplets creation
 
-    frAlgo.fMonitorData.StartTimer(ETimer::TripletConstructionWindow);
+    frMonitorData.StartTimer(ETimer::TripletConstructionWindow);
 
     ca::TripletConstructor constructor(frAlgo, frWData);
 
@@ -339,10 +340,10 @@ void TrackFinderWindow::CaTrackFinderSlice()
       }
     }  // istal
 
-    frAlgo.fMonitorData.StopTimer(ETimer::TripletConstructionWindow);
+    frMonitorData.StopTimer(ETimer::TripletConstructionWindow);
 
     // search for neighbouring triplets
-    frAlgo.fMonitorData.StartTimer(ETimer::NeighboringTripletSearchWindow);
+    frMonitorData.StartTimer(ETimer::NeighboringTripletSearchWindow);
 
     for (int istal = frAlgo.GetParameters().GetNstationsActive() - 2; istal >= iStFirst; istal--) {
       // start with downstream chambers
@@ -388,10 +389,10 @@ void TrackFinderWindow::CaTrackFinderSlice()
         tr.SetLevel(level);
       }  // neighbour search
 
-      frAlgo.fMonitorData.IncrementCounter(ECounter::Triplet, fvTriplets[istal].size());
+      frMonitorData.IncrementCounter(ECounter::Triplet, fvTriplets[istal].size());
 
     }  // istal
-    frAlgo.fMonitorData.StopTimer(ETimer::NeighboringTripletSearchWindow);
+    frMonitorData.StopTimer(ETimer::NeighboringTripletSearchWindow);
 
 
     ///====================================================================
@@ -671,18 +672,18 @@ void TrackFinderWindow::CaTrackFinderSlice()
   }  // ---- Loop over Track Finder iterations: END -----------------------------------------------------------//
 
   // Fit tracks
-  frAlgo.fMonitorData.StartTimer(ETimer::TrackFitterWindow);
+  frMonitorData.StartTimer(ETimer::TrackFitterWindow);
   fTrackFitter.FitCaTracks();
-  frAlgo.fMonitorData.StopTimer(ETimer::TrackFitterWindow);
+  frMonitorData.StopTimer(ETimer::TrackFitterWindow);
 
   // Merge clones
-  frAlgo.fMonitorData.StartTimer(ETimer::CloneMergerWindow);
+  frMonitorData.StartTimer(ETimer::CloneMergerWindow);
   fCloneMerger.Exec(frWData.RecoTracks(), frWData.RecoHitIndices());
-  frAlgo.fMonitorData.StopTimer(ETimer::CloneMergerWindow);
+  frMonitorData.StopTimer(ETimer::CloneMergerWindow);
 
-  frAlgo.fMonitorData.StartTimer(ETimer::TrackFitterWindow);
+  frMonitorData.StartTimer(ETimer::TrackFitterWindow);
   fTrackFitter.FitCaTracks();
-  frAlgo.fMonitorData.StopTimer(ETimer::TrackFitterWindow);
+  frMonitorData.StopTimer(ETimer::TrackFitterWindow);
 }
 
 
diff --git a/algo/ca/core/tracking/CaTrackFinderWindow.h b/algo/ca/core/tracking/CaTrackFinderWindow.h
index b47eab980768024cf7493cd1921770ab5ddb65bd..d26cb0000ca92d5f5361844632aab59776d99fed 100644
--- a/algo/ca/core/tracking/CaTrackFinderWindow.h
+++ b/algo/ca/core/tracking/CaTrackFinderWindow.h
@@ -17,6 +17,7 @@
 #include "CaTrackExtender.h"
 #include "CaTrackFitter.h"
 #include "CaTrackParam.h"
+#include "CaTrackingMonitor.h"
 #include "CaVector.h"
 #include "CaWindowData.h"
 
@@ -37,7 +38,7 @@ namespace cbm::algo::ca
   class TrackFinderWindow {
    public:
     /// Default constructor
-    TrackFinderWindow(ca::Framework& algo, ca::WindowData& wData);
+    TrackFinderWindow(ca::Framework& algo, ca::WindowData& wData, ca::TrackingMonitorData& monitorData);
 
     /// Destructor
     ~TrackFinderWindow();
@@ -91,6 +92,7 @@ namespace cbm::algo::ca
     static constexpr bool fDebug = false;  // print debug info
 
     WindowData& frWData;
+    TrackingMonitorData& frMonitorData;  ///< Reference to monitor data
     TrackExtender fTrackExtender;  ///< Object of the track extender algorithm
     CloneMerger fCloneMerger;      ///< Object of  the clone merger algorithm
     TrackFitter fTrackFitter;      ///< Object of the track extender algorithm