diff --git a/algo/ca/core/CMakeLists.txt b/algo/ca/core/CMakeLists.txt
index 0f73dd62989789977811ea4b2e63a0d8dc3ed79a..da259ab55b1644c8cc6a8318a634b2fcfa5b4c4a 100644
--- a/algo/ca/core/CMakeLists.txt
+++ b/algo/ca/core/CMakeLists.txt
@@ -26,7 +26,6 @@ set(SRCS
   ${CMAKE_CURRENT_SOURCE_DIR}/pars/CaSearchWindow.cxx
   ${CMAKE_CURRENT_SOURCE_DIR}/pars/CaStation.cxx
   ${CMAKE_CURRENT_SOURCE_DIR}/pars/CaStationInitializer.cxx
-  ${CMAKE_CURRENT_SOURCE_DIR}/utils/CaTimer.cxx
   ${CMAKE_CURRENT_SOURCE_DIR}/tracking/CaTrackFit.cxx
 )
 
@@ -85,6 +84,7 @@ install(
     utils/CaTrackingMonitor.h
     utils/CaEnumArray.h
     utils/CaMonitor.h
+    utils/CaMonitorData.h
     utils/CaObjectInitController.h
     utils/CaSimd.h
     utils/CaSimdVc.h
diff --git a/algo/ca/core/utils/CaMonitor.h b/algo/ca/core/utils/CaMonitor.h
index aa88a10558bb98006021c28b003b8eb4778b1e20..5a65f0f0bf3b22275250a1c76911f5f34fdd8546 100644
--- a/algo/ca/core/utils/CaMonitor.h
+++ b/algo/ca/core/utils/CaMonitor.h
@@ -147,21 +147,19 @@ namespace cbm::algo::ca
     using std::setfill;
     using std::setw;
     std::stringstream msg;
-    constexpr size_t width = 24;
-    size_t fillWidth       = (width + 2) * (1 + fvCounterRatioKeys.size());
-    msg << "----- Monitor: " << fsName << ' ' << setw(fillWidth - fsName.size() - 16) << setfill('-') << '-' << '\n';
-    msg << setfill(' ');
-
+    constexpr size_t width = 30;
+    msg << "\n===== Monitor: " << fsName << "\n";
     if constexpr (!std::is_same_v<ETimerKey, EDummy>) {
-      msg << "----- Timers:\n";
-      msg << setw(width) << "Name" << ' ';
-      msg << setw(width) << "N Calls" << ' ';
-      msg << setw(width) << "Average [ns]" << ' ';
-      msg << setw(width) << "Min [ns]" << ' ';
-      msg << setw(width) << "Max [ns]" << ' ';
-      msg << setw(width) << "Total [ns]" << '\n';
+      msg << "\n----- Timers:\n";
+      msg << setw(width) << left << "Key" << ' ';
+      msg << setw(width) << left << "N Calls" << ' ';
+      msg << setw(width) << left << "Average [s]" << ' ';
+      msg << setw(width) << left << "Min [s]" << ' ';
+      msg << setw(width) << left << "Max [s]" << ' ';
+      msg << setw(width) << left << "Total [s]" << '\n';
+      msg << right;
       for (int iKey = 0; iKey < fMonitorData.GetNofTimers(); ++iKey) {
-        const auto& timer = fMonitorData.GetTimer(static_cast<ETimerKey>(iKey));
+        const Timer& timer = fMonitorData.GetTimer(static_cast<ETimerKey>(iKey));
         msg << setw(width) << faTimerNames[iKey] << ' ';
         msg << setw(width) << timer.GetNofCalls() << ' ';
         msg << setw(width) << timer.GetAverage() << ' ';
@@ -171,7 +169,7 @@ namespace cbm::algo::ca
       }
     }
 
-    msg << "----- Counters:\n";
+    msg << "\n----- Counters:\n";
     msg << setw(width) << left << "Key" << ' ';
     msg << setw(width) << left << "Total" << ' ';
     for (auto key : fvCounterRatioKeys) {
@@ -188,8 +186,6 @@ namespace cbm::algo::ca
       }
       msg << '\n';
     }
-    msg << setw(fillWidth) << setfill('-') << '-' << '\n';
-    msg << setfill(' ');
     return msg.str();
   }
 }  // namespace cbm::algo::ca
diff --git a/algo/ca/core/utils/CaMonitorData.h b/algo/ca/core/utils/CaMonitorData.h
index 20f7270c9be1a61558e4036b7227da19b3851e70..ef316ce0d92148b3c550a169bbb22955c5073aad 100644
--- a/algo/ca/core/utils/CaMonitorData.h
+++ b/algo/ca/core/utils/CaMonitorData.h
@@ -59,12 +59,7 @@ namespace cbm::algo::ca
     int GetNofTimers() const { return static_cast<int>(ETimerKey::kEND); }
 
     /// \brief Gets timer
-    /// \param key Timer key
-    template<typename T>
-    const Timer& GetTimer(ETimerKey key) const
-    {
-      return faTimers[key];
-    }
+    const Timer& GetTimer(ETimerKey key) const { return faTimers[key]; }
 
     /// \brief Increments key counter by 1
     /// \param key Counter key
diff --git a/algo/ca/core/utils/CaTimer.cxx b/algo/ca/core/utils/CaTimer.cxx
deleted file mode 100644
index d55c2e62ae4e75a5d0958c974711e8dc35e3da53..0000000000000000000000000000000000000000
--- a/algo/ca/core/utils/CaTimer.cxx
+++ /dev/null
@@ -1,29 +0,0 @@
-/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
-   SPDX-License-Identifier: GPL-3.0-only
-   Authors: Sergei Zharko [committer] */
-
-/// \file   CaTimer.h
-/// \brief  Timer class for CA tracking (implementation)
-/// \since  18.10.2023
-/// \author S.Zharko <s.zharko@gsi.de>
-
-#include "CaTimer.h"
-
-#include <iomanip>
-#include <sstream>
-
-using cbm::algo::ca::Timer;
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
-std::string Timer::ToString() const
-{
-  using std::left;
-  using std::right;
-  using std::setw;
-
-  std::stringstream msg;
-  msg << "min = " << setw(15) << fMin << " ns, max = " << setw(15) << fMax << " ns, average = " << setw(15)
-      << GetAverage() << " ns, total = " << fTotal << " ns, N calls = " << fNofCalls;
-  return msg.str();
-}
diff --git a/algo/ca/core/utils/CaTimer.h b/algo/ca/core/utils/CaTimer.h
index 25f9dac591c0f2143caeb7522b2e611cb1e88e93..8646dc5656d6b23e0f649e4838ac18761b80bbac 100644
--- a/algo/ca/core/utils/CaTimer.h
+++ b/algo/ca/core/utils/CaTimer.h
@@ -44,14 +44,14 @@ namespace cbm::algo::ca
     /// \brief Move assignment operator
     Timer& operator=(Timer&&) = default;
 
-    /// \brief Gets average time [ns]
-    DurationCount GetAverage() const { return fTotal / fNofCalls; }
+    /// \brief Gets average time [s]
+    double GetAverage() const { return static_cast<double>(fTotal / fNofCalls) * 1.e-9; }
 
-    /// \brief Gets time of the longest call [ns]
-    DurationCount GetMax() const { return fMax; }
+    /// \brief Gets time of the longest call [s]
+    double GetMax() const { return static_cast<double>(fMax) * 1.e-9; }
 
-    /// \brief Gets time of the shortest call [ns]
-    DurationCount GetMin() const { return fMin; }
+    /// \brief Gets time of the shortest call [s]
+    double GetMin() const { return static_cast<double>(fMin) * 1.e-9; }
 
     /// \brief Gets number of calls
     int GetNofCalls() const { return fNofCalls; }
@@ -62,8 +62,8 @@ namespace cbm::algo::ca
     /// \brief Gets index of the longest call
     int GetMinCallIndex() const { return fMinCallIndex; }
 
-    /// \brief Gets total time [ns]
-    DurationCount GetTotal() const;
+    /// \brief Gets total time [s]
+    double GetTotal() const { return static_cast<double>(fTotal) * 1.e-9; }
 
     /// \brief Resets the timer
     void Reset();
@@ -74,17 +74,14 @@ namespace cbm::algo::ca
     /// \brief Stops the timer
     void Stop();
 
-    /// \brief Prints statistics
-    std::string ToString() const;
-
   private:
     TimePoint fStart     = TimePoint();
     DurationCount fMin   = std::numeric_limits<DurationCount>::max();  ///< Minimal time period
     DurationCount fMax   = std::numeric_limits<DurationCount>::min();  ///< Maximal time period
-    DurationCount fTotal = DurationCount(0);                           ///< Total measured time period
-    int fNofCalls        = 0;                                          ///< Number of timer calls
-    int fMinCallIndex    = -1;                                         ///< Index of the shortest call
-    int fMaxCallIndex    = -1;                                         ///< Index of the longest call
+    DurationCount fTotal = DurationCount(0);                           ///< Total measured time period [ns]
+    int fNofCalls        = 0;                                          ///< Number of timer calls [ns]
+    int fMinCallIndex    = -1;                                         ///< Index of the shortest call [ns]
+    int fMaxCallIndex    = -1;                                         ///< Index of the longest call [ns]
   };                                                                   // class Timer
 
 
@@ -115,11 +112,11 @@ namespace cbm::algo::ca
       fMin          = time;
       fMinCallIndex = fNofCalls;
     }
-    else if (fMax < time) {
+    if (fMax < time) {
       fMax          = time;
       fMaxCallIndex = fNofCalls;
     }
     fTotal += time;
     ++fNofCalls;
   }
-}  // namespace cbm::algo::ca
\ No newline at end of file
+}  // namespace cbm::algo::ca
diff --git a/algo/ca/core/utils/CaTrackingMonitor.h b/algo/ca/core/utils/CaTrackingMonitor.h
index 49b522c9c3cebe9c55a2c067af9a4de437115e4f..9aa13cd11303b89faad49f5b2a1f404cedded4c0 100644
--- a/algo/ca/core/utils/CaTrackingMonitor.h
+++ b/algo/ca/core/utils/CaTrackingMonitor.h
@@ -17,8 +17,11 @@ namespace cbm::algo::ca
   /// \brief Counter keys for the CA algo monitor
   enum class ECounter
   {
-    RecoTrack,  ///< number of reconstructed tracks
-    RecoHit,    ///< number of reconstructed hits
+    RecoTrack,    ///< number of reconstructed tracks
+    RecoHit,      ///< number of reconstructed hits
+    RecoHitUsed,  ///< number of used reconstructed hits
+    Triplet,      ///< number of triplets
+    SubTS,        ///< number of sub time-slices
     kEND
   };
 
@@ -29,6 +32,8 @@ namespace cbm::algo::ca
     Tracking,
     TrackFinder,
     TrackFitter,
+    TripletConstruction,
+    NeighboringTripletSearch,
     kEND
   };
 
diff --git a/reco/L1/CbmL1.cxx b/reco/L1/CbmL1.cxx
index 917c25f2f39c78f9780e22f07f368a17a4e36fb3..4cf9dec8e7cf0171a3a521d7243a14d27435e782 100644
--- a/reco/L1/CbmL1.cxx
+++ b/reco/L1/CbmL1.cxx
@@ -800,6 +800,8 @@ void CbmL1::Reconstruct(CbmEvent* event)
 
   if (fVerbose > 1) { LOG(info) << "L1 Track finder ok"; }
 
+  LOG(info) << fpAlgo->GetMonitor().ToString();
+
   // save reconstructed tracks
 
   fvRecoTracks.clear();
@@ -824,10 +826,7 @@ void CbmL1::Reconstruct(CbmEvent* event)
   }
 
   fMonitor.IncrementCounter(EMonitorKey::kRecoTrack, fvRecoTracks.size());
-
   LOG(info) << "CA Track Finder: " << fpAlgo->fCaRecoTime << " s/sub-ts";
-  LOG(info) << GetName() << ": " << fpAlgo->fRecoTimer.ToString();
-
 
   // output performance
   if (fPerformance) {
diff --git a/reco/L1/L1Algo/L1Algo.cxx b/reco/L1/L1Algo/L1Algo.cxx
index 88ab80bb68708160e9adbe2f1235cb20a3ff82e6..9b3a9f2e276fc311a347cccff810e65600fe4fe0 100644
--- a/reco/L1/L1Algo/L1Algo.cxx
+++ b/reco/L1/L1Algo/L1Algo.cxx
@@ -30,10 +30,15 @@ void L1Algo::Init(const TrackingMode mode)
   // Monitor settings
   fMonitor.SetCounterName(ECounter::RecoTrack, "reco tracks");
   fMonitor.SetCounterName(ECounter::RecoHit, "reco hits");
+  fMonitor.SetCounterName(ECounter::Triplet, "triplets");
+  fMonitor.SetCounterName(ECounter::RecoHitUsed, "used reco hits");
+  fMonitor.SetCounterName(ECounter::SubTS, "sub-timeslices");
   fMonitor.SetTimerName(ETimer::Tracking, "full tracking");
   fMonitor.SetTimerName(ETimer::TrackFinder, "track finder");
   fMonitor.SetTimerName(ETimer::TrackFitter, "track fitter");
-  fMonitor.SetRatioKeys({ECounter::RecoTrack});
+  fMonitor.SetTimerName(ETimer::TripletConstruction, "triplet construction");
+  fMonitor.SetTimerName(ETimer::NeighboringTripletSearch, "neighboring triplet search");
+  fMonitor.SetRatioKeys({ECounter::SubTS, ECounter::RecoTrack});
   fMonitor.Reset();
 }
 
@@ -69,8 +74,6 @@ void L1Algo::ReceiveParameters(Parameters&& parameters)
   fGhostSuppression = fParameters.GetGhostSuppression();
 
   ca::FieldRegion::ForceUseOfOriginalField(fParameters.DevIsUseOfOriginalField());
-
-  fRecoTimer.Reset();
 }
 
 int L1Algo::GetMcTrackIdForCaHit(int iHit) const
diff --git a/reco/L1/L1Algo/L1Algo.h b/reco/L1/L1Algo/L1Algo.h
index 90e91aa0698a05565f504da9eac99e819dc3d3ff..41bd91f5c35a1d88dae080a425a8a567acd0d74c 100644
--- a/reco/L1/L1Algo/L1Algo.h
+++ b/reco/L1/L1Algo/L1Algo.h
@@ -282,7 +282,7 @@ private:
   Vector<unsigned char> fvHitKeyFlags {
     "L1Algo::fvHitKeyFlags"};  ///< List of key flags: has been this hit or cluster already used
 
-  ca::TrackingMonitor fMonitor {};  ///< Tracking monitor
+  ca::TrackingMonitor fMonitor {"CA Algo"};  ///< Tracking monitor
 
 public:
   Vector<L1HitTimeInfo> fHitTimeInfo;
@@ -309,9 +309,6 @@ public:
 
   double fCaRecoTime {0.};  // time of the track finder + fitter
 
-  ca::Timer fRecoTimer;  // TMP
-
-
   Vector<Track> fRecoTracks {"L1Algo::fRecoTracks"};       ///< reconstructed tracks
   Vector<ca::HitIndex_t> fRecoHits {"L1Algo::fRecoHits"};  ///< packed hits of reconstructed tracks
 
@@ -319,13 +316,16 @@ public:
   Vector<ca::HitIndex_t> fSliceRecoHits {"L1Algo::fSliceRecoHits"};  ///< packed hits of reconstructed tracks
 
   /// Created triplets vs station index
+  // FIXME: Better std::array<Vector<Triplet>, constants::size::MaxNstations>
   Vector<ca::Triplet> fTriplets[constants::size::MaxNstations] {{"L1Algo::fTriplets"}};
 
   /// Track candidates created out of adjacent triplets before the final track selection.
   /// The candidates may share any amount of hits.
+  // FIXME: Better std::array<Vector<Branch>, constants::size::MaxNstations>
   Vector<ca::Branch> fTrackCandidates {"L1Algo::fTrackCandidates"};
 
   ///< indices of the sub-slice hits
+  // FIXME: Better std::array<Vector<HitIndex_t>, constants::size::MaxNstations>
   Vector<ca::HitIndex_t> fSliceHitIds[constants::size::MaxNstations] {"L1Algo::fSliceHitIds"};
 
   Vector<int> fStripToTrack {"L1Algo::fStripToTrack"};  // strip to track pointers
diff --git a/reco/L1/L1Algo/L1CaTrackFinder.cxx b/reco/L1/L1Algo/L1CaTrackFinder.cxx
index 081b193c94cabb067b495dbdfbdae8ca7939aec5..fc80be5d5dc1d71b15e9d9a61eaa9a4138b60740 100644
--- a/reco/L1/L1Algo/L1CaTrackFinder.cxx
+++ b/reco/L1/L1Algo/L1CaTrackFinder.cxx
@@ -23,7 +23,9 @@
 #include "CaTrack.h"
 #include "L1Algo.h"
 
-using Track = cbm::algo::ca::Track;
+using cbm::algo::ca::ECounter;
+using cbm::algo::ca::ETimer;
+using cbm::algo::ca::Track;
 
 void L1Algo::CaTrackFinder()
 {
@@ -33,9 +35,13 @@ void L1Algo::CaTrackFinder()
   // and runs the track finder over the sub-slices
   //
 
-  fRecoTimer.Reset();
+  // Reset monitor
+  fMonitor.Reset();
+  fMonitor.IncrementCounter(ECounter::RecoHit, fInputData.GetNhits());
+  fMonitor.StartTimer(ETimer::Tracking);
+
   auto timerStart = std::chrono::high_resolution_clock::now();
-  fRecoTimer.Start();
+
 
   // ----- Reset data arrays -------------------------------------------------------------------------------------------
   fvHitKeyFlags.reset(fInputData.GetNhitKeys(), 0);
@@ -123,7 +129,6 @@ void L1Algo::CaTrackFinder()
   // cut data into sub-timeslices and process them one by one
 
   bool areDataLeft = true;  // is the whole TS processed
-  int nSubSlices   = 0;
 
   ca::HitIndex_t sliceFirstHit[nDataStreams];
 
@@ -132,8 +137,7 @@ void L1Algo::CaTrackFinder()
   }
 
   while (areDataLeft) {
-
-    nSubSlices++;
+    fMonitor.IncrementCounter(ECounter::SubTS);
 
     // select the sub-slice hits
     for (int iS = 0; iS < fParameters.GetNstationsActive(); ++iS) {
@@ -172,8 +176,14 @@ void L1Algo::CaTrackFinder()
       }
     }
 
+    fMonitor.StartTimer(ETimer::TrackFinder);
     CaTrackFinderSlice();
+    fMonitor.StopTimer(ETimer::TrackFinder);
+
+
+    fMonitor.StartTimer(ETimer::TrackFitter);
     L1KFTrackFitter();
+    fMonitor.StopTimer(ETimer::TrackFitter);
 
     // save reconstructed tracks with no hits in the overlap region
 
@@ -229,7 +239,9 @@ void L1Algo::CaTrackFinder()
   }
 
   auto timerEnd = std::chrono::high_resolution_clock::now();
-  fRecoTimer.Stop();
+  fMonitor.StopTimer(ETimer::Tracking);
+  fMonitor.IncrementCounter(ECounter::RecoTrack, fRecoTracks.size());
+  fMonitor.IncrementCounter(ECounter::RecoHitUsed, fRecoHits.size());
+
   fCaRecoTime   = (double) (std::chrono::duration<double>(timerEnd - timerStart).count());
-  LOG(debug) << "CaTracker: nSubSlices processed = " << nSubSlices;
 }
diff --git a/reco/L1/L1Algo/L1CaTrackFinderSlice.cxx b/reco/L1/L1Algo/L1CaTrackFinderSlice.cxx
index ca2249227bca77dda5f6fc01dcb328250fe07d3e..c4b39e28e2dd0e1bd8e0ab91f67874c8961e3fba 100644
--- a/reco/L1/L1Algo/L1CaTrackFinderSlice.cxx
+++ b/reco/L1/L1Algo/L1CaTrackFinderSlice.cxx
@@ -162,6 +162,8 @@ void L1Algo::ReadWindowData()
   }
 }
 
+// ---------------------------------------------------------------------------------------------------------------------
+//
 void L1Algo::CaTrackFinderSlice()
 {
   fNFindIterations = fParameters.GetNcaIterations();
@@ -350,7 +352,7 @@ void L1Algo::CaTrackFinderSlice()
 
 
     ///   stage for triplets creation
-
+    fMonitor.StartTimer(ETimer::TripletConstruction);
     L1TripletConstructor constructor1(this);
     L1TripletConstructor constructor2(this);
     L1TripletConstructor constructor3(this);
@@ -380,11 +382,12 @@ void L1Algo::CaTrackFinderSlice()
         fHitFirstTriplet[ihitl] = PackTripletId(istal, oldSize);
         fHitNtriplets[ihitl]    = fTriplets[istal].size() - oldSize;
       }
+      fMonitor.IncrementCounter(ECounter::Triplet, fTriplets[istal].size());
     }  // istal
-
+    fMonitor.StopTimer(ETimer::TripletConstruction);
 
     // search for neighbouring triplets
-
+    fMonitor.StartTimer(ETimer::NeighboringTripletSearch);
     for (int istal = fParameters.GetNstationsActive() - 2; istal >= fFirstCAstation;
          istal--) {  // start with downstream chambers
 
@@ -425,6 +428,7 @@ void L1Algo::CaTrackFinderSlice()
         tr.SetLevel(level);
       }  // neighbour search
     }    // istal
+    fMonitor.StopTimer(ETimer::NeighboringTripletSearch);
 
     ///====================================================================
     ///=                                                                  =
@@ -729,15 +733,15 @@ void L1Algo::CaTrackFinderSlice()
 }
 
 
-/** *************************************************************
-     *                                                              *
-     *     The routine performs recursive search for tracks         *
-     *                                                              *
-     *     I. Kisel                                    06.03.05     *
-     *     I.Kulakov                                    2012        *
-     *                                                              *
-     ****************************************************************/
-
+// ---------------------------------------------------------------------------------------------------------------------
+//  ****************************************************************
+//  *                                                              *
+//  *     The routine performs recursive search for tracks         *
+//  *                                                              *
+//  *     I. Kisel                                    06.03.05     *
+//  *     I.Kulakov                                    2012        *
+//  *                                                              *
+//  ****************************************************************
 void L1Algo::CAFindTrack(int ista, ca::Branch& best_tr, const ca::Triplet* curr_trip, ca::Branch& curr_tr,
                          unsigned char min_best_l, ca::Branch* new_tr)
 /// recursive search for tracks