···66#[derive(Serialize)]
77pub struct StatsResponse {
88 pub counts: BTreeMap<&'static str, u64>,
99+ pub size: BTreeMap<&'static str, u64>,
910}
10111112pub async fn get_stats(State(state): State<Arc<AppState>>) -> Result<Json<StatsResponse>> {
1212- let db = &state.db;
1313+ let db = state.db.clone();
13141415 let mut counts: BTreeMap<&'static str, u64> = futures::future::join_all(
1516 [
···2324 "error_generic",
2425 ]
2526 .into_iter()
2626- .map(|name| async move { (name, db.get_count(name).await) }),
2727+ .map(|name| {
2828+ let db = db.clone();
2929+ async move { (name, db.get_count(name).await) }
3030+ }),
2731 )
2832 .await
2933 .into_iter()
3034 .collect();
3135 // this should be accurate since we dont remove events
3636+ // todo: ...unless in ephemeral mode
3237 counts.insert("events", db.events.approximate_len() as u64);
33383434- Ok(Json(StatsResponse { counts }))
3939+ let size = tokio::task::spawn_blocking(move || {
4040+ let mut size = BTreeMap::new();
4141+ size.insert("repos", db.repos.disk_space());
4242+ size.insert("records", db.records.disk_space());
4343+ size.insert("blocks", db.blocks.disk_space());
4444+ size.insert("cursors", db.cursors.disk_space());
4545+ size.insert("pending", db.pending.disk_space());
4646+ size.insert("resync", db.resync.disk_space());
4747+ size.insert("resync_buffer", db.resync_buffer.disk_space());
4848+ size.insert("events", db.events.disk_space());
4949+ size.insert("counts", db.counts.disk_space());
5050+ size.insert("filter", db.filter.disk_space());
5151+ size.insert("crawler", db.crawler.disk_space());
5252+ size
5353+ })
5454+ .await
5555+ .map_err(|_| axum::http::StatusCode::INTERNAL_SERVER_ERROR)?;
5656+5757+ Ok(Json(StatsResponse { counts, size }))
3558}
+4
src/db/mod.rs
···2828 KeyspaceCreateOptions::default()
2929}
30303131+#[derive(Clone)]
3132pub struct Db {
3233 pub inner: Arc<Database>,
3334 pub repos: Keyspace,
···230231 .max_memtable_size(mb(16))
231232 .data_block_size_policy(BlockSizePolicy::all(kb(1))),
232233 )?;
234234+235235+ // when adding new keyspaces, make sure to add them to the /stats endpoint
236236+ // and also update any relevant /debug/* endpoints
233237234238 let mut last_id = 0;
235239 if let Some(guard) = events.iter().next_back() {
+13
tests/debug_endpoints.nu
···7676 print "PASSED: /debug/iter on events returns JSON objects"
7777 }
78787979+ # 4. Test size in /stats
8080+ print "testing size in /stats"
8181+ let stats = http get $"($url)/stats"
8282+ if ($stats.size | is-empty) {
8383+ print "FAILED: /stats returned empty size"
8484+ exit 1
8585+ }
8686+ if not ("repos" in ($stats.size | columns)) {
8787+ print "FAILED: /stats missing 'repos' in size"
8888+ exit 1
8989+ }
9090+ print "PASSED: /stats returns keyspace sizes"
9191+7992 } else {
8093 print "backfill failed"
8194 exit 1