Skip to content

Commit 2c57e33

Browse files
kriszypclaude
andcommitted
fix(analytics): transaction-commit-time is silent on a true wedge, not rising
Domain review caught an inversion in the prior commit: recordCommitLatency only fires on commitResolution.then(record, record), so a commit that never settles produces zero samples for transaction-commit-time — the opposite of "rising p99/p999 predicts the 503" for that failure mode. Reframe: commit-time is the leading indicator for gradual slowdowns toward the storage.maxTransactionQueueTime bound; write-transaction-queue-depth's depth staying elevated (plus Harper's own stuck-commit log line) is the signal for a genuine wedge. Also fix the transaction-commit-time table row (percentiles are aggregate-only per resources/analytics/write.ts, not present on hdb_raw_analytics) and note that per-thread analytics rows are activity-gated, so a quiet thread emits no row at all rather than an implicit zero. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent 5ffa6c5 commit 2c57e33

2 files changed

Lines changed: 33 additions & 24 deletions

File tree

reference/analytics/overview.md

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ Harper automatically tracks the following metrics for all services. Applications
179179
| `resource-usage` | (see below) | | various | Node.js process resource usage (see [resource-usage](#resource-usage-metric)) |
180180
| `storage-volume` | `available`, `free`, `size` | `database` | bytes | Storage volume size breakdown |
181181
| `table-size` | `size` | `database`, `table` | bytes | Table file size |
182-
| `transaction-commit-time` | `median`, `mean`, `p95`, `p90` | | ms | Duration from write commit submission to settlement (see [transaction queue depth](#transaction-queue-depth-metrics)) |
182+
| `transaction-commit-time` | `mean`, `median`, `p90`, `p95`, `p99`, `p999` | | ms | Duration from write commit submission to settlement (see [transaction queue depth](#transaction-queue-depth-metrics)) |
183183
| `utilization` | | | % | Percentage of time the worker thread was processing requests |
184184
| `write-transaction-queue-depth` | `depth`, `maxDepth` | | count | In-flight write transaction commits (see [transaction queue depth](#transaction-queue-depth-metrics)) |
185185

@@ -188,16 +188,21 @@ Harper automatically tracks the following metrics for all services. Applications
188188
<VersionBadge version="v5.2.0" />
189189

190190
`write-transaction-queue-depth` and `read-transaction-queue-depth` expose how many transactions are
191-
in flight against the storage engine per worker thread — a concurrency and throughput signal.
192-
`maxDepth` amplitude alone is not a reliable predictor of the `Outstanding write transactions have too
193-
long of queue, please try again later` (HTTP 503) rejection: a thread can carry a high `maxDepth` with
194-
fast commits and never trip it. But a single commit stuck in flight — the precondition for that
195-
rejection — does show up here as a distinguishing pattern: `depth` pinned at 1 or more across many
196-
consecutive raw samples (rather than a brief blip that clears) means a commit isn't settling. For a
197-
direct duration reading on that specific risk, use `transaction-commit-time`, which records each
198-
commit's submit-to-settle time on the same clock as the
191+
in flight against the storage engine per worker thread — a concurrency and throughput signal, not a
192+
reliable predictor on their own of the `Outstanding write transactions have too long of queue, please
193+
try again later` (HTTP 503) rejection: `maxDepth` amplitude reflects concurrent commits, not whether
194+
any single one is approaching the
199195
[`storage.maxTransactionQueueTime`](../database/storage-tuning.md#storagemaxtransactionqueuetime)
200-
check (default 45s) — a rising p99/p999 there is the leading indicator for the 503.
196+
duration limit (default 45s) that actually trips the 503.
197+
198+
`transaction-commit-time` records each commit's submit-to-settle duration on that same clock, and a
199+
rising `p99`/`p999` (in the `hdb_analytics` aggregate table, where percentiles are computed — they
200+
aren't present on `hdb_raw_analytics`) is a leading indicator of _gradual_ slowdowns approaching that
201+
limit. It doesn't help with a single commit that hangs indefinitely, though: the metric only records
202+
once a commit settles, so a genuinely wedged commit contributes no sample at all, while
203+
`write-transaction-queue-depth`'s `depth` stays elevated on that thread for as long as the commit
204+
remains outstanding. Harper also logs once per stuck commit when the 503 check itself fires, which is
205+
the authoritative signal for that specific failure.
201206

202207
| Field | Unit | Description |
203208
| ---------- | ----- | ------------------------------------------------- |
@@ -214,19 +219,23 @@ check (default 45s) — a rising p99/p999 there is the leading indicator for the
214219
duration-based metric would be needed to identify a single transaction held open long enough to
215220
hold back compaction.
216221

217-
Both metrics are tracked only on the RocksDB write/read path. On an LMDB-backed database
218-
(`storage.engine: lmdb`), `depth` and `maxDepth` for both metrics always read `0` — indistinguishable
219-
from a healthy, empty queue — regardless of actual read/write load.
220-
221-
Both are gauges sampled per worker thread. The raw per-thread entries in `hdb_raw_analytics` retain
222-
each thread's true instantaneous `depth` and per-period `maxDepth`; treat those as the reliable
223-
source for spike detection. The aggregate `hdb_analytics` table is not a sum of per-thread peaks —
224-
each thread's `maxDepth` is first averaged across its raw samples for the period, then those
225-
per-thread averages are summed — so a brief single-thread spike is diluted rather than preserved.
226-
Always alert on `hdb_raw_analytics.maxDepth` (or lower the sampling/aggregation period) rather than
227-
relying on the aggregate table to catch short spikes. Tune the concrete alert threshold against a
228-
baseline for your workload, since absolute depth scales with worker-thread count and per-transaction
229-
size.
222+
Both metrics are gauges tracked only on the RocksDB write/read path, sampled per worker thread. On an
223+
LMDB-backed database (`storage.engine: lmdb`), `depth` and `maxDepth` for both metrics always read `0`
224+
— indistinguishable from a healthy, empty queue — regardless of actual read/write load. All per-thread
225+
analytics reporting, including these gauges, piggybacks on the thread having recorded some other
226+
analytics-eligible activity in the period — a thread with no recordable activity in a given second
227+
emits no row at all rather than an explicit `depth: 0`. Absence of a sample is not the same as a
228+
healthy reading, particularly for `read-transaction-queue-depth` on an otherwise-quiet thread holding a
229+
single long-lived read.
230+
231+
The raw per-thread entries in `hdb_raw_analytics` retain each thread's true instantaneous `depth` and
232+
per-period `maxDepth`; treat those as the reliable source for spike detection. The aggregate
233+
`hdb_analytics` table is not a sum of per-thread peaks — each thread's `maxDepth` is first averaged
234+
across its raw samples for the period, then those per-thread averages are summed — so a brief
235+
single-thread spike is diluted rather than preserved. Always alert on `hdb_raw_analytics.maxDepth` (or
236+
lower the sampling/aggregation period) rather than relying on the aggregate table to catch short
237+
spikes. Tune the concrete alert threshold against a baseline for your workload, since absolute depth
238+
scales with worker-thread count and per-transaction size.
230239

231240
#### `resource-usage` Metric
232241

release-notes/v5-lincoln/5.2.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,4 @@ The `set_configuration` operation now accepts `"replicated": true` to apply a co
1818

1919
### Transaction queue depth metrics
2020

21-
New `write-transaction-queue-depth` and `read-transaction-queue-depth` metrics report per-thread write-commit and open-read-transaction concurrency against the storage engine, as a throughput/concurrency signal. A new `transaction-commit-time` metric records per-commit submit-to-settle duration, the leading indicator for the write-queue HTTP 503 rejection — see [Transaction Queue Depth Metrics](/reference/v5/analytics/overview#transaction-queue-depth-metrics).
21+
New `write-transaction-queue-depth` and `read-transaction-queue-depth` metrics report per-thread write-commit and open-read-transaction concurrency against the storage engine, as a throughput/concurrency signal. A new `transaction-commit-time` metric records per-commit submit-to-settle duration, a leading indicator of gradual slowdowns toward the write-queue HTTP 503 rejection — see [Transaction Queue Depth Metrics](/reference/v5/analytics/overview#transaction-queue-depth-metrics).

0 commit comments

Comments
 (0)