Skip to content
This repository was archived by the owner on Aug 11, 2025. It is now read-only.

Commit 7254d1c

Browse files
authored
Merge pull request #46 from opentracing/21_adds_mock_tracer
[#21] Adds mock tracer.
2 parents 5f9eec4 + bbfd21c commit 7254d1c

18 files changed

+877
-14
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,15 @@ Tracers will throw an exception if the requested format is not handled by them.
272272
- `Tracer::FORMAT_BINARY` makes no assumptions about the data format other than it is
273273
proprietary and each Tracer can handle it as it wants.
274274

275+
## Mock implementation
276+
277+
OpenTracing PHP comes with a mock implementation, it has three purposes:
278+
279+
1. Helps to iron the API.
280+
2. Works as a reference implementation.
281+
3. Enhances vendor agnostic unit testing as it allows developers to inspect the tracing objects
282+
in order to do assertions about them.
283+
275284
## Coding Style
276285

277286
OpenTracing PHP follows the [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
},
2626
"autoload-dev": {
2727
"psr-4": {
28-
"OpenTracingTests\\": "./tests/"
28+
"OpenTracing\\Tests\\": "./tests/OpenTracing"
2929
}
3030
},
3131
"scripts": {

src/OpenTracing/Mock/MockScope.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
namespace OpenTracing\Mock;
4+
5+
use OpenTracing\Scope;
6+
use OpenTracing\Span;
7+
8+
final class MockScope implements Scope
9+
{
10+
/**
11+
* @var Span
12+
*/
13+
private $span;
14+
15+
/**
16+
* @var MockScopeManager
17+
*/
18+
private $scopeManager;
19+
20+
public function __construct(MockScopeManager $scopeManager, Span $span)
21+
{
22+
$this->scopeManager = $scopeManager;
23+
$this->span = $span;
24+
}
25+
26+
/**
27+
* {@inheritdoc}
28+
*/
29+
public function close()
30+
{
31+
$this->scopeManager->deactivate($this);
32+
}
33+
34+
/**
35+
* {@inheritdoc}
36+
* @return Span|MockSpan
37+
*/
38+
public function getSpan()
39+
{
40+
return $this->span;
41+
}
42+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
namespace OpenTracing\Mock;
4+
5+
use OpenTracing\Scope;
6+
use OpenTracing\ScopeManager;
7+
use OpenTracing\Span;
8+
9+
final class MockScopeManager implements ScopeManager
10+
{
11+
/**
12+
* @var array|Scope[]
13+
*/
14+
private $scopes = [];
15+
16+
/**
17+
* {@inheritdoc}
18+
*/
19+
public function activate(Span $span)
20+
{
21+
$this->scopes[] = new MockScope($this, $span);
22+
}
23+
24+
/**
25+
* {@inheritdoc}
26+
*/
27+
public function getActive()
28+
{
29+
if (empty($this->scopes)) {
30+
return null;
31+
}
32+
33+
return $this->scopes[count($this->scopes) - 1];
34+
}
35+
36+
/**
37+
* {@inheritdoc}
38+
* @param Span|MockSpan $span
39+
*/
40+
public function getScope(Span $span)
41+
{
42+
$scopeLength = count($this->scopes);
43+
44+
for ($i = 0; $i < $scopeLength; $i++) {
45+
if ($span === $this->scopes[$i]->getSpan()) {
46+
return $this->scopes[$i];
47+
}
48+
}
49+
50+
return null;
51+
}
52+
53+
public function deactivate(MockScope $scope)
54+
{
55+
$scopeLength = count($this->scopes);
56+
57+
for ($i = 0; $i < $scopeLength; $i++) {
58+
if ($scope === $this->scopes[$i]) {
59+
unset($this->scopes[$i]);
60+
}
61+
}
62+
}
63+
}

src/OpenTracing/Mock/MockSpan.php

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
<?php
2+
3+
namespace OpenTracing\Mock;
4+
5+
use OpenTracing\ScopeManager;
6+
use OpenTracing\Span;
7+
use OpenTracing\SpanContext;
8+
9+
final class MockSpan implements Span
10+
{
11+
/**
12+
* @var string
13+
*/
14+
private $operationName;
15+
16+
/**
17+
* @var MockSpanContext
18+
*/
19+
private $context;
20+
21+
/**
22+
* @var array
23+
*/
24+
private $tags = [];
25+
26+
/**
27+
* @var array
28+
*/
29+
private $logs = [];
30+
31+
/**
32+
* @var int
33+
*/
34+
private $startTime;
35+
36+
/**
37+
* @var int|null
38+
*/
39+
private $duration;
40+
41+
/**
42+
* @var bool
43+
*/
44+
private $closeOnFinish;
45+
46+
/**
47+
* @var ScopeManager
48+
*/
49+
private $scopeManager;
50+
51+
public function __construct(
52+
ScopeManager $scopeManager,
53+
$operationName,
54+
MockSpanContext $context,
55+
$startTime = null,
56+
$closeOnFinish = false
57+
) {
58+
$this->scopeManager = $scopeManager;
59+
$this->operationName = $operationName;
60+
$this->context = $context;
61+
$this->startTime = $startTime ?: time();
62+
$this->closeOnFinish = $closeOnFinish;
63+
}
64+
65+
/**
66+
* {@inheritdoc}
67+
*/
68+
public function getOperationName()
69+
{
70+
return $this->operationName;
71+
}
72+
73+
/**
74+
* {@inheritdoc}
75+
* @return SpanContext|MockSpanContext
76+
*/
77+
public function getContext()
78+
{
79+
return $this->context;
80+
}
81+
82+
public function getStartTime()
83+
{
84+
return $this->startTime;
85+
}
86+
87+
/**
88+
* {@inheritdoc}
89+
*/
90+
public function finish($finishTime = null)
91+
{
92+
$finishTime = ($finishTime ?: time());
93+
$this->duration = $finishTime - $this->startTime;
94+
95+
if (!$this->closeOnFinish) {
96+
return;
97+
}
98+
99+
if (($scope = $this->scopeManager->getScope($this)) !== null) {
100+
$scope->close();
101+
}
102+
}
103+
104+
public function isFinished()
105+
{
106+
return $this->duration !== null;
107+
}
108+
109+
public function getDuration()
110+
{
111+
return $this->duration;
112+
}
113+
114+
/**
115+
* {@inheritdoc}
116+
*/
117+
public function overwriteOperationName($newOperationName)
118+
{
119+
$this->operationName = (string) $newOperationName;
120+
}
121+
122+
/**
123+
* {@inheritdoc}
124+
*/
125+
public function setTag($key, $value)
126+
{
127+
$this->tags[$key] = $value;
128+
}
129+
130+
public function getTags()
131+
{
132+
return $this->tags;
133+
}
134+
135+
/**
136+
* {@inheritdoc}
137+
*/
138+
public function log(array $fields = [], $timestamp = null)
139+
{
140+
$this->logs[] = [
141+
'timestamp' => $timestamp ?: time(),
142+
'fields' => $fields,
143+
];
144+
}
145+
146+
public function getLogs()
147+
{
148+
return $this->logs;
149+
}
150+
151+
/**
152+
* {@inheritdoc}
153+
*/
154+
public function addBaggageItem($key, $value)
155+
{
156+
$this->context = $this->context->withBaggageItem($key, $value);
157+
}
158+
159+
/**
160+
* {@inheritdoc}
161+
*/
162+
public function getBaggageItem($key)
163+
{
164+
return $this->context->getBaggageItem($key);
165+
}
166+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<?php
2+
3+
namespace OpenTracing\Mock;
4+
5+
use ArrayIterator;
6+
use OpenTracing\SpanContext;
7+
8+
final class MockSpanContext implements SpanContext
9+
{
10+
/**
11+
* @var int
12+
*/
13+
private $traceId;
14+
15+
/**
16+
* @var int
17+
*/
18+
private $spanId;
19+
20+
/**
21+
* @var bool
22+
*/
23+
private $isSampled;
24+
25+
/**
26+
* @var array
27+
*/
28+
private $items;
29+
30+
private function __construct($traceId, $spanId, $isSampled, array $items)
31+
{
32+
$this->traceId = $traceId;
33+
$this->spanId = $spanId;
34+
$this->isSampled = $isSampled;
35+
$this->items = $items;
36+
}
37+
38+
public static function create($traceId, $spanId, $sampled = true, array $items = [])
39+
{
40+
return new self($traceId, $spanId, $sampled, $items);
41+
}
42+
43+
public static function createAsRoot($sampled = true, array $items = [])
44+
{
45+
$traceId = $spanId = self::nextId();
46+
return new self($traceId, $spanId, $sampled, $items);
47+
}
48+
49+
public static function createAsChildOf(MockSpanContext $spanContext)
50+
{
51+
$spanId = self::nextId();
52+
return new self($spanContext->traceId, $spanId, $spanContext->isSampled, $spanContext->items);
53+
}
54+
55+
public function getTraceId()
56+
{
57+
return $this->traceId;
58+
}
59+
60+
public function getSpanId()
61+
{
62+
return $this->spanId;
63+
}
64+
65+
public function isSampled()
66+
{
67+
return $this->isSampled;
68+
}
69+
70+
/**
71+
* {@inheritdoc}
72+
*/
73+
public function getIterator()
74+
{
75+
return new ArrayIterator($this->items);
76+
}
77+
78+
/**
79+
* {@inheritdoc}
80+
*/
81+
public function getBaggageItem($key)
82+
{
83+
return array_key_exists($key, $this->items) ? $this->items[$key] : null;
84+
}
85+
86+
/**
87+
* {@inheritdoc}
88+
*/
89+
public function withBaggageItem($key, $value)
90+
{
91+
return new self($this->traceId, $this->spanId, $this->isSampled, array_merge($this->items, [$key => $value]));
92+
}
93+
94+
private static function nextId()
95+
{
96+
return mt_rand(0, 99999);
97+
}
98+
}

0 commit comments

Comments
 (0)