Skip to content

Commit 887c34d

Browse files
authored
[amazon_rose_forest] add stats metrics (#46)
removed and replaced nonfunctional placeholders for metrics with an initial implementation along with test(s)
1 parent 7b1f808 commit 887c34d

3 files changed

Lines changed: 47 additions & 8 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ blake3 = { version = "1", optional = true }
3232
serde_bytes = "0.11"
3333
wide = "0.7"
3434
warp = "0.3"
35+
sysinfo = "0.28"
3536

3637
# Holochain dependencies
3738
hdk = "0.1.0"

src/server/mod.rs

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ use anyhow::{anyhow, Result};
22
use prometheus::{Encoder, Registry, TextEncoder};
33
use std::net::SocketAddr;
44
use std::sync::Arc;
5+
use std::time::Instant;
6+
use sysinfo::{get_current_pid, ProcessExt, System, SystemExt};
57
use tokio::sync::RwLock;
68
use tokio::task::JoinHandle;
79
use tracing::{debug, error, info, warn};
@@ -54,6 +56,7 @@ pub struct Server {
5456
runtime: Option<Arc<Runtime>>,
5557
shard_manager: Option<Arc<ShardManager>>,
5658
server_handle: RwLock<Option<JoinHandle<Result<()>>>>,
59+
start_time: Instant,
5760
}
5861

5962
impl Server {
@@ -70,6 +73,7 @@ impl Server {
7073
runtime,
7174
shard_manager,
7275
server_handle: RwLock::new(None),
76+
start_time: Instant::now(),
7377
}
7478
}
7579

@@ -78,12 +82,7 @@ impl Server {
7882
let addr = format!("{}:{}", self.config.address, self.config.port);
7983
let addr: SocketAddr = addr.parse()?;
8084

81-
let metrics = self.metrics.clone();
82-
let config = self.config.clone();
83-
let runtime = self.runtime.clone();
84-
let shard_manager = self.shard_manager.clone();
85-
86-
let server = warp::serve(self.routes(metrics, config, runtime, shard_manager));
85+
let server = warp::serve(self.filter());
8786

8887
info!("Starting server on {}", addr);
8988

@@ -122,13 +121,27 @@ impl Server {
122121
Ok(())
123122
}
124123

124+
/// Get the Warp filter for this server
125+
pub fn filter(
126+
&self,
127+
) -> impl warp::Filter<Extract = impl warp::Reply, Error = warp::Rejection> + Clone {
128+
self.routes(
129+
self.metrics.clone(),
130+
self.config.clone(),
131+
self.runtime.clone(),
132+
self.shard_manager.clone(),
133+
self.start_time,
134+
)
135+
}
136+
125137
/// Create the server routes
126138
fn routes(
127139
&self,
128140
metrics: Arc<MetricsCollector>,
129141
config: ServerConfig,
130142
runtime: Option<Arc<Runtime>>,
131143
shard_manager: Option<Arc<ShardManager>>,
144+
start_time: Instant,
132145
) -> impl warp::Filter<Extract = impl warp::Reply, Error = warp::Rejection> + Clone {
133146
let health_route = warp::path("health").map(move || {
134147
debug!("Health check request received");
@@ -182,10 +195,14 @@ impl Server {
182195
let stats_route = warp::path(api_path)
183196
.and(warp::path("stats"))
184197
.map(move || {
198+
let mut sys = System::new();
199+
let pid = get_current_pid().unwrap();
200+
sys.refresh_process(pid);
201+
let mem_mb = sys.process(pid).map(|p| p.memory() / 1024).unwrap_or(0);
185202
let stats = serde_json::json!({
186203
"version": crate::VERSION,
187-
"uptime_seconds": 0, // TODO: Add actual uptime
188-
"memory_usage_mb": 0, // TODO: Add actual memory usage
204+
"uptime_seconds": start_time.elapsed().as_secs(),
205+
"memory_usage_mb": mem_mb,
189206
});
190207

191208
warp::reply::json(&stats).into_response()

tests/server_stats.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
use amazon_rose_forest::core::metrics::MetricsCollector;
2+
use amazon_rose_forest::server::{Server, ServerConfig};
3+
use std::sync::Arc;
4+
use warp::http::StatusCode;
5+
6+
#[tokio::test]
7+
async fn stats_returns_metrics() {
8+
let metrics = Arc::new(MetricsCollector::new());
9+
let server = Server::new(ServerConfig::default(), metrics, None, None);
10+
let filter = server.filter();
11+
12+
let res = warp::test::request()
13+
.method("GET")
14+
.path("/api/stats")
15+
.reply(&filter)
16+
.await;
17+
assert_eq!(res.status(), StatusCode::OK);
18+
let body: serde_json::Value = serde_json::from_slice(res.body()).unwrap();
19+
assert_eq!(body["version"], amazon_rose_forest::VERSION);
20+
assert!(body["uptime_seconds"].as_u64().unwrap() >= 0);
21+
}

0 commit comments

Comments
 (0)