40 std::unique_lock lock(other.mutex_);
41 config_ = std::move(other.config_);
42 database_ = other.database_;
43 storage_ = other.storage_;
44 custom_checks_ = std::move(other.custom_checks_);
45 cached_status_ = std::move(other.cached_status_);
46 last_check_time_ = other.last_check_time_;
47 associations_ = other.associations_;
48 storage_metrics_ = other.storage_metrics_;
49 version_ = std::move(other.version_);
50 other.database_ =
nullptr;
51 other.storage_ =
nullptr;
56 std::unique_lock lock1(mutex_, std::defer_lock);
57 std::unique_lock lock2(other.mutex_, std::defer_lock);
58 std::lock(lock1, lock2);
60 config_ = std::move(other.config_);
61 database_ = other.database_;
62 storage_ = other.storage_;
63 custom_checks_ = std::move(other.custom_checks_);
64 cached_status_ = std::move(other.cached_status_);
65 last_check_time_ = other.last_check_time_;
66 associations_ = other.associations_;
67 storage_metrics_ = other.storage_metrics_;
68 version_ = std::move(other.version_);
69 other.database_ =
nullptr;
70 other.storage_ =
nullptr;
80 std::unique_lock lock(
mutex_);
85 std::unique_lock lock(
mutex_);
91 std::unique_lock lock(
mutex_);
96 std::unique_lock lock(
mutex_);
106 status.timestamp = std::chrono::system_clock::now();
109 std::shared_lock lock(
mutex_);
122 status.update_level();
126 std::unique_lock lock(
mutex_);
141 return status.is_operational();
145 std::shared_lock lock(
mutex_);
152 std::shared_lock lock(
mutex_);
153 const auto now = std::chrono::system_clock::now();
154 const auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(
172 std::uint64_t total_established,
173 std::uint64_t total_failed) {
174 std::unique_lock lock(
mutex_);
182 std::uint64_t studies,
183 std::uint64_t series,
184 std::uint64_t successful_stores,
185 std::uint64_t failed_stores) {
186 std::unique_lock lock(
mutex_);
197 std::string_view build_id) {
198 std::unique_lock lock(
mutex_);
214 std::unique_lock lock(
mutex_);
224 std::chrono::milliseconds timeout{};
227 std::shared_lock lock(
mutex_);
235 status.database.connected =
true;
236 status.database.active_connections = 0;
241 const auto start = std::chrono::steady_clock::now();
246 status.database.connected =
true;
247 status.database.last_connected = std::chrono::system_clock::now();
248 status.database.active_connections = 1;
250 const auto end = std::chrono::steady_clock::now();
251 status.database.response_time =
252 std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
253 }
catch (
const std::exception& e) {
254 status.database.connected =
false;
255 status.database.error_message = e.what();
261 double warning_threshold = 0.0;
262 double critical_threshold = 0.0;
265 std::shared_lock lock(
mutex_);
271 if (storage ==
nullptr) {
273 status.storage.readable =
true;
274 status.storage.writable =
true;
280 const auto root = storage->root_path();
281 if (std::filesystem::exists(root)) {
282 const auto space_info = std::filesystem::space(root);
283 status.storage.total_bytes = space_info.capacity;
284 status.storage.available_bytes = space_info.available;
285 status.storage.used_bytes =
286 space_info.capacity - space_info.available;
290 status.storage.readable =
true;
294 const auto test_path = root /
".health_check_test";
297 std::ofstream test_file(test_path, std::ios::binary);
298 test_file <<
"health_check";
300 std::filesystem::remove(test_path);
301 status.storage.writable =
true;
303 status.storage.writable =
false;
304 status.storage.error_message =
"Storage is not writable";
308 const double usage = status.storage.usage_percent();
309 if (usage >= critical_threshold) {
310 status.storage.error_message =
311 "Storage usage critical: " + std::to_string(usage) +
"%";
312 }
else if (usage >= warning_threshold) {
313 if (!status.storage.error_message) {
314 status.storage.error_message =
315 "Storage usage warning: " + std::to_string(usage) +
"%";
318 }
catch (
const std::exception& e) {
319 status.storage.readable =
false;
320 status.storage.writable =
false;
321 status.storage.error_message = e.what();
326 std::unordered_map<std::string, check_callback> checks;
329 std::shared_lock lock(
mutex_);
333 for (
const auto& [
name, callback] : checks) {
335 std::string error_message;
336 const bool healthy = callback(error_message);
340 const std::string check_msg =
341 "Custom check '" +
name +
"' failed: " + error_message;
342 if (status.message) {
343 status.message = *status.message +
"; " + check_msg;
345 status.message = check_msg;
348 }
catch (
const std::exception& e) {
349 const std::string check_msg =
350 "Custom check '" +
name +
"' threw exception: " + e.what();
351 if (status.message) {
352 status.message = *status.message +
"; " + check_msg;
354 status.message = check_msg;
Performs comprehensive health checks on PACS system components.
void register_check(std::string_view name, check_callback callback)
Register a custom health check.
void update_association_metrics(std::uint32_t active, std::uint32_t max, std::uint64_t total_established, std::uint64_t total_failed)
Update association metrics.
health_status get_cached_status() const
Get cached health status.
kcenon::pacs::storage::file_storage * storage_
Storage instance to monitor.
~health_checker()
Destructor - stops background checking if enabled.
void update_storage_metrics(std::uint64_t instances, std::uint64_t studies, std::uint64_t series, std::uint64_t successful_stores, std::uint64_t failed_stores)
Update storage metrics.
association_metrics associations_
Association metrics (updated externally)
health_checker & operator=(const health_checker &)=delete
kcenon::pacs::storage::index_database * database_
Database instance to monitor.
void set_database(kcenon::pacs::storage::index_database *database)
Set the database instance to monitor.
storage_metrics storage_metrics_
Storage metrics (updated externally)
std::chrono::system_clock::time_point last_check_time_
Timestamp of last check.
void unregister_check(std::string_view name)
Unregister a custom health check.
void set_config(const health_checker_config &config)
Update configuration.
void check_database(health_status &status)
Check database connectivity.
void set_storage(kcenon::pacs::storage::file_storage *storage)
Set the storage instance to monitor.
health_status get_status()
Get cached status or perform check if stale.
std::unordered_map< std::string, check_callback > custom_checks_
Custom health checks.
health_status check()
Perform a full health check.
version_info version_
Version information.
bool is_ready()
Perform a readiness check.
bool is_alive() const noexcept
Perform a quick liveness check.
health_checker_config config_
Configuration.
void set_version(std::uint16_t major, std::uint16_t minor, std::uint16_t patch, std::string_view build_id="")
Set version information.
const health_checker_config & config() const noexcept
Get current configuration.
void run_custom_checks(health_status &status)
Run all custom checks.
health_status cached_status_
Cached health status.
void check_storage(health_status &status)
Check storage availability.
std::shared_mutex mutex_
Mutex for thread safety.
health_checker()
Construct health checker with default configuration.
std::function< bool(std::string &error_message)> check_callback
Custom health check callback type.
Filesystem-based DICOM storage with hierarchical organization.
Health check service for PACS system components.
PACS index database for metadata storage and retrieval.
@ healthy
All components healthy, system fully operational.
@ unhealthy
Critical components failing, system may not function correctly.
std::uint32_t active_associations
Number of currently active associations.
std::uint64_t failed_associations
Number of failed associations.
std::uint32_t max_associations
Maximum concurrent associations allowed.
std::uint64_t total_associations
Total associations since server start.
Configuration options for the health checker.
std::chrono::seconds cache_duration
Cache health check results for this duration.
std::chrono::milliseconds database_timeout
Timeout for database connectivity test.
double storage_critical_threshold
Storage usage threshold for unhealthy status (percentage)
double storage_warning_threshold
Storage usage threshold for degraded status (percentage)
Comprehensive health status of the PACS system.
health_level level
Overall health level.
std::optional< std::string > message
Optional human-readable status message.
std::uint64_t successful_stores
Successful C-STORE operations.
std::uint64_t total_instances
Total DICOM instances stored.
std::uint64_t total_studies
Total studies in the archive.
std::uint64_t failed_stores
Failed C-STORE operations.
std::uint64_t total_series
Total series in the archive.
std::chrono::system_clock::time_point startup_time
Server startup timestamp.
std::string build_id
Build identifier (e.g., git commit hash)
std::uint16_t major
Major version number.
std::uint16_t patch
Patch version number.
std::uint16_t minor
Minor version number.