Skip to content

Commit c3bdb12

Browse files
committed
feat: add resource utilization middleware to monitor CPU and memory usage
1 parent 97e5d42 commit c3bdb12

File tree

3 files changed

+79
-1
lines changed

3 files changed

+79
-1
lines changed

src/handlers/http/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ pub mod cluster;
3636
pub mod correlation;
3737
pub mod health_check;
3838
pub mod ingest;
39+
pub mod resource_check;
3940
mod kinesis;
4041
pub mod llm;
4142
pub mod logstream;

src/handlers/http/modal/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ use crate::{
4545
utils::get_node_id,
4646
};
4747

48-
use super::{audit, cross_origin_config, health_check, API_BASE_PATH, API_VERSION};
48+
use super::{audit, cross_origin_config, health_check, resource_check, API_BASE_PATH, API_VERSION};
4949

5050
pub mod ingest;
5151
pub mod ingest_server;
@@ -113,6 +113,7 @@ pub trait ParseableServer {
113113
.wrap(prometheus.clone())
114114
.configure(|config| Self::configure_routes(config, oidc_client.clone()))
115115
.wrap(from_fn(health_check::check_shutdown_middleware))
116+
.wrap(from_fn(resource_check::check_resource_utilization_middleware))
116117
.wrap(from_fn(audit::audit_log_middleware))
117118
.wrap(actix_web::middleware::Logger::default())
118119
.wrap(actix_web::middleware::Compress::default())

src/handlers/http/resource_check.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Parseable Server (C) 2022 - 2024 Parseable, Inc.
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU Affero General Public License as
6+
* published by the Free Software Foundation, either version 3 of the
7+
* License, or (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU Affero General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU Affero General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*
17+
*/
18+
19+
use actix_web::{
20+
body::MessageBody,
21+
dev::{ServiceRequest, ServiceResponse},
22+
error::Error,
23+
error::ErrorServiceUnavailable,
24+
middleware::Next,
25+
};
26+
use sysinfo::System;
27+
use tracing::warn;
28+
29+
const CPU_UTILIZATION_THRESHOLD: f32 = 50.0;
30+
const MEMORY_UTILIZATION_THRESHOLD: f32 = 50.0;
31+
32+
/// Middleware to check system resource utilization before processing requests
33+
/// Returns 503 Service Unavailable if CPU or memory usage exceeds thresholds
34+
pub async fn check_resource_utilization_middleware(
35+
req: ServiceRequest,
36+
next: Next<impl MessageBody>,
37+
) -> Result<ServiceResponse<impl MessageBody>, Error> {
38+
39+
let mut sys = System::new_all();
40+
sys.refresh_cpu_usage();
41+
sys.refresh_memory();
42+
43+
let used_memory = sys.used_memory() as f32;
44+
let total_memory = sys.total_memory() as f32;
45+
46+
// Check memory utilization
47+
if total_memory > 0.0 {
48+
let memory_usage = (used_memory / total_memory) * 100.0;
49+
if memory_usage > MEMORY_UTILIZATION_THRESHOLD {
50+
let error_msg = format!("Memory is over-utilized: {:.1}%", memory_usage);
51+
warn!(
52+
"Rejecting request to {} due to high memory usage: {:.1}% (threshold: {:.1}%)",
53+
req.path(),
54+
memory_usage,
55+
MEMORY_UTILIZATION_THRESHOLD
56+
);
57+
return Err(ErrorServiceUnavailable(error_msg));
58+
}
59+
}
60+
61+
// Check CPU utilization
62+
let cpu_usage = sys.global_cpu_usage();
63+
if cpu_usage > CPU_UTILIZATION_THRESHOLD {
64+
let error_msg = format!("CPU is over-utilized: {:.1}%", cpu_usage);
65+
warn!(
66+
"Rejecting request to {} due to high CPU usage: {:.1}% (threshold: {:.1}%)",
67+
req.path(),
68+
cpu_usage,
69+
CPU_UTILIZATION_THRESHOLD
70+
);
71+
return Err(ErrorServiceUnavailable(error_msg));
72+
}
73+
74+
// Continue processing the request if resource utilization is within limits
75+
next.call(req).await
76+
}

0 commit comments

Comments
 (0)