Passed
Pull Request — master (#19)
by
unknown
03:04
created

SentryTraceWebListener::listen()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 25
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
cc 5
eloc 14
nc 5
nop 1
dl 0
loc 25
ccs 0
cts 15
cp 0
crap 30
rs 9.4888
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Sentry\Tracing;
6
7
use Psr\Http\Server\MiddlewareInterface;
8
use Sentry\Tracing\SpanContext;
9
use Yiisoft\Middleware\Dispatcher\Event\AfterMiddleware;
10
use Yiisoft\Middleware\Dispatcher\Event\BeforeMiddleware;
11
use Yiisoft\Yii\Http\Event\ApplicationShutdown;
12
use Yiisoft\Yii\Sentry\Integration\Integration;
13
14
final class SentryTraceWebListener
15
{
16
    private ?float $prevTime = null;
17
18
    private ?string $prevClass = null;
19
20
    private ?bool $isFirstPopFromMiddlewareStack = true;
21
22
    public function __construct(private SentryTraceMiddleware $traceMiddleware)
23
    {
24
    }
25
26
    /**
27
     * @param array ...$params
28
     */
29
    public function listen(...$params): void
30
    {
31
        /** @var false|object $event */
32
        $event = current($params);
33
34
        if (!is_object($event)) {
35
            return;
36
        }
37
38
        if ($event instanceof BeforeMiddleware) {
39
            $middleware = $event->getMiddleware();
40
            $this->handleStart($middleware);
41
42
            return;
43
        }
44
        if ($event instanceof AfterMiddleware) {
45
            $middleware = $event->getMiddleware();
46
            $this->handleDone($middleware);
47
48
            return;
49
        }
50
        if ($event instanceof ApplicationShutdown) {
51
            $this->traceMiddleware->terminate();
52
53
            return;
54
        }
55
    }
56
57
    private function handleStart(MiddlewareInterface $middleware): void
58
    {
59
        $currentTime = microtime(true);
60
        $currentClass = $middleware::class;
61
62
        if (null === $this->prevTime || null === $this->prevClass) {
63
            $this->prevTime = $currentTime;
64
            $this->prevClass = $currentClass;
65
66
            return;
67
        }
68
        $this->log('middleware in', $this->prevClass, $this->prevTime, $currentTime);
0 ignored issues
show
Bug introduced by
It seems like $currentTime can also be of type string; however, parameter $currentTime of Yiisoft\Yii\Sentry\Traci...TraceWebListener::log() does only seem to accept double, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

68
        $this->log('middleware in', $this->prevClass, $this->prevTime, /** @scrutinizer ignore-type */ $currentTime);
Loading history...
69
        $this->prevTime = $currentTime;
70
        $this->prevClass = $currentClass;
71
    }
72
73
    private function log(
74
        string $op,
75
        string $currentClass,
76
        float $prevTime,
77
        float $currentTime
78
    ): void {
79
        $parentSpan = Integration::currentTracingSpan();
80
        // If there is no tracing span active there is no need to handle the event
81
        if ($parentSpan === null) {
82
            return;
83
        }
84
        $spanContext = new SpanContext();
85
        $spanContext->setOp($op);
86
        $spanContext->setDescription($currentClass);
87
        $spanContext->setStartTimestamp($prevTime);
88
        $spanContext->setEndTimestamp($currentTime);
89
        $parentSpan->startChild($spanContext);
90
    }
91
92
    private function handleDone(MiddlewareInterface $middleware): void
93
    {
94
        $currentTime = microtime(true);
95
        $currentClass = $middleware::class;
96
        if (null === $this->prevTime) {
97
            return;
98
        }
99
100
        if ($this->isFirstPopFromMiddlewareStack) {
101
            $this->isFirstPopFromMiddlewareStack = false;
102
            $this->log('action', $currentClass, $this->prevTime, $currentTime);
0 ignored issues
show
Bug introduced by
It seems like $currentTime can also be of type string; however, parameter $currentTime of Yiisoft\Yii\Sentry\Traci...TraceWebListener::log() does only seem to accept double, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

102
            $this->log('action', $currentClass, $this->prevTime, /** @scrutinizer ignore-type */ $currentTime);
Loading history...
103
            $this->prevTime = $currentTime;
104
105
            return;
106
        }
107
108
        $this->log('middleware out', $currentClass, $this->prevTime, $currentTime);
109
        $this->prevTime = $currentTime;
110
    }
111
}
112