Passed
Push — master ( 1177ba...21cebb )
by Zoilo
01:39
created

ElasticApmTracer::captureException()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 11
c 1
b 0
f 0
nc 2
nop 2
dl 0
loc 18
ccs 13
cts 13
cp 1
crap 2
rs 9.9
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 9
    public function __construct(
63
        CoreConfiguration $coreConfiguration,
64
        Reporter $reporter,
65
        PoolFactory $poolFactory
66
    ) {
67 9
        $this->coreConfiguration = $coreConfiguration;
68 9
        $this->reporter = $reporter;
69
70 9
        $this->metadata = Metadata::create($this->coreConfiguration);
71 9
        $this->context = Context::discover();
72 9
        $this->handler = Handler::create($this->coreConfiguration);
73
74 9
        $this->transactionPool = $poolFactory->createTransactionPool();
75 9
        $this->spanPool = $poolFactory->createSpanPool();
76 9
        $this->errorPool = $poolFactory->createErrorPool();
77 9
    }
78
79
    /**
80
     * @param string $name
81
     * @param string $type
82
     * @param Context $context
83
     *
84
     * @return Transaction
85
     *
86
     * @throws \Exception
87
     */
88 4
    public function startTransaction($name, $type, $context = null)
89
    {
90 4
        if (null === $context) {
91 4
            $context = $this->context;
92 4
        }
93
94 4
        $lastEvent = $this->getLastUnfinishedEvent();
95
96 4
        $transaction = new Transaction(
97 4
            $name,
98 4
            $type,
99 4
            $context,
100 4
            null !== $lastEvent ? $lastEvent->traceId() : null,
101 4
            null !== $lastEvent ? $lastEvent->parentId() : null
102 4
        );
103
104 4
        $this->transactionPool->put($transaction);
105
106 4
        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
     *
116
     * @return Span
117
     *
118
     * @throws \Exception
119
     */
120 2
    public function startSpan(
121
        $name,
122
        $type,
123
        $subtype = null,
124
        $action = null,
125
        Events\Span\Context $context = null
126
    ) {
127 2
        $stacktrace = Stacktrace::getDebugBacktrace(
128 2
            $this->coreConfiguration->stacktraceLimit()
129 2
        );
130
131 2
        $lastTransaction = $this->transactionPool->findLastUnfinished();
132 2
        if (null === $lastTransaction) {
133 1
            throw new \Exception('To create a span, there must be a transaction started.');
134
        }
135
136 1
        $lastEvent = $this->getLastUnfinishedEvent();
137
138 1
        $span = new Span(
139 1
            $name,
140 1
            $type,
141 1
            $lastEvent->traceId(),
142 1
            $lastEvent->id(),
143 1
            $subtype,
144 1
            $lastTransaction->id(),
145 1
            $action,
146 1
            $context,
147
            $stacktrace
148 1
        );
149
150 1
        $this->spanPool->put($span);
151
152 1
        return $span;
153
    }
154
155
    /**
156
     * @param mixed $exception
157
     * @param Context|null $context
158
     *
159
     * @return void
160
     *
161
     * @throws \Exception
162
     */
163 2
    public function captureException($exception, Context $context = null)
164
    {
165 2
        $lastTransaction = $this->transactionPool->findLastUnfinished();
166 2
        if (null === $lastTransaction) {
167 1
            throw new \Exception('To capture exception, there must be a transaction started.');
168
        }
169
170 1
        $lastEvent = $this->getLastUnfinishedEvent();
171
172 1
        $error = new Error(
173 1
            $lastEvent->traceId(),
174 1
            $lastEvent->id(),
175 1
            $exception,
176 1
            $context,
177 1
            $lastTransaction->id()
178 1
        );
179
180 1
        $this->errorPool->put($error);
181 1
    }
182
183
    /**
184
     * @return void
185
     */
186 3
    public function flush()
187
    {
188 3
        if (false === $this->coreConfiguration->active()) {
189 1
            $this->eraseAllPools();
190
191 1
            return;
192
        }
193
194 2
        $items = $this->getEventsToSend();
195 2
        $this->eraseAllPools();
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
        return array_merge(
212
            [
213 2
                $this->metadata,
214 2
            ],
215 2
            $this->transactionPool->findFinished(),
216 2
            $this->spanPool->findFinished(),
217 2
            $this->errorPool->findAll()
218 2
        );
219
    }
220
221
    /**
222
     * @return void
223
     */
224 3
    private function eraseAllPools()
225
    {
226 3
        $this->transactionPool->eraseAll();
227 3
        $this->spanPool->eraseAll();
228 3
        $this->errorPool->eraseAll();
229 3
    }
230
231
    /**
232
     * @return TraceableEvent|null
233
     */
234 4
    private function getLastUnfinishedEvent()
235
    {
236 4
        $lastTransaction = $this->transactionPool->findLastUnfinished();
237 4
        $lastSpan = $this->spanPool->findLastUnfinished();
238
239 4
        return null !== $lastSpan
240 4
            ? $lastSpan
241 4
            : $lastTransaction;
242
    }
243
}
244