Common System 0.2.0
Common interfaces and patterns for system integration
Loading...
Searching...
No Matches
composite_health_check.h
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2025, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
13#pragma once
14
15#include <memory>
16#include <mutex>
17#include <string>
18#include <vector>
19
20#include "health_check.h"
21
23
44public:
52 std::string name,
54 bool critical = true)
55 : name_(std::move(name)), type_(type), critical_(critical) {}
56
57 [[nodiscard]] std::string get_name() const override { return name_; }
58
59 [[nodiscard]] health_check_type get_type() const override { return type_; }
60
61 [[nodiscard]] bool is_critical() const override { return critical_; }
62
74 std::lock_guard<std::mutex> lock(mutex_);
75
78 auto start_time = std::chrono::steady_clock::now();
79
80 std::vector<std::string> messages;
81 std::size_t healthy_count = 0;
82 std::size_t degraded_count = 0;
83 std::size_t unhealthy_count = 0;
84
85 for (const auto& check : checks_) {
86 auto child_result = check->check();
87
88 switch (child_result.status) {
90 ++unhealthy_count;
92 messages.push_back(check->get_name() + ": " + child_result.message);
93 break;
95 ++degraded_count;
96 if (result.status != health_status::unhealthy) {
98 }
99 messages.push_back(check->get_name() + ": " + child_result.message);
100 break;
102 if (result.status == health_status::healthy) {
104 }
105 messages.push_back(check->get_name() + ": " + child_result.message);
106 break;
108 ++healthy_count;
109 break;
110 }
111 }
112
113 auto end_time = std::chrono::steady_clock::now();
114 result.check_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
115 end_time - start_time);
116
117 if (messages.empty()) {
118 result.message = "All " + std::to_string(healthy_count) + " checks passed";
119 } else {
120 result.message = std::to_string(unhealthy_count) + " unhealthy, " +
121 std::to_string(degraded_count) + " degraded";
122 for (const auto& msg : messages) {
123 result.message += "; " + msg;
124 }
125 }
126
127 result.metadata["total_checks"] = std::to_string(checks_.size());
128 result.metadata["healthy_count"] = std::to_string(healthy_count);
129 result.metadata["degraded_count"] = std::to_string(degraded_count);
130 result.metadata["unhealthy_count"] = std::to_string(unhealthy_count);
131
132 return result;
133 }
134
139 void add_check(std::shared_ptr<health_check> check) {
140 if (!check) {
141 return;
142 }
143 std::lock_guard<std::mutex> lock(mutex_);
144 checks_.push_back(std::move(check));
145 }
146
152 bool remove_check(const std::string& name) {
153 std::lock_guard<std::mutex> lock(mutex_);
154 auto it = std::find_if(checks_.begin(), checks_.end(),
155 [&name](const std::shared_ptr<health_check>& check) {
156 return check->get_name() == name;
157 });
158 if (it != checks_.end()) {
159 checks_.erase(it);
160 return true;
161 }
162 return false;
163 }
164
169 [[nodiscard]] std::size_t size() const {
170 std::lock_guard<std::mutex> lock(mutex_);
171 return checks_.size();
172 }
173
178 [[nodiscard]] bool empty() const {
179 std::lock_guard<std::mutex> lock(mutex_);
180 return checks_.empty();
181 }
182
186 void clear() {
187 std::lock_guard<std::mutex> lock(mutex_);
188 checks_.clear();
189 }
190
195 [[nodiscard]] std::vector<std::string> get_check_names() const {
196 std::lock_guard<std::mutex> lock(mutex_);
197 std::vector<std::string> names;
198 names.reserve(checks_.size());
199 for (const auto& check : checks_) {
200 names.push_back(check->get_name());
201 }
202 return names;
203 }
204
205private:
206 std::string name_;
209 std::vector<std::shared_ptr<health_check>> checks_;
210 mutable std::mutex mutex_;
211};
212
213} // namespace kcenon::common::interfaces
Aggregates multiple health checks into a single check.
std::string get_name() const override
Get the unique name of this health check.
bool remove_check(const std::string &name)
Remove a child health check by name.
bool is_critical() const override
Check if this health check is critical.
bool empty() const
Check if this composite has no child checks.
health_check_type get_type() const override
Get the type of this health check.
composite_health_check(std::string name, health_check_type type=health_check_type::custom, bool critical=true)
Construct a composite health check.
void add_check(std::shared_ptr< health_check > check)
Add a child health check.
std::vector< std::string > get_check_names() const
Get all child check names.
std::vector< std::shared_ptr< health_check > > checks_
std::size_t size() const
Get the number of child checks.
health_check_result check() override
Execute all child health checks and aggregate results.
Abstract base class for health checks.
Base classes and types for health checking functionality.
health_check_type
Types of health checks supported by the system.
std::unordered_map< std::string, std::string > metadata