-
-
Notifications
You must be signed in to change notification settings - Fork 452
/
Copy pathHttpTransport.php
132 lines (113 loc) · 4.23 KB
/
HttpTransport.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
<?php
declare(strict_types=1);
namespace Sentry\Transport;
use Http\Client\HttpAsyncClient as HttpAsyncClientInterface;
use Http\Message\RequestFactory as RequestFactoryInterface;
use Http\Promise\Promise as PromiseInterface;
use Sentry\Event;
use Sentry\Exception\MissingProjectIdCredentialException;
use Sentry\Options;
use Sentry\Util\JSON;
/**
* This transport sends the events using a syncronous HTTP client that will
* delay sending of the requests until the shutdown of the application.
*
* @author Stefano Arlandini <[email protected]>
*/
final class HttpTransport implements TransportInterface
{
/**
* @var Options The Raven client configuration
*/
private $config;
/**
* @var HttpAsyncClientInterface The HTTP client
*/
private $httpClient;
/**
* @var RequestFactoryInterface The PSR-7 request factory
*/
private $requestFactory;
/**
* @var PromiseInterface[] The list of pending promises
*/
private $pendingRequests = [];
/**
* @var bool Flag indicating whether the sending of the events should be
* delayed until the shutdown of the application
*/
private $delaySendingUntilShutdown = false;
/**
* Constructor.
*
* @param Options $config The Raven client configuration
* @param HttpAsyncClientInterface $httpClient The HTTP client
* @param RequestFactoryInterface $requestFactory The PSR-7 request factory
* @param bool $delaySendingUntilShutdown This flag controls whether to delay
* sending of the events until the shutdown
* of the application. This is a legacy feature
* that will stop working in version 3.0.
*/
public function __construct(Options $config, HttpAsyncClientInterface $httpClient, RequestFactoryInterface $requestFactory, bool $delaySendingUntilShutdown = true)
{
if ($delaySendingUntilShutdown) {
@trigger_error(sprintf('Delaying the sending of the events using the "%s" class is deprecated since version 2.2 and will not work in 3.0.', __CLASS__), E_USER_DEPRECATED);
}
$this->config = $config;
$this->httpClient = $httpClient;
$this->requestFactory = $requestFactory;
$this->delaySendingUntilShutdown = $delaySendingUntilShutdown;
// By calling the cleanupPendingRequests function from a shutdown function
// registered inside another shutdown function we can be confident that it
// will be executed last
register_shutdown_function('register_shutdown_function', \Closure::fromCallable([$this, 'cleanupPendingRequests']));
}
/**
* Destructor. Ensures that all pending requests ends before destroying this
* object instance.
*/
public function __destruct()
{
$this->cleanupPendingRequests();
}
/**
* {@inheritdoc}
*/
public function send(Event $event): ?string
{
$projectId = $this->config->getProjectId();
if (null === $projectId) {
throw new MissingProjectIdCredentialException();
}
$request = $this->requestFactory->createRequest(
'POST',
sprintf('/api/%d/store/', $projectId),
['Content-Type' => 'application/json'],
JSON::encode($event)
);
$promise = $this->httpClient->sendAsyncRequest($request);
if ($this->delaySendingUntilShutdown) {
$this->pendingRequests[] = $promise;
} else {
try {
$promise->wait();
} catch (\Exception $exception) {
return null;
}
}
return $event->getId();
}
/**
* Cleanups the pending promises by awaiting for them. Any error that occurs
* will be ignored.
*/
private function cleanupPendingRequests(): void
{
while ($promise = array_pop($this->pendingRequests)) {
try {
$promise->wait();
} catch (\Exception $exception) {
}
}
}
}