Skip to content

Commit

Permalink
Merge pull request #23 from adnanjpg/kill_process
Browse files Browse the repository at this point in the history
add kill_process api
  • Loading branch information
isaidsari authored May 20, 2024
2 parents 66db1dd + c69b1ba commit 425d7ad
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 58 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),

## [Unreleased] - 19-04-2024
## [0.1.2]

### Added

- v0.1.2 kill process added

## [0.1.1]

### Added

Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "remon-server"
version = "0.1.1"
version = "0.1.2"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand Down
1 change: 1 addition & 0 deletions src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub mod teapot;
pub mod update_info;
pub mod validate_token_test;
pub mod get_processes;
pub mod kill_process;

pub mod logs {
pub mod get_app_ids;
Expand Down
8 changes: 4 additions & 4 deletions src/api/get_processes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,19 @@ pub async fn get_processes(req: Request<Body>) -> Result<Response<Body>, Infalli
};

let start = std::time::Instant::now();
let processes = get_process_list();
let processes = get_process_list().await;
debug!(
"get_processes[{}] took: {:?}",
processes.len(),
start.elapsed()
);

let res = ResponseData { processes };

let response = Response::builder()
.status(hyper::StatusCode::OK)
.header("Content-Type", "application/json")
.body(Body::from(serde_json::to_string(&res).unwrap()))
.body(Body::from(
serde_json::to_string(&ResponseData { processes }).unwrap(),
))
.unwrap();

Ok(response)
Expand Down
88 changes: 88 additions & 0 deletions src/api/kill_process.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use hyper::{Body, Request, Response};
use log::debug;
use std::convert::Infallible;

use crate::{
api::{authenticate, ResponseBody},
monitor,
};

pub async fn kill_process(req: Request<Body>) -> Result<Response<Body>, Infallible> {
match authenticate(&req) {
Ok(val) => val,
Err(err) => {
return Ok(err);
}
};

// extract pid from query params
let query_str = match req.uri().query() {
Some(q) => q,
None => {
let response = Response::builder()
.status(hyper::StatusCode::BAD_REQUEST)
.header("Content-Type", "application/json")
.body(Body::from(
serde_json::to_string(&ResponseBody::Error("The query parameters are missing.".to_string()))
.unwrap(),
))
.unwrap();
return Ok(response);
}
};
let query_params: Vec<&str> = query_str.split("&").collect();
let pid = match query_params[0].split("=").collect::<Vec<&str>>().get(1) {
Some(p) => match p.parse::<u32>() {
Ok(pid) => pid,
Err(_) => {
let response = Response::builder()
.status(hyper::StatusCode::BAD_REQUEST)
.header("Content-Type", "application/json")
.body(Body::from(
serde_json::to_string(&ResponseBody::Error("Query paramter parse error.".to_string()))
.unwrap(),
))
.unwrap();
return Ok(response);
}
},
None => {
let response = Response::builder()
.status(hyper::StatusCode::BAD_REQUEST)
.header("Content-Type", "application/json")
.body(Body::from(
serde_json::to_string(&ResponseBody::Error("Invalid query parameters.".to_string()))
.unwrap(),
))
.unwrap();
return Ok(response);
}

};

match monitor::kill_process(pid).await {
Ok(_) => {
debug!("Process {} killed successfully", pid);
let response = Response::builder()
.status(hyper::StatusCode::OK)
.header("Content-Type", "application/json")
.body(Body::from(
serde_json::to_string(&ResponseBody::Success(true)).unwrap(),
))
.unwrap();
Ok(response)
}
Err(err) => {
debug!("Error killing process: {}", err);
let response = Response::builder()
.status(hyper::StatusCode::INTERNAL_SERVER_ERROR)
.header("Content-Type", "application/json")
.body(Body::from(
serde_json::to_string(&ResponseBody::Error(err.to_string()))
.unwrap(),
))
.unwrap();
Ok(response)
}
}
}
4 changes: 0 additions & 4 deletions src/logger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,6 @@ impl Write for CustomPipe {
let log_parts: Vec<&str> = log_str.splitn(4, " ").collect();
let log_level = log_parts[2];

io::stdout()
.write_all(format!("{:?}\n", log_level).as_bytes())
.unwrap();

let app_log = AppLog {
id: -1,
log_level: LogLevel::from_string(log_level),
Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ async fn req_handler(req: Request<Body>) -> Result<Response<Body>, Infallible> {
(&Method::GET, "/get-mem-status") => api::get_mem_status::get_mem_status(req).await,
(&Method::GET, "/get-disk-status") => api::get_disk_status::get_disk_status(req).await,
(&Method::GET, "/get-processes") => api::get_processes::get_processes(req).await,
(&Method::GET, "/kill-process") => api::kill_process::kill_process(req).await,
(&Method::GET, "/validate-token-test") => {
api::validate_token_test::validate_token_test(req).await
}
Expand Down
83 changes: 35 additions & 48 deletions src/monitor.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use self::models::{ProcessInfo, ServerDescription};

use log::debug;
use sysinfo::{CpuRefreshKind, ProcessRefreshKind, RefreshKind, System};
use log::{debug, error};
use sysinfo::{CpuRefreshKind, Pid, ProcessRefreshKind, RefreshKind, System};

mod config_exceeds;
pub mod models;
Expand Down Expand Up @@ -36,8 +36,8 @@ pub fn get_default_server_desc() -> ServerDescription {
ServerDescription { name, description }
}

pub fn get_process_list() -> Vec<ProcessInfo> {
let system = System::new_with_specifics(
pub async fn get_process_list() -> Vec<ProcessInfo> {
let mut system = System::new_with_specifics(
RefreshKind::new().with_processes(
ProcessRefreshKind::new()
.with_cpu()
Expand All @@ -46,6 +46,11 @@ pub fn get_process_list() -> Vec<ProcessInfo> {
),
);

system.refresh_processes();
// wait for a while to get the updated process list
tokio::time::sleep(sysinfo::MINIMUM_CPU_UPDATE_INTERVAL).await;
system.refresh_processes();

let mut processes = Vec::new();
for (pid, process) in system.processes() {
processes.push(models::ProcessInfo {
Expand All @@ -58,49 +63,31 @@ pub fn get_process_list() -> Vec<ProcessInfo> {
});
}

processes
// sort list descending order by cpu and return
processes.sort_by(|a, b| b.cpu.partial_cmp(&a.cpu).unwrap());

return processes;
}

// for testing
// TODO(isaidsari): use this in a test
// fn get_process_list_wmetrics() -> Vec<models::ProcessInfo> {
// let start_total_time = Instant::now();

// // Timing metrics for fetching process information
// let start_process_time = Instant::now();
// let system = System::new_with_specifics(
// RefreshKind::new().with_processes(
// ProcessRefreshKind::new()
// .with_cpu()
// .with_memory()
// .with_cmd(sysinfo::UpdateKind::Always),
// ),
// );
// let process_time = start_process_time.elapsed();

// // Timing metrics for processing process information
// let start_process_processing_time = Instant::now();
// let mut processes = Vec::new();
// for (pid, process) in system.processes() {
// processes.push(models::ProcessInfo {
// pid: pid.as_u32(),
// name: process.name().to_string(),
// cpu: process.cpu_usage(),
// mem: process.memory(),
// status: process.status().to_string(),
// cmd: process.cmd().to_vec(),
// });
// }
// let process_processing_time = start_process_processing_time.elapsed();

// let total_time = start_total_time.elapsed();

// debug!("get_process_list took: {:?}", total_time);
// debug!("get_process_list process took: {:?}", process_time);
// debug!(
// "get_process_list process processing took: {:?}",
// process_processing_time
// );

// processes
// }
pub async fn kill_process(pid: u32) -> Result<(), String> {
let system =
System::new_with_specifics(RefreshKind::new().with_processes(ProcessRefreshKind::new()));

let process = system.process(Pid::from_u32(pid));

match process {
Some(process) => {
debug!("Killing process with pid {} , name {}", process.pid(), process.name());
let success = process.kill();
if success {
debug!("Process with pid {} killed successfully", pid);
Ok(())
} else {
error!("Failed to kill process with pid {}", pid);
Err(format!("Failed to kill process with pid {}", pid))
}
}
None => Err(format!("Process with pid {} not found", pid)),
}

}

0 comments on commit 425d7ad

Please sign in to comment.