* Update some Labrinth dependencies * Update some Labrinth dependencies * Update some Labrinth dependencies * Update zip in Labrinth * Update itertools in Labrinth * Update validator in labrinth * Update thiserror in labrinth * Update rust_decimal, redis, and deadpool-redis in labrinth * Update totp-rs and spdx in labrinth * Update maxminddb and tar in labrinth * Update sentry and sentry-actix in labrinth * Update image in labrinth * Update lettre in labrinth * Update derive-new and rust_iso3166 in labrinth * Update async-stripe and json-patch in labrinth * Update clap and iana-time-zone in labrinth * Update labrinth to Rust 2024 * Cargo fmt * Just do a full cargo update * Update daedelus to Rust 2024 * Update daedelus_client to Rust 2024 * Set the formatting edition to 2024 * Fix formatting IntelliJ messed up my formatting
88 lines
2.6 KiB
Rust
88 lines
2.6 KiB
Rust
use crate::routes::ApiError;
|
|
use crate::util::cors::default_cors;
|
|
use crate::util::guards::admin_key_guard;
|
|
use actix_web::{HttpResponse, get};
|
|
use prometheus::{IntGauge, Registry};
|
|
use std::time::Duration;
|
|
|
|
pub fn config(cfg: &mut actix_web::web::ServiceConfig) {
|
|
cfg.service(
|
|
actix_web::web::scope("/debug")
|
|
.wrap(default_cors())
|
|
.service(heap)
|
|
.service(flame_graph),
|
|
);
|
|
}
|
|
|
|
#[get("pprof/heap", guard = "admin_key_guard")]
|
|
pub async fn heap() -> Result<HttpResponse, ApiError> {
|
|
let mut prof_ctl = jemalloc_pprof::PROF_CTL.as_ref().unwrap().lock().await;
|
|
require_profiling_activated(&prof_ctl)?;
|
|
let pprof = prof_ctl
|
|
.dump_pprof()
|
|
.map_err(|err| ApiError::InvalidInput(err.to_string()))?;
|
|
|
|
Ok(HttpResponse::Ok()
|
|
.content_type("application/octet-stream")
|
|
.body(pprof))
|
|
}
|
|
|
|
#[get("pprof/heap/flamegraph", guard = "admin_key_guard")]
|
|
pub async fn flame_graph() -> Result<HttpResponse, ApiError> {
|
|
let mut prof_ctl = jemalloc_pprof::PROF_CTL.as_ref().unwrap().lock().await;
|
|
require_profiling_activated(&prof_ctl)?;
|
|
let svg = prof_ctl
|
|
.dump_flamegraph()
|
|
.map_err(|err| ApiError::InvalidInput(err.to_string()))?;
|
|
|
|
Ok(HttpResponse::Ok().content_type("image/svg+xml").body(svg))
|
|
}
|
|
|
|
fn require_profiling_activated(
|
|
prof_ctl: &jemalloc_pprof::JemallocProfCtl,
|
|
) -> Result<(), ApiError> {
|
|
if prof_ctl.activated() {
|
|
Ok(())
|
|
} else {
|
|
Err(ApiError::InvalidInput(
|
|
"Profiling is not activated".to_string(),
|
|
))
|
|
}
|
|
}
|
|
|
|
pub fn jemalloc_mmeory_stats(
|
|
registry: &Registry,
|
|
) -> Result<(), prometheus::Error> {
|
|
let allocated_mem = IntGauge::new(
|
|
"labrinth_memory_allocated",
|
|
"Labrinth allocated memory",
|
|
)?;
|
|
let resident_mem =
|
|
IntGauge::new("labrinth_resident_memory", "Labrinth resident memory")?;
|
|
|
|
registry.register(Box::new(allocated_mem.clone()))?;
|
|
registry.register(Box::new(resident_mem.clone()))?;
|
|
|
|
tokio::spawn(async move {
|
|
let e = tikv_jemalloc_ctl::epoch::mib().unwrap();
|
|
let allocated = tikv_jemalloc_ctl::stats::allocated::mib().unwrap();
|
|
let resident = tikv_jemalloc_ctl::stats::resident::mib().unwrap();
|
|
|
|
loop {
|
|
e.advance().unwrap();
|
|
|
|
if let Ok(allocated) = allocated.read() {
|
|
allocated_mem.set(allocated as i64);
|
|
}
|
|
|
|
if let Ok(resident) = resident.read() {
|
|
resident_mem.set(resident as i64);
|
|
}
|
|
|
|
tokio::time::sleep(Duration::from_secs(5)).await;
|
|
}
|
|
});
|
|
|
|
Ok(())
|
|
}
|