Skip to main content

feagi_api/endpoints/
monitoring.rs

1// Copyright 2025 Neuraville Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4/*!
5 * FEAGI v1 Monitoring API
6 *
7 * Endpoints for system monitoring, metrics, and telemetry
8 * Maps to Python: feagi/api/v1/monitoring.py
9 */
10
11use crate::common::ApiState;
12use crate::common::{ApiError, ApiResult, Json, State};
13// Removed - using crate::common::State instead
14use serde_json::{json, Value};
15use std::collections::HashMap;
16
17// ============================================================================
18// MONITORING & METRICS
19// ============================================================================
20
21/// Get monitoring system status including metrics collection and brain readiness.
22#[utoipa::path(
23    get,
24    path = "/v1/monitoring/status",
25    tag = "monitoring",
26    responses(
27        (status = 200, description = "Monitoring status", body = HashMap<String, serde_json::Value>),
28        (status = 500, description = "Internal server error")
29    )
30)]
31pub async fn get_status(State(state): State<ApiState>) -> ApiResult<Json<HashMap<String, Value>>> {
32    // Get monitoring status from analytics service
33    let analytics_service = state.analytics_service.as_ref();
34
35    // Get system health as a proxy for monitoring status
36    let health = analytics_service
37        .get_system_health()
38        .await
39        .map_err(|e| ApiError::internal(format!("Failed to get system health: {}", e)))?;
40
41    let mut response = HashMap::new();
42    response.insert("enabled".to_string(), json!(true));
43    response.insert("metrics_collected".to_string(), json!(5)); // Static count for now
44    response.insert("brain_readiness".to_string(), json!(health.brain_readiness));
45    response.insert(
46        "burst_engine_active".to_string(),
47        json!(health.burst_engine_active),
48    );
49
50    Ok(Json(response))
51}
52
53/// Get system metrics including burst frequency, neuron count, and brain readiness.
54#[utoipa::path(
55    get,
56    path = "/v1/monitoring/metrics",
57    tag = "monitoring",
58    responses(
59        (status = 200, description = "System metrics", body = HashMap<String, serde_json::Value>),
60        (status = 500, description = "Internal server error")
61    )
62)]
63pub async fn get_metrics(State(state): State<ApiState>) -> ApiResult<Json<HashMap<String, Value>>> {
64    // Get system metrics from analytics and runtime services
65    let runtime_service = state.runtime_service.as_ref();
66    let analytics_service = state.analytics_service.as_ref();
67
68    let runtime_status = runtime_service
69        .get_status()
70        .await
71        .map_err(|e| ApiError::internal(format!("Failed to get runtime status: {}", e)))?;
72
73    let health = analytics_service
74        .get_system_health()
75        .await
76        .map_err(|e| ApiError::internal(format!("Failed to get system health: {}", e)))?;
77
78    let mut response = HashMap::new();
79    response.insert(
80        "burst_frequency_hz".to_string(),
81        json!(runtime_status.frequency_hz),
82    );
83    response.insert("burst_count".to_string(), json!(runtime_status.burst_count));
84    response.insert("neuron_count".to_string(), json!(health.neuron_count));
85    response.insert(
86        "cortical_area_count".to_string(),
87        json!(health.cortical_area_count),
88    );
89    response.insert("brain_readiness".to_string(), json!(health.brain_readiness));
90    response.insert(
91        "burst_engine_active".to_string(),
92        json!(health.burst_engine_active),
93    );
94
95    Ok(Json(response))
96}
97
98/// Get detailed monitoring data with timestamps for analysis and debugging.
99#[utoipa::path(
100    get,
101    path = "/v1/monitoring/data",
102    tag = "monitoring",
103    responses(
104        (status = 200, description = "Monitoring data", body = HashMap<String, serde_json::Value>),
105        (status = 500, description = "Internal server error")
106    )
107)]
108pub async fn get_data(State(state): State<ApiState>) -> ApiResult<Json<HashMap<String, Value>>> {
109    // Get detailed monitoring data from all services
110    let analytics_service = state.analytics_service.as_ref();
111
112    let health = analytics_service
113        .get_system_health()
114        .await
115        .map_err(|e| ApiError::internal(format!("Failed to get system health: {}", e)))?;
116
117    // Return comprehensive monitoring data
118    let mut data = HashMap::new();
119    data.insert("neuron_count".to_string(), json!(health.neuron_count));
120    data.insert(
121        "cortical_area_count".to_string(),
122        json!(health.cortical_area_count),
123    );
124    data.insert("burst_count".to_string(), json!(health.burst_count));
125    data.insert("brain_readiness".to_string(), json!(health.brain_readiness));
126    data.insert(
127        "burst_engine_active".to_string(),
128        json!(health.burst_engine_active),
129    );
130
131    let mut response = HashMap::new();
132    response.insert("data".to_string(), json!(data));
133    response.insert(
134        "timestamp".to_string(),
135        json!(chrono::Utc::now().to_rfc3339()),
136    );
137
138    Ok(Json(response))
139}
140
141/// Get performance metrics including CPU and memory usage.
142#[utoipa::path(
143    get,
144    path = "/v1/monitoring/performance",
145    tag = "monitoring",
146    responses(
147        (status = 200, description = "Performance metrics", body = HashMap<String, serde_json::Value>),
148        (status = 500, description = "Internal server error")
149    )
150)]
151pub async fn get_performance(
152    State(_state): State<ApiState>,
153) -> ApiResult<Json<HashMap<String, Value>>> {
154    let mut response = HashMap::new();
155    response.insert("cpu_usage".to_string(), json!(0.0));
156    response.insert("memory_usage".to_string(), json!(0.0));
157
158    Ok(Json(response))
159}