Monitoring API
## Конфигурационная система
### Основной класс конфигурации
Класс `MonitoringConfig` определяет все настраиваемые параметры системы мониторинга:
«`rust
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct MonitoringConfig {
pub enabled: bool, // Включение/выключение системы
pub prometheus_enabled: bool, // Экспорт метрик в Prometheus
pub prometheus_port: u16, // Порт для Prometheus (9090 по умолчанию)
pub alerting_enabled: bool, // Включение системы оповещений
pub metrics_interval_sec: u64, // Интервал сбора метрик в секундах
pub retention_days: u32, // Дни хранения исторических данных
pub max_alerts: usize, // Максимальное количество хранимых оповещений
}
«`
### Значения по умолчанию
Система предоставляет разумные значения по умолчанию для всех параметров:
«`rust
impl Default for MonitoringConfig {
fn default() -> Self {
Self {
enabled: true,
prometheus_enabled: true,
prometheus_port: 9090,
alerting_enabled: true,
metrics_interval_sec: 60,
retention_days: 30,
max_alerts: 1000,
}
}
}
«`
## UnifiedMonitor — ядро системы
### Инициализация центрального монитора
Класс `UnifiedMonitor` является центральным компонентом системы:
«`rust
pub struct UnifiedMonitor {
monitors: Arc
health_checks: Arc
alerts: Arc
config: MonitoringConfig,
health_history: Arc
}
impl UnifiedMonitor {
pub fn new(config: MonitoringConfig) -> Self {
Self {
monitors: Arc::new(RwLock::new(HashMap::new())),
health_checks: Arc::new(RwLock::new(HashMap::new())),
alerts: Arc::new(RwLock::new(VecDeque::with_capacity(config.max_alerts))),
config,
health_history: Arc::new(RwLock::new(VecDeque::with_capacity(100))),
}
}
}
«`
### Основные интерфейсы
#### Интерфейс Monitor
Все мониторы должны реализовывать следующий интерфейс:
«`rust
#[async_trait::async_trait]
pub trait Monitor: Send + Sync {
fn name(&self) -> &’static str;
async fn collect_metrics(&self) -> MonitorMetrics;
async fn health_check(&self) -> bool;
async fn reset_metrics(&self);
}
«`
#### Интерфейс HealthCheckable
Компоненты проверки здоровья реализуют этот интерфейс:
«`rust
#[async_trait]
pub trait HealthCheckable: Send + Sync {
async fn health_check(&self) -> HealthStatus;
fn component_name(&self) -> &’static str;
fn component_type(&self) -> ComponentType;
}
«`
## Монитор сервера (ServerMonitor)
### Структура метрик сервера
Класс `ServerMonitor` отслеживает метрики, связанные с работой сервера:
«`rust
#[derive(Debug, Clone)]
pub struct ServerMetrics {
pub active_sessions: u64, // Активные пользовательские сессии
pub total_connections: u64, // Общее количество соединений
pub failed_connections: u64, // Неудачные попытки подключения
pub heartbeat_timeouts: u64, // Пропущенные heartbeat’ы
pub avg_response_time: f64, // Среднее время ответа
}
«`
### Инициализация и управление сессиями
«`rust
impl ServerMonitor {
pub fn new() -> Self {
Self {
metrics: Arc::new(RwLock::new(ServerMetrics {
active_sessions: 0,
total_connections: 0,
failed_connections: 0,
heartbeat_timeouts: 0,
avg_response_time: 0.0,
})),
unified_monitor: None,
}
}
pub async fn record_session_connected(&self) {
let mut metrics = self.metrics.write().await;
metrics.active_sessions += 1;
metrics.total_connections += 1;
}
pub async fn record_session_disconnected(&self) {
let mut metrics = self.metrics.write().await;
metrics.active_sessions = metrics.active_sessions.saturating_sub(1);
}
}
«`
## Проверки здоровья (Health Checks)
### DatabaseHealthCheck
Проверка работоспособности базы данных с механизмом повторных попыток:
«`rust
impl DatabaseHealthCheck {
async fn execute_health_query_with_retry(&self) -> Result<(bool, u128), String> {
const MAX_RETRIES: u32 = 3;
const INITIAL_DELAY_MS: u64 = 100;
let mut last_error = None;
for attempt in 0..MAX_RETRIES {
match self.execute_single_health_query().await {
Ok(result) => return Ok(result),
Err(e) => {
last_error = Some(e);
if attempt < MAX_RETRIES - 1 {
let delay_ms = INITIAL_DELAY_MS * 2u64.pow(attempt);
tokio::time::sleep(Duration::from_millis(delay_ms)).await;
}
}
}
}
Err(last_error.unwrap_or_else(|| "All retry attempts failed".to_string()))
}
}
```
### NetworkHealthCheck
Проверка сетевой доступности внешних ресурсов:
```rust
impl NetworkHealthCheck {
async fn check_external_connectivity_async(&self) -> Result
let mut results = Vec::new();
let targets = vec![
(«google.com», 80),
(«cloudflare.com», 80),
(«github.com», 80),
];
let mut futures = Vec::new();
for (host, port) in targets {
let host = host.to_string();
futures.push(async move {
match self.check_port_async(&host, port, 3).await {
Ok(duration) => Ok((format!(«{}:{}», host, port), duration)),
Err(e) => Err(format!(«{}:{} — {}», host, port, e)),
}
});
}
let check_results = futures::future::join_all(futures).await;
// Обработка результатов…
}
}
«`
### MemoryHealthCheck с кэшированием
Проверка использования памяти с интеллектуальным кэшированием:
«`rust
pub struct MemoryHealthCheck {
cache: SimpleCache,
system_info: Arc
}
impl MemoryHealthCheck {
pub fn new() -> Self {
Self {
cache: SimpleCache::new(Duration::from_secs(10)),
system_info: Arc::new(RealSystemInfo),
}
}
async fn get_memory_info_cached(&self) -> serde_json::Value {
self.cache.get_or_compute(|| async {
match self.system_info.get_memory_info().await {
Ok(mem_info) => {
let total_mb = mem_info.total / 1024;
let available_mb = mem_info.avail / 1024;
let used_mb = total_mb.saturating_sub(available_mb);
let usage_percent = (used_mb as f64 / total_mb as f64) * 100.0;
serde_json::json!({
«total_mb»: total_mb,
«used_mb»: used_mb,
«available_mb»: available_mb,
«usage_percent»: usage_percent,
«is_healthy»: usage_percent < 90.0,
"status": if usage_percent < 80.0 { "Normal" }
else if usage_percent < 90.0 { "High" }
else { "Critical" }
})
},
Err(e) => serde_json::json!({
«error»: format!(«Cannot read memory info: {}», e)
})
}
}).await
}
}
«`
## Система кэширования
### Класс MetricsCache
Общий кэш для хранения метрик с поддержкой TTL (Time-To-Live):
«`rust
pub struct MetricsCache {
cache: Arc
ttl: Duration,
}
impl MetricsCache {
pub async fn get_or_compute
where
F: FnOnce() -> Fut,
Fut: Future
if let Some((timestamp, value)) = cache.get(key) {
if now.duration_since(*timestamp) < self.ttl {
return value.clone();
}
}
let value = computer().await;
cache.insert(key.to_string(), (now, value.clone()));
value
}
}
```
## MonitorRegistry - реестр мониторов
### Инициализация системы
Класс `MonitorRegistry` отвечает за регистрацию всех компонентов мониторинга:
```rust
impl MonitorRegistry {
pub async fn new() -> Self {
info!(«🚀 Initializing comprehensive monitoring system…»);
let config = MonitoringConfig::default();
let unified_monitor = Arc::new(UnifiedMonitor::new(config));
// Регистрация серверного монитора
let server_monitor = ServerMonitor::new();
unified_monitor.register_monitor(Arc::new(server_monitor.clone())).await;
// Регистрация системных проверок здоровья
unified_monitor.register_health_check(Arc::new(DatabaseHealthCheck::new())).await;
unified_monitor.register_health_check(Arc::new(NetworkHealthCheck::new())).await;
unified_monitor.register_health_check(Arc::new(MemoryHealthCheck::new())).await;
unified_monitor.register_health_check(Arc::new(CpuHealthCheck::new())).await;
unified_monitor.register_health_check(Arc::new(DiskHealthCheck::new())).await;
unified_monitor.register_health_check(Arc::new(ApiHealthCheck::new())).await;
// Создание вспомогательных компонентов
let start_time = Instant::now();
let health_runner = HealthCheckRunner::new(Arc::clone(&unified_monitor));
let metrics_reporter = MetricsReporter::new(Arc::clone(&unified_monitor), start_time);
Self {
unified_monitor,
server_monitor: Arc::new(server_monitor),
health_runner,
metrics_reporter,
start_time,
}
}
}
«`
### Запуск фонового мониторинга
«`rust
pub async fn start_background_monitoring(self: Arc
let registry = Arc::clone(&self);
tokio::spawn(async move {
// Первая проверка через 30 секунд после запуска
tokio::time::sleep(Duration::from_secs(30)).await;
let mut interval = interval(Duration::from_secs(60));
let mut error_count = 0;
const MAX_CONSECUTIVE_ERRORS: u32 = 5;
loop {
interval.tick().await;
let report = registry.health_runner.get_detailed_report().await;
if !report.overall_health {
error_count += 1;
if error_count >= MAX_CONSECUTIVE_ERRORS {
error_count = 0;
tokio::time::sleep(Duration::from_secs(300)).await;
continue;
}
} else {
error_count = 0;
}
// Детальный отчет каждые 5 минут
if registry.start_time.elapsed().as_secs() % 300 < 60 {
registry.metrics_reporter.print_comprehensive_report().await;
}
}
});
BackgroundMonitorHandle::new()
}
```
## Система логирования
### Настройка логирования
Функция `init_logging` настраивает систему логирования с кастомным форматом:
```rust
pub fn init_logging() {
let filter = EnvFilter::try_from_default_env()
.unwrap_or_else(|_| EnvFilter::new("info"));
tracing_subscriber::fmt()
.with_env_filter(filter)
.with_timer(CustomTime) // UTC время с миллисекундами
.with_file(true) // Отображение имени файла
.with_line_number(true) // Отображение номера строки
.init();
}
```
### Макросы для мониторинга
Специальные макросы добавляют контекстную информацию к логам:
```rust
#[macro_export]
macro_rules! monitor_info {
($msg:literal $(, $key:ident = $value:expr)*) => {
tracing::info!(
monitor_component = module_path!(), // Автоматическое имя компонента
$($key = $value,)*
$msg
)
};
}
«`
## Типы данных и структуры
### HealthStatus
Структура для представления статуса здоровья компонента:
«`rust
#[derive(Debug, Serialize, Clone)]
pub struct HealthStatus {
pub is_healthy: bool, // Бинарный статус здоровья
pub message: String, // Человекочитаемое сообщение
pub details: Option
pub timestamp: u64, // Временная метка
}
«`
### SystemHealthReport
Комплексный отчет о состоянии системы:
«`rust
#[derive(Debug, Serialize, Clone)]
pub struct SystemHealthReport {
pub overall_health: bool, // Общий статус системы
pub components: HashMap
pub critical_components: Vec
pub warnings: Vec
pub timestamp: u64, // Временная метка отчета
}
«`
### Alert и AlertLevel
Система оповещений с уровнями серьезности:
«`rust
#[derive(Debug, Serialize, Clone, PartialEq)]
pub enum AlertLevel {
Info, // Информационные сообщения
Warning, // Предупреждения
Error, // Ошибки
Critical, // Критические события
}
#[derive(Debug, Serialize, Clone)]
pub struct Alert {
pub level: AlertLevel, // Уровень серьезности
pub source: String, // Источник оповещения
pub message: String, // Текст сообщения
pub timestamp: u64, // Временная метка
pub metadata: HashMap
}
«`
## Работа с системной информацией
### Интерфейс SystemInfoProvider
Абстрактный интерфейс для получения системной информации:
«`rust
#[async_trait]
pub trait SystemInfoProvider: Send + Sync {
async fn get_memory_info(&self) -> Result
async fn get_load_avg(&self) -> Result
async fn get_disk_info(&self) -> Result
}
«`
### Реализация RealSystemInfo
Реальная реализация, использующая системные вызовы:
«`rust
pub struct RealSystemInfo;
#[async_trait]
impl SystemInfoProvider for RealSystemInfo {
async fn get_memory_info(&self) -> Result
tokio::task::spawn_blocking(|| {
sys_info::mem_info()
.map(|info| MemoryInfo {
total: info.total,
free: info.free,
avail: info.avail,
})
.map_err(|e| e.to_string())
})
.await
.map_err(|e| e.to_string())?
}
}
«`
## Экспорт метрик
### Поддержка Prometheus
Система поддерживает экспорт метрик в формате Prometheus:
«`rust
pub async fn get_prometheus_metrics(&self) -> String {
if !self.config.prometheus_enabled {
return String::new();
}
let all_metrics = self.collect_all_metrics().await;
let mut prometheus_output = String::new();
for (monitor_name, metrics) in all_metrics {
for (metric_name, metric_value) in metrics.metrics {
let metric_line = match metric_value {
MetricValue::Counter(value) => {
format!(«{}_{}{{monitor=\»{}\»}} {}\n»,
monitor_name, metric_name, monitor_name, value)
}
MetricValue::Gauge(value) => {
format!(«{}_{}{{monitor=\»{}\»}} {}\n»,
monitor_name, metric_name, monitor_name, value)
}
_ => continue,
};
prometheus_output.push_str(&metric_line);
}
}
prometheus_output
}
«`
## Практическое использование
### Добавление нового монитора
Для добавления нового монитора необходимо:
1. Реализовать трейт `Monitor` или `HealthCheckable`
2. Зарегистрировать в `MonitorRegistry::new()`
3. Настроить параметры сбора метрик
**Пример кастомного монитора:**
«`rust
pub struct CustomMonitor {
metrics: Arc
}
#[async_trait::async_trait]
impl Monitor for CustomMonitor {
fn name(&self) -> &’static str {
«custom_monitor»
}
async fn collect_metrics(&self) -> MonitorMetrics {
let metrics = self.metrics.read().await;
let mut metric_map = HashMap::new();
metric_map.insert(«custom_counter».to_string(),
MetricValue::Counter(metrics.counter));
MonitorMetrics {
name: self.name().to_string(),
timestamp: std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_secs(),
metrics: metric_map,
health: self.health_check().await,
}
}
async fn health_check(&self) -> bool {
true
}
async fn reset_metrics(&self) {
let mut metrics = self.metrics.write().await;
metrics.counter = 0;
}
}
«`
### Настройка конфигурации
Конфигурация может быть загружена из файла или установлена программно:
«`rust
let config = MonitoringConfig {
enabled: true,
prometheus_enabled: true,
prometheus_port: 9090,
alerting_enabled: true,
metrics_interval_sec: 30, // Уменьшенный интервал
retention_days: 14,
max_alerts: 500,
};
let monitor = UnifiedMonitor::new(config);
«`
## Оптимизация производительности
### Кэширование результатов
Система использует многоуровневое кэширование для оптимизации производительности:
«`rust
impl MemoryHealthCheck {
async fn get_memory_info_cached(&self) -> serde_json::Value {
self.cache.get_or_compute(|| async {
// Тяжелая операция получения информации о памяти
self.system_info.get_memory_info().await
}).await
}
}
«`
### Асинхронные операции
Все операции сбора метрик выполняются асинхронно:
«`rust
pub async fn collect_all_metrics(&self) -> HashMap
let monitors = self.monitors.read().await;
let mut futures = Vec::new();
for (name, monitor) in monitors.iter() {
let name_clone = name.clone();
let monitor_clone = monitor.clone();
futures.push(async move {
let metrics = monitor_clone.collect_metrics().await;
(name_clone, metrics)
});
}
futures::future::join_all(futures).await.into_iter().collect()
}
«`
## Обработка ошибок
### Механизмы повторных попыток
Система реализует паттерн повторных попыток с экспоненциальным откладыванием:
«`rust
async fn execute_health_query_with_retry(&self) -> Result<(bool, u128), String> {
const MAX_RETRIES: u32 = 3;
const INITIAL_DELAY_MS: u64 = 100;
for attempt in 0..MAX_RETRIES {
match self.execute_single_health_query().await {
Ok(result) => return Ok(result),
Err(e) => {
if attempt < MAX_RETRIES - 1 {
let delay_ms = INITIAL_DELAY_MS * 2u64.pow(attempt);
tokio::time::sleep(Duration::from_millis(delay_ms)).await;
}
}
}
}
Err("All retry attempts failed".to_string())
}
```
## Заключение
Данная система мониторинга предоставляет комплексное решение для наблюдения за состоянием приложений. Модульная архитектура, поддержка асинхронных операций и расширяемость делают её подходящей для использования в проектах различного масштаба. Система готова к интеграции с внешними инструментами мониторинга и может быть расширена для решения специфических задач.