Skip to content

Commit

Permalink
Implementing runtime statistics on the cli
Browse files Browse the repository at this point in the history
  • Loading branch information
bjohnson5 committed Aug 9, 2024
1 parent 002d641 commit f0dbd11
Show file tree
Hide file tree
Showing 9 changed files with 125 additions and 47 deletions.
2 changes: 1 addition & 1 deletion blast_cli/src/configure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ impl BlastTab for ConfigureTab {
2
}

fn update_runtime_data(&mut self) {
fn update_runtime_data(&mut self, _: Option<Vec<String>>, _: Option<Vec<String>>, _: Option<Vec<String>>, _: u64, _: u64, _: f64) {
return;
}

Expand Down
2 changes: 1 addition & 1 deletion blast_cli/src/load.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ impl BlastTab for LoadTab {
1
}

fn update_runtime_data(&mut self) {
fn update_runtime_data(&mut self, _: Option<Vec<String>>, _: Option<Vec<String>>, _: Option<Vec<String>>, _: u64, _: u64, _: f64) {
return;
}

Expand Down
10 changes: 9 additions & 1 deletion blast_cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,15 @@ async fn run<B: Backend>(terminal: &mut Terminal<B>, mut blast_cli: BlastCli) ->
}

if last_tick.elapsed() >= tick_rate {
current.update_runtime_data();
let blast_stats = blast_cli.blast.get_stats().await;
match blast_stats {
Some(s) => {
let events_list: Vec<String> = blast_cli.blast.get_events();
let activity_list: Vec<String> = blast_cli.blast.get_activity();
current.update_runtime_data(Some(events_list), Some(activity_list), Some(s.stats), s.frame, s.total_frames, s.success_rate);
},
None => {}
}
last_tick = Instant::now();
}
}
Expand Down
2 changes: 1 addition & 1 deletion blast_cli/src/new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ impl BlastTab for NewTab {
0
}

fn update_runtime_data(&mut self) {
fn update_runtime_data(&mut self, _: Option<Vec<String>>, _: Option<Vec<String>>, _: Option<Vec<String>>, _: u64, _: u64, _: f64) {
return;
}

Expand Down
58 changes: 26 additions & 32 deletions blast_cli/src/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,34 +20,20 @@ pub struct RunTab {
pub progress: f64,
pub window: [f64; 2],
pub success_rate_data: [(f64, f64); 21],
add: bool
pub points: usize
}

impl RunTab {
pub fn new() -> Self {
// TODO: this is a placeholder, initialize with the actual saved simulations
let mut events_list: Vec<String> = Vec::new();
let mut activity_list: Vec<String> = Vec::new();
let mut stats_list: Vec<String> = Vec::new();
events_list.push(String::from("10s OpenChannel (blast_lnd0000 --> blast_lnd0001: 2000msat)"));
events_list.push(String::from("20s CloseChannel (0)"));
activity_list.push(String::from("blast_ldk0000 --> blast_lnd0004: 2000msat, 5s"));
activity_list.push(String::from("blast_ldk0001 --> blast_lnd0005: 1000msat, 15s"));
activity_list.push(String::from("blast_ldk0002 --> blast_lnd0006: 8000msat, 10s"));
activity_list.push(String::from("blast_ldk0003 --> blast_lnd0007: 5000msat, 25s"));
stats_list.push(String::from("Number of Nodes: 15"));
stats_list.push(String::from("Total Payment Attempts: 76"));
stats_list.push(String::from("Payment Success Rate: 100%"));

Self {
events: StatefulList::with_items(events_list),
activity: StatefulList::with_items(activity_list),
stats: StatefulList::with_items(stats_list),
events: StatefulList::with_items(Vec::new()),
activity: StatefulList::with_items(Vec::new()),
stats: StatefulList::with_items(Vec::new()),
current_section: RunSection::Events,
progress: 0.0,
window: [0.0, 20.0],
success_rate_data: [(0.0, 0.0); 21],
add: true
points: 0
}
}
}
Expand Down Expand Up @@ -77,7 +63,7 @@ impl BlastTab for RunTab {
.block(Block::new().title("Simulation Progress:"))
.filled_style(Style::default().fg(Color::LightBlue))
.line_set(symbols::line::THICK)
.ratio(self.progress/100.0);
.ratio(self.progress);
frame.render_widget(line_gauge, layout[1]);

let layout2 = Layout::new(
Expand Down Expand Up @@ -244,22 +230,30 @@ impl BlastTab for RunTab {
3
}

fn update_runtime_data(&mut self) {
self.progress = self.progress + 1.0;
self.window[0] += 1.0;
self.window[1] += 1.0;
for i in 0..20 {
self.success_rate_data[i] = self.success_rate_data[i + 1];
}
fn update_runtime_data(&mut self, events: Option<Vec<String>>, activity: Option<Vec<String>>, stats: Option<Vec<String>>, frame: u64, num_frames: u64, succes_rate: f64) {
self.events.items = events.unwrap_or(Vec::new());
self.activity.items = activity.unwrap_or(Vec::new());
self.stats.items = stats.unwrap_or(Vec::new());

if self.add {
self.success_rate_data[20] = (self.window[1], self.success_rate_data[19].1 + 5.0);
if frame >= num_frames {
self.progress = 1.0;
} else {
self.success_rate_data[20] = (self.window[1], self.success_rate_data[19].1 - 5.0);
self.progress = frame as f64 / num_frames as f64;
}

if self.window[1] % 10.0 == 0.0 {
self.add = !self.add;
if self.points <= 20 {
self.window[0] = 0.0;
self.window[1] = 20.0;
self.success_rate_data[self.points] = (frame as f64, succes_rate);
self.points += 1;
} else {
self.window[0] = frame as f64 - 20.0;
self.window[1] = frame as f64;
for i in 0..20 {
self.success_rate_data[i] = self.success_rate_data[i + 1];
}

self.success_rate_data[20] = (frame as f64, succes_rate);
}
}

Expand Down
2 changes: 1 addition & 1 deletion blast_cli/src/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ pub trait BlastTab {
fn close(&mut self);
fn process(&mut self, key: KeyEvent) -> ProcessResult;
fn get_index(&self) -> usize;
fn update_runtime_data(&mut self);
fn update_runtime_data(&mut self, events: Option<Vec<String>>, activity: Option<Vec<String>>, stats: Option<Vec<String>>, frame: u64, num_frames: u64, succes_rate: f64);
fn update_config_data(&mut self, data1: Option<Vec<String>>, data2: Option<Vec<String>>, data3: Option<Vec<String>>, data4: Option<Vec<String>>);
fn esc_operation(&mut self) -> ProcessResult;
}
43 changes: 34 additions & 9 deletions blast_core/src/blast_event_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use std::sync::Arc;
use std::fmt;
use std::collections::HashMap;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::atomic::{AtomicBool, Ordering, AtomicU64};
use std::time::Duration;
use std::fs::File;
use std::io::BufReader;
Expand Down Expand Up @@ -31,6 +31,7 @@ pub struct BlastEventManager {
running: Arc<AtomicBool>,
events: HashMap<u64,Vec<BlastEvent>>,
bitcoin_rpc: Option<Client>,
frame_number: Arc<AtomicU64>
}

impl Clone for BlastEventManager {
Expand All @@ -41,7 +42,8 @@ impl Clone for BlastEventManager {
bitcoin_rpc: match Client::new(crate::BITCOIND_RPC, Auth::UserPass(String::from(crate::BITCOIND_USER), String::from(crate::BITCOIND_PASS))) {
Ok(c) => Some(c),
Err(_) => None
}
},
frame_number: self.frame_number.clone()
}
}
}
Expand All @@ -55,7 +57,8 @@ impl BlastEventManager {
bitcoin_rpc: match Client::new(crate::BITCOIND_RPC, Auth::UserPass(String::from(crate::BITCOIND_USER), String::from(crate::BITCOIND_PASS))) {
Ok(c) => Some(c),
Err(_) => None
}
},
frame_number: Arc::new(AtomicU64::new(0))
};

event_manager
Expand All @@ -64,26 +67,35 @@ impl BlastEventManager {
/// Start the event thread
pub async fn start(&mut self, sender: Sender<BlastEvent>) -> Result<(), Error> {
self.running.store(true, Ordering::SeqCst);
let mut frame_num = 0;
self.frame_number.store(0, Ordering::SeqCst);
loop {
// Make sure the blast simulation is still running and exit when it has shutdown
if !self.running.load(Ordering::SeqCst) {
self.frame_number.store(0, Ordering::SeqCst);
break;
}

log::info!("BlastEventManager running frame number {}", frame_num);
let frame = self.frame_number.load(Ordering::SeqCst);

if frame >= crate::TOTAL_FRAMES {
self.running.store(false, Ordering::SeqCst);
self.frame_number.store(0, Ordering::SeqCst);
break;
}

log::info!("BlastEventManager running frame number {}", frame);

// If it is time to mine new bocks, use the bitcoind RPC client to generate new blocks
if frame_num % MINE_RATE == 0 {
if frame % MINE_RATE == 0 {
match crate::mine_blocks(&mut self.bitcoin_rpc, BLOCKS_PER_MINE) {
Ok(_) => {},
Err(e) => return Err(anyhow::Error::msg(e)),
}
}

// If there are events to run this frame, get the list of events and send them
if self.events.contains_key(&frame_num) {
let current_events = &self.events[&frame_num];
if self.events.contains_key(&frame) {
let current_events = &self.events[&frame];
let current_events_iter = current_events.iter();
for e in current_events_iter {
log::info!("BlastEventManager sending event {}", e);
Expand All @@ -94,7 +106,7 @@ impl BlastEventManager {
}

// Wait until the next frame
frame_num = frame_num + 1;
self.frame_number.fetch_add(1, Ordering::SeqCst);
tokio::time::sleep(Duration::from_secs(FRAME_RATE)).await;
}
Ok(())
Expand All @@ -106,6 +118,14 @@ impl BlastEventManager {
self.running.store(false, Ordering::SeqCst);
}

/// Reset the event manager when the current blast network is shutdown
pub fn reset(&mut self) {
log::info!("BlastEventManager resetting.");
self.running.store(false, Ordering::SeqCst);
self.events.clear();
self.frame_number.store(0, Ordering::SeqCst);
}

/// Get all of the events in json format
pub fn get_event_json(&self) -> Result<String, String> {
match serde_json::to_string(&self.events) {
Expand Down Expand Up @@ -217,6 +237,11 @@ impl BlastEventManager {
events
}

/// Get the current frame number
pub fn get_frame_number(&self) -> u64 {
self.frame_number.load(Ordering::SeqCst)
}

/// Validate that the correct args were given
fn validate_args(&self, args: Option<Vec<String>>, event: BlastEvent) -> Result<Vec<String>, String> {
match args {
Expand Down
19 changes: 18 additions & 1 deletion blast_core/src/blast_simln_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ impl BlastSimLnManager {
let sim = Simulation::new(
clients,
validated_activities,
None,
Some(crate::TOTAL_FRAMES as u32),
EXPECTED_PAYMENT_AMOUNT,
ACTIVITY_MULTIPLIER,
Some(WriteResults {
Expand Down Expand Up @@ -255,6 +255,13 @@ impl BlastSimLnManager {
};
}

/// Reset the simln manager when the current blast network is shutdown
pub fn reset(&mut self) {
log::info!("BlastEventManager resetting.");
self.data.activity.clear();
self.data.nodes.clear();
}

/// Get all the nodes
pub fn get_nodes(&self) -> Vec<String> {
let mut ids = Vec::<String>::new();
Expand All @@ -267,4 +274,14 @@ impl BlastSimLnManager {
}
ids
}

pub fn get_success_rate(&self) -> f64 {
// TODO implement
30.0
}

pub fn get_attempts(&self) -> u64 {
// TODO implement
53
}
}
34 changes: 34 additions & 0 deletions blast_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ pub const BITCOIND_PASS: &str = "pass";
/// The directory to save simulations in
pub const BLAST_SIM_DIR: &str = ".blast/blast_sims";

/// TODO: make this configurable
pub const TOTAL_FRAMES: u64 = 40;

/// The Blast struct is the main public interface that can be used to run a simulation.
pub struct Blast {
blast_model_manager: BlastModelManager,
Expand All @@ -63,6 +66,14 @@ pub struct BlastNetwork {
model_map: HashMap<String, i32>
}

/// The BlastStats struct holds statistics about the currently running simulation
pub struct BlastStats {
pub total_frames: u64,
pub frame: u64,
pub success_rate: f64,
pub stats: Vec<String>
}

impl Blast {
/// Create a new Blast object with a new BlastModelManager.
pub fn new() -> Self {
Expand Down Expand Up @@ -141,6 +152,9 @@ impl Blast {
Err(e) => return Err(format!("Could not stop bitcoind: {}", e)),
};

self.blast_event_manager.reset();
self.blast_simln_manager.reset();

Ok(())
}

Expand Down Expand Up @@ -419,6 +433,26 @@ impl Blast {
self.blast_simln_manager.get_nodes()
}

/// Get some basic simulation stats
pub async fn get_stats(&mut self) -> Option<BlastStats> {
let f = self.blast_event_manager.get_frame_number();
if f == 0 {
None
} else {
let sr = self.blast_simln_manager.get_success_rate();
let pa = self.blast_simln_manager.get_attempts();
let mut stats_list: Vec<String> = Vec::new();
stats_list.push(format!("Number of Nodes: {}", self.get_nodes().len()));
stats_list.push(format!("Number of Channels: {}", self.get_channels().await.len()));
stats_list.push(format!("Number of Events : {}", self.get_events().len()));
stats_list.push(format!("Payment Attempts: {}", pa));
stats_list.push(format!("Payment Success Rate: {}", sr));

let stats = BlastStats{total_frames: TOTAL_FRAMES, frame: f, success_rate: sr, stats: stats_list};
Some(stats)
}
}

/// Get the public key of a node
pub async fn get_pub_key(&mut self, node_id: String) -> Result<String, String> {
match self.blast_model_manager.get_pub_key(node_id).await {
Expand Down

0 comments on commit f0dbd11

Please sign in to comment.