Skip to content

Commit fe41a35

Browse files
committed
Record completed/failed spans via SpanRecorder
1 parent 0ec38de commit fe41a35

8 files changed

Lines changed: 102 additions & 29 deletions

File tree

src/Span/SpanError.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ public function __construct(
1313
public string $message,
1414
public ?string $file,
1515
public ?int $line,
16-
) {
17-
}
16+
) {}
1817

1918
public static function fromThrowable(Throwable $exception): self
2019
{

src/Tracing/Tracer.php

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,20 @@
66

77
use DateTimeImmutable;
88
use LaravelTrace\LaravelTrace\Context\TraceContext;
9+
use LaravelTrace\LaravelTrace\Contracts\SpanRecorder;
910
use LaravelTrace\LaravelTrace\Contracts\TraceContextStore;
1011
use LaravelTrace\LaravelTrace\Contracts\Tracer as TracerContract;
1112
use LaravelTrace\LaravelTrace\Span\Span;
1213
use LaravelTrace\LaravelTrace\Span\SpanType;
1314
use LaravelTrace\LaravelTrace\Trace\Trace;
1415
use LogicException;
15-
use RuntimeException;
1616
use Throwable;
1717

1818
final readonly class Tracer implements TracerContract
1919
{
2020
public function __construct(
2121
private TraceContextStore $contextStore,
22+
private SpanRecorder $spanRecorder,
2223
) {}
2324

2425
public function start(string $name): Trace
@@ -81,16 +82,26 @@ public function clearContext(): void
8182

8283
public function complete(Span $span): Span
8384
{
84-
return $span->complete(
85+
$completed = $span->complete(
8586
new DateTimeImmutable,
8687
);
88+
89+
$this->spanRecorder->record($completed);
90+
91+
return $completed;
8792
}
8893

89-
public function fail(Span $span,Throwable $exception,): Span
90-
{
91-
return $span->fail(
92-
$exception,
93-
new DateTimeImmutable,
94+
public function fail(
95+
Span $span,
96+
Throwable $exception,
97+
): Span {
98+
$failed = $span->fail(
99+
exception: $exception,
100+
finishedAt: new DateTimeImmutable,
94101
);
102+
103+
$this->spanRecorder->record($failed);
104+
105+
return $failed;
95106
}
96107
}

tests/Unit/Context/InMemoryTraceContextStoreTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66
use LaravelTrace\LaravelTrace\Context\TraceContext;
77
use LaravelTrace\LaravelTrace\Trace\TraceId;
88

9-
it('returns null when no context exists', function () {
9+
it('returns null when no context exists', function (): void {
1010
$store = new InMemoryTraceContextStore;
1111

1212
expect($store->get())->toBeNull();
1313
});
1414

15-
it('stores and retrieves a context', function () {
15+
it('stores and retrieves a context', function (): void {
1616
$store = new InMemoryTraceContextStore;
1717

1818
$context = new TraceContext(
@@ -24,7 +24,7 @@
2424
expect($store->get())->toBe($context);
2525
});
2626

27-
it('can clear the current context', function () {
27+
it('can clear the current context', function (): void {
2828
$store = new InMemoryTraceContextStore;
2929

3030
$context = new TraceContext(

tests/Unit/Context/TraceContextTest.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use LaravelTrace\LaravelTrace\Context\TraceContext;
77
use LaravelTrace\LaravelTrace\Span\SpanId;
88
use LaravelTrace\LaravelTrace\Trace\TraceId;
9+
use LaravelTrace\LaravelTrace\Tracing\InMemorySpanRecorder;
910
use LaravelTrace\LaravelTrace\Tracing\Tracer;
1011

1112
it('creates a context with a trace', function (): void {
@@ -50,9 +51,10 @@
5051
->toBe($spanId);
5152
});
5253

53-
it('sets the trace context when starting a trace', function () {
54+
it('sets the trace context when starting a trace', function (): void {
5455
$store = new InMemoryTraceContextStore;
55-
$tracer = new Tracer($store);
56+
$record = new InMemorySpanRecorder;
57+
$tracer = new Tracer($store, $record);
5658

5759
$trace = $tracer->start('CreateOrder');
5860

tests/Unit/Span/SpanErrorTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
use LaravelTrace\LaravelTrace\Span\SpanError;
66

7-
it('creates an error from a throwable', function () {
7+
it('creates an error from a throwable', function (): void {
88
$exception = new RuntimeException(
99
'Payment provider timed out',
1010
);

tests/Unit/Span/SpanTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
->toBe($parent->id);
5151
});
5252

53-
it('completes a span', function () {
53+
it('completes a span', function (): void {
5454
$traceId = TraceId::generate();
5555

5656
$span = Span::start(
@@ -71,7 +71,7 @@
7171
->toBe(SpanStatus::Running);
7272
});
7373

74-
it('fails a span', function () {
74+
it('fails a span', function (): void {
7575
$traceId = TraceId::generate();
7676

7777
$span = Span::start(
@@ -86,7 +86,7 @@
8686
'Inventory service failed',
8787
);
8888

89-
$failed = $span->fail($exception,$finishedAt);
89+
$failed = $span->fail($exception, $finishedAt);
9090

9191
expect($failed->status)
9292
->toBe(SpanStatus::Failed)

tests/Unit/Tracing/SpanScopeTest.php

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@
77
use LaravelTrace\LaravelTrace\Span\SpanStatus;
88
use LaravelTrace\LaravelTrace\Span\SpanType;
99
use LaravelTrace\LaravelTrace\Trace\TraceId;
10+
use LaravelTrace\LaravelTrace\Tracing\InMemorySpanRecorder;
1011
use LaravelTrace\LaravelTrace\Tracing\Tracer;
1112

12-
it('restores the previous context when closed', function () {
13+
it('restores the previous context when closed', function (): void {
1314
$store = new InMemoryTraceContextStore;
14-
$tracer = new Tracer($store);
15+
$record = new InMemorySpanRecorder;
16+
$tracer = new Tracer($store, $record);
1517

1618
$tracer->start('CreateOrder');
1719

@@ -36,9 +38,10 @@
3638
->toBe($parentContext);
3739
});
3840

39-
it('fails a span and restores the previous context', function () {
40-
$store = new InMemoryTraceContextStore();
41-
$tracer = new Tracer($store);
41+
it('fails a span and restores the previous context', function (): void {
42+
$store = new InMemoryTraceContextStore;
43+
$record = new InMemorySpanRecorder;
44+
$tracer = new Tracer($store, $record);
4245

4346
$tracer->start('CreateOrder');
4447

@@ -70,7 +73,7 @@
7073
->toBe($parentContext);
7174
});
7275

73-
it('does not retain an error when completing a span', function () {
76+
it('does not retain an error when completing a span', function (): void {
7477
$traceId = TraceId::generate();
7578

7679
$span = Span::start(
@@ -80,7 +83,7 @@
8083
);
8184

8285
$completed = $span->complete(
83-
new DateTimeImmutable(),
86+
new DateTimeImmutable,
8487
);
8588

8689
expect($completed->status)

tests/Unit/Tracing/TracerTest.php

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,15 @@
66
use LaravelTrace\LaravelTrace\Span\SpanStatus;
77
use LaravelTrace\LaravelTrace\Span\SpanType;
88
use LaravelTrace\LaravelTrace\Trace\TraceStatus;
9+
use LaravelTrace\LaravelTrace\Tracing\InMemorySpanRecorder;
910
use LaravelTrace\LaravelTrace\Tracing\Tracer;
1011

11-
it('starts a trace', function () {
12+
it('starts a trace', function (): void {
13+
$recorder = new InMemorySpanRecorder;
14+
1215
$tracer = new Tracer(
13-
new InMemoryTraceContextStore(),
16+
new InMemoryTraceContextStore,
17+
$recorder,
1418
);
1519

1620
$trace = $tracer->start('CreateOrder');
@@ -21,9 +25,11 @@
2125
->toBe(TraceStatus::Running);
2226
});
2327

24-
it('starts a span inside a trace', function () {
28+
it('starts a span inside a trace', function (): void {
29+
$recorder = new InMemorySpanRecorder;
2530
$tracer = new Tracer(
26-
new InMemoryTraceContextStore(),
31+
new InMemoryTraceContextStore,
32+
$recorder,
2733
);
2834

2935
$trace = $tracer->start('CreateOrder');
@@ -44,3 +50,55 @@
4450
->and($span->status)
4551
->toBe(SpanStatus::Running);
4652
});
53+
54+
it('records a completed span', function (): void {
55+
$recorder = new InMemorySpanRecorder;
56+
57+
$tracer = new Tracer(
58+
new InMemoryTraceContextStore,
59+
$recorder,
60+
);
61+
62+
$tracer->start('CreateOrder');
63+
64+
$scope = $tracer->span(
65+
'ReserveInventory',
66+
SpanType::Action,
67+
);
68+
69+
$completed = $scope->close();
70+
71+
expect($recorder->all())
72+
->toHaveCount(1)
73+
->and($recorder->all()[0])
74+
->toBe($completed);
75+
});
76+
77+
it('records a failed span', function (): void {
78+
$recorder = new InMemorySpanRecorder;
79+
80+
$tracer = new Tracer(
81+
new InMemoryTraceContextStore,
82+
$recorder,
83+
);
84+
85+
$tracer->start('CreateOrder');
86+
87+
$scope = $tracer->span(
88+
'ChargePayment',
89+
SpanType::Action,
90+
);
91+
92+
$exception = new RuntimeException(
93+
'Payment provider failed',
94+
);
95+
96+
$failed = $scope->fail($exception);
97+
98+
expect($recorder->all())
99+
->toHaveCount(1)
100+
->and($recorder->all()[0])
101+
->toBe($failed)
102+
->and($failed->status)
103+
->toBe(SpanStatus::Failed);
104+
});

0 commit comments

Comments
 (0)