diff --git a/src/main.rs b/src/main.rs index f005ca2..2a8598c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,11 +9,10 @@ use tokio::net::{UnixListener, UnixStream}; use tokio::sync::Mutex; use tracing::{error, info, debug}; use sqlx::{sqlite::SqlitePoolOptions, sqlite::SqliteConnectOptions, Pool, Sqlite, Row}; -use chrono::Utc; +use chrono::{Utc, DateTime}; use std::str::FromStr; use std::fmt; - #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(u64)] enum ActivityType { @@ -81,7 +80,6 @@ enum Commands { } #[derive(Debug, Deserialize, Serialize)] -#[serde(rename_all = "camelCase")] struct NixEvent { action: String, id: u64, @@ -96,20 +94,20 @@ struct NixEvent { parent: u64, } -struct State { - active_activities: HashMap, - pool: Pool, -} - struct Activity { id: u64, event_type: u64, text: String, - start_time: chrono::DateTime, + start_time: DateTime, fields: Vec, result_fields: Vec, } +struct State { + active_activities: HashMap, + pool: Pool, +} + #[tokio::main] async fn main() -> Result<()> { tracing_subscriber::fmt::init(); @@ -207,7 +205,9 @@ async fn process_event(event: NixEvent, state: &Arc>) -> Result<()> match event.action.as_str() { "start" => { - info!(id = event.id, type = event.event_type, "Activity started: {}", event.text); + let act_type = ActivityType::from(event.event_type); + info!(id = event.id, %act_type, "Activity started: {}", event.text); + s.active_activities.insert(event.id, Activity { id: event.id, event_type: event.event_type, @@ -218,7 +218,6 @@ async fn process_event(event: NixEvent, state: &Arc>) -> Result<()> }); } "result" => { - debug!(id = event.id, "Received result for activity"); if let Some(activity) = s.active_activities.get_mut(&event.id) { activity.result_fields = event.fields; } @@ -227,9 +226,11 @@ async fn process_event(event: NixEvent, state: &Arc>) -> Result<()> if let Some(activity) = s.active_activities.remove(&event.id) { let end_time = Utc::now(); let duration = end_time.signed_duration_since(activity.start_time); + let act_type = ActivityType::from(activity.event_type); info!( id = activity.id, + %act_type, duration_ms = duration.num_milliseconds(), "Activity finished: {}", activity.text @@ -238,16 +239,14 @@ async fn process_event(event: NixEvent, state: &Arc>) -> Result<()> let mut drv_path = None; let mut cache_url = None; - // Expand detection to include more activity types - match activity.event_type { - // 101: CopyPath, 102: FileTransfer, 103: Realise, 105: Build - 101 | 102 | 103 | 105 => { + match act_type { + ActivityType::CopyPath | ActivityType::FileTransfer | + ActivityType::Realise | ActivityType::Builds | ActivityType::Build => { drv_path = activity.fields.get(0) .and_then(|v| v.as_str()) .map(|s| s.to_string()); } - // 108: Substitute - 108 => { + ActivityType::Substitute => { drv_path = activity.fields.get(0) .and_then(|v| v.as_str()) .map(|s| s.to_string()); @@ -304,27 +303,16 @@ async fn show_stats(pool: Pool) -> Result<()> { return Ok(()); } - // Header println!("{:<20} {:>10} {:>15} {:>15}", "Activity", "Count", "Avg Time", "Total Time"); println!("{:-<20} {:->10} {:->15} {:->15}", "", "", "", ""); for row in rows { - let ty: i64 = row.get("event_type"); + let ty_code: i64 = row.get("event_type"); let count: i64 = row.get("count"); let avg: f64 = row.get("avg_ms"); let total: i64 = row.get("total_ms"); - let label = match ty { - 0 => "Log/Output", - 101 => "Copy Path", - 102 => "File Transfer", - 103 => "Realise", - 104 => "Copy Paths", - 105 => "Build", - 108 => "Substitute", - 109 => "Query Info", - _ => "Other", - }; + let label = ActivityType::from(ty_code as u64).to_string(); println!( "{:<20} {:>10} {:>14.2}s {:>14.2}s", @@ -335,7 +323,6 @@ async fn show_stats(pool: Pool) -> Result<()> { ); } - // Top 5 most "expensive" individual events println!("\nTop 5 Most Time-Consuming Tasks:"); println!("{:<12} {:<15} {}", "Duration", "Type", "Resource/Text"); println!("{:-<12} {:-<15} {:-<30}", "", "", ""); @@ -352,13 +339,14 @@ async fn show_stats(pool: Pool) -> Result<()> { for row in top_events { let dur: i64 = row.get("duration_ms"); - let ty: i64 = row.get("event_type"); + let ty_code: i64 = row.get("event_type"); + let label = ActivityType::from(ty_code as u64).to_string(); let path: String = row.get::, _>("drv_path") .or_else(|| row.get::, _>("text")) .unwrap_or_else(|| "unknown".to_string()); - let short_path = if path.len() > 50 { - format!("...{}", &path[path.len()-47..]) + let short_path = if path.len() > 60 { + format!("...{}", &path[path.len()-57..]) } else { path }; @@ -366,7 +354,7 @@ async fn show_stats(pool: Pool) -> Result<()> { println!( "{:>10.2}s {:<15} {}", dur as f64 / 1000.0, - match ty { 105 => "Build", 108 => "Subst", 102 => "Xfer", 103 => "Realise", _ => "Other" }, + label, short_path ); }