Merge branch 'pratik/otel-phase10-workload-validation' into pratik/otel-sync-diagnostics

Resolves the nodestore latency-accumulator conflict by keeping this
branch's API surface and applying the incoming nanosecond fix to it.

This branch had renamed storeDurationStats() to recordStoreDuration() and
given it noexcept, an explicit relaxed fetch_add, and call-frequency and
thread-safety notes. The incoming change fixed the accumulators to hold
nanoseconds so sub-microsecond backend calls stop rounding to zero. Both
are kept: the name, signature and documentation from here, the nanosecond
accumulation from there.

The incoming duplicate getFetchDurationUs()/getStoreDurationUs() pair is
dropped in favour of this branch's noexcept versions, which now read the
nanosecond members and convert on read. recordStoreDuration()'s `if (us >
0)` guard is gone: it discarded every sub-microsecond store, which is the
same rounding the incoming change removes one level up.

Also updates a MetricMacros comment that explained the zero write mean in
terms of that removed guard; the injected totals it asserts on are
unchanged.
This commit is contained in:
Pratik Mankawde
2026-08-07 16:54:24 +01:00
5 changed files with 106 additions and 68 deletions

View File

@@ -161,20 +161,17 @@ private:
};
/**
* Assert the read accumulator holds exactly what the fetch reports carried.
* Assert the read accumulator agrees with what the fetch reports carried.
*
* Deliberately not `getFetchDurationUs() > 0`: an individual read served
* from NuDB's in-memory buckets can genuinely measure under one
* microsecond and truncate to zero, so on a fast enough host every read
* truncates and the total stays at zero with nothing wrong. That makes
* `> 0` an assertion about the machine rather than about the code, and it
* is what failed on the macOS runner.
* The accumulator keeps nanoseconds and each report carries its own fetch
* truncated to whole microseconds, so the reported sum is the accumulated
* total minus one sub-microsecond remainder per fetch. That gives a bound
* rather than an equality, and the bound is machine-independent: an
* accumulator that dropped a fetch, double-counted one, or reported the
* write member instead would break it however fast the host is.
*
* The equality below is machine-independent and strictly stronger: each
* fetch is measured once and that one value feeds both the accumulator
* and the report, so an accumulator that dropped a fetch, double-counted
* one, or reported the write member instead would break the equality
* however fast the host is.
* Deliberately not `getFetchDurationUs() > 0` on its own: that is an
* assertion about how fast the host reads, not about the code.
*
* @param db Database whose read accumulator is checked.
* @param scheduler Scheduler that received the reports for @p db.
@@ -187,7 +184,10 @@ private:
std::uint64_t expectedReports)
{
BEAST_EXPECT(scheduler.fetchReports.load() == expectedReports);
BEAST_EXPECT(db.getFetchDurationUs() == scheduler.reportedFetchUs.load());
auto const accumulatedUs = db.getFetchDurationUs();
auto const reportedUs = scheduler.reportedFetchUs.load();
BEAST_EXPECT(reportedUs <= accumulatedUs);
BEAST_EXPECT(accumulatedUs - reportedUs <= expectedReports);
}
public: