Skip to content
This repository was archived by the owner on Oct 18, 2023. It is now read-only.

Commit 1ce18e4

Browse files
authored
stats: add storage_bytes_used (#372)
The new metrics track how many storage bytes are used by this sqld instance. It only tracks the main database file, under the assumption that the most interesting metrics for users is "how large is my database after I successfully checkpoint the write-ahead log". Right now we don't have a separate fiber that performs checkpoints, but that's planned. And once we have it, inspecting storage should happen right after the checkpoint. For now, the fiber that monitors storage used just runs once every 15 minutes. Fixes #340
1 parent a14accd commit 1ce18e4

File tree

4 files changed

+44
-8
lines changed

4 files changed

+44
-8
lines changed

sqld/src/heartbeat.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,7 @@ pub async fn server_heartbeat(
1313
let client = reqwest::Client::new();
1414
loop {
1515
sleep(update_period).await;
16-
let body = StatsResponse {
17-
rows_read_count: stats.rows_read(),
18-
rows_written_count: stats.rows_written(),
19-
};
16+
let body = StatsResponse::from(&stats);
2017
let request = client.post(&url);
2118
let request = if let Some(ref auth) = auth {
2219
request.header("Authorization", auth.clone())

sqld/src/http/stats.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,27 @@ use crate::stats::Stats;
77
pub struct StatsResponse {
88
pub rows_read_count: u64,
99
pub rows_written_count: u64,
10+
pub storage_bytes_used: u64,
11+
}
12+
13+
impl From<&Stats> for StatsResponse {
14+
fn from(stats: &Stats) -> Self {
15+
Self {
16+
rows_read_count: stats.rows_read(),
17+
rows_written_count: stats.rows_written(),
18+
storage_bytes_used: stats.storage_bytes_used(),
19+
}
20+
}
21+
}
22+
23+
impl From<Stats> for StatsResponse {
24+
fn from(stats: Stats) -> Self {
25+
(&stats).into()
26+
}
1027
}
1128

1229
pub fn handle_stats(stats: &Stats) -> Response<Body> {
13-
let resp = StatsResponse {
14-
rows_read_count: stats.rows_read(),
15-
rows_written_count: stats.rows_written(),
16-
};
30+
let resp: StatsResponse = stats.into();
1731

1832
let payload = serde_json::to_vec(&resp).unwrap();
1933
Response::builder()

sqld/src/lib.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,19 @@ async fn start_primary(
390390
Ok(())
391391
}
392392

393+
// Periodically check the storage used by the database and save it in the Stats structure.
394+
// TODO: Once we have a separate fiber that does WAL checkpoints, running this routine
395+
// right after checkpointing is exactly where it should be done.
396+
async fn run_storage_monitor(mut db_path: PathBuf, stats: Stats) -> anyhow::Result<()> {
397+
let duration = tokio::time::Duration::from_secs(60 * 15);
398+
db_path.push("data");
399+
loop {
400+
let attr = tokio::fs::metadata(&db_path).await;
401+
stats.set_storage_bytes_used(attr.map_or(0, |stats| stats.len()));
402+
tokio::time::sleep(duration).await;
403+
}
404+
}
405+
393406
pub async fn run_server(config: Config) -> anyhow::Result<()> {
394407
tracing::trace!("Backend: {:?}", config.backend);
395408

@@ -425,6 +438,8 @@ pub async fn run_server(config: Config) -> anyhow::Result<()> {
425438

426439
let stats = Stats::new(&config.db_path)?;
427440

441+
join_set.spawn(run_storage_monitor(config.db_path.clone(), stats.clone()));
442+
428443
match config.writer_rpc_addr {
429444
Some(_) => start_replica(&config, &mut join_set, idle_shutdown_layer, stats).await?,
430445
None => start_primary(&config, &mut join_set, idle_shutdown_layer, stats).await?,

sqld/src/stats.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ pub struct Stats {
1616
struct StatsInner {
1717
rows_written: AtomicU64,
1818
rows_read: AtomicU64,
19+
storage_bytes_used: AtomicU64,
1920
}
2021

2122
impl Stats {
@@ -46,6 +47,10 @@ impl Stats {
4647
self.inner.rows_read.fetch_add(n, Ordering::Relaxed);
4748
}
4849

50+
pub fn set_storage_bytes_used(&self, n: u64) {
51+
self.inner.storage_bytes_used.store(n, Ordering::Relaxed);
52+
}
53+
4954
/// returns the total number of rows read since this database was created
5055
pub fn rows_read(&self) -> u64 {
5156
self.inner.rows_read.load(Ordering::Relaxed)
@@ -55,6 +60,11 @@ impl Stats {
5560
pub fn rows_written(&self) -> u64 {
5661
self.inner.rows_written.load(Ordering::Relaxed)
5762
}
63+
64+
/// returns the total number of bytes used by the database (excluding uncheckpointed WAL entries)
65+
pub fn storage_bytes_used(&self) -> u64 {
66+
self.inner.storage_bytes_used.load(Ordering::Relaxed)
67+
}
5868
}
5969

6070
fn spawn_stats_persist_thread(stats: Arc<StatsInner>, mut file: File) {

0 commit comments

Comments
 (0)