Skip to content

Commit d405aaf

Browse files
committed
Adds improvements based on feedback.
1 parent dc2f460 commit d405aaf

6 files changed

Lines changed: 108 additions & 34 deletions

File tree

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
namespace DDTrace\Exceptions;
4+
5+
use InvalidArgumentException;
6+
7+
final class InvalidSpanArgument extends InvalidArgumentException
8+
{
9+
public static function forTagKey($key)
10+
{
11+
return new self(
12+
sprintf('Invalid key type in given span tags. Expected string, got %s.', gettype($key))
13+
);
14+
}
15+
16+
public static function forError($error)
17+
{
18+
return new self(
19+
sprintf('Error should be either Exception or Throwable, got %s.', gettype($error))
20+
);
21+
}
22+
}

src/DDTrace/Span.php

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace DDTrace;
44

5+
use DDTrace\Exceptions\InvalidSpanArgument;
56
use Exception;
67
use InvalidArgumentException;
78
use OpenTracing\SpanContext as OpenTracingContext;
@@ -11,7 +12,7 @@
1112
final class Span implements OpenTracingSpan
1213
{
1314
/**
14-
* Name is the name of the operation being measured. Some examples
15+
* Operation Name is the name of the operation being measured. Some examples
1516
* might be "http.handler", "fileserver.upload" or "video.decompress".
1617
* Name should be set on every span.
1718
*
@@ -82,20 +83,20 @@ final class Span implements OpenTracingSpan
8283
* @param SpanContext $context
8384
* @param string $service
8485
* @param string $resource
85-
* @param int|null $start
86+
* @param int|null $startTime
8687
*/
8788
public function __construct(
8889
$operationName,
8990
SpanContext $context,
9091
$service,
9192
$resource,
92-
$start = null
93+
$startTime = null
9394
) {
9495
$this->context = $context;
9596
$this->operationName = (string) $operationName;
9697
$this->service = (string) $service;
9798
$this->resource = (string) $resource;
98-
$this->startTime = $start ?: Time\now();
99+
$this->startTime = $startTime ?: Time\now();
99100
}
100101

101102
/**
@@ -181,9 +182,7 @@ public function setTags(array $tags)
181182

182183
foreach ($tags as $key => $value) {
183184
if ($key !== (string) $key) {
184-
throw new InvalidArgumentException(
185-
sprintf('First argument expected to be string, got %s', gettype($key))
186-
);
185+
throw InvalidSpanArgument::forTagKey($key);
187186
}
188187

189188
if ($key === Tags\SERVICE_NAME) {
@@ -231,28 +230,26 @@ public function getAllTags()
231230
* updated and the error.Error() string is included with a default meta key.
232231
* If the Span has been finished, it will not be modified by this method.
233232
*
234-
* @param Throwable|Exception $e
233+
* @param Throwable|Exception $error
235234
* @throws InvalidArgumentException
236235
*/
237-
public function setError($e)
236+
public function setError($error)
238237
{
239238
if ($this->isFinished()) {
240239
return;
241240
}
242241

243-
if (($e instanceof Exception) || ($e instanceof Throwable)) {
242+
if (($error instanceof Exception) || ($error instanceof Throwable)) {
244243
$this->hasError = true;
245244
$this->setTags([
246-
Tags\ERROR_MSG => $e->getMessage(),
247-
Tags\ERROR_TYPE => get_class($e),
248-
Tags\ERROR_STACK => $e->getTraceAsString(),
245+
Tags\ERROR_MSG => $error->getMessage(),
246+
Tags\ERROR_TYPE => get_class($error),
247+
Tags\ERROR_STACK => $error->getTraceAsString(),
249248
]);
250249
return;
251250
}
252251

253-
throw new InvalidArgumentException(
254-
sprintf('Error should be either Exception or Throwable, got %s.', gettype($e))
255-
);
252+
throw InvalidSpanArgument::forError($error);
256253
}
257254

258255
public function hasError()
@@ -273,12 +270,12 @@ public function finish($finishTime = null, array $logRecords = [])
273270
}
274271

275272
/**
276-
* @param Throwable|Exception $e
273+
* @param Throwable|Exception $error
277274
* @return void
278275
*/
279-
public function finishWithError($e)
276+
public function finishWithError($error)
280277
{
281-
$this->setError($e);
278+
$this->setError($error);
282279
$this->finish();
283280
}
284281

src/DDTrace/Time.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<?php
2+
23
/**
34
* Although DataDog uses nanotime to report spans PHP does not support nanotime
45
* plus, nanotime is a uint64 which is not supported either. Microtime will be used

src/DDTrace/Tracer.php

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,17 @@ public function flush()
164164
return;
165165
}
166166

167+
$tracesToBeSent = $this->shiftFinishedTraces();
168+
169+
if (empty($tracesToBeSent)) {
170+
return;
171+
}
172+
173+
$this->transport->send($tracesToBeSent);
174+
}
175+
176+
private function shiftFinishedTraces()
177+
{
167178
$tracesToBeSent = [];
168179

169180
foreach ($this->traces as $trace) {
@@ -174,18 +185,18 @@ public function flush()
174185
$traceToBeSent = null;
175186
break;
176187
}
177-
$tracesToBeSent[] = $span;
188+
$traceToBeSent[] = $span;
178189
}
179190

180191
if ($traceToBeSent === null) {
181192
continue;
182193
}
183194

184195
$tracesToBeSent[] = $traceToBeSent;
185-
unset($this->traces[$span->getTraceId()]);
196+
unset($this->traces[$traceToBeSent[0]->getTraceId()]);
186197
}
187-
188-
$this->transport->send($tracesToBeSent);
198+
199+
return $tracesToBeSent;
189200
}
190201

191202
private function record(Span $span)

tests/Unit/SpanTest.php

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace DDTrace\Tests\Unit;
44

5+
use DDTrace\Exceptions\InvalidSpanArgument;
56
use DDTrace\SpanContext;
67
use DDTrace\Tags;
78
use DDTrace\Span;
@@ -10,26 +11,26 @@
1011

1112
final class SpanTest extends PHPUnit_Framework_TestCase
1213
{
13-
const NAME = 'test_span';
14+
const OPERATION_NAME = 'test_span';
1415
const SERVICE = 'test_service';
1516
const RESOURCE = 'test_resource';
1617
const ANOTHER_NAME = 'test_span2';
1718
const ANOTHER_SERVICE = 'test_service2';
1819
const ANOTHER_RESOURCE = 'test_resource2';
1920
const ANOTHER_TYPE = 'test_type2';
20-
const META_KEY = 'test_key';
21-
const META_VALUE = 'test_value';
21+
const TAG_KEY = 'test_key';
22+
const TAG_VALUE = 'test_value';
2223
const EXCEPTION_MESSAGE = 'exception message';
2324

2425
public function testCreateSpanSuccess()
2526
{
2627
$span = $this->createSpan();
27-
$span->setTags([self::META_KEY => self::META_VALUE]);
28+
$span->setTags([self::TAG_KEY => self::TAG_VALUE]);
2829

29-
$this->assertSame(self::NAME, $span->getOperationName());
30+
$this->assertSame(self::OPERATION_NAME, $span->getOperationName());
3031
$this->assertSame(self::SERVICE, $span->getService());
3132
$this->assertSame(self::RESOURCE, $span->getResource());
32-
$this->assertSame(self::META_VALUE, $span->getTag(self::META_KEY));
33+
$this->assertSame(self::TAG_VALUE, $span->getTag(self::TAG_KEY));
3334
}
3435

3536
public function testOverwriteOperationNameSuccess()
@@ -39,16 +40,16 @@ public function testOverwriteOperationNameSuccess()
3940
$this->assertSame(self::ANOTHER_NAME, $span->getOperationName());
4041
}
4142

42-
public function testSpanMetaRemainsImmutableAfterFinishing()
43+
public function testSpanTagsRemainImmutableAfterFinishing()
4344
{
4445
$span = $this->createSpan();
4546
$span->finish();
4647

47-
$span->setTags([self::META_KEY => self::META_VALUE]);
48-
$this->assertNull($span->getTag(self::META_KEY));
48+
$span->setTags([self::TAG_KEY => self::TAG_VALUE]);
49+
$this->assertNull($span->getTag(self::TAG_KEY));
4950
}
5051

51-
public function testSpanErrorAddsExpectedMeta()
52+
public function testSpanErrorAddsExpectedTags()
5253
{
5354
$span = $this->createSpan();
5455
$span->setError(new Exception(self::EXCEPTION_MESSAGE));
@@ -67,6 +68,14 @@ public function testSpanErrorRemainsImmutableAfterFinishing()
6768
$this->assertFalse($span->hasError());
6869
}
6970

71+
public function testSpanErrorFailsForInvalidError()
72+
{
73+
$this->expectException(InvalidSpanArgument::class);
74+
$this->expectExceptionMessage('Error should be either Exception or Throwable, got integer.');
75+
$span = $this->createSpan();
76+
$span->setError(1);
77+
}
78+
7079
public function testAddCustomTagsSuccess()
7180
{
7281
$span = $this->createSpan();
@@ -81,12 +90,20 @@ public function testAddCustomTagsSuccess()
8190
$this->assertEquals(self::ANOTHER_TYPE, $span->getType());
8291
}
8392

93+
public function testAddTagsFailsForInvalidTagKey()
94+
{
95+
$this->expectException(InvalidSpanArgument::class);
96+
$this->expectExceptionMessage('Invalid key type in given span tags. Expected string, got integer.');
97+
$span = $this->createSpan();
98+
$span->setTags([self::TAG_KEY]);
99+
}
100+
84101
private function createSpan()
85102
{
86103
$context = SpanContext::createAsRoot();
87104

88105
$span = new Span(
89-
self::NAME,
106+
self::OPERATION_NAME,
90107
$context,
91108
self::SERVICE,
92109
self::RESOURCE

tests/Unit/TracerTest.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use DDTrace\Propagator;
66
use DDTrace\SpanContext;
77
use DDTrace\Tracer;
8+
use DDTrace\Transport;
89
use DDTrace\Transport\Noop as NoopTransport;
910
use OpenTracing\Exceptions\UnsupportedFormat;
1011
use OpenTracing\NoopSpan;
@@ -14,6 +15,7 @@
1415
final class TracerTest extends PHPUnit_Framework_TestCase
1516
{
1617
const OPERATION_NAME = 'test_span';
18+
const ANOTHER_OPERATION_NAME = 'test_span2';
1719
const TAG_KEY = 'test_key';
1820
const TAG_VALUE = 'test_value';
1921
const FORMAT = 'test_format';
@@ -91,4 +93,28 @@ public function testExtractCallsTheRightExtractor()
9193
$actualContext = $tracer->extract(self::FORMAT, $carrier);
9294
$this->assertEquals($expectedContext, $actualContext);
9395
}
96+
97+
public function testOnlyFinishedTracesAreBeingSent()
98+
{
99+
$transport = $this->prophesize(Transport::class);
100+
$tracer = new Tracer($transport->reveal());
101+
$span = $tracer->startSpan(self::OPERATION_NAME);
102+
$tracer->startSpan(self::ANOTHER_OPERATION_NAME, [
103+
'child_of' => $span,
104+
]);
105+
$span->finish();
106+
107+
$span2 = $tracer->startSpan(self::OPERATION_NAME);
108+
$span3 = $tracer->startSpan(self::ANOTHER_OPERATION_NAME, [
109+
'child_of' => $span2,
110+
]);
111+
$span2->finish();
112+
$span3->finish();
113+
114+
$transport->send([
115+
[$span2, $span3],
116+
])->shouldBeCalled();
117+
118+
$tracer->flush();
119+
}
94120
}

0 commit comments

Comments
 (0)