Test Failed
Push — master ( 86fa5f...d794d1 )
by Dmitry
02:18
created

TracingTest::testBasisConverter()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 27
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 20
nc 1
nop 0
dl 0
loc 27
rs 9.6
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
use OpenTelemetry\Exporter\BasisExporter;
6
use OpenTelemetry\Exporter\ZipkinExporter;
7
use OpenTelemetry\Tracing\Builder;
8
use OpenTelemetry\Tracing\SpanContext;
9
use OpenTelemetry\Tracing\Status;
10
use OpenTelemetry\Tracing\Tracer;
11
use OpenTelemetry\Transport\TarantoolQueueTransport;
12
use PHPUnit\Framework\TestCase;
13
14
class TracingTest extends TestCase
15
{
16
    public function testContextGenerationAndRestore()
17
    {
18
        $spanContext = SpanContext::generate();
19
        $this->assertSame(strlen($spanContext->getTraceId()), 32);
20
        $this->assertSame(strlen($spanContext->getSpanId()), 16);
21
22
        $spanContext2 = SpanContext::generate();
23
        $this->assertNotSame($spanContext->getTraceId(), $spanContext2->getTraceId());
24
        $this->assertNotSame($spanContext->getSpanId(), $spanContext2->getSpanId());
25
26
        $spanContext3 = SpanContext::restore($spanContext->getTraceId(), $spanContext->getSpanId());
27
        $this->assertSame($spanContext3->getTraceId(), $spanContext->getTraceId());
28
        $this->assertSame($spanContext3->getSpanId(), $spanContext->getSpanId());
29
    }
30
31
    public function testTracerSpanContextRestore()
32
    {
33
        $tracer = new Tracer();
34
        $spanContext = $tracer->getActiveSpan()->getSpanContext();
35
36
        $spanContext2 = SpanContext::restore($spanContext->getTraceId(), $spanContext->getSpanId());
37
        $tracer2 = new Tracer($spanContext2);
38
39
        $this->assertSame($tracer->getActiveSpan()->getSpanContext()->getTraceId(), $tracer2->getActiveSpan()->getSpanContext()->getTraceId());
40
    }
41
42
    public function testSpanNameUpdate()
43
    {
44
        $database = (new Tracer)->createSpan('database');
45
        $this->assertSame($database->getName(), 'database');
46
        $database->setName('tarantool');
47
        $this->assertSame($database->getName(), 'tarantool');
48
    }
49
50
    public function testNestedSpans()
51
    {
52
        $tracer = new Tracer();
53
54
        $guard = $tracer->createSpan('guard.validate');
55
        $connection = $tracer->createSpan('guard.database.connection');
56
        $procedure = $tracer->createSpan('guard.procedure.registration')->end();
57
        $connection->end();
58
        $policy = $tracer->createSpan('policy.describe')->end();
59
60
        $guard->end();
61
62
        $this->assertSame($connection->getParentSpanContext(), $guard->getSpanContext());
63
        $this->assertSame($procedure->getParentSpanContext(), $connection->getSpanContext());
64
        $this->assertSame($policy->getParentSpanContext(), $guard->getSpanContext());
65
66
        $this->assertCount(5, $tracer->getSpans());
67
    }
68
69
    public function testCreateSpan()
70
    {
71
        $tracer = new Tracer();
72
        $global = $tracer->getActiveSpan();
73
74
        $mysql = $tracer->createSpan('mysql');
75
        $this->assertSame($tracer->getActiveSpan(), $mysql);
76
        $this->assertSame($global->getSpanContext()->getTraceId(), $mysql->getSpanContext()->getTraceId());
77
        $this->assertSame($mysql->getParentSpanContext(), $global->getSpanContext());
78
        $this->assertNotNull($mysql->getStart());
79
        $this->assertTrue($mysql->isRecordingEvents());
80
        $this->assertNull($mysql->getDuration());
81
82
        $mysql->end();
83
        $this->assertFalse($mysql->isRecordingEvents());
84
        $this->assertNotNull($mysql->getDuration());
85
86
        $duration = $mysql->getDuration();
87
        $this->assertSame($duration, $mysql->getDuration());
88
        $mysql->end();
89
        $this->assertGreaterThan($duration, $mysql->getDuration());
90
91
        $this->assertTrue($mysql->getStatus()->isOk());
92
        
93
        // active span rolled back
94
        $this->assertSame($tracer->getActiveSpan(), $global);
95
        $this->assertNull($global->getStatus());
96
        
97
        // active span should be kept for global span
98
        $global->end();
99
        $this->assertSame($tracer->getActiveSpan(), $global);
100
        $this->assertTrue($global->getStatus()->isOk());
101
    }
102
103
    public function testStatusManipulation()
104
    {
105
        $tracer = new Tracer();
106
107
        $cancelled = $tracer->createSpan('cancelled');
108
        $cancelled->end(new Status(Status::CANCELLED));
109
        $this->assertFalse($cancelled->getStatus()->isOk());
110
        $this->assertSame($cancelled->getStatus()->getCanonicalCode(), Status::CANCELLED);
111
        $this->assertSame($cancelled->getStatus()->getDescription(), Status::DESCRIPTION[Status::CANCELLED]);
112
113
        $custom = $tracer->createSpan('custom');
114
        $custom->end(new Status(404, 'Not found'));
115
        $this->assertFalse($custom->getStatus()->isOk());
116
        $this->assertSame($custom->getStatus()->getCanonicalCode(), 404);
117
        $this->assertSame($custom->getStatus()->getDescription(), 'Not found');
118
119
        $noDescription = new Status(500);
120
        $this->assertNull($noDescription->getDescription());
121
122
        $custom->setStatus(new Status(Status::OK));
123
        $this->assertTrue($custom->getStatus()->isOk());
124
125
        $this->assertCount(3, $tracer->getSpans());
126
    }
127
128
    public function testSpanAttributesApi()
129
    {
130
        $span = (new Tracer())->getActiveSpan();
131
132
        // set attributes
133
        $span->setAttributes([ 'username' => 'nekufa' ]);
134
135
        // get attribute
136
        $this->assertSame($span->getAttribute('username'), 'nekufa');
137
        
138
        // otherwrite
139
        $span->setAttributes([ 'email' => '[email protected]', ]);
140
141
        // null attributes
142
        $this->assertNull($span->getAttribute('username'));
143
        $this->assertSame($span->getAttribute('email'), '[email protected]');
144
145
        // set attribute
146
        $span->setAttribute('username', 'nekufa');
147
        $this->assertSame($span->getAttribute('username'), 'nekufa');
148
        $this->assertSame($span->getAttributes(), [
149
            'email' => '[email protected]',
150
            'username' => 'nekufa',
151
        ]);
152
153
        // keep order
154
        $span->setAttributes([ 'a' => 1, 'b' => 2]);
155
        $this->assertSame(array_keys($span->getAttributes()), ['a', 'b']);
156
        $span->setAttributes([ 'b' => 2, 'a' => 1, ]);
157
        $this->assertSame(array_keys($span->getAttributes()), ['b', 'a']);
158
159
        // attribute update don't change the order
160
        $span->setAttribute('a', 3);
161
        $span->setAttribute('b', 4);
162
        $this->assertSame(array_keys($span->getAttributes()), ['b', 'a']);
163
164
        $this->expectExceptionMessage("Span is readonly");
165
        $span->end();
166
        $span->setAttribute('b', 5);
167
    }
168
169
    public function testEventRegistration()
170
    {
171
        $span = (new Tracer)->createSpan('database');
172
        $event = $span->addEvent('select', [
173
            'space' => 'guard.session',
174
            'id' => 67235
175
        ]);
176
        $this->assertSame($event->getName(), 'select');
177
        $this->assertSame($event->getAttributes(), [
178
            'space' => 'guard.session',
179
            'id' => 67235,
180
        ]);
181
        $this->assertSame($event->getAttribute('space'), 'guard.session');
182
        $this->assertNull($event->getAttribute('invalid-attribute'));
183
        $this->assertCount(1, $span->getEvents());
184
        $this->assertSame($span->getEvents(), [$event]);
185
        
186
        $span->addEvent('update')
187
            ->setAttribute('space', 'guard.session')
188
            ->setAttribute('id', 67235)
189
            ->setAttribute('active_at', time());
190
191
        $this->assertCount(2, $span->getEvents());
192
193
        $this->expectExceptionMessage("Span is readonly");
194
        $span->end();
195
        $span->addEvent('update');
196
    }
197
198
    public function testBuilder()
199
    {
200
        $spanContext = SpanContext::generate();
201
        $tracer = Builder::create()
202
            ->setSpanContext($spanContext)
203
            ->getTracer();
204
205
        $this->assertInstanceOf(Tracer::class, $tracer);
206
        $this->assertSame($tracer->getActiveSpan()->getSpanContext(), $spanContext);
207
    }
208
209
    public function testParentSpanContext()
210
    {
211
        $tracer = new Tracer;
212
        $global = $tracer->getActiveSpan();
213
        $request = $tracer->createSpan('request');
214
        $this->assertSame($request->getParentSpanContext()->getSpanId(), $global->getSpanContext()->getSpanId());
215
        $this->assertNull($global->getParentSpanContext());
216
        $this->assertNotNull($request->getParentSpanContext());
217
    }
218
219
    public function testSerialization()
220
    {
221
        $tracer = new Tracer();
222
        $span = $tracer->createSpan('serializable');
223
        $span->setAttribute('attribute', 'value');
224
        $span->addEvent('greet', [ 'name' => 'nekufa' ]);
225
226
        $serialized = serialize($span);
227
        $unserialized = unserialize($serialized);
228
229
        $this->assertSame($span->getName(), $unserialized->getName());
230
        $this->assertSame($span->getStart(), $unserialized->getStart());
231
        $this->assertSame($span->getEnd(), $unserialized->getEnd());
232
233
        $this->assertSame($unserialized->getAttribute('attribute'), 'value');
234
        $this->assertCount(1, $unserialized->getEvents());
235
        [$event] = $unserialized->getEvents();
236
        $this->assertSame($event->getName(), 'greet');
237
        $this->assertSame($event->getAttribute('name'), 'nekufa');
238
239
        return $tracer;
240
    }
241
242
    public function testBasisConverter()
243
    {
244
        $tracer = new Tracer();
245
        $span = $tracer->createSpan('guard.validate');
246
        $span->setAttribute('service', 'guard');
247
        $event = $span->addEvent('validators.list', [ 'job' => 'stage.updateTime' ]);
0 ignored issues
show
Unused Code introduced by
The assignment to $event is dead and can be removed.
Loading history...
248
        $span->end();
249
250
        $exporter = new BasisExporter();
251
        $row = $exporter->convertSpan($span);
252
        $this->assertSame($row['traceId'], $span->getSpanContext()->getTraceId());
253
        $this->assertSame($row['spanId'], $span->getSpanContext()->getSpanId());
254
        $this->assertSame($row['parentSpanId'], $span->getParentSpanContext()->getSpanId());
255
256
        $this->assertNotNull($row['body']);
257
        $unserialized = unserialize($row['body']);
258
        $this->assertSame($unserialized->getName(), $span->getName());
259
        $this->assertSame($unserialized->getAttributes(), $span->getAttributes());
260
261
        $this->assertSame(
262
            $unserialized->getEvents()[0]->getName(),
263
            $span->getEvents()[0]->getName(),
264
        );
265
266
        $this->assertSame(
267
            $unserialized->getEvents()[0]->getTimestamp(),
268
            $span->getEvents()[0]->getTimestamp(),
269
        );
270
    }
271
272
    public function testZipkinConverter()
273
    {
274
        $tracer = new Tracer();
275
        $span = $tracer->createSpan('guard.validate');
276
        $span->setAttribute('service', 'guard');
277
        $event = $span->addEvent('validators.list', [ 'job' => 'stage.updateTime' ]);
278
        $span->end();
279
280
        $exporter = new ZipkinExporter();
281
        $row = $exporter->convertSpan($span);
282
        $this->assertSame($row['name'], $span->getName());
283
284
        $this->assertSame($row['tags'], $span->getAttributes());
285
        $this->assertSame($row['tags']['service'], $span->getAttribute('service'));
286
287
        $this->assertCount(1, $row['annotations']);
288
        [$annotation] = $row['annotations'];
289
        $this->assertSame($annotation['value'], $event->getName());
290
        $this->assertSame($annotation['timestamp'], 1000000 * $event->getTimestamp());
291
    }
292
}