use crate::mock::metrics::GpuMetrics;
use all_smi::traits::mock_generator::{
MockConfig, MockData, MockGenerator, MockPlatform, MockResult,
};
use rand::{RngExt, rng};
pub struct RebellionsMockGenerator {
gpu_name: String,
instance_name: String,
}
impl RebellionsMockGenerator {
pub fn new(gpu_name: Option<String>, instance_name: String) -> Self {
Self {
gpu_name: gpu_name.unwrap_or_else(|| "Rebellions ATOM".to_string()),
instance_name,
}
}
pub fn build_rebellions_template(&self, gpus: &[GpuMetrics]) -> String {
let mut template = String::with_capacity(3072);
super::common::add_basic_gpu_metrics(
&mut template,
&self.gpu_name,
&self.instance_name,
gpus,
);
self.add_npu_metrics(&mut template, gpus);
self.add_core_metrics(&mut template, gpus);
super::common::add_system_metrics(&mut template, &self.instance_name);
self.add_driver_metrics(&mut template);
template
}
fn add_npu_metrics(&self, template: &mut String, gpus: &[GpuMetrics]) {
template.push_str("# HELP all_smi_npu_core_utilization NPU core utilization percentage\n");
template.push_str("# TYPE all_smi_npu_core_utilization gauge\n");
for (i, gpu) in gpus.iter().enumerate() {
let labels = format!(
"npu=\"{}\", instance=\"{}\", npu_uuid=\"{}\", npu_index=\"{i}\"",
self.gpu_name, self.instance_name, gpu.uuid
);
template.push_str(&format!(
"all_smi_npu_core_utilization{{{labels}}} {{{{NPU_UTIL_{i}}}}}\n"
));
}
template.push_str("# HELP all_smi_npu_memory_bandwidth_percent NPU memory bandwidth utilization percentage\n");
template.push_str("# TYPE all_smi_npu_memory_bandwidth_percent gauge\n");
for (i, gpu) in gpus.iter().enumerate() {
let labels = format!(
"npu=\"{}\", instance=\"{}\", npu_uuid=\"{}\", npu_index=\"{i}\"",
self.gpu_name, self.instance_name, gpu.uuid
);
template.push_str(&format!(
"all_smi_npu_memory_bandwidth_percent{{{labels}}} {{{{NPU_BW_{i}}}}}\n"
));
}
}
fn add_core_metrics(&self, template: &mut String, gpus: &[GpuMetrics]) {
template.push_str("# HELP all_smi_npu_cores_active Number of active NPU cores\n");
template.push_str("# TYPE all_smi_npu_cores_active gauge\n");
for (i, gpu) in gpus.iter().enumerate() {
let labels = format!(
"npu=\"{}\", instance=\"{}\", npu_uuid=\"{}\", npu_index=\"{i}\"",
self.gpu_name, self.instance_name, gpu.uuid
);
template.push_str(&format!(
"all_smi_npu_cores_active{{{labels}}} {{{{CORES_ACTIVE_{i}}}}}\n"
));
}
template.push_str("# HELP all_smi_npu_cores_total Total number of NPU cores\n");
template.push_str("# TYPE all_smi_npu_cores_total gauge\n");
for (i, gpu) in gpus.iter().enumerate() {
let labels = format!(
"npu=\"{}\", instance=\"{}\", npu_uuid=\"{}\", npu_index=\"{i}\"",
self.gpu_name, self.instance_name, gpu.uuid
);
template.push_str(&format!(
"all_smi_npu_cores_total{{{labels}}} 16\n" ));
}
}
fn add_driver_metrics(&self, template: &mut String) {
template.push_str("# HELP all_smi_rebellions_driver_version Rebellions driver version\n");
template.push_str("# TYPE all_smi_rebellions_driver_version gauge\n");
template.push_str(&format!(
"all_smi_rebellions_driver_version{{instance=\"{}\"}} 1\n",
self.instance_name
));
}
pub fn render_rebellions_response(&self, template: &str, gpus: &[GpuMetrics]) -> String {
let mut response = template.to_string();
let mut rng = rng();
response = super::common::render_basic_gpu_metrics(response, gpus);
for (i, gpu) in gpus.iter().enumerate() {
let npu_util = (gpu.utilization + rng.random_range(-5.0..5.0)).clamp(0.0, 100.0);
response =
response.replace(&format!("{{{{NPU_UTIL_{i}}}}}"), &format!("{npu_util:.2}"));
let mem_bw = rng.random_range(20.0..95.0);
response = response.replace(&format!("{{{{NPU_BW_{i}}}}}"), &format!("{mem_bw:.2}"));
let cores_active = if gpu.utilization > 80.0 {
16 } else if gpu.utilization > 50.0 {
12
} else if gpu.utilization > 20.0 {
8
} else if gpu.utilization > 0.0 {
4
} else {
0
};
response = response.replace(
&format!("{{{{CORES_ACTIVE_{i}}}}}"),
&cores_active.to_string(),
);
}
response = super::common::render_system_metrics(response);
response
}
}
impl MockGenerator for RebellionsMockGenerator {
fn generate(&self, config: &MockConfig) -> MockResult<MockData> {
self.validate_config(config)?;
let gpus = super::common::generate_gpu_metrics(config.device_count, 24_000_000_000); let template = self.build_rebellions_template(&gpus);
let response = self.render_rebellions_response(&template, &gpus);
Ok(MockData {
response,
content_type: "text/plain; version=0.0.4".to_string(),
timestamp: chrono::Utc::now(),
platform: MockPlatform::Custom("Rebellions".to_string()),
})
}
fn generate_template(&self, config: &MockConfig) -> MockResult<String> {
self.validate_config(config)?;
let gpus = super::common::generate_empty_gpu_metrics(config.device_count, 24_000_000_000);
Ok(self.build_rebellions_template(&gpus))
}
fn render(&self, template: &str, _config: &MockConfig) -> MockResult<String> {
Ok(template.to_string())
}
fn platform(&self) -> MockPlatform {
MockPlatform::Custom("Rebellions".to_string())
}
}