Skip to content

Commit

Permalink
Merge pull request #49 from summerKK/support-percentageSampler-20230818
Browse files Browse the repository at this point in the history
feat: zipkin support PercentageSampler
  • Loading branch information
KinaneD authored Nov 9, 2023
2 parents ad404e9 + 12d8794 commit 5ca6e81
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 6 deletions.
2 changes: 2 additions & 0 deletions config/tracing.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@
'max_tag_len' => 1048576,
'request_timeout' => 5,
],
'sampler_class' => \Zipkin\Samplers\BinarySampler::class,
'percentage_sampler_rate' => env('ZIPKIN_PERCENTAGE_SAMPLER_RATE', 0.2),
],

];
18 changes: 15 additions & 3 deletions src/Drivers/Zipkin/ZipkinTracer.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ class ZipkinTracer implements Tracer
*/
protected $reporter;

/**
* @var Sampler|null
*/
protected $sampler;

/**
* @var \Zipkin\DefaultTracing|\Zipkin\Tracing
*/
Expand Down Expand Up @@ -107,21 +112,24 @@ class ZipkinTracer implements Tracer
* @param bool|null $usesTraceId128bits
* @param int|null $requestTimeout
* @param Reporter|null $reporter
* @param Sampler|null $sampler
*/
public function __construct(
string $serviceName,
string $host,
int $port,
?bool $usesTraceId128bits = false,
?int $requestTimeout = 5,
?Reporter $reporter = null
?Reporter $reporter = null,
?Sampler $sampler = null
) {
$this->serviceName = $serviceName;
$this->host = $host;
$this->port = $port;
$this->usesTraceId128bits = $usesTraceId128bits;
$this->requestTimeout = $requestTimeout;
$this->reporter = $reporter;
$this->sampler = $sampler;
}

/**
Expand Down Expand Up @@ -320,7 +328,7 @@ public function flush(): void
protected function createReporter(): Reporter
{
if (!$this->reporter) {
return new HttpReporter([
$this->reporter = new HttpReporter([
'endpoint_url' => sprintf('http://%s:%s/api/v2/spans', $this->host, $this->port),
'timeout' => $this->requestTimeout,
]);
Expand Down Expand Up @@ -348,7 +356,11 @@ protected function createEndpoint(): Endpoint
*/
protected function createSampler(): Sampler
{
return BinarySampler::createAsAlwaysSample();
if (!$this->sampler) {
$this->sampler = BinarySampler::createAsAlwaysSample();
}

return $this->sampler;
}

protected function registerDefaultExtractionFormats(): void
Expand Down
33 changes: 32 additions & 1 deletion src/TracingDriverManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@

use Illuminate\Contracts\Config\Repository;
use Illuminate\Support\Manager;
use InvalidArgumentException;
use Vinelab\Tracing\Contracts\Tracer;
use Vinelab\Tracing\Drivers\Null\NullTracer;
use Vinelab\Tracing\Drivers\Zipkin\ZipkinTracer;
use Zipkin\Samplers\BinarySampler;
use Zipkin\Samplers\PercentageSampler;

class TracingDriverManager extends Manager
{
Expand Down Expand Up @@ -43,6 +46,7 @@ public function getDefaultDriver()
* Create an instance of Zipkin tracing engine
*
* @return ZipkinTracer|Tracer
* @throws InvalidArgumentException
*/
public function createZipkinDriver()
{
Expand All @@ -51,7 +55,9 @@ public function createZipkinDriver()
$this->config->get('tracing.zipkin.host'),
$this->config->get('tracing.zipkin.port'),
$this->config->get('tracing.zipkin.options.128bit'),
$this->config->get('tracing.zipkin.options.request_timeout', 5)
$this->config->get('tracing.zipkin.options.request_timeout', 5),
null,
$this->getZipkinSampler()
);

ZipkinTracer::setMaxTagLen(
Expand All @@ -65,4 +71,29 @@ public function createNullDriver()
{
return new NullTracer();
}

/**
* @return BinarySampler|PercentageSampler
* @throws InvalidArgumentException
*/
protected function getZipkinSampler()
{
$samplerClassName = $this->config->get('tracing.zipkin.sampler_class');
if (!class_exists($samplerClassName)) {
throw new InvalidArgumentException(
\sprintf('Invalid sampler class. Expected `BinarySampler` or `PercentageSampler`, got %f', $samplerClassName)
);
}

switch ($samplerClassName) {
case BinarySampler::class:
$sampler = BinarySampler::createAsAlwaysSample();
break;
case PercentageSampler::class:
$sampler = PercentageSampler::create($this->config->get('tracing.zipkin.percentage_sampler_rate'));
break;
}

return $sampler;
}
}
7 changes: 5 additions & 2 deletions tests/Zipkin/InteractsWithZipkin.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Vinelab\Tracing\Drivers\Zipkin\ZipkinTracer;
use Zipkin\Recording\Span;
use Zipkin\Reporter;
use Zipkin\Sampler;

trait InteractsWithZipkin
{
Expand All @@ -15,6 +16,7 @@ trait InteractsWithZipkin
* @param int $port
* @param int $requestTimeout
* @param bool $usesTraceId128bits
* @param Sampler|null $sampler
* @return ZipkinTracer
*/
protected function createTracer(
Expand All @@ -23,10 +25,11 @@ protected function createTracer(
string $host = 'localhost',
int $port = 9411,
int $requestTimeout = 5,
bool $usesTraceId128bits = false
bool $usesTraceId128bits = false,
?Sampler $sampler = null
): ZipkinTracer
{
$tracer = new ZipkinTracer($serviceName, $host, $port, $usesTraceId128bits, $requestTimeout, $reporter);
$tracer = new ZipkinTracer($serviceName, $host, $port, $usesTraceId128bits, $requestTimeout, $reporter, $sampler);
$tracer->init();

return $tracer;
Expand Down
74 changes: 74 additions & 0 deletions tests/Zipkin/TracerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Vinelab\Tracing\Tests\Zipkin;

use Carbon\Carbon;
use Closure;
use Google\Cloud\PubSub\Message;
use GuzzleHttp\Psr7\Request as PsrRequest;
use Illuminate\Http\Request;
Expand All @@ -16,11 +17,52 @@
use Vinelab\Tracing\Propagation\Formats;
use Vinelab\Tracing\Tests\Fixtures\NoopReporter;
use Zipkin\Propagation\TraceContext;
use Zipkin\Recording\Span;
use Zipkin\Samplers\BinarySampler;
use Zipkin\Samplers\PercentageSampler;

class TracerTest extends TestCase
{
use InteractsWithZipkin;

/** @test */
public function create_tracer_with_BinarySampler()
{
$reporter = Mockery::spy(NoopReporter::class);

$sampler = BinarySampler::createAsAlwaysSample();

$tracer = $this->createTracer($reporter, 'orders', '192.88.105.145', 9444, 5, false, $sampler);

$this->assertSpan($reporter, $tracer);
}

/** @test */
public function create_tracer_with_PercentageSampler_1_rate()
{
$reporter = Mockery::spy(NoopReporter::class);

$sampler = PercentageSampler::create(1);

$tracer = $this->createTracer($reporter, 'orders', '192.88.105.145', 9444, 5, false, $sampler);

$this->assertSpan($reporter, $tracer);
}

/** @test */
public function create_tracer_with_PercentageSampler_0_rate()
{
$reporter = Mockery::spy(NoopReporter::class);

$sampler = PercentageSampler::create(0);

$tracer = $this->createTracer($reporter, 'orders', '192.88.105.145', 9444, 5, false, $sampler);

$this->assertSpan($reporter, $tracer,function ($spans){
$this->assertEmpty($spans);
});
}

/** @test */
public function configure_reporter()
{
Expand Down Expand Up @@ -362,4 +404,36 @@ protected function assertValidTraceContext(SpanContext $spanContext): void
$this->assertNotNull($spanContext);
$this->assertInstanceOf(TraceContext::class, $spanContext->getRawContext());
}

protected function assertSpan($reporter, ZipkinTracer $tracer, Closure $assert = null)
{
$startTimestamp = intval(microtime(true) * 1000000);
$span = $tracer->startSpan('Http Request', null, $startTimestamp);
$span->setName('Create Order');
$span->tag('request_path', 'api/orders');
$span->annotate('Create Payment');
$span->annotate('Update Order Status');
$finishTimestamp = intval(microtime(true) * 1000000);
$span->finish($finishTimestamp);
$tracer->flush();

if (!$assert) {
$assert = function ($spans) use ($startTimestamp, $finishTimestamp) {
/** @var Span $span */
$span = $this->shiftSpan($spans);
$this->assertEquals('Create Order', $span->getName());
$this->assertEquals($finishTimestamp - $startTimestamp, $span->getDuration());
$this->assertEquals('api/orders', Arr::get($span->getTags(), 'request_path'));
$this->assertEquals('Create Payment', Arr::get($span->getAnnotations(), '0.value'));
$this->assertEquals('Update Order Status', Arr::get($span->getAnnotations(), '1.value'));
};
}

$reporter->shouldHaveReceived('report')->with(
Mockery::on(function ($spans) use ($assert) {
$assert($spans);
return true;
})
);
}
}

0 comments on commit 5ca6e81

Please sign in to comment.