Monitoring System 0.1.0
System resource monitoring with pluggable collectors and alerting
Loading...
Searching...
No Matches
kcenon::monitoring::adaptive_collector Class Reference

Adaptive collector wrapper. More...

#include <adaptive_monitor.h>

Collaboration diagram for kcenon::monitoring::adaptive_collector:
Collaboration graph

Public Member Functions

 adaptive_collector (std::shared_ptr< kcenon::monitoring::metrics_collector > collector, const adaptive_config &config={})
 
common::Result< kcenon::monitoring::metrics_snapshotcollect ()
 Collect metrics with adaptive sampling.
 
void adapt (const kcenon::monitoring::system_metrics &sys_metrics)
 Adapt collection behavior based on load.
 
adaptation_stats get_stats () const
 Get current adaptation statistics.
 
std::chrono::milliseconds get_current_interval () const
 Get current collection interval.
 
void set_config (const adaptive_config &config)
 Set adaptive configuration.
 
adaptive_config get_config () const
 Get adaptive configuration.
 
void set_enabled (bool enabled)
 Enable or disable adaptive behavior.
 
bool is_enabled () const
 Check if adaptive behavior is enabled.
 

Private Member Functions

bool should_sample () const
 Determine if current sample should be collected.
 

Static Private Member Functions

static load_level calculate_load_level_with_config (double cpu_usage, double memory_usage, const adaptive_config &cfg)
 Calculate load level from metrics with provided config.
 
static load_level calculate_load_level_with_hysteresis (double cpu_usage, double memory_usage, load_level current_level, const adaptive_config &cfg)
 Calculate load level with hysteresis support (ARC-005)
 
static double get_threshold_for_level (load_level level, const adaptive_config &cfg)
 Get the threshold value for a given load level.
 

Private Attributes

std::shared_ptr< kcenon::monitoring::metrics_collectorcollector_
 
adaptive_config config_
 
std::mutex config_mutex_
 
adaptation_stats stats_
 
std::atomic< bool > enabled_ {true}
 
std::atomic< double > current_sampling_rate_ {1.0}
 
std::mutex stats_mutex_
 

Detailed Description

Adaptive collector wrapper.

Thread Safety:
Thread-safe. All public methods can be called concurrently.
  • config_ protected by config_mutex_
  • stats_ protected by stats_mutex_
  • Uses std::atomic for enabled_ and current_sampling_rate_
  • Avoids deadlock by copying config before acquiring stats_mutex_

Definition at line 156 of file adaptive_monitor.h.

Constructor & Destructor Documentation

◆ adaptive_collector()

kcenon::monitoring::adaptive_collector::adaptive_collector ( std::shared_ptr< kcenon::monitoring::metrics_collector > collector,
const adaptive_config & config = {} )
inline

Definition at line 167 of file adaptive_monitor.h.

169 {}
170 ) : collector_(collector), config_(config) {
172 stats_.last_adaptation = std::chrono::system_clock::now();
173 }
std::shared_ptr< kcenon::monitoring::metrics_collector > collector_
std::chrono::milliseconds current_interval
std::chrono::system_clock::time_point last_adaptation
std::chrono::milliseconds moderate_interval

Member Function Documentation

◆ adapt()

void kcenon::monitoring::adaptive_collector::adapt ( const kcenon::monitoring::system_metrics & sys_metrics)
inline

Adapt collection behavior based on load.

Thread Safety:
Thread-safe. Uses mutex for synchronization.

Definition at line 192 of file adaptive_monitor.h.

192 {
193 // Copy config under lock to avoid holding both locks
194 adaptive_config local_config;
195 {
196 std::lock_guard<std::mutex> config_lock(config_mutex_);
197 local_config = config_;
198 }
199
200 std::lock_guard<std::mutex> lock(stats_mutex_);
201
202 bool is_first_adaptation = (stats_.total_adaptations == 0);
203
204 // Initialize averages on first adaptation
205 if (is_first_adaptation) {
208 } else {
209 // Update average metrics using exponential smoothing
211 local_config.smoothing_factor * sys_metrics.cpu_usage_percent +
212 (1.0 - local_config.smoothing_factor) * stats_.average_cpu_usage;
213
215 local_config.smoothing_factor * sys_metrics.memory_usage_percent +
216 (1.0 - local_config.smoothing_factor) * stats_.average_memory_usage;
217 }
218
219 // Determine load level with hysteresis support
224 local_config
225 );
226
227 // Adapt if load level changed
228 if (new_level != stats_.current_load_level) {
229 auto now = std::chrono::system_clock::now();
230
231 // Check cooldown period (ARC-005)
232 // Skip cooldown check for first adaptation to allow initial level setting
233 if (local_config.enable_cooldown && !is_first_adaptation) {
234 auto time_since_last_change = std::chrono::duration_cast<std::chrono::milliseconds>(
236 );
237 if (time_since_last_change < local_config.cooldown_period) {
239 return; // Skip this adaptation due to cooldown
240 }
241 }
242
243 if (new_level > stats_.current_load_level) {
245 } else {
247 }
248
249 stats_.current_load_level = new_level;
250 stats_.current_interval = local_config.get_interval_for_load(new_level);
251 current_sampling_rate_ = local_config.get_sampling_rate_for_load(new_level);
256 }
257 }
static load_level calculate_load_level_with_hysteresis(double cpu_usage, double memory_usage, load_level current_level, const adaptive_config &cfg)
Calculate load level with hysteresis support (ARC-005)
std::chrono::system_clock::time_point last_level_change

References kcenon::monitoring::adaptation_stats::average_cpu_usage, kcenon::monitoring::adaptation_stats::average_memory_usage, calculate_load_level_with_hysteresis(), config_, config_mutex_, kcenon::monitoring::adaptive_config::cooldown_period, kcenon::monitoring::adaptation_stats::cooldown_prevented_changes, kcenon::monitoring::system_metrics::cpu_usage_percent, kcenon::monitoring::adaptation_stats::current_interval, kcenon::monitoring::adaptation_stats::current_load_level, kcenon::monitoring::adaptation_stats::current_sampling_rate, current_sampling_rate_, kcenon::monitoring::adaptation_stats::downscale_count, kcenon::monitoring::adaptive_config::enable_cooldown, kcenon::monitoring::adaptive_config::get_interval_for_load(), kcenon::monitoring::adaptive_config::get_sampling_rate_for_load(), kcenon::monitoring::adaptation_stats::last_adaptation, kcenon::monitoring::adaptation_stats::last_level_change, kcenon::monitoring::system_metrics::memory_usage_percent, kcenon::monitoring::adaptive_config::smoothing_factor, stats_, stats_mutex_, kcenon::monitoring::adaptation_stats::total_adaptations, and kcenon::monitoring::adaptation_stats::upscale_count.

Referenced by TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), and TEST_F().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ calculate_load_level_with_config()

static load_level kcenon::monitoring::adaptive_collector::calculate_load_level_with_config ( double cpu_usage,
double memory_usage,
const adaptive_config & cfg )
inlinestaticprivate

Calculate load level from metrics with provided config.

Note
Thread-safe as it only uses the provided config copy

Definition at line 324 of file adaptive_monitor.h.

328 {
329 // Consider memory pressure in load calculation
330 double effective_load = cpu_usage;
331
332 // Memory pressure should escalate load level
333 if (memory_usage > cfg.memory_critical_threshold) {
334 // Critical memory -> at least high load
335 effective_load = std::max(effective_load, cfg.high_threshold + 1.0);
336 } else if (memory_usage > cfg.memory_warning_threshold) {
337 // Warning memory -> at least moderate load
338 effective_load = std::max(effective_load, cfg.moderate_threshold + 1.0);
339 }
340
341 // Apply strategy-specific adjustments BEFORE determining level
342 switch (cfg.strategy) {
344 effective_load *= 0.8; // Be more conservative
345 break;
347 effective_load *= 1.2; // Be more aggressive
348 break;
350 default:
351 break;
352 }
353
354 // Determine load level
355 if (effective_load >= cfg.high_threshold) {
357 } else if (effective_load >= cfg.moderate_threshold) {
358 return load_level::high;
359 } else if (effective_load >= cfg.low_threshold) {
361 } else if (effective_load >= cfg.idle_threshold) {
362 return load_level::low;
363 } else {
364 return load_level::idle;
365 }
366 }

References kcenon::monitoring::aggressive, kcenon::monitoring::balanced, kcenon::monitoring::conservative, kcenon::monitoring::critical, kcenon::monitoring::high, kcenon::monitoring::adaptive_config::high_threshold, kcenon::monitoring::idle, kcenon::monitoring::adaptive_config::idle_threshold, kcenon::monitoring::low, kcenon::monitoring::adaptive_config::low_threshold, kcenon::monitoring::adaptive_config::memory_critical_threshold, kcenon::monitoring::adaptive_config::memory_warning_threshold, kcenon::monitoring::moderate, kcenon::monitoring::adaptive_config::moderate_threshold, and kcenon::monitoring::adaptive_config::strategy.

Referenced by calculate_load_level_with_hysteresis().

Here is the caller graph for this function:

◆ calculate_load_level_with_hysteresis()

static load_level kcenon::monitoring::adaptive_collector::calculate_load_level_with_hysteresis ( double cpu_usage,
double memory_usage,
load_level current_level,
const adaptive_config & cfg )
inlinestaticprivate

Calculate load level with hysteresis support (ARC-005)

Hysteresis prevents oscillation at threshold boundaries by requiring the metric to cross a margin before changing levels.

Parameters
cpu_usageCurrent CPU usage percentage
memory_usageCurrent memory usage percentage
current_levelCurrent load level
cfgAdaptive configuration
Returns
New load level (may be same as current if within hysteresis margin)

Definition at line 380 of file adaptive_monitor.h.

385 {
386 // First calculate what the level would be without hysteresis
387 load_level raw_level = calculate_load_level_with_config(cpu_usage, memory_usage, cfg);
388
389 // If hysteresis is disabled, return raw level
390 if (!cfg.enable_hysteresis) {
391 return raw_level;
392 }
393
394 // If no change, return current level
395 if (raw_level == current_level) {
396 return current_level;
397 }
398
399 // Calculate effective load (same logic as calculate_load_level_with_config)
400 double effective_load = cpu_usage;
401 if (memory_usage > cfg.memory_critical_threshold) {
402 effective_load = std::max(effective_load, cfg.high_threshold + 1.0);
403 } else if (memory_usage > cfg.memory_warning_threshold) {
404 effective_load = std::max(effective_load, cfg.moderate_threshold + 1.0);
405 }
406
407 switch (cfg.strategy) {
409 effective_load *= 0.8;
410 break;
412 effective_load *= 1.2;
413 break;
415 default:
416 break;
417 }
418
419 // Get threshold for current level
420 double current_threshold = get_threshold_for_level(current_level, cfg);
421 double margin = cfg.hysteresis_margin;
422
423 // For upward transitions (higher load), require crossing threshold + margin
424 // For downward transitions (lower load), require crossing threshold - margin
425 if (raw_level > current_level) {
426 // Moving to higher load level - need to exceed threshold by margin
427 double next_threshold = get_threshold_for_level(
428 static_cast<load_level>(static_cast<int>(current_level) + 1), cfg);
429 if (effective_load < next_threshold + margin) {
430 return current_level; // Stay at current level (hysteresis)
431 }
432 } else {
433 // Moving to lower load level - need to drop below threshold by margin
434 if (effective_load > current_threshold - margin) {
435 return current_level; // Stay at current level (hysteresis)
436 }
437 }
438
439 return raw_level;
440 }
static load_level calculate_load_level_with_config(double cpu_usage, double memory_usage, const adaptive_config &cfg)
Calculate load level from metrics with provided config.
static double get_threshold_for_level(load_level level, const adaptive_config &cfg)
Get the threshold value for a given load level.
load_level
System load levels.

References kcenon::monitoring::aggressive, kcenon::monitoring::balanced, calculate_load_level_with_config(), kcenon::monitoring::conservative, kcenon::monitoring::adaptive_config::enable_hysteresis, get_threshold_for_level(), kcenon::monitoring::adaptive_config::high_threshold, kcenon::monitoring::adaptive_config::hysteresis_margin, kcenon::monitoring::adaptive_config::memory_critical_threshold, kcenon::monitoring::adaptive_config::memory_warning_threshold, kcenon::monitoring::adaptive_config::moderate_threshold, and kcenon::monitoring::adaptive_config::strategy.

Referenced by adapt().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ collect()

common::Result< kcenon::monitoring::metrics_snapshot > kcenon::monitoring::adaptive_collector::collect ( )
inline

Collect metrics with adaptive sampling.

Definition at line 178 of file adaptive_monitor.h.

178 {
179 if (!should_sample()) {
181 return common::Result<kcenon::monitoring::metrics_snapshot>::err(error_info(kcenon::monitoring::monitoring_error_code::operation_cancelled, "Sample dropped due to adaptive sampling").to_common_error());
182 }
183
185 return collector_->collect();
186 }
bool should_sample() const
Determine if current sample should be collected.
virtual common::Result< metrics_snapshot > collect()=0
Collect metrics.

References kcenon::monitoring::metrics_collector::collect(), collector_, kcenon::monitoring::operation_cancelled, kcenon::monitoring::adaptation_stats::samples_collected, kcenon::monitoring::adaptation_stats::samples_dropped, should_sample(), and stats_.

Referenced by TEST_F(), and TEST_F().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_config()

adaptive_config kcenon::monitoring::adaptive_collector::get_config ( ) const
inline

Get adaptive configuration.

Thread Safety:
Thread-safe. Uses mutex for synchronization.

Definition at line 288 of file adaptive_monitor.h.

288 {
289 std::lock_guard<std::mutex> lock(config_mutex_);
290 return config_;
291 }

References config_, and config_mutex_.

◆ get_current_interval()

std::chrono::milliseconds kcenon::monitoring::adaptive_collector::get_current_interval ( ) const
inline

Get current collection interval.

Definition at line 270 of file adaptive_monitor.h.

270 {
271 std::lock_guard lock(stats_mutex_);
273 }

References kcenon::monitoring::adaptation_stats::current_interval, stats_, and stats_mutex_.

◆ get_stats()

adaptation_stats kcenon::monitoring::adaptive_collector::get_stats ( ) const
inline

Get current adaptation statistics.

Definition at line 262 of file adaptive_monitor.h.

262 {
263 std::lock_guard lock(stats_mutex_);
264 return stats_;
265 }

References stats_, and stats_mutex_.

Referenced by TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), and TEST_F().

Here is the caller graph for this function:

◆ get_threshold_for_level()

static double kcenon::monitoring::adaptive_collector::get_threshold_for_level ( load_level level,
const adaptive_config & cfg )
inlinestaticprivate

Get the threshold value for a given load level.

Definition at line 445 of file adaptive_monitor.h.

445 {
446 switch (level) {
447 case load_level::idle: return 0.0;
448 case load_level::low: return cfg.idle_threshold;
449 case load_level::moderate: return cfg.low_threshold;
450 case load_level::high: return cfg.moderate_threshold;
451 case load_level::critical: return cfg.high_threshold;
452 }
453 return cfg.moderate_threshold;
454 }

References kcenon::monitoring::critical, kcenon::monitoring::high, kcenon::monitoring::adaptive_config::high_threshold, kcenon::monitoring::idle, kcenon::monitoring::adaptive_config::idle_threshold, kcenon::monitoring::low, kcenon::monitoring::adaptive_config::low_threshold, kcenon::monitoring::moderate, and kcenon::monitoring::adaptive_config::moderate_threshold.

Referenced by calculate_load_level_with_hysteresis().

Here is the caller graph for this function:

◆ is_enabled()

bool kcenon::monitoring::adaptive_collector::is_enabled ( ) const
inline

Check if adaptive behavior is enabled.

Definition at line 303 of file adaptive_monitor.h.

303 {
304 return enabled_;
305 }

References enabled_.

Referenced by TEST_F().

Here is the caller graph for this function:

◆ set_config()

void kcenon::monitoring::adaptive_collector::set_config ( const adaptive_config & config)
inline

Set adaptive configuration.

Thread Safety:
Thread-safe. Uses mutex for synchronization.

Definition at line 279 of file adaptive_monitor.h.

279 {
280 std::lock_guard<std::mutex> lock(config_mutex_);
281 config_ = config;
282 }

References config_, and config_mutex_.

Referenced by TEST_F().

Here is the caller graph for this function:

◆ set_enabled()

void kcenon::monitoring::adaptive_collector::set_enabled ( bool enabled)
inline

Enable or disable adaptive behavior.

Definition at line 296 of file adaptive_monitor.h.

296 {
297 enabled_ = enabled;
298 }

References enabled_.

Referenced by TEST_F().

Here is the caller graph for this function:

◆ should_sample()

bool kcenon::monitoring::adaptive_collector::should_sample ( ) const
inlineprivate

Determine if current sample should be collected.

Definition at line 311 of file adaptive_monitor.h.

311 {
312 if (!enabled_) return true;
313
314 // Use random sampling based on current rate
315 static thread_local std::mt19937 gen(std::random_device{}());
316 std::uniform_real_distribution<> dis(0.0, 1.0);
317 return dis(gen) < current_sampling_rate_.load();
318 }

References current_sampling_rate_, and enabled_.

Referenced by collect().

Here is the caller graph for this function:

Member Data Documentation

◆ collector_

std::shared_ptr<kcenon::monitoring::metrics_collector> kcenon::monitoring::adaptive_collector::collector_
private

Definition at line 158 of file adaptive_monitor.h.

Referenced by collect().

◆ config_

adaptive_config kcenon::monitoring::adaptive_collector::config_
private

Definition at line 159 of file adaptive_monitor.h.

Referenced by adapt(), get_config(), and set_config().

◆ config_mutex_

std::mutex kcenon::monitoring::adaptive_collector::config_mutex_
mutableprivate

Definition at line 160 of file adaptive_monitor.h.

Referenced by adapt(), get_config(), and set_config().

◆ current_sampling_rate_

std::atomic<double> kcenon::monitoring::adaptive_collector::current_sampling_rate_ {1.0}
private

Definition at line 163 of file adaptive_monitor.h.

163{1.0};

Referenced by adapt(), and should_sample().

◆ enabled_

std::atomic<bool> kcenon::monitoring::adaptive_collector::enabled_ {true}
private

Definition at line 162 of file adaptive_monitor.h.

162{true};

Referenced by is_enabled(), set_enabled(), and should_sample().

◆ stats_

adaptation_stats kcenon::monitoring::adaptive_collector::stats_
private

Definition at line 161 of file adaptive_monitor.h.

Referenced by adapt(), collect(), get_current_interval(), and get_stats().

◆ stats_mutex_

std::mutex kcenon::monitoring::adaptive_collector::stats_mutex_
mutableprivate

Definition at line 164 of file adaptive_monitor.h.

Referenced by adapt(), get_current_interval(), and get_stats().


The documentation for this class was generated from the following file: