TracerFactory implementation (#38)
* implement TracerFactory, begin migration to recommended library layout, use docker-compose and make to simplify development * add tests for all TracerFactory method, move TraceFactory configuration in constructor * run phan in travis-ci build * rename namespace Tracing into Trace
This commit is contained in:
parent
cf85f7d5f7
commit
0991f72146
|
|
@ -0,0 +1,6 @@
|
|||
<ruleset name="PSR2 extended">
|
||||
<rule ref="PSR2" />
|
||||
<rule ref="Squiz.Strings.DoubleQuoteUsage.NotRequired" />
|
||||
<rule ref="Generic.Arrays.DisallowLongArraySyntax" />
|
||||
<rule ref="PEAR.ControlStructures.MultiLineCondition" />
|
||||
</ruleset>
|
||||
|
|
@ -13,10 +13,12 @@ cache:
|
|||
- $HOME/.composer/cache
|
||||
|
||||
before_script:
|
||||
- pecl install ast-1.0.4
|
||||
- travis_retry composer update ${COMPOSER_FLAGS} --no-interaction --prefer-dist
|
||||
|
||||
script:
|
||||
- vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover
|
||||
- vendor/bin/phan
|
||||
|
||||
after_script:
|
||||
- |
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
DC_RUN_PHP = docker-compose run php
|
||||
|
||||
install:
|
||||
$(DC_RUN_PHP) composer install
|
||||
test:
|
||||
$(DC_RUN_PHP) php ./vendor/bin/phpunit --colors=always
|
||||
phan:
|
||||
$(DC_RUN_PHP) php ./vendor/bin/phan
|
||||
examples: FORCE
|
||||
$(DC_RUN_PHP) php ./examples/AlwaysOnTraceExample.php
|
||||
bash:
|
||||
$(DC_RUN_PHP) bash
|
||||
FORCE:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
version: '3.7'
|
||||
services:
|
||||
php:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: docker/Dockerfile
|
||||
volumes:
|
||||
- ./:/usr/src/myapp
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
FROM php:7.1-buster
|
||||
|
||||
RUN apt-get -y update && apt-get -y install git zip && \
|
||||
curl -sS https://getcomposer.org/installer | php && \
|
||||
mv composer.phar /usr/local/bin/composer && \
|
||||
chmod +x /usr/local/bin/composer && \
|
||||
|
||||
pecl install ast-1.0.4 && \
|
||||
echo "extension=ast.so" >> /usr/local/etc/php/conf.d/docker-php-ext-ast.ini
|
||||
|
||||
WORKDIR /usr/src/myapp
|
||||
|
|
@ -1,14 +1,15 @@
|
|||
<?php
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
use OpenTelemetry\Tracing\SpanContext;
|
||||
use OpenTelemetry\Tracing\Sampler\AlwaysOffSampler;
|
||||
use OpenTelemetry\Tracing\Tracer;
|
||||
use OpenTelemetry\Context\SpanContext;
|
||||
use OpenTelemetry\Trace\Sampler\AlwaysOffSampler;
|
||||
use OpenTelemetry\Trace\Tracer;
|
||||
use OpenTelemetry\Trace\TracerFactory;
|
||||
|
||||
$sampler = AlwaysOffSampler::shouldSample();
|
||||
if ($sampler) {
|
||||
$spanContext = SpanContext::generate(); // or extract from headers
|
||||
$tracer = new Tracer($spanContext);
|
||||
$tracer = TracerFactory::getInstance()
|
||||
->getTracer('io.opentelemetry.contrib.php');
|
||||
|
||||
// start a span, register some events
|
||||
$span = $tracer->createSpan('session.generate');
|
||||
|
|
|
|||
|
|
@ -1,30 +1,29 @@
|
|||
<?php
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
use OpenTelemetry\Tracing\SpanContext;
|
||||
use OpenTelemetry\Tracing\Sampler\AlwaysOnSampler;
|
||||
use OpenTelemetry\Tracing\Tracer;
|
||||
use OpenTelemetry\Trace\TracerFactory;
|
||||
use OpenTelemetry\Trace\Sampler\AlwaysOnSampler;
|
||||
|
||||
$sampler = AlwaysOnSampler::shouldSample();
|
||||
if ($sampler) {
|
||||
$spanContext = SpanContext::generate(); // or extract from headers
|
||||
$tracer = new Tracer($spanContext);
|
||||
$tracer = (TracerFactory::getInstance())
|
||||
->getTracer('io.opentelemetry.contrib.php');
|
||||
|
||||
// start a span, register some events
|
||||
$span = $tracer->createSpan('session.generate');
|
||||
$span->setAttributes(['remote_ip' => '1.2.3.4']);
|
||||
$span->setAttribute('country', 'USA');
|
||||
// start a span, register some events
|
||||
$span = $tracer->createSpan('session.generate');
|
||||
$span->setAttributes(['remote_ip' => '1.2.3.4']);
|
||||
$span->setAttribute('country', 'USA');
|
||||
|
||||
$span->addEvent('found_login', [
|
||||
$span->addEvent('found_login', [
|
||||
'id' => 12345,
|
||||
'username' => 'otuser',
|
||||
]);
|
||||
$span->addEvent('generated_session', [
|
||||
]);
|
||||
$span->addEvent('generated_session', [
|
||||
'id' => md5(microtime(true))
|
||||
]);
|
||||
]);
|
||||
|
||||
$span->end(); // pass status as an optional argument
|
||||
print_r($span); // print the span as a resulting output
|
||||
$span->end(); // pass status as an optional argument
|
||||
print_r($span); // print the span as a resulting output
|
||||
} else {
|
||||
echo "Sampling is not enabled";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Tracing;
|
||||
namespace OpenTelemetry\Context;
|
||||
|
||||
class SpanContext
|
||||
{
|
||||
|
|
@ -60,6 +60,6 @@ class SpanContext
|
|||
/* TODO : Finish this function */
|
||||
public function IsRemote() : bool
|
||||
{
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -4,8 +4,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace OpenTelemetry\Exporter;
|
||||
|
||||
use OpenTelemetry\Exporter\ExporterInterface;
|
||||
use OpenTelemetry\Tracing\Span;
|
||||
use OpenTelemetry\Trace\Span;
|
||||
|
||||
class BasisExporter implements ExporterInterface
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace OpenTelemetry\Exporter;
|
||||
|
||||
use OpenTelemetry\Tracing\Span;
|
||||
use OpenTelemetry\Trace\Span;
|
||||
|
||||
/**
|
||||
* A simple Exporter interface
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace OpenTelemetry\Exporter;
|
||||
|
||||
use OpenTelemetry\Exporter\ExporterInterface;
|
||||
use OpenTelemetry\Tracing\Span;
|
||||
use OpenTelemetry\Trace\Span;
|
||||
|
||||
/**
|
||||
* Class ZipkinExporter - implements the export interface for data transfer via Zipkin protocol
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Tracing;
|
||||
namespace OpenTelemetry\Trace;
|
||||
|
||||
class Event
|
||||
{
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<?php
|
||||
namespace OpenTelemetry\Tracing\Sampler;
|
||||
namespace OpenTelemetry\Trace\Sampler;
|
||||
|
||||
/**
|
||||
* This implementation of the SamplerInterface always returns false.
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<?php
|
||||
namespace OpenTelemetry\Tracing\Sampler;
|
||||
namespace OpenTelemetry\Trace\Sampler;
|
||||
|
||||
/**
|
||||
* This implementation of the SamplerInterface always returns true.
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<?php
|
||||
namespace OpenTelemetry\Tracing\Sampler;
|
||||
namespace OpenTelemetry\Trace\Sampler;
|
||||
|
||||
/**
|
||||
* This interface is used to organize sampling logic.
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Tracing;
|
||||
namespace OpenTelemetry\Trace;
|
||||
|
||||
use Exception;
|
||||
use OpenTelemetry\Context\SpanContext;
|
||||
|
||||
class Span
|
||||
{
|
||||
|
|
@ -31,9 +31,9 @@ class Span
|
|||
// describes the relationship between the Span, its parents, and its children in a Trace. SpanKind describes two independent properties that benefit tracing systems during analysis.
|
||||
// This was also updated recently -> https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/api-tracing.md#spankind
|
||||
|
||||
// Links
|
||||
// Links
|
||||
// A Span may be linked to zero or more other Spans (defined by SpanContext) that are causally related. Links can point to SpanContexts inside a single Trace
|
||||
// or across different Traces. Links can be used to represent batched operations where a Span was initiated by multiple initiating Spans,
|
||||
// or across different Traces. Links can be used to represent batched operations where a Span was initiated by multiple initiating Spans,
|
||||
// each representing a single incoming item being processed in the batch.
|
||||
// https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/overview.md#links-between-spans
|
||||
|
||||
|
|
@ -89,7 +89,7 @@ class Span
|
|||
return Status::new($this->statusCode, $this->statusDescription);
|
||||
}
|
||||
|
||||
// I think this is too simple, see: https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/api-tracing.md#isrecording
|
||||
// I think this is too simple, see: https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/api-tracing.md#isrecording
|
||||
// -> This had an update this past month: https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/api-tracing.md#isrecording
|
||||
public function isRecording(): bool
|
||||
{
|
||||
|
|
@ -181,4 +181,4 @@ class Span
|
|||
throw new Exception("Span is readonly");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace OpenTelemetry;
|
||||
namespace OpenTelemetry\Trace;
|
||||
|
||||
use OpenTelemetry\Tracing\Span;
|
||||
use OpenTelemetry\Trace\Span;
|
||||
|
||||
interface SpanProcessorInterface
|
||||
{
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Tracing;
|
||||
namespace OpenTelemetry\Trace;
|
||||
|
||||
class Status
|
||||
{
|
||||
|
|
@ -2,7 +2,9 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Tracing;
|
||||
namespace OpenTelemetry\Trace;
|
||||
|
||||
use OpenTelemetry\Context\SpanContext;
|
||||
|
||||
class Tracer
|
||||
{
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
namespace OpenTelemetry\Trace;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use OpenTelemetry\Context\SpanContext;
|
||||
use OpenTelemetry\Trace\SpanProcessorInterface;
|
||||
|
||||
class TracerFactory
|
||||
{
|
||||
/**
|
||||
* @var self
|
||||
*/
|
||||
protected static $instance;
|
||||
|
||||
/**
|
||||
* @var Tracer[]
|
||||
*/
|
||||
protected $tracers;
|
||||
|
||||
/**
|
||||
* @var SpanProcessorInterface[]
|
||||
*/
|
||||
protected $spanProcessors;
|
||||
|
||||
/**
|
||||
* TracerFactory constructor.
|
||||
*
|
||||
* @param SpanProcessorInterface[] $spanProcessors
|
||||
*/
|
||||
final private function __construct(array $spanProcessors = [])
|
||||
{
|
||||
foreach ($spanProcessors as $spanProcessor) {
|
||||
if (!$spanProcessor instanceof SpanProcessorInterface) {
|
||||
throw new InvalidArgumentException(
|
||||
sprintf(
|
||||
"Span Processors should be of type %s, but object of type %s provided",
|
||||
SpanProcessorInterface::class,
|
||||
gettype($spanProcessor) == "object" ? get_class($spanProcessor) : gettype($spanProcessor)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$this->spanProcessors = $spanProcessors;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SpanProcessorInterface[] $spanProcessors
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function getInstance(array $spanProcessors = []): self
|
||||
{
|
||||
if (self::$instance instanceof TracerFactory) {
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
$instance = new TracerFactory($spanProcessors);
|
||||
|
||||
return self::$instance = $instance;
|
||||
}
|
||||
|
||||
public function getTracer(string $name, string $version = ""): Tracer
|
||||
{
|
||||
|
||||
if ($this->tracers[$name] instanceof Tracer) {
|
||||
return $this->tracers[$name];
|
||||
}
|
||||
|
||||
$spanContext = SpanContext::generate();
|
||||
return $this->tracers[$name] = new Tracer($spanContext);
|
||||
}
|
||||
}
|
||||
|
|
@ -6,11 +6,9 @@ namespace OpenTelemetry\Tests;
|
|||
|
||||
use OpenTelemetry\Exporter\BasisExporter;
|
||||
use OpenTelemetry\Exporter\ZipkinExporter;
|
||||
use OpenTelemetry\Tracing\Builder;
|
||||
use OpenTelemetry\Tracing\SpanContext;
|
||||
use OpenTelemetry\Tracing\Status;
|
||||
use OpenTelemetry\Tracing\Tracer;
|
||||
use OpenTelemetry\Transport\TarantoolQueueTransport;
|
||||
use OpenTelemetry\Context\SpanContext;
|
||||
use OpenTelemetry\Trace\Status;
|
||||
use OpenTelemetry\Trace\Tracer;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use ReflectionMethod;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,94 @@
|
|||
<?php
|
||||
|
||||
namespace OpenTelemetry\Tests\Trace;
|
||||
|
||||
use Error;
|
||||
use InvalidArgumentException;
|
||||
use OpenTelemetry\Trace\SpanProcessorInterface;
|
||||
use OpenTelemetry\Trace\TracerFactory;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use ReflectionProperty;
|
||||
use StdClass;
|
||||
|
||||
class TracerFactoryTest extends TestCase
|
||||
{
|
||||
public function tearDown()
|
||||
{
|
||||
// since a singleton is tested we need to reset instance after every test
|
||||
$refProperty = new ReflectionProperty(TracerFactory::class, 'instance');
|
||||
$refProperty->setAccessible(true);
|
||||
$refProperty->setValue(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @expectedException Error
|
||||
*/
|
||||
public function shouldNotBeAbleToInstantiateDirectly()
|
||||
{
|
||||
new TracerFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function gettingSameTracerMultipleTimesShouldReturnSameObject()
|
||||
{
|
||||
$tracer1 = TracerFactory::getInstance()->getTracer('test_tracer');
|
||||
$tracer2 = TracerFactory::getInstance()->getTracer('test_tracer');
|
||||
|
||||
$this->assertTrue($tracer1 === $tracer2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function callingSameInstanceMultipleTimesShouldReturnSameFactoryObject()
|
||||
{
|
||||
$instance1 = TracerFactory::getInstance();
|
||||
$instance2 = TracerFactory::getInstance();
|
||||
|
||||
$this->assertTrue($instance1 === $instance2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function shouldInstantiateWithoutErrorIfConfigurationIsOk()
|
||||
{
|
||||
$factory = TracerFactory::getInstance([
|
||||
$this->createMock(SpanProcessorInterface::class),
|
||||
$this->createMock(SpanProcessorInterface::class)
|
||||
]);
|
||||
|
||||
$this->assertInstanceOf(TracerFactory::class, $factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @dataProvider wrongConfigurationDataProvider
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function shouldThrowExceptionIfConfigurationParamsAreInvalid($spanProcessors)
|
||||
{
|
||||
TracerFactory::getInstance($spanProcessors);
|
||||
}
|
||||
|
||||
public function wrongConfigurationDataProvider()
|
||||
{
|
||||
return [
|
||||
'array of numbers' => [
|
||||
'spanProcessors' => [1, -1, 0.1, -0.1, 0]
|
||||
],
|
||||
'array of strings' => [
|
||||
'spanProcessors' => ['aaa', 'bbb', '']
|
||||
],
|
||||
'array of standardObjects' => [
|
||||
'spanProcessors' => [new StdClass(), new StdClass()]
|
||||
],
|
||||
'array of boolean' => [
|
||||
'spanProcessors' => [true, false, null]
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace OpenTelemetry\Tests\Unit\Tracing\Sampler;
|
||||
|
||||
use OpenTelemetry\Tracing\Sampler\AlwaysOffSampler;
|
||||
use OpenTelemetry\Trace\Sampler\AlwaysOffSampler;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
class AlwaysOffSamplerTest extends TestCase
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace OpenTelemetry\Tests\Unit\Tracing\Sampler;
|
||||
|
||||
use OpenTelemetry\Tracing\Sampler\AlwaysOnSampler;
|
||||
use OpenTelemetry\Trace\Sampler\AlwaysOnSampler;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class AlwaysOnTest extends TestCase
|
||||
|
|
|
|||
Loading…
Reference in New Issue