mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-21 05:58:13 +02:00
Lot 4 : /api/ram et /api/vram servis par Rust
RAM lue dans /proc/meminfo, jauges des cartes par un seul nvidia-smi partagé entre tous les onglets (cache de deux secondes, une minute quand nvidia-smi est absent), comme le Go. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
dc6a001581
commit
b98ee5c3e7
2 files changed
+36
-1
No files matched your search
+21
-1
@@ -14,6 +14,7 @@ use crate::auth::{self, HostEnv, InternalClient};
|
|||||||
use crate::engine;
|
use crate::engine;
|
||||||
use crate::proxy::Body;
|
use crate::proxy::Body;
|
||||||
use crate::store::{BK_STATE, Store};
|
use crate::store::{BK_STATE, Store};
|
||||||
|
use crate::sysinfo;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
/// Ce dont les routes ont besoin, partagé par toutes les connexions.
|
/// Ce dont les routes ont besoin, partagé par toutes les connexions.
|
||||||
@@ -39,7 +40,10 @@ impl Ctx {
|
|||||||
|
|
||||||
/// Cette route est-elle servie par Rust ?
|
/// Cette route est-elle servie par Rust ?
|
||||||
pub fn handles(_method: &Method, path: &str) -> bool {
|
pub fn handles(_method: &Method, path: &str) -> bool {
|
||||||
matches!(path, "/api/ping" | "/api/config" | "/api/engine/cmdline")
|
matches!(
|
||||||
|
path,
|
||||||
|
"/api/ping" | "/api/config" | "/api/engine/cmdline" | "/api/ram" | "/api/vram"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn serve(ctx: &Ctx, req: Request<Incoming>) -> Response<Body> {
|
pub async fn serve(ctx: &Ctx, req: Request<Incoming>) -> Response<Body> {
|
||||||
@@ -65,6 +69,22 @@ pub async fn serve(ctx: &Ctx, req: Request<Incoming>) -> Response<Body> {
|
|||||||
let cmdline = ctx.store.get_str(BK_STATE, "engine_cmdline").await;
|
let cmdline = ctx.store.get_str(BK_STATE, "engine_cmdline").await;
|
||||||
auth::json(StatusCode::OK, &json!({ "ok": true, "cmdline": cmdline }))
|
auth::json(StatusCode::OK, &json!({ "ok": true, "cmdline": cmdline }))
|
||||||
}
|
}
|
||||||
|
// RAM système en Mo (total = 0 : l'UI masque le bloc).
|
||||||
|
"/api/ram" => {
|
||||||
|
let (used, total) = sysinfo::ram_usage_mb();
|
||||||
|
auth::json(StatusCode::OK, &json!({ "used": used, "total": total }))
|
||||||
|
}
|
||||||
|
// Jauges des cartes : un seul nvidia-smi partagé par tous les onglets.
|
||||||
|
"/api/vram" => {
|
||||||
|
let gpus: Vec<_> = sysinfo::gpu_stats_cached()
|
||||||
|
.await
|
||||||
|
.into_iter()
|
||||||
|
.map(|g| {
|
||||||
|
json!({ "name": g.name, "used": g.used, "total": g.total, "util": g.util, "temp": g.temp })
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
auth::json(StatusCode::OK, &json!(gpus))
|
||||||
|
}
|
||||||
_ => not_found(),
|
_ => not_found(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,3 +65,18 @@ async fn routes_portees_protegees_par_la_cle() {
|
|||||||
assert_eq!(code, StatusCode::OK, "{path}");
|
assert_eq!(code, StatusCode::OK, "{path}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn ram_et_vram() {
|
||||||
|
let t = tempfile::tempdir().unwrap();
|
||||||
|
let (f, go, _stop) = fakego::start(t.path().into()).await;
|
||||||
|
let (code, _, body) = fakego::get(f, "/api/ram", &[]).await;
|
||||||
|
assert_eq!(code, StatusCode::OK);
|
||||||
|
let v: serde_json::Value = serde_json::from_slice(&body).unwrap();
|
||||||
|
assert!(v["used"].is_i64() && v["total"].is_i64(), "{v}");
|
||||||
|
let (code, _, body) = fakego::get(f, "/api/vram", &[]).await;
|
||||||
|
assert_eq!(code, StatusCode::OK);
|
||||||
|
let v: serde_json::Value = serde_json::from_slice(&body).unwrap();
|
||||||
|
assert!(v.is_array(), "{v}");
|
||||||
|
assert!(go.relayed.lock().unwrap().is_empty());
|
||||||
|
}
|
||||||
Reference in new issue
Block a user