use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SystemIo {
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub interconnects: Vec<Interconnect>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub storage: Vec<StorageDevice>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub environment: Option<RuntimeEnvironment>,
}
impl SystemIo {
pub fn empty() -> Self {
Self {
interconnects: Vec::new(),
storage: Vec::new(),
environment: None,
}
}
#[inline]
pub fn has_interconnect(&self) -> bool {
!self.interconnects.is_empty()
}
#[must_use]
#[inline]
pub fn total_interconnect_bandwidth_gbps(&self) -> f64 {
self.interconnects.iter().map(|i| i.bandwidth_gbps).sum()
}
#[must_use]
#[inline]
pub fn estimate_ingestion_secs(&self, dataset_bytes: u64) -> Option<f64> {
let best_storage_gbps = self
.storage
.iter()
.map(|s| s.bandwidth_gbps)
.fold(0.0f64, f64::max);
if best_storage_gbps <= 0.0 {
return None;
}
let bytes_per_sec = best_storage_gbps * crate::units::BYTES_PER_GB;
Some(dataset_bytes as f64 / bytes_per_sec)
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Interconnect {
pub kind: InterconnectKind,
pub name: String,
pub bandwidth_gbps: f64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub state: Option<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[non_exhaustive]
pub enum InterconnectKind {
InfiniBand,
RoCE,
NVLink,
NVSwitch,
XgmiInfinityFabric,
Ici,
}
impl std::fmt::Display for InterconnectKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::InfiniBand => write!(f, "InfiniBand"),
Self::RoCE => write!(f, "RoCE"),
Self::NVLink => write!(f, "NVLink"),
Self::NVSwitch => write!(f, "NVSwitch"),
Self::XgmiInfinityFabric => write!(f, "XGMI"),
Self::Ici => write!(f, "ICI"),
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct StorageDevice {
pub name: String,
pub kind: StorageKind,
pub bandwidth_gbps: f64,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[non_exhaustive]
pub enum StorageKind {
NVMe,
SataSsd,
Hdd,
Unknown,
}
impl std::fmt::Display for StorageKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::NVMe => write!(f, "NVMe"),
Self::SataSsd => write!(f, "SATA SSD"),
Self::Hdd => write!(f, "HDD"),
Self::Unknown => write!(f, "Unknown"),
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct RuntimeEnvironment {
pub is_docker: bool,
pub is_kubernetes: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub kubernetes_namespace: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cloud_instance: Option<CloudInstanceMeta>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CloudInstanceMeta {
pub provider: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub instance_type: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub instance_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub region: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub zone: Option<String>,
}