aboutsummaryrefslogtreecommitdiffstats
path: root/src/swarm
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-09 20:31:10 +0000
committertv <tv@krebsco.de>2026-11-09 22:21:15 +0100
commit67b5c3ae079f9f524bf0c52521a62811da407ad0 (patch)
treedb60596400fee35617d0fd3847987195efbb7ba0 /src/swarm
parent152890f321075beede075314d37ff6451604c359 (diff)
stats: the writers of the document
How many writers (Automerge actors) the document's changes have matters: a writer is a node's run (each start, rejoin or drop makes one, a start keeping the one of before with `--keep-actor` after a clean stop), and every transfer of the whole history carries a signature for each. `/admin/stats` now says it (`document.writers`, and `document_writers` for Prometheus), counted from the changes' metadata alongside the saved size's measurement in the background (at least a minute apart), as that takes time proportional to the document too; an export, which measures the size alone, keeps the count of before. The dashboard's figures show it with the rest.
Diffstat (limited to 'src/swarm')
-rw-r--r--src/swarm/stats.rs14
1 files changed, 11 insertions, 3 deletions
diff --git a/src/swarm/stats.rs b/src/swarm/stats.rs
index ed12888..3665b5a 100644
--- a/src/swarm/stats.rs
+++ b/src/swarm/stats.rs
@@ -99,12 +99,16 @@ impl Propagation {
}
/// The document's size as saved (compressed), when it was measured and how long that
-/// took (copy and save).
+/// took (copy and save), and how many writers (Automerge actors) its changes have.
#[derive(Debug, Clone, Copy)]
pub(crate) struct SavedSize {
pub(crate) bytes: u64,
pub(crate) at: Instant,
pub(crate) took: Duration,
+ /// Writers with changes in the document, counted with the measurement: a node's
+ /// run each, so many a transfer of the whole history carries a signature for. None
+ /// where only the size was measured (an export).
+ pub(crate) writers: Option<usize>,
}
/// Passing changes on (`swarm::relay`), since start.
@@ -434,10 +438,12 @@ impl NodeStats {
/// measurement for free.
pub(crate) fn saved_size_measured(&self, bytes: u64, took: Duration, version: (u64, Epoch)) {
let mut inner = self.lock();
+ let writers = inner.saved_size.and_then(|saved| saved.writers);
inner.saved_size = Some(SavedSize {
bytes,
at: Instant::now(),
took,
+ writers,
});
inner.measured_version = Some(version);
}
@@ -494,11 +500,12 @@ pub(crate) fn measure_saved_size(state: &AppState) {
// Both steps take time proportional to the document: off the async threads.
let measured = match tokio::task::spawn_blocking(move || {
let copy = doc.blocking_read().doc.clone();
- crate::document::save(&copy).len() as u64
+ let writers = crate::document::writers(&copy);
+ (crate::document::save(&copy).len() as u64, writers)
})
.await
{
- Ok(bytes) => {
+ Ok((bytes, writers)) => {
let took = start.elapsed();
debug!(
bytes,
@@ -510,6 +517,7 @@ pub(crate) fn measure_saved_size(state: &AppState) {
bytes,
at: Instant::now(),
took,
+ writers: Some(writers),
},
version,
))