Skip to content

Commit

Permalink
Merge pull request #46 from opentracing/21_adds_mock_tracer
Browse files Browse the repository at this point in the history
[#21] Adds mock tracer.
  • Loading branch information
jcchavezs authored Mar 18, 2018
2 parents 5f9eec4 + bbfd21c commit 7254d1c
Show file tree
Hide file tree
Showing 18 changed files with 877 additions and 14 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,15 @@ Tracers will throw an exception if the requested format is not handled by them.
- `Tracer::FORMAT_BINARY` makes no assumptions about the data format other than it is
proprietary and each Tracer can handle it as it wants.

## Mock implementation

OpenTracing PHP comes with a mock implementation, it has three purposes:

1. Helps to iron the API.
2. Works as a reference implementation.
3. Enhances vendor agnostic unit testing as it allows developers to inspect the tracing objects
in order to do assertions about them.

## Coding Style

OpenTracing PHP follows the [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
},
"autoload-dev": {
"psr-4": {
"OpenTracingTests\\": "./tests/"
"OpenTracing\\Tests\\": "./tests/OpenTracing"
}
},
"scripts": {
Expand Down
42 changes: 42 additions & 0 deletions src/OpenTracing/Mock/MockScope.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace OpenTracing\Mock;

use OpenTracing\Scope;
use OpenTracing\Span;

final class MockScope implements Scope
{
/**
* @var Span
*/
private $span;

/**
* @var MockScopeManager
*/
private $scopeManager;

public function __construct(MockScopeManager $scopeManager, Span $span)
{
$this->scopeManager = $scopeManager;
$this->span = $span;
}

/**
* {@inheritdoc}
*/
public function close()
{
$this->scopeManager->deactivate($this);
}

/**
* {@inheritdoc}
* @return Span|MockSpan
*/
public function getSpan()
{
return $this->span;
}
}
63 changes: 63 additions & 0 deletions src/OpenTracing/Mock/MockScopeManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

namespace OpenTracing\Mock;

use OpenTracing\Scope;
use OpenTracing\ScopeManager;
use OpenTracing\Span;

final class MockScopeManager implements ScopeManager
{
/**
* @var array|Scope[]
*/
private $scopes = [];

/**
* {@inheritdoc}
*/
public function activate(Span $span)
{
$this->scopes[] = new MockScope($this, $span);
}

/**
* {@inheritdoc}
*/
public function getActive()
{
if (empty($this->scopes)) {
return null;
}

return $this->scopes[count($this->scopes) - 1];
}

/**
* {@inheritdoc}
* @param Span|MockSpan $span
*/
public function getScope(Span $span)
{
$scopeLength = count($this->scopes);

for ($i = 0; $i < $scopeLength; $i++) {
if ($span === $this->scopes[$i]->getSpan()) {
return $this->scopes[$i];
}
}

return null;
}

public function deactivate(MockScope $scope)
{
$scopeLength = count($this->scopes);

for ($i = 0; $i < $scopeLength; $i++) {
if ($scope === $this->scopes[$i]) {
unset($this->scopes[$i]);
}
}
}
}
166 changes: 166 additions & 0 deletions src/OpenTracing/Mock/MockSpan.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
<?php

namespace OpenTracing\Mock;

use OpenTracing\ScopeManager;
use OpenTracing\Span;
use OpenTracing\SpanContext;

final class MockSpan implements Span
{
/**
* @var string
*/
private $operationName;

/**
* @var MockSpanContext
*/
private $context;

/**
* @var array
*/
private $tags = [];

/**
* @var array
*/
private $logs = [];

/**
* @var int
*/
private $startTime;

/**
* @var int|null
*/
private $duration;

/**
* @var bool
*/
private $closeOnFinish;

/**
* @var ScopeManager
*/
private $scopeManager;

public function __construct(
ScopeManager $scopeManager,
$operationName,
MockSpanContext $context,
$startTime = null,
$closeOnFinish = false
) {
$this->scopeManager = $scopeManager;
$this->operationName = $operationName;
$this->context = $context;
$this->startTime = $startTime ?: time();
$this->closeOnFinish = $closeOnFinish;
}

/**
* {@inheritdoc}
*/
public function getOperationName()
{
return $this->operationName;
}

/**
* {@inheritdoc}
* @return SpanContext|MockSpanContext
*/
public function getContext()
{
return $this->context;
}

public function getStartTime()
{
return $this->startTime;
}

/**
* {@inheritdoc}
*/
public function finish($finishTime = null)
{
$finishTime = ($finishTime ?: time());
$this->duration = $finishTime - $this->startTime;

if (!$this->closeOnFinish) {
return;
}

if (($scope = $this->scopeManager->getScope($this)) !== null) {
$scope->close();
}
}

public function isFinished()
{
return $this->duration !== null;
}

public function getDuration()
{
return $this->duration;
}

/**
* {@inheritdoc}
*/
public function overwriteOperationName($newOperationName)
{
$this->operationName = (string) $newOperationName;
}

/**
* {@inheritdoc}
*/
public function setTag($key, $value)
{
$this->tags[$key] = $value;
}

public function getTags()
{
return $this->tags;
}

/**
* {@inheritdoc}
*/
public function log(array $fields = [], $timestamp = null)
{
$this->logs[] = [
'timestamp' => $timestamp ?: time(),
'fields' => $fields,
];
}

public function getLogs()
{
return $this->logs;
}

/**
* {@inheritdoc}
*/
public function addBaggageItem($key, $value)
{
$this->context = $this->context->withBaggageItem($key, $value);
}

/**
* {@inheritdoc}
*/
public function getBaggageItem($key)
{
return $this->context->getBaggageItem($key);
}
}
98 changes: 98 additions & 0 deletions src/OpenTracing/Mock/MockSpanContext.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<?php

namespace OpenTracing\Mock;

use ArrayIterator;
use OpenTracing\SpanContext;

final class MockSpanContext implements SpanContext
{
/**
* @var int
*/
private $traceId;

/**
* @var int
*/
private $spanId;

/**
* @var bool
*/
private $isSampled;

/**
* @var array
*/
private $items;

private function __construct($traceId, $spanId, $isSampled, array $items)
{
$this->traceId = $traceId;
$this->spanId = $spanId;
$this->isSampled = $isSampled;
$this->items = $items;
}

public static function create($traceId, $spanId, $sampled = true, array $items = [])
{
return new self($traceId, $spanId, $sampled, $items);
}

public static function createAsRoot($sampled = true, array $items = [])
{
$traceId = $spanId = self::nextId();
return new self($traceId, $spanId, $sampled, $items);
}

public static function createAsChildOf(MockSpanContext $spanContext)
{
$spanId = self::nextId();
return new self($spanContext->traceId, $spanId, $spanContext->isSampled, $spanContext->items);
}

public function getTraceId()
{
return $this->traceId;
}

public function getSpanId()
{
return $this->spanId;
}

public function isSampled()
{
return $this->isSampled;
}

/**
* {@inheritdoc}
*/
public function getIterator()
{
return new ArrayIterator($this->items);
}

/**
* {@inheritdoc}
*/
public function getBaggageItem($key)
{
return array_key_exists($key, $this->items) ? $this->items[$key] : null;
}

/**
* {@inheritdoc}
*/
public function withBaggageItem($key, $value)
{
return new self($this->traceId, $this->spanId, $this->isSampled, array_merge($this->items, [$key => $value]));
}

private static function nextId()
{
return mt_rand(0, 99999);
}
}
Loading

0 comments on commit 7254d1c

Please sign in to comment.