17 private $queuedValues = [];
21 private $prefixComponents;
31 $this->store = $store;
32 $this->metricSpecs = [];
33 foreach ( $specs as $name => $spec ) {
34 $this->metricSpecs[$name] =
new MetricSpec( $spec );
36 $this->prefixComponents = is_array( $prefix ) ? $prefix : [ $prefix ];
37 if ( !count( $this->prefixComponents ) ) {
39 ': there must be at least one prefix component' );
51 $metricSpec = $this->metricSpecs[$name] ??
null;
53 if ( $metricSpec ===
null ) {
54 throw new WRStatsError( __METHOD__ .
": Unrecognised metric \"$name\"" );
56 $res = $metricSpec->resolution;
57 $scaledValue = $value /
$res;
59 foreach ( $metricSpec->sequences as $seqSpec ) {
60 $timeStep = $seqSpec->timeStep;
61 $timeBucket = (int)( $this->now() / $timeStep );
62 $key = $this->store->makeKey(
63 $this->prefixComponents,
64 [ $name, $seqSpec->name, $timeBucket ],
68 $ttl = $seqSpec->hardExpiry;
70 if ( !isset( $this->queuedValues[$ttl][$key] ) ) {
71 $this->queuedValues[$ttl][$key] = 0;
73 $this->queuedValues[$ttl][$key] += (int)round( $scaledValue );
99 private function now() {
100 $this->now ??= microtime(
true );
108 foreach ( $this->queuedValues as $ttl => $values ) {
109 $this->store->incr( $values, $ttl );
111 $this->queuedValues = [];
128 public function resetAll( ?array $entities =
null ) {
130 $this->queuedValues = [];
132 foreach ( $this->metricSpecs as $name => $metricSpec ) {
133 foreach ( $metricSpec->sequences as $seqSpec ) {
134 $timeStep = $seqSpec->timeStep;
135 $ttl = $seqSpec->hardExpiry;
136 $lastBucket = (int)( $this->now() / $timeStep ) + 1;
137 $firstBucket = (int)( ( $this->now() - $ttl ) / $timeStep ) - 1;
138 for ( $bucket = $firstBucket; $bucket <= $lastBucket; $bucket++ ) {
139 foreach ( $entities as $entity ) {
140 $keys[] = $this->store->makeKey(
141 $this->prefixComponents,
142 [ $name, $seqSpec->name, $bucket ],
149 $this->store->delete(
$keys );