Coverage Report

Created: 2026-07-26 07:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gbmcweb/tlbmc/pacemaker/pacemaker.h
Line
Count
Source
1
#ifndef THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_PACEMAKER_PACEMAKER_H_
2
#define THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_PACEMAKER_PACEMAKER_H_
3
4
#include <cstdint>
5
#include <memory>
6
#include <string>
7
#include <utility>
8
9
#include "absl/base/thread_annotations.h"
10
#include "absl/memory/memory.h"
11
#include "absl/status/status.h"
12
#include "absl/status/statusor.h"
13
#include "absl/synchronization/mutex.h"
14
#include "absl/time/time.h"
15
#include "boost/circular_buffer.hpp"
16
#include "time/clock.h"
17
#include "nlohmann/json.hpp"
18
#include "tlbmc/scheduler/scheduler.h"
19
20
namespace milotic_tlbmc {
21
22
class ShellCommandExecutor {
23
 public:
24
2.04k
  virtual ~ShellCommandExecutor() = default;
25
26
  virtual absl::StatusOr<std::string> Execute(const std::string& command);
27
};
28
29
enum class ErrorType : uint8_t {
30
  kUnknown = 0,
31
  kServiceInactive,
32
  kPortNotListening,
33
  kMemoryUsageAboveThreshold,
34
};
35
36
class Pacemaker {
37
 public:
38
  struct ErrorInfo {
39
    nlohmann::json ToJson() const;
40
41
    ErrorType type;
42
    absl::Time timestamp;
43
  };
44
45
  struct MonitoredData {
46
    nlohmann::json ToJson() const;
47
48
    boost::circular_buffer<int> memory_usage_bytes =
49
        boost::circular_buffer<int>(50);
50
    boost::circular_buffer<ErrorInfo> restart_log =
51
        boost::circular_buffer<ErrorInfo>(50);
52
    int pid = -1;
53
    int cpu_usage = -1;
54
    // ActiveEnterTimestampMonotonic value of the process as captured from
55
    // systemctl show --property=ActiveEnterTimestampMonotonic.
56
    // This is only used to detect if the process was restarted outside of
57
    // pacemaker.
58
    int64_t last_active_timestamp = -1;
59
    absl::Time last_reset_time = absl::InfinitePast();
60
    bool restart_triggered = false;
61
    int consecutive_restart_attempts = 0;
62
  };
63
64
  static std::unique_ptr<Pacemaker> Create(
65
      absl::Duration interval,
66
      std::unique_ptr<ShellCommandExecutor> shell_command_executor =
67
          std::make_unique<ShellCommandExecutor>(),
68
2.04k
      ecclesia::Clock* clock = ecclesia::Clock::RealClock()) {
69
2.04k
    return absl::WrapUnique(
70
2.04k
        new Pacemaker(interval, std::move(shell_command_executor), clock));
71
2.04k
  }
72
73
  nlohmann::json GetMonitoringData() const ABSL_LOCKS_EXCLUDED(mutex_);
74
75
  absl::Status PerformChecks();
76
  absl::StatusOr<int> GetPid(const std::string& process_name) const;
77
  absl::StatusOr<bool> IsPortListening(int port) const;
78
  absl::StatusOr<bool> IsServiceActive(const std::string& service_name) const;
79
  absl::StatusOr<int> GetMemoryUsage(int pid) const;
80
  absl::StatusOr<int> GetCpuUsage(const std::string& process_name) const;
81
  absl::StatusOr<int64_t> GetLastActiveTimestamp(
82
      const std::string& process_name) const;
83
  absl::Status RestartService(const std::string& service_name)
84
      ABSL_LOCKS_EXCLUDED(mutex_);
85
  void RecordError(ErrorType type) ABSL_LOCKS_EXCLUDED(mutex_);
86
87
2.04k
  ~Pacemaker() { scheduler_.Stop(); }
88
89
 private:
90
  explicit Pacemaker(
91
      absl::Duration interval,
92
      std::unique_ptr<ShellCommandExecutor> shell_command_executor,
93
      ecclesia::Clock* clock);
94
95
  mutable absl::Mutex mutex_;
96
  std::unique_ptr<ShellCommandExecutor> shell_command_executor_;
97
  TaskScheduler scheduler_;
98
  MonitoredData monitored_data_ ABSL_GUARDED_BY(mutex_);
99
};
100
101
}  // namespace milotic_tlbmc
102
103
#endif  // THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_PACEMAKER_PACEMAKER_H_