Passed
Push — master ( 8a631f...a79a09 )
by Zoilo
01:53
created

ElasticApmTracer::eraseAllPools()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 5
ccs 4
cts 4
cp 1
crap 1
rs 10
1
<?php
2
3
namespace ZoiloMora\ElasticAPM;
4
5
use ZoiloMora\ElasticAPM\Configuration\CoreConfiguration;
6
use ZoiloMora\ElasticAPM\Events\Common\Context;
7
use ZoiloMora\ElasticAPM\Events\Error\Error;
8
use ZoiloMora\ElasticAPM\Events\Metadata\Metadata;
9
use ZoiloMora\ElasticAPM\Events\Span\Span;
10
use ZoiloMora\ElasticAPM\Events\TraceableEvent;
11
use ZoiloMora\ElasticAPM\Events\Transaction\Transaction;
12
use ZoiloMora\ElasticAPM\Helper\Stacktrace;
13
use ZoiloMora\ElasticAPM\Pool\ErrorPool;
14
use ZoiloMora\ElasticAPM\Pool\PoolFactory;
15
use ZoiloMora\ElasticAPM\Pool\SpanPool;
16
use ZoiloMora\ElasticAPM\Pool\TransactionPool;
17
use ZoiloMora\ElasticAPM\Processor\Handler;
18
use ZoiloMora\ElasticAPM\Reporter\Reporter;
19
20
final class ElasticApmTracer
21
{
22
    /**
23
     * @var CoreConfiguration
24
     */
25
    private $coreConfiguration;
26
27
    /**
28
     * @var Metadata
29
     */
30
    private $metadata;
31
32
    /**
33
     * @var Context
34
     */
35
    private $context;
36
37
    /**
38
     * @var Handler
39
     */
40
    private $handler;
41
42
    /**
43
     * @var Reporter
44
     */
45
    private $reporter;
46
47
    /**
48
     * @var TransactionPool
49
     */
50
    private $transactionPool;
51
52
    /**
53
     * @var SpanPool
54
     */
55
    private $spanPool;
56
57
    /**
58
     * @var ErrorPool
59
     */
60
    private $errorPool;
61
62 11
    public function __construct(
63
        CoreConfiguration $coreConfiguration,
64
        Reporter $reporter,
65
        PoolFactory $poolFactory
66
    ) {
67 11
        $this->coreConfiguration = $coreConfiguration;
68 11
        $this->reporter = $reporter;
69
70 11
        $this->metadata = Metadata::create($this->coreConfiguration);
71 11
        $this->context = Context::discover();
72 11
        $this->handler = Handler::create($this->coreConfiguration);
73
74 11
        $this->transactionPool = $poolFactory->createTransactionPool();
75 11
        $this->spanPool = $poolFactory->createSpanPool();
76 11
        $this->errorPool = $poolFactory->createErrorPool();
77 11
    }
78
79
    /**
80
     * @param string $name
81
     * @param string $type
82
     * @param Context $context
83
     *
84
     * @return Transaction
85
     *
86
     * @throws \Exception
87
     */
88 6
    public function startTransaction($name, $type, $context = null)
89
    {
90 6
        if (null === $context) {
91 6
            $context = $this->context;
92 6
        }
93
94 6
        $lastEvent = $this->getLastUnfinishedEvent();
95
96 6
        $transaction = new Transaction(
97 6
            $name,
98 6
            $type,
99 6
            $context,
100 6
            null !== $lastEvent ? $lastEvent->traceId() : null,
101 6
            null !== $lastEvent ? $lastEvent->id() : null
102 6
        );
103
104 6
        $this->transactionPool->put($transaction);
105
106 6
        return $transaction;
107
    }
108
109
    /**
110
     * @param string $name
111
     * @param string $type
112
     * @param string|null $subtype
113
     * @param string|null $action
114
     * @param Events\Span\Context|null $context
115
     * @param int $stacktraceSkip
116
     *
117
     * @return Span
118
     *
119
     * @throws \Exception
120
     */
121 4
    public function startSpan(
122
        $name,
123
        $type,
124
        $subtype = null,
125
        $action = null,
126
        Events\Span\Context $context = null,
127
        $stacktraceSkip = 1
128
    ) {
129 4
        $stacktrace = Stacktrace::getDebugBacktrace(
130 4
            $this->coreConfiguration->stacktraceLimit(),
131
            $stacktraceSkip
132 4
        );
133
134 4
        $lastTransaction = $this->transactionPool->findLastUnfinished();
135 4
        if (null === $lastTransaction) {
136 1
            throw new \Exception('To create a span, there must be a transaction started.');
137
        }
138
139 3
        $lastEvent = $this->getLastUnfinishedEvent();
140
141 3
        $span = new Span(
142 3
            $name,
143 3
            $type,
144 3
            $lastEvent->traceId(),
145 3
            $lastEvent->id(),
146 3
            $subtype,
147 3
            $lastTransaction->id(),
148 3
            $action,
149 3
            $context,
150
            $stacktrace
151 3
        );
152
153 3
        $this->spanPool->put($span);
154
155 3
        return $span;
156
    }
157
158
    /**
159
     * @param mixed $exception
160
     * @param Context|null $context
161
     *
162
     * @return void
163
     *
164
     * @throws \Exception
165
     */
166 2
    public function captureException($exception, Context $context = null)
167
    {
168 2
        $lastTransaction = $this->transactionPool->findLastUnfinished();
169 2
        if (null === $lastTransaction) {
170 1
            throw new \Exception('To capture exception, there must be a transaction started.');
171
        }
172
173 1
        $lastEvent = $this->getLastUnfinishedEvent();
174
175 1
        $error = new Error(
176 1
            $lastEvent->traceId(),
177 1
            $lastEvent->id(),
178 1
            $exception,
179 1
            $context,
180 1
            $lastTransaction->id()
181 1
        );
182
183 1
        $this->errorPool->put($error);
184 1
    }
185
186
    /**
187
     * @return void
188
     */
189 3
    public function flush()
190
    {
191 3
        if (false === $this->coreConfiguration->active()) {
192 1
            return;
193 1
        }
194
195 2
        $items = $this->getEventsToSend();
196
197 2
        if (1 === count($items)) {
198 1
            return;
199
        }
200
201 1
        $items = $this->handler->execute($items);
202
203 1
        $this->reporter->report($items);
204 1
    }
205
206
    /**
207
     * @return array
208
     */
209 2
    private function getEventsToSend()
210
    {
211 2
        $transactions = $this->transactionPool->findFinishedAndDelete();
212
213 2
        $events = [];
214 2
        foreach ($transactions as $transaction) {
215 1
            $events = array_merge(
216 1
                $events,
217 1
                $this->spanPool->findFinishedAndDelete($transaction),
218 1
                $this->errorPool->findAndDelete($transaction)
219 1
            );
220 2
        }
221
222 2
        return array_merge(
223
            [
224 2
                $this->metadata,
225 2
            ],
226 2
            $transactions,
227
            $events
228 2
        );
229
    }
230
231
    /**
232
     * @return TraceableEvent|null
233
     */
234 6
    private function getLastUnfinishedEvent()
235
    {
236 6
        $lastTransaction = $this->transactionPool->findLastUnfinished();
237 6
        if (null === $lastTransaction) {
238 6
            return null;
239
        }
240
241 4
        $lastSpan = $this->spanPool->findLastUnfinished();
242 4
        if (null === $lastSpan) {
243 4
            return $lastTransaction;
244
        }
245
246 1
        return $lastTransaction->timestamp() > $lastSpan->timestamp()
247 1
            ? $lastTransaction
248 1
            : $lastSpan;
249
    }
250
}
251