MediaWiki master
WRStatsWriter.php
Go to the documentation of this file.
1<?php
2
3namespace Wikimedia\WRStats;
4
13 private $store;
15 private $metricSpecs;
17 private $queuedValues = [];
19 private $now;
21 private $prefixComponents;
22
29 public function __construct( StatsStore $store, $specs, $prefix ) {
30 $this->store = $store;
31 $this->metricSpecs = [];
32 foreach ( $specs as $name => $spec ) {
33 $this->metricSpecs[$name] = new MetricSpec( $spec );
34 }
35 $this->prefixComponents = is_array( $prefix ) ? $prefix : [ $prefix ];
36 if ( !count( $this->prefixComponents ) ) {
37 throw new WRStatsError( __METHOD__ .
38 ': there must be at least one prefix component' );
39 }
40 }
41
49 public function incr( $name, ?EntityKey $entity = null, $value = 1 ) {
50 $metricSpec = $this->metricSpecs[$name] ?? null;
51 $entity ??= new LocalEntityKey;
52 if ( $metricSpec === null ) {
53 throw new WRStatsError( "Unrecognised metric \"$name\"" );
54 }
55 $res = $metricSpec->resolution;
56 $scaledValue = $value / $res;
57
58 foreach ( $metricSpec->sequences as $seqSpec ) {
59 $timeStep = $seqSpec->timeStep;
60 $timeBucket = (int)( $this->now() / $timeStep );
61 $key = $this->store->makeKey(
62 $this->prefixComponents,
63 [ $name, $seqSpec->name, $timeBucket ],
64 $entity
65 );
66
67 $ttl = $seqSpec->hardExpiry;
68
69 if ( !isset( $this->queuedValues[$ttl][$key] ) ) {
70 $this->queuedValues[$ttl][$key] = 0;
71 }
72 $this->queuedValues[$ttl][$key] += (int)round( $scaledValue );
73 }
74 }
75
81 public function setCurrentTime( $now ) {
82 $this->now = $now;
83 }
84
91 public function resetCurrentTime() {
92 $this->now = null;
93 }
94
98 private function now() {
99 $this->now ??= microtime( true );
100 return $this->now;
101 }
102
106 public function flush() {
107 foreach ( $this->queuedValues as $ttl => $values ) {
108 $this->store->incr( $values, $ttl );
109 }
110 $this->queuedValues = [];
111 }
112
116 public function __destruct() {
117 $this->flush();
118 }
119
127 public function resetAll( ?array $entities = null ) {
128 $entities ??= [ new LocalEntityKey ];
129 $this->queuedValues = [];
130 $keys = [];
131 foreach ( $this->metricSpecs as $name => $metricSpec ) {
132 foreach ( $metricSpec->sequences as $seqSpec ) {
133 $timeStep = $seqSpec->timeStep;
134 $ttl = $seqSpec->hardExpiry;
135 $lastBucket = (int)( $this->now() / $timeStep ) + 1;
136 $firstBucket = (int)( ( $this->now() - $ttl ) / $timeStep ) - 1;
137 for ( $bucket = $firstBucket; $bucket <= $lastBucket; $bucket++ ) {
138 foreach ( $entities as $entity ) {
139 $keys[] = $this->store->makeKey(
140 $this->prefixComponents,
141 [ $name, $seqSpec->name, $bucket ],
142 $entity
143 );
144 }
145 }
146 }
147 }
148 $this->store->delete( $keys );
149 }
150}
Base class for entity keys.
Definition EntityKey.php:13
Entity key with isGlobal=false.
Class representation of normalized metric specifications.
Exception class for errors thrown by the WRStats library.
Writers gather a batch of increment operations and then commit them when flush() is called,...
resetCurrentTime()
Reset the stored current time.
incr( $name, ?EntityKey $entity=null, $value=1)
Queue an increment operation.
__construct(StatsStore $store, $specs, $prefix)
resetAll(?array $entities=null)
Delete all stored metrics corresponding to the specs supplied to the constructor, resetting the count...
__destruct()
Commit the batch of increment operations.
setCurrentTime( $now)
Set the time to be used as the current time.
flush()
Commit the batch of increment operations.
Narrow interface for WRStatsFactory to a memcached-like key-value store.