use crate::{config::*, error::*, profiler::*};
use std::path::PathBuf;
use std::sync::Mutex;
use tauri::{AppHandle, Manager, Runtime, State, command};
pub struct ProfilingState {
pub config: ProfilingConfig,
pub session: Mutex<Option<ProfileSession>>,
}
impl ProfilingState {
pub fn new(config: ProfilingConfig) -> Self {
Self {
config,
session: Mutex::new(None),
}
}
}
#[command]
pub async fn start_cpu_profile<R: Runtime>(
app: AppHandle<R>,
state: State<'_, ProfilingState>,
options: Option<StartOptions>,
) -> Result<PathBuf> {
let mut session_lock = state.session.lock().map_err(|_| Error::LockPoisoned)?;
if session_lock.is_some() {
return Err(Error::AlreadyRunning);
}
let options = options.unwrap_or_default();
let frequency = options.frequency.unwrap_or(state.config.frequency);
let output_dir = state
.config
.output_dir
.clone()
.or_else(|| app.path().app_data_dir().ok().map(|p| p.join("profiles")))
.ok_or_else(|| Error::PathResolution("Could not determine output directory".into()))?;
std::fs::create_dir_all(&output_dir)?;
let filename_prefix = options
.filename
.unwrap_or_else(|| state.config.filename_prefix.clone());
let output_path = generate_output_path(&output_dir, &filename_prefix);
let session = ProfileSession::start(frequency, output_path.clone())?;
*session_lock = Some(session);
log::info!("CPU profiling started at {}Hz", frequency);
Ok(output_path)
}
#[command]
pub async fn stop_cpu_profile(state: State<'_, ProfilingState>) -> Result<ProfileResult> {
let mut session_lock = state.session.lock().map_err(|_| Error::LockPoisoned)?;
let session = session_lock.take().ok_or(Error::NotRunning)?;
let result = session.stop()?;
log::info!(
"CPU profiling stopped. {} samples collected over {}ms. Flamegraph: {:?}",
result.sample_count,
result.duration_ms,
result.flamegraph_path
);
Ok(result)
}
#[command]
pub fn is_profiling(state: State<'_, ProfilingState>) -> Result<bool> {
let session_lock = state.session.lock().map_err(|_| Error::LockPoisoned)?;
Ok(session_lock.is_some())
}
#[command]
pub fn is_profiling_supported() -> bool {
cfg!(any(unix, windows))
}