Skip to content

Commit ecf838d

Browse files
authored
Expose the number of observations (#13)
1 parent f432ecb commit ecf838d

5 files changed

+27
-8
lines changed

composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
],
1212
"require": {
1313
"php": "^8.1",
14-
"sanmai/pipeline": "^6.8",
14+
"sanmai/pipeline": "^6.11",
1515
"tumblr/chorus-timekeeper": "^0.1.0"
1616
},
1717
"require-dev": {

src/AnomalyDetectionResult.php

+14-1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ class AnomalyDetectionResult
4848
*/
4949
public const DIRECTION_DOWN = 'down';
5050

51+
/** @var int The number of observations */
52+
private int $count;
53+
5154
/** @var float The standard deviation */
5255
private float $std_dev;
5356

@@ -75,13 +78,15 @@ class AnomalyDetectionResult
7578
/**
7679
* Create a new anomaly detection result instance.
7780
*
81+
* @param int $count The number of observations
7882
* @param float $std_dev The standard deviation
7983
* @param float $mean The mean value
8084
* @param float $latest The latest value
8185
* @param float|int $sensitivity The sensitivity (see `SlidingWindowCounter::detectAnomaly()`)
8286
*/
83-
public function __construct(float $std_dev, float $mean, float $latest, float|int $sensitivity)
87+
public function __construct(int $count, float $std_dev, float $mean, float $latest, float|int $sensitivity)
8488
{
89+
$this->count = $count;
8590
$this->std_dev = $std_dev;
8691
$this->mean = $mean;
8792
$this->latest = $latest;
@@ -126,6 +131,14 @@ public function toArray(int $precision = 2): array
126131
);
127132
}
128133

134+
/**
135+
* The number of observations
136+
*/
137+
public function getCount(): int
138+
{
139+
return $this->count;
140+
}
141+
129142
/**
130143
* The standard deviation.
131144
*/

src/SlidingWindowCounter.php

+1
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ public function detectAnomaly(string $bucket_key, float|int $sensitivity = 2, ?i
249249
$variance = $this->getHistoricVariance($bucket_key, $start_time);
250250

251251
return new AnomalyDetectionResult(
252+
$variance->getCount(),
252253
$variance->getStandardDeviation(),
253254
$variance->getMean(),
254255
$this->getLatestValue($bucket_key),

tests/AnomalyDetectionResultTest.php

+9-5
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,13 @@ final class AnomalyDetectionResultTest extends TestCase
3535
*/
3636
public function testHappyPath(): void
3737
{
38-
$result = new AnomalyDetectionResult(0.999, 10.0, 11.0, 1);
38+
$result = new AnomalyDetectionResult(10, 0.999, 10.0, 11.0, 1);
3939

4040
$this->assertFalse($result->isAnomaly());
4141
$this->assertSame(AnomalyDetectionResult::DIRECTION_NONE, $result->getDirection());
4242

4343
$this->assertSame([
44+
'count' => 10,
4445
'std_dev' => 1.0,
4546
'mean' => 10.0,
4647
'sensitivity' => 1,
@@ -57,8 +58,9 @@ public function testHappyPath(): void
5758
*/
5859
public function testAllGetters(): void
5960
{
60-
$result = new AnomalyDetectionResult(1.0, 10.0, 11.0, 0.9);
61+
$result = new AnomalyDetectionResult(11, 1.0, 10.0, 11.0, 0.9);
6162

63+
$this->assertSame(11, $result->getCount());
6264
$this->assertSame(1.0, $result->getStandardDeviation());
6365
$this->assertSame(10.0, $result->getMean());
6466
$this->assertSame(0.9, $result->getSensitivity());
@@ -74,11 +76,12 @@ public function testAllGetters(): void
7476
*/
7577
public function testAnomalyDirectionUp(): void
7678
{
77-
$result = new AnomalyDetectionResult(1.0, 10.0, 12.011, 1);
79+
$result = new AnomalyDetectionResult(22, 1.0, 10.0, 12.011, 1);
7880

7981
$this->assertTrue($result->isAnomaly());
8082

8183
$this->assertSame([
84+
'count' => 22,
8285
'std_dev' => 1.0,
8386
'mean' => 10.0,
8487
'sensitivity' => 1,
@@ -95,11 +98,12 @@ public function testAnomalyDirectionUp(): void
9598
*/
9699
public function testAnomalyDetectionDown(): void
97100
{
98-
$result = new AnomalyDetectionResult(1.0, 10.0, 1.123456, 3);
101+
$result = new AnomalyDetectionResult(33, 1.0, 10.0, 1.123456, 3);
99102

100103
$this->assertTrue($result->isAnomaly());
101104

102105
$this->assertSame([
106+
'count' => 33,
103107
'std_dev' => 1.0,
104108
'mean' => 10.0,
105109
'sensitivity' => 3,
@@ -142,7 +146,7 @@ public static function providerDirections(): iterable
142146
*/
143147
public function testDirections(float $latest, bool $expected_is_anomaly, string $expected_direction): void
144148
{
145-
$result = new AnomalyDetectionResult(1.0, 10.0, $latest, 1);
149+
$result = new AnomalyDetectionResult(100, 1.0, 10.0, $latest, 1);
146150

147151
$this->assertSame($expected_is_anomaly, $result->isAnomaly(), 'Unexpected anomaly result');
148152
$this->assertSame($expected_direction, $result->getDirection(), 'Unexpected direction');

tests/SlidingWindowCounterTest.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ public function testIncrementThrowsTimeInPast(): void
113113
$window_size = 60;
114114
$observation_period = 1000;
115115

116-
$counter = new SlidingWindowCounter('default', 60, $observation_period, new FakeCache(), $time_keeper);
116+
$counter = new SlidingWindowCounter('default', $window_size, $observation_period, new FakeCache(), $time_keeper);
117117

118118
$this->expectException(InvalidArgumentException::class);
119119
$this->expectExceptionMessageMatches('/The time provided \(\d+\) is too far in the past \(current time: \d+, observation period: 1000\)/');
@@ -248,6 +248,7 @@ public function testVariance(): void
248248
$this->assertSame(5, $counter->getHistoricVariance('test')->getCount());
249249

250250
$this->assertSame([
251+
'count' => 5,
251252
'std_dev' => 7.24,
252253
'mean' => 6.82,
253254
'sensitivity' => 3,

0 commit comments

Comments
 (0)