Skip to content

Commit

Permalink
Merge pull request #11 from Slickdeals/CLOUD-1540
Browse files Browse the repository at this point in the history
CLOUD-1540 - feat: set sample rate to be min of global and metric sample rate
  • Loading branch information
drwho725 authored Dec 20, 2024
2 parents 96b8a5e + ec03bd2 commit 34a2ca7
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 38 deletions.
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ When establishing the connection to statsd and sending metrics, errors will be s
If you run statsd in TCP mode, there is also a `\Domnikl\Statsd\Connection\TcpSocket` adapter that works like the `UdpSocket` except that it throws a `\Domnikl\Statsd\Connection\TcpSocketException` if no connection could be established.
Please consider that unlike UDP, TCP is used for reliable networks and therefor exceptions (and errors) will not be suppressed in TCP mode.

### Sampling Rate

You can set global sampling rate when constructing instance of `Client`. If a metric call passes lower sampling rate than the global one, it would be
used instead. However if a metric call passes sampling rate higher than the global one, that would be ignored in favor of global sampling rate.

### [Timings](https://github.com/etsy/statsd/blob/master/docs/metric_types.md#timing)

```php
Expand Down Expand Up @@ -71,9 +76,9 @@ $statsd->memory('foo.memory_peak_usage');

### [Gauges](https://github.com/etsy/statsd/blob/master/docs/metric_types.md#gauges)

statsd supports gauges, arbitrary values which can be recorded.
statsd supports gauges, arbitrary values which can be recorded.

This method accepts both absolute (3) and delta (+11) values.
This method accepts both absolute (3) and delta (+11) values.

*NOTE:* Negative values are treated as delta values, not absolute.

Expand All @@ -82,9 +87,9 @@ This method accepts both absolute (3) and delta (+11) values.
// Absolute value
$statsd->gauge('foobar', 3);

// Pass delta values as a string.
// Pass delta values as a string.
// Accepts both positive (+11) and negative (-4) delta values.
$statsd->gauge('foobar', '+11');
$statsd->gauge('foobar', '+11');
```

### [Sets](https://github.com/etsy/statsd/blob/master/docs/metric_types.md#sets)
Expand All @@ -99,7 +104,7 @@ $statsd->set('userId', 1234);
### disabling sending of metrics

To disable sending any metrics to the statsd server, you can use the `Domnikl\Statsd\Connection\Blackhole` connection
class instead of the default socket abstraction. This may be incredibly useful for feature flags. Another options is
class instead of the default socket abstraction. This may be incredibly useful for feature flags. Another options is
to use `Domnikl\Statsd\Connection\InMemory` connection class, that will collect your messages but won't actually send them.

## StatsdAwareInterface
Expand All @@ -121,6 +126,7 @@ services:
arguments:
$connection: '@app.statsd_connection'
$namespace: '<namespace>'
$sampleRateAllMetrics: '0.1' # set global sample rate of 10%

app.statsd_connection:
class: Domnikl\Statsd\Connection\UdpSocket
Expand Down
2 changes: 1 addition & 1 deletion src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ private function send(string $key, $value, string $type, float $sampleRate, arra
{
// override sampleRate if all metrics should be sampled
if ($this->sampleRateAllMetrics < 1) {
$sampleRate = $this->sampleRateAllMetrics;
$sampleRate = min($sampleRate, $this->sampleRateAllMetrics);
}

if ($sampleRate < 1 && mt_rand() / mt_getrandmax() > $sampleRate) {
Expand Down
80 changes: 48 additions & 32 deletions tests/unit/ClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,32 +58,42 @@ public function testCountWithFloatValue()
);
}

public function sampleRateData()
{
return [
[0.9, 1, '0.9'],
[0.9, 0.5, '0.5'],
];
}

/**
* @dataProvider sampleRateData
* @group sampling
*/
public function testCountWithSamplingRate()
public function testCountWithSamplingRate(float $globalSampleRate, float $sampleRate, string $expectedSampleRate)
{
$client = new Client($this->connection, 'test', 9 / 10);
$client = new Client($this->connection, 'test', $globalSampleRate);
for ($i = 0; $i < 10; $i++) {
$client->count('foo.baz', 100, 1);
$client->count('foo.baz', 100, $sampleRate);
}
$this->assertEquals(
'test.foo.baz:100|c|@0.9',
"test.foo.baz:100|c|@{$expectedSampleRate}",
$this->connection->getLastMessage()
);
}

/**
* @dataProvider sampleRateData
* @group sampling
*/
public function testCountWithSamplingRateAndTags()
public function testCountWithSamplingRateAndTags(float $globalSampleRate, float $sampleRate, string $expectedSampleRate)
{
$client = new Client($this->connection, 'test', 9 / 10);
$client = new Client($this->connection, 'test', $globalSampleRate);
for ($i = 0; $i < 10; $i++) {
$client->count('foo.baz', 100, 1, ['tag' => 'value']);
$client->count('foo.baz', 100, $sampleRate, ['tag' => 'value']);
}
$this->assertEquals(
'test.foo.baz:100|c|@0.9|#tag:value',
"test.foo.baz:100|c|@{$expectedSampleRate}|#tag:value",
$this->connection->getLastMessage()
);
}
Expand All @@ -98,31 +108,33 @@ public function testIncrement()
}

/**
* @dataProvider sampleRateData
* @group sampling
*/
public function testIncrementWithSamplingRate()
public function testIncrementWithSamplingRate(float $globalSampleRate, float $sampleRate, string $expectedSampleRate)
{
$client = new Client($this->connection, 'test', 0.9);
$client = new Client($this->connection, 'test', $globalSampleRate);
for ($i = 0; $i < 10; $i++) {
$client->increment('foo.baz', 1);
$client->increment('foo.baz', $sampleRate);
}
$this->assertEquals(
'test.foo.baz:1|c|@0.9',
"test.foo.baz:1|c|@{$expectedSampleRate}",
$this->connection->getLastMessage()
);
}

/**
* @dataProvider sampleRateData
* @group sampling
*/
public function testIncrementWithSamplingRateAndTags()
public function testIncrementWithSamplingRateAndTags(float $globalSampleRate, float $sampleRate, string $expectedSampleRate)
{
$client = new Client($this->connection, 'test', 0.9);
$client = new Client($this->connection, 'test', $globalSampleRate);
for ($i = 0; $i < 10; $i++) {
$client->increment('foo.baz', 1, ['tag' => 'value']);
$client->increment('foo.baz', $sampleRate, ['tag' => 'value']);
}
$this->assertEquals(
'test.foo.baz:1|c|@0.9|#tag:value',
"test.foo.baz:1|c|@{$expectedSampleRate}|#tag:value",
$this->connection->getLastMessage()
);
}
Expand All @@ -137,31 +149,33 @@ public function testDecrement()
}

/**
* @dataProvider sampleRateData
* @group sampling
*/
public function testDecrementWithSamplingRate()
public function testDecrementWithSamplingRate(float $globalSampleRate, float $sampleRate, string $expectedSampleRate)
{
$client = new Client($this->connection, 'test', 0.9);
$client = new Client($this->connection, 'test', $globalSampleRate);
for ($i = 0; $i < 10; $i++) {
$client->decrement('foo.baz', 1);
$client->decrement('foo.baz', $sampleRate);
}
$this->assertEquals(
'test.foo.baz:-1|c|@0.9',
"test.foo.baz:-1|c|@{$expectedSampleRate}",
$this->connection->getLastMessage()
);
}

/**
* @dataProvider sampleRateData
* @group sampling
*/
public function testDecrementWithSamplingRateAndTags()
public function testDecrementWithSamplingRateAndTags(float $globalSampleRate, float $sampleRate, string $expectedSampleRate)
{
$client = new Client($this->connection, 'test', 0.9);
$client = new Client($this->connection, 'test', $globalSampleRate);
for ($i = 0; $i < 10; $i++) {
$client->decrement('foo.baz', 1, ['tag' => 'value']);
$client->decrement('foo.baz', $sampleRate, ['tag' => 'value']);
}
$this->assertEquals(
'test.foo.baz:-1|c|@0.9|#tag:value',
"test.foo.baz:-1|c|@{$expectedSampleRate}|#tag:value",
$this->connection->getLastMessage()
);
}
Expand All @@ -177,16 +191,17 @@ public function testCanMeasureTimingWithClosure()


/**
* @dataProvider sampleRateData
* @group sampling
*/
public function testTimingWithSamplingRate()
public function testTimingWithSamplingRate(float $globalSampleRate, float $sampleRate, string $expectedSampleRate)
{
$client = new Client($this->connection, 'test', 0.9);
$client = new Client($this->connection, 'test', $globalSampleRate);
for ($i = 0; $i < 10; $i++) {
$client->timing('foo.baz', 2000, 1);
$client->timing('foo.baz', 2000, $sampleRate);
}
$this->assertEquals(
'test.foo.baz:2000|ms|@0.9',
"test.foo.baz:2000|ms|@{$expectedSampleRate}",
$this->connection->getLastMessage()
);
}
Expand Down Expand Up @@ -218,20 +233,21 @@ public function testEndTimingReturnsTiming()
}

/**
* @dataProvider sampleRateData
* @group sampling
*/
public function testStartEndTimingWithSamplingRate()
public function testStartEndTimingWithSamplingRate(float $globalSampleRate, float $sampleRate, string $expectedSampleRate)
{
$client = new Client($this->connection, 'test', 0.9);
$client = new Client($this->connection, 'test', $globalSampleRate);
for ($i = 0; $i < 10; $i++) {
$client->startTiming('foo.baz');
usleep(10000);
$client->endTiming('foo.baz');
$client->endTiming('foo.baz', $sampleRate);
}

// ranges between 1000 and 1001ms
$this->assertMatchesRegularExpression(
'/^test\.foo\.baz:1[0-9](.[0-9]+)?\|ms\|@0.9$/',
"/^test\.foo\.baz:1[0-9](.[0-9]+)?\|ms\|@{$expectedSampleRate}$/",
$this->connection->getLastMessage()
);
}
Expand Down

0 comments on commit 34a2ca7

Please sign in to comment.