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 if ( $this->now ===
null ) {
101 $this->now = microtime(
true );
110 foreach ( $this->queuedValues as $ttl => $values ) {
111 $this->store->incr( $values, $ttl );
113 $this->queuedValues = [];
130 public function resetAll( ?array $entities =
null ) {
132 $this->queuedValues = [];
134 foreach ( $this->metricSpecs as $name => $metricSpec ) {
135 foreach ( $metricSpec->sequences as $seqSpec ) {
136 $timeStep = $seqSpec->timeStep;
137 $ttl = $seqSpec->hardExpiry;
138 $lastBucket = (int)( $this->now() / $timeStep ) + 1;
139 $firstBucket = (int)( ( $this->now() - $ttl ) / $timeStep ) - 1;
140 for ( $bucket = $firstBucket; $bucket <= $lastBucket; $bucket++ ) {
141 foreach ( $entities as $entity ) {
142 $keys[] = $this->store->makeKey(
143 $this->prefixComponents,
144 [ $name, $seqSpec->name, $bucket ],
151 $this->store->delete(
$keys );