Passed
Push — master ( ddb4d4...f3d4b9 )
by Frank
02:18
created

HttplugAsyncClient::verifyResponse()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 7
cts 7
cp 1
rs 9.2
c 0
b 0
f 0
cc 4
eloc 6
nc 3
nop 1
crap 4
1
<?php
2
declare(strict_types=1);
3
4
namespace TechDeCo\ElasticApmAgent\Client;
5
6
use Http\Client\HttpAsyncClient;
7
use Http\Discovery\Exception as DiscoveryException;
8
use Http\Discovery\HttpAsyncClientDiscovery;
9
use Http\Discovery\MessageFactoryDiscovery;
10
use Http\Message\MessageFactory;
11
use Psr\Http\Message\RequestInterface;
12
use Psr\Log\LoggerInterface;
13
use TechDeCo\ElasticApmAgent\Client;
14
use TechDeCo\ElasticApmAgent\ClientConfiguration;
15
use TechDeCo\ElasticApmAgent\Exception\ClientException;
16
use TechDeCo\ElasticApmAgent\Request\Error;
17
use TechDeCo\ElasticApmAgent\Request\Transaction;
18
use Throwable;
19
use function count;
20
use function json_encode;
21
use function register_shutdown_function;
22
23
final class HttplugAsyncClient implements Client
24
{
25
    /**
26
     * @var ClientConfiguration
27
     */
28
    private $config;
29
30
    /**
31
     * @var HttpAsyncClient
32
     */
33
    private $httpClient;
34
35
    /**
36
     * @var MessageFactory
37
     */
38
    private $httpMessageFactory;
39
40
    /**
41
     * @var PromiseCollection
42
     */
43
    private $promises;
44
45
    /**
46
     * @var LoggerInterface
47
     */
48
    private $logger;
49
50
    /**
51
     * @throws DiscoveryException
52
     */
53 10
    public function __construct(
54
        LoggerInterface $logger,
55
        ClientConfiguration $config,
56
        ?HttpAsyncClient $httpClient,
57
        ?MessageFactory $httpMessageFactory
58
    ) {
59 10
        $this->logger             = $logger;
60 10
        $this->config             = $config;
61 10
        $this->httpClient         = $httpClient ?? HttpAsyncClientDiscovery::find();
62 10
        $this->httpMessageFactory = $httpMessageFactory ?? MessageFactoryDiscovery::find();
63 10
        $this->promises           = new PromiseCollection($logger);
64
65 10
        register_shutdown_function([$this, 'waitForResponses']);
66 10
    }
67
68
    /**
69
     * @throws ClientException
70
     */
71 9
    public function sendTransaction(Transaction $transaction): void
72
    {
73 9
        $request = $this->httpMessageFactory->createRequest(
74 9
            'POST',
75 9
            $this->config->getTransactionsEndpoint(),
76 9
            [],
77 9
            json_encode($transaction)
78
        );
79
80 9
        $this->sendRequest($request);
81 8
    }
82
83
    /**
84
     * @throws ClientException
85
     */
86 1
    public function sendError(Error $error): void
87
    {
88 1
        $request = $this->httpMessageFactory->createRequest(
89 1
            'POST',
90 1
            $this->config->getErrorsEndpoint(),
91 1
            [],
92 1
            json_encode($error)
93
        );
94
95 1
        $this->sendRequest($request);
96 1
    }
97
98
    /**
99
     * @throws ClientException
100
     */
101 10
    private function sendRequest(RequestInterface $request): void
102
    {
103 10
        $requestCount = count($this->promises) + 1;
104
105
        try {
106 10
            $request = $request->withHeader('Content-Type', 'application/json');
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $request. This often makes code more readable.
Loading history...
107 10
            if ($this->config->needsAuthentication()) {
108 10
                $this->logger->debug('Adding authentication token to request');
109 10
                $request = $request->withHeader('Authorization', 'Bearer ' . $this->config->getToken());
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $request. This often makes code more readable.
Loading history...
110
            }
111
112 10
            $this->logger->debug('Sending asynchronous request #' . $requestCount);
113 10
            $this->promises->add($this->httpClient->sendAsyncRequest($request));
114 1
        } catch (Throwable $e) {
115 1
            $this->logger->error('Encountered error while sending asynchronous request #' . $requestCount, [
116 1
                'exception' => $e,
117 1
                'message' => $e->getMessage(),
118
            ]);
119 1
            throw new ClientException('Could not send request due to configuration error', 0, $e);
120
        }
121 9
    }
122
123
    /**
124
     * @throws ClientException
125
     */
126 4
    public function waitForResponses(): void
127
    {
128 4
        $exceptionList = $this->promises->resolveAll();
129
130 4
        if (! empty($exceptionList)) {
131 3
            throw ClientException::fromException('Encountered errors while resolving requests', ...$exceptionList);
132
        }
133 1
    }
134
}
135