use serde::{Deserialize, Serialize};
use std::time::{SystemTime, UNIX_EPOCH};
use std::collections::HashMap;
use crate::error::SystemAnalysisError;
use crate::types::SystemProfile;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PerformanceFeedback {
pub session_id: String,
pub timestamp: u64,
pub system_profile: SystemProfile,
pub workload_id: String,
pub metrics: PerformanceMetrics,
pub resource_utilization: ResourceUtilization,
pub issues: Vec<PerformanceIssue>,
pub metadata: HashMap<String, String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PerformanceMetrics {
pub latency_ms: Option<f64>,
pub throughput_ops_per_sec: Option<f64>,
pub peak_memory_gb: Option<f64>,
pub avg_memory_gb: Option<f64>,
pub cpu_utilization_percent: Option<f64>,
pub gpu_utilization_percent: Option<f64>,
pub power_consumption_watts: Option<f64>,
pub thermal: Option<ThermalMetrics>,
pub quality: Option<QualityMetrics>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ThermalMetrics {
pub cpu_temp_celsius: Option<f64>,
pub gpu_temp_celsius: Option<f64>,
pub thermal_throttling: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct QualityMetrics {
pub accuracy: Option<f64>,
pub loss: Option<f64>,
pub confidence_scores: Vec<f64>,
pub custom_metrics: HashMap<String, f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ResourceUtilization {
pub cpu: CpuUtilization,
pub gpu: Vec<GpuUtilization>,
pub memory: MemoryUtilization,
pub storage: StorageUtilization,
pub network: NetworkUtilization,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CpuUtilization {
pub overall_percent: f64,
pub per_core_percent: Vec<f64>,
pub frequency_mhz: Option<f64>,
pub power_watts: Option<f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GpuUtilization {
pub gpu_index: u32,
pub utilization_percent: f64,
pub memory_used_gb: f64,
pub memory_percent: f64,
pub temperature_celsius: Option<f64>,
pub power_watts: Option<f64>,
pub clock_speeds: Option<GpuClocks>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GpuClocks {
pub core_mhz: f64,
pub memory_mhz: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MemoryUtilization {
pub used_gb: f64,
pub available_gb: f64,
pub usage_percent: f64,
pub swap_used_gb: Option<f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StorageUtilization {
pub read_mbps: f64,
pub write_mbps: f64,
pub iops: f64,
pub usage_percent: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NetworkUtilization {
pub download_mbps: f64,
pub upload_mbps: f64,
pub latency_ms: f64,
pub packet_loss_percent: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PerformanceIssue {
pub severity: IssueSeverity,
pub category: IssueCategory,
pub description: String,
pub timestamp: u64,
pub suggestion: Option<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum IssueSeverity {
Info,
Warning,
Error,
Critical,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum IssueCategory {
Memory,
Cpu,
Gpu,
Storage,
Network,
Thermal,
Power,
Configuration,
Model,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FeedbackAggregation {
pub system_hash: String,
pub workload_id: String,
pub sample_count: u32,
pub avg_metrics: PerformanceMetrics,
pub variance: PerformanceMetrics,
pub common_issues: Vec<(PerformanceIssue, u32)>,
pub prediction_accuracy: PredictionAccuracy,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PredictionAccuracy {
pub latency_accuracy: Option<f64>,
pub throughput_accuracy: Option<f64>,
pub memory_accuracy: Option<f64>,
pub overall_accuracy: f64,
}
pub trait FeedbackCollector: Send + Sync {
fn submit_feedback(&mut self, feedback: PerformanceFeedback) -> Result<(), SystemAnalysisError>;
fn get_aggregation(&self, system_hash: &str, workload_id: &str) -> Option<FeedbackAggregation>;
fn get_prediction_accuracy(&self, system_hash: &str) -> Option<PredictionAccuracy>;
fn cleanup_old_data(&mut self, retention_days: u32) -> Result<u32, SystemAnalysisError>;
}
pub struct InMemoryFeedbackCollector {
feedback_history: Vec<PerformanceFeedback>,
aggregations: HashMap<String, FeedbackAggregation>,
}
impl InMemoryFeedbackCollector {
pub fn new() -> Self {
Self {
feedback_history: Vec::new(),
aggregations: HashMap::new(),
}
}
fn current_timestamp() -> u64 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_secs()
}
fn generate_key(system_hash: &str, workload_id: &str) -> String {
format!("{system_hash}:{workload_id}")
}
fn update_aggregations(&mut self, feedback: &PerformanceFeedback) {
let key = Self::generate_key(&feedback.system_profile.system_hash(), &feedback.workload_id);
let aggregation = FeedbackAggregation {
system_hash: feedback.system_profile.system_hash(),
workload_id: feedback.workload_id.clone(),
sample_count: 1,
avg_metrics: feedback.metrics.clone(),
variance: feedback.metrics.clone(), common_issues: feedback.issues.iter()
.map(|issue| (issue.clone(), 1))
.collect(),
prediction_accuracy: PredictionAccuracy {
latency_accuracy: Some(0.8), throughput_accuracy: Some(0.8), memory_accuracy: Some(0.8), overall_accuracy: 0.8, },
};
self.aggregations.insert(key, aggregation);
}
}
impl FeedbackCollector for InMemoryFeedbackCollector {
fn submit_feedback(&mut self, feedback: PerformanceFeedback) -> Result<(), SystemAnalysisError> {
if feedback.session_id.is_empty() {
return Err(SystemAnalysisError::invalid_workload(
"Session ID cannot be empty".to_string()
));
}
if feedback.workload_id.is_empty() {
return Err(SystemAnalysisError::invalid_workload(
"Workload ID cannot be empty".to_string()
));
}
self.update_aggregations(&feedback);
self.feedback_history.push(feedback);
Ok(())
}
fn get_aggregation(&self, system_hash: &str, workload_id: &str) -> Option<FeedbackAggregation> {
let key = Self::generate_key(system_hash, workload_id);
self.aggregations.get(&key).cloned()
}
fn get_prediction_accuracy(&self, system_hash: &str) -> Option<PredictionAccuracy> {
let system_aggregations: Vec<_> = self.aggregations.values()
.filter(|agg| agg.system_hash == system_hash)
.collect();
if system_aggregations.is_empty() {
return None;
}
let total_accuracy: f64 = system_aggregations.iter()
.map(|agg| agg.prediction_accuracy.overall_accuracy)
.sum();
Some(PredictionAccuracy {
latency_accuracy: Some(0.8), throughput_accuracy: Some(0.8), memory_accuracy: Some(0.8), overall_accuracy: total_accuracy / system_aggregations.len() as f64,
})
}
fn cleanup_old_data(&mut self, retention_days: u32) -> Result<u32, SystemAnalysisError> {
let cutoff_timestamp = Self::current_timestamp() - (retention_days as u64 * 24 * 60 * 60);
let initial_count = self.feedback_history.len();
self.feedback_history.retain(|feedback| feedback.timestamp >= cutoff_timestamp);
let removed_count = initial_count - self.feedback_history.len();
Ok(removed_count as u32)
}
}
impl Default for InMemoryFeedbackCollector {
fn default() -> Self {
Self::new()
}
}
pub struct FeedbackIntegration {
collector: Box<dyn FeedbackCollector>,
enabled: bool,
}
impl FeedbackIntegration {
pub fn new(collector: Box<dyn FeedbackCollector>) -> Self {
Self {
collector,
enabled: true,
}
}
pub fn with_memory_collector() -> Self {
Self::new(Box::new(InMemoryFeedbackCollector::new()))
}
pub fn set_enabled(&mut self, enabled: bool) {
self.enabled = enabled;
}
pub fn is_enabled(&self) -> bool {
self.enabled
}
pub fn submit_feedback(&mut self, feedback: PerformanceFeedback) -> Result<(), SystemAnalysisError> {
if !self.enabled {
return Ok(());
}
self.collector.submit_feedback(feedback)
}
pub fn get_aggregation(&self, system_hash: &str, workload_id: &str) -> Option<FeedbackAggregation> {
if !self.enabled {
return None;
}
self.collector.get_aggregation(system_hash, workload_id)
}
pub fn get_prediction_accuracy(&self, system_hash: &str) -> Option<PredictionAccuracy> {
if !self.enabled {
return None;
}
self.collector.get_prediction_accuracy(system_hash)
}
pub fn cleanup_old_data(&mut self, retention_days: u32) -> Result<u32, SystemAnalysisError> {
if !self.enabled {
return Ok(0);
}
self.collector.cleanup_old_data(retention_days)
}
}
pub struct FeedbackBuilder {
session_id: String,
workload_id: String,
system_profile: Option<SystemProfile>,
metrics: PerformanceMetrics,
resource_utilization: Option<ResourceUtilization>,
issues: Vec<PerformanceIssue>,
metadata: HashMap<String, String>,
}
impl FeedbackBuilder {
pub fn new(session_id: impl Into<String>, workload_id: impl Into<String>) -> Self {
Self {
session_id: session_id.into(),
workload_id: workload_id.into(),
system_profile: None,
metrics: PerformanceMetrics {
latency_ms: None,
throughput_ops_per_sec: None,
peak_memory_gb: None,
avg_memory_gb: None,
cpu_utilization_percent: None,
gpu_utilization_percent: None,
power_consumption_watts: None,
thermal: None,
quality: None,
},
resource_utilization: None,
issues: Vec::new(),
metadata: HashMap::new(),
}
}
pub fn system_profile(mut self, profile: SystemProfile) -> Self {
self.system_profile = Some(profile);
self
}
pub fn latency_ms(mut self, latency: f64) -> Self {
self.metrics.latency_ms = Some(latency);
self
}
pub fn throughput_ops_per_sec(mut self, throughput: f64) -> Self {
self.metrics.throughput_ops_per_sec = Some(throughput);
self
}
pub fn memory_usage(mut self, peak_gb: f64, avg_gb: f64) -> Self {
self.metrics.peak_memory_gb = Some(peak_gb);
self.metrics.avg_memory_gb = Some(avg_gb);
self
}
pub fn cpu_utilization(mut self, percent: f64) -> Self {
self.metrics.cpu_utilization_percent = Some(percent);
self
}
pub fn gpu_utilization(mut self, percent: f64) -> Self {
self.metrics.gpu_utilization_percent = Some(percent);
self
}
pub fn add_issue(mut self, severity: IssueSeverity, category: IssueCategory, description: impl Into<String>) -> Self {
self.issues.push(PerformanceIssue {
severity,
category,
description: description.into(),
timestamp: SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_secs(),
suggestion: None,
});
self
}
pub fn metadata(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
self.metadata.insert(key.into(), value.into());
self
}
pub fn build(self) -> Result<PerformanceFeedback, SystemAnalysisError> {
let system_profile = self.system_profile.ok_or_else(|| {
SystemAnalysisError::invalid_workload(
"System profile is required for feedback".to_string()
)
})?;
Ok(PerformanceFeedback {
session_id: self.session_id,
timestamp: SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_secs(),
system_profile,
workload_id: self.workload_id,
metrics: self.metrics,
resource_utilization: self.resource_utilization.unwrap_or_else(|| {
ResourceUtilization {
cpu: CpuUtilization {
overall_percent: 0.0,
per_core_percent: Vec::new(),
frequency_mhz: None,
power_watts: None,
},
gpu: Vec::new(),
memory: MemoryUtilization {
used_gb: 0.0,
available_gb: 0.0,
usage_percent: 0.0,
swap_used_gb: None,
},
storage: StorageUtilization {
read_mbps: 0.0,
write_mbps: 0.0,
iops: 0.0,
usage_percent: 0.0,
},
network: NetworkUtilization {
download_mbps: 0.0,
upload_mbps: 0.0,
latency_ms: 0.0,
packet_loss_percent: 0.0,
},
}
}),
issues: self.issues,
metadata: self.metadata,
})
}
}