-
Notifications
You must be signed in to change notification settings - Fork 49
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for RateLimitingSampler (#72)
* Add support for Tracing headers configuration * Add support for RateLimitingSampler * Use previous config, that follows JaegerConfig docs * Increase code coverage & Fix some bugs * Trying to find problem in Travis CI tests * Update tests * Fix test * Commit RateLimitSamplerTest to be less dependend on test machine speed * Fix 7.2 specific error
- Loading branch information
1 parent
cb6bbd1
commit 05ed92f
Showing
11 changed files
with
482 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
<?php | ||
|
||
namespace Jaeger\Sampler; | ||
|
||
use Jaeger\Util\RateLimiter; | ||
|
||
use const Jaeger\SAMPLER_PARAM_TAG_KEY; | ||
use const Jaeger\SAMPLER_TYPE_RATE_LIMITING; | ||
use const Jaeger\SAMPLER_TYPE_TAG_KEY; | ||
|
||
class RateLimitingSampler implements SamplerInterface | ||
{ | ||
/** | ||
* @var RateLimiter | ||
*/ | ||
private $rateLimiter; | ||
|
||
/** | ||
* A list of the sampler tags. | ||
* | ||
* @var array | ||
*/ | ||
private $tags = []; | ||
|
||
public function __construct($maxTracesPerSecond, RateLimiter $rateLimiter) | ||
{ | ||
$this->tags = [ | ||
SAMPLER_TYPE_TAG_KEY => SAMPLER_TYPE_RATE_LIMITING, | ||
SAMPLER_PARAM_TAG_KEY => $maxTracesPerSecond, | ||
]; | ||
|
||
$maxTracesPerNanosecond = $maxTracesPerSecond / 1000000000.0; | ||
$this->rateLimiter = $rateLimiter; | ||
$this->rateLimiter->initialize($maxTracesPerNanosecond, $maxTracesPerSecond > 1.0 ? 1.0 : $maxTracesPerSecond); | ||
} | ||
|
||
/** | ||
* Whether or not the new trace should be sampled. | ||
* | ||
* Implementations should return an array in the format [$decision, $tags]. | ||
* | ||
* @param string $traceId The traceId on the span. | ||
* @param string $operation The operation name set on the span. | ||
* @return array | ||
*/ | ||
public function isSampled(string $traceId = '', string $operation = '') | ||
{ | ||
return [$this->rateLimiter->checkCredit(1.0), $this->tags]; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
* | ||
* Only implemented to satisfy the sampler interface. | ||
* | ||
* @return void | ||
*/ | ||
public function close() | ||
{ | ||
// nothing to do | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
<?php | ||
|
||
namespace Jaeger\Util; | ||
|
||
use Psr\Cache\CacheItemInterface; | ||
use Psr\Cache\CacheItemPoolInterface; | ||
|
||
class RateLimiter | ||
{ | ||
/** | ||
* @var CacheItemPoolInterface | ||
*/ | ||
private $cache; | ||
|
||
/** | ||
* @var CacheItemInterface | ||
*/ | ||
private $balance; | ||
|
||
/** | ||
* @var CacheItemInterface | ||
*/ | ||
private $lastTick; | ||
|
||
/** | ||
* @var float | ||
*/ | ||
private $creditsPerNanosecond = 0; | ||
|
||
/** | ||
* @var float | ||
*/ | ||
private $maxBalance = 0; | ||
|
||
/** | ||
* RateLimiter constructor. | ||
* | ||
* @param CacheItemPoolInterface $cache | ||
* @param string $currentBalanceKey key of current balance value in $cache | ||
* @param string $lastTickKey key of last tick value in $cache | ||
* @throws \Psr\Cache\InvalidArgumentException | ||
*/ | ||
public function __construct( | ||
CacheItemPoolInterface $cache, | ||
string $currentBalanceKey, | ||
string $lastTickKey | ||
) { | ||
$this->cache = $cache; | ||
$this->balance = $this->cache->getItem($currentBalanceKey); | ||
$this->lastTick = $this->cache->getItem($lastTickKey); | ||
} | ||
|
||
/** | ||
* @param $itemCost | ||
* @return bool | ||
*/ | ||
public function checkCredit($itemCost) | ||
{ | ||
if (!$this->creditsPerNanosecond) { | ||
return false; | ||
} | ||
|
||
list($lastTick, $balance) = $this->getState(); | ||
|
||
if (!$lastTick) { | ||
$this->saveState(hrtime(true), 0); | ||
return true; | ||
} | ||
|
||
$currentTick = hrtime(true); | ||
$elapsedTime = $currentTick - $lastTick; | ||
$balance += $elapsedTime * $this->creditsPerNanosecond; | ||
if ($balance > $this->maxBalance) { | ||
$balance = $this->maxBalance; | ||
} | ||
|
||
$result = false; | ||
if ($balance >= $itemCost) { | ||
$balance -= $itemCost; | ||
$result = true; | ||
} | ||
|
||
$this->saveState($currentTick, $balance); | ||
|
||
return $result; | ||
} | ||
|
||
|
||
/** | ||
* Initializes limiter costs and boundaries | ||
* | ||
* @param float $creditsPerNanosecond | ||
* @param float $maxBalance | ||
*/ | ||
public function initialize(float $creditsPerNanosecond, float $maxBalance) | ||
{ | ||
$this->creditsPerNanosecond = $creditsPerNanosecond; | ||
$this->maxBalance = $maxBalance; | ||
} | ||
|
||
/** | ||
* Method loads last tick and current balance from cache | ||
* | ||
* @return array [$lastTick, $balance] | ||
*/ | ||
private function getState() : array | ||
{ | ||
return [ | ||
$this->lastTick->get(), | ||
$this->balance->get() | ||
]; | ||
} | ||
|
||
/** | ||
* Method saves last tick and current balance into cache | ||
* | ||
* @param integer $lastTick | ||
* @param float $balance | ||
*/ | ||
private function saveState($lastTick, $balance) | ||
{ | ||
$this->lastTick->set($lastTick); | ||
$this->balance->set($balance); | ||
$this->cache->saveDeferred($this->lastTick); | ||
$this->cache->saveDeferred($this->balance); | ||
$this->cache->commit(); | ||
} | ||
} |
Oops, something went wrong.