OPERATIONS
OPERATIONS = ['put', 'delete', 'list', 'get', 'head']
Every operation that is counted, class A first.
What a store cost over one window: requests, bytes, failures and latency.
Object storage is not billed by volume alone. Cloudflare R2 charges $0.015 per GB-month of storage, $4.50 per million class-A operations and $0.36 per million class-B operations; AWS S3 charges $0.023, $5.00 and $0.40 for the same three lines. A capture that writes a million small frames costs more in requests than in storage, and an accounting that only summed bytes would never show it.
Class A is the billed-write set: put, delete and list. Class B is the billed-read set: get and head. Every attempt is counted, failures included, because an endpoint that refused a request still handled it and still billed for it. ProviderStats::failures() is what separates the two.
Mutable, and scoped to one request or one flush; this is an accumulator, not a record. ProviderStats::merge() folds one window into another and ProviderStats::reset() starts a fresh one.
LATENCY_SAMPLES = 1000
Most latency samples held per operation.
A flush of a large site issues far more requests than a percentile needs to describe, and one float per request would let the accumulator grow for the length of the run. The newest samples are kept and the oldest dropped, so the figures describe what the store is doing now rather than what it did during the first thousand calls.
fromOperations(array$byOperation) : self
Rebuilds a window from figures already accumulated per operation.
The inverse of ProviderStats::byOperation(), for a caller reading a window back out of the stat table rather than watching it happen. Replaying ProviderStats::record() once per request would be correct and costs a call per request in the window, which for a month of traffic is millions of calls to reproduce three totals.
Latency samples are not reproduced, because the table does not hold them. ProviderStats::p95() on a rebuilt window therefore reports nothing, while the counts, the volumes and the failures are exact.
| array |
$byOperation | Operation keyed to its figures, as ProviderStatStore::byOperation() returns them. |
When an operation is not a billed verb.
The window.
record(string $operation, int $bytes, float $seconds, bool $failed = false) : void
Records one attempt against the store.
| string | $operation | One of ProviderStats::OPERATIONS. |
| int | $bytes | Bytes that crossed the wire. Zero for an operation that moves no body, such as a head or a delete. |
| float | $seconds | Wall-clock time the attempt took. |
| bool | $failed | TRUE when the attempt raised. It is still counted, because the request was still made. |
When $operation is not a billed verb, or $bytes or $seconds is negative. Each of those is a caller bug that would otherwise show up as a budget reading nobody can explain.
merge(\Drupal\strata\Storage\ProviderStats $other) : void
Folds another window into this one.
Latency samples are appended, so the other window's observations count as the newer ones and the cap is applied to the result.
| \Drupal\strata\Storage\ProviderStats | $other | The window to fold in. It is left unchanged. |
byOperation() : array<string,array{count: int, bytes: int, failures: int}>
Per-operation attempts, bytes and failures.
Operations that were never attempted are left out, so a table rendered from this shows the verbs the run actually used. Order follows ProviderStats::OPERATIONS.
Keyed by operation.
secondsFor(string $operation) : float
Wall-clock time spent on one operation.
Counted over every attempt, so it is the figure to persist. ProviderStats::latency() reports the retained sample instead and can describe less than the whole run.
| string | $operation | One of ProviderStats::OPERATIONS. |
When $operation is not a billed verb.
Seconds, or 0.0 when the operation was never attempted.
slowestOf(string $operation) : float
The slowest single attempt at one operation.
Taken over every attempt rather than the retained sample, so a spike that happened early in a long run is still reported.
| string | $operation | One of ProviderStats::OPERATIONS. |
When $operation is not a billed verb.
Seconds, or 0.0 when the operation was never attempted.
latency(string $operation) : array{count: int, total: float, min: float, max: float, mean: float, p95: float}
Latency figures for one operation.
Every figure describes the retained sample, which is the newest LATENCY_SAMPLES durations for
that operation. Below the cap that is every attempt; above it, count and total describe
the retained window rather than the whole run, and ProviderStats::byOperation() and
ProviderStats::seconds() carry the untruncated figures.
The percentile is nearest-rank: the smallest sample at or above the 95th position of the sorted window, with no interpolation between neighbours.
| string | $operation | One of ProviderStats::OPERATIONS. |
When $operation is not a billed verb.
All zeroes when the operation has not been attempted.