Skip to content

Commit ce2689b

Browse files
authored
ref(client): replace nullable client with NoOpClient (#1957)
1 parent aad2e28 commit ce2689b

21 files changed

+188
-153
lines changed

src/Integration/ErrorListenerIntegration.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,13 @@ public function setupOnce(): void
3535
static function (\ErrorException $exception): void {
3636
$currentHub = SentrySdk::getCurrentHub();
3737
$integration = $currentHub->getIntegration(self::class);
38-
$client = $currentHub->getClient();
3938

40-
// The client bound to the current hub, if any, could not have this
41-
// integration enabled. If this is the case, bail out
42-
if ($integration === null || $client === null) {
39+
if ($integration === null) {
4340
return;
4441
}
4542

43+
$client = $currentHub->getClient();
44+
4645
if ($exception instanceof SilencedErrorException && !$client->getOptions()->shouldCaptureSilencedErrors()) {
4746
return;
4847
}

src/Integration/FatalErrorListenerIntegration.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,13 @@ public function setupOnce(): void
2424
$errorHandler->addFatalErrorHandlerListener(static function (FatalErrorException $exception): void {
2525
$currentHub = SentrySdk::getCurrentHub();
2626
$integration = $currentHub->getIntegration(self::class);
27-
$client = $currentHub->getClient();
2827

29-
// The client bound to the current hub, if any, could not have this
30-
// integration enabled. If this is the case, bail out
31-
if ($integration === null || $client === null) {
28+
if ($integration === null) {
3229
return;
3330
}
3431

32+
$client = $currentHub->getClient();
33+
3534
if (!($client->getOptions()->getErrorTypes() & $exception->getSeverity())) {
3635
return;
3736
}

src/Integration/FrameContextifierIntegration.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,6 @@ public function setupOnce(): void
4343
Scope::addGlobalEventProcessor(static function (Event $event): Event {
4444
$client = SentrySdk::getCurrentHub()->getClient();
4545

46-
if ($client === null) {
47-
return $event;
48-
}
49-
5046
$maxContextLines = $client->getOptions()->getContextLines();
5147
$integration = $client->getIntegration(self::class);
5248

src/Integration/RequestIntegration.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,14 +94,13 @@ public function setupOnce(): void
9494
Scope::addGlobalEventProcessor(function (Event $event): Event {
9595
$currentHub = SentrySdk::getCurrentHub();
9696
$integration = $currentHub->getIntegration(self::class);
97-
$client = $currentHub->getClient();
9897

99-
// The client bound to the current hub, if any, could not have this
100-
// integration enabled. If this is the case, bail out
101-
if ($integration === null || $client === null) {
98+
if ($integration === null) {
10299
return $event;
103100
}
104101

102+
$client = $currentHub->getClient();
103+
105104
$this->processEvent($event, $client->getOptions());
106105

107106
return $event;

src/Logs/LogsAggregator.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,6 @@ public function add(
4040
$hub = SentrySdk::getCurrentHub();
4141
$client = $hub->getClient();
4242

43-
// There is no need to continue if there is no client
44-
if ($client === null) {
45-
return;
46-
}
47-
4843
$options = $client->getOptions();
4944
$sdkLogger = $options->getLogger();
5045

src/NoOpClient.php

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Sentry;
6+
7+
use Sentry\Integration\IntegrationInterface;
8+
use Sentry\Serializer\RepresentationSerializer;
9+
use Sentry\State\Scope;
10+
use Sentry\Transport\Result;
11+
use Sentry\Transport\ResultStatus;
12+
13+
/**
14+
* This client does not perform any operations, it acts as an interface compatible layer in order to
15+
* simply workflows where previously the client was null.
16+
* It also holds options which helps with situations where no options were available if the client was set to `null`.
17+
*/
18+
class NoOpClient implements ClientInterface
19+
{
20+
/**
21+
* @var array<string, mixed>
22+
*/
23+
private $options;
24+
25+
/**
26+
* @var Options
27+
*/
28+
private $sentryOptions;
29+
30+
/**
31+
* @var StacktraceBuilder|null
32+
*/
33+
private $stacktraceBuilder;
34+
35+
/**
36+
* @param array<string, mixed> $options
37+
*/
38+
public function __construct(array $options = [])
39+
{
40+
$this->options = $options;
41+
}
42+
43+
public function getOptions(): Options
44+
{
45+
if ($this->sentryOptions === null) {
46+
$this->sentryOptions = new Options($this->options);
47+
}
48+
49+
return $this->sentryOptions;
50+
}
51+
52+
public function getCspReportUrl(): ?string
53+
{
54+
return null;
55+
}
56+
57+
public function captureMessage(string $message, ?Severity $level = null, ?Scope $scope = null, ?EventHint $hint = null): ?EventId
58+
{
59+
return null;
60+
}
61+
62+
public function captureException(\Throwable $exception, ?Scope $scope = null, ?EventHint $hint = null): ?EventId
63+
{
64+
return null;
65+
}
66+
67+
public function captureLastError(?Scope $scope = null, ?EventHint $hint = null): ?EventId
68+
{
69+
return null;
70+
}
71+
72+
public function captureEvent(Event $event, ?EventHint $hint = null, ?Scope $scope = null): ?EventId
73+
{
74+
return null;
75+
}
76+
77+
public function getIntegration(string $className): ?IntegrationInterface
78+
{
79+
return null;
80+
}
81+
82+
public function flush(?int $timeout = null): Result
83+
{
84+
return new Result(ResultStatus::skipped());
85+
}
86+
87+
public function getStacktraceBuilder(): StacktraceBuilder
88+
{
89+
if ($this->stacktraceBuilder === null) {
90+
$this->stacktraceBuilder = new StacktraceBuilder($this->getOptions(), new RepresentationSerializer($this->getOptions()));
91+
}
92+
93+
return $this->stacktraceBuilder;
94+
}
95+
}

src/SentrySdk.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,12 @@ private function __construct()
3030
* Initializes the SDK by creating a new hub instance each time this method
3131
* gets called.
3232
*/
33-
public static function init(): HubInterface
33+
public static function init(?ClientInterface $client = null): HubInterface
3434
{
35-
self::$currentHub = new Hub();
35+
if ($client === null) {
36+
$client = new NoOpClient();
37+
}
38+
self::$currentHub = new Hub($client);
3639

3740
return self::$currentHub;
3841
}
@@ -44,7 +47,7 @@ public static function init(): HubInterface
4447
public static function getCurrentHub(): HubInterface
4548
{
4649
if (self::$currentHub === null) {
47-
self::$currentHub = new Hub();
50+
self::$currentHub = new Hub(new NoOpClient());
4851
}
4952

5053
return self::$currentHub;

src/State/Hub.php

Lines changed: 18 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
namespace Sentry\State;
66

7-
use Psr\Log\NullLogger;
87
use Sentry\Attachment\Attachment;
98
use Sentry\Breadcrumb;
109
use Sentry\CheckIn;
@@ -15,6 +14,7 @@
1514
use Sentry\EventId;
1615
use Sentry\Integration\IntegrationInterface;
1716
use Sentry\MonitorConfig;
17+
use Sentry\NoOpClient;
1818
use Sentry\Severity;
1919
use Sentry\Tracing\SamplingContext;
2020
use Sentry\Tracing\Span;
@@ -39,18 +39,18 @@ class Hub implements HubInterface
3939
/**
4040
* Hub constructor.
4141
*
42-
* @param ClientInterface|null $client The client bound to the hub
43-
* @param Scope|null $scope The scope bound to the hub
42+
* @param ClientInterface $client The client bound to the hub
43+
* @param Scope|null $scope The scope bound to the hub
4444
*/
45-
public function __construct(?ClientInterface $client = null, ?Scope $scope = null)
45+
public function __construct(ClientInterface $client, ?Scope $scope = null)
4646
{
4747
$this->stack[] = new Layer($client, $scope ?? new Scope());
4848
}
4949

5050
/**
5151
* {@inheritdoc}
5252
*/
53-
public function getClient(): ?ClientInterface
53+
public function getClient(): ClientInterface
5454
{
5555
return $this->getStackTop()->getClient();
5656
}
@@ -123,55 +123,31 @@ public function bindClient(ClientInterface $client): void
123123
*/
124124
public function captureMessage(string $message, ?Severity $level = null, ?EventHint $hint = null): ?EventId
125125
{
126-
$client = $this->getClient();
127-
128-
if ($client !== null) {
129-
return $this->lastEventId = $client->captureMessage($message, $level, $this->getScope(), $hint);
130-
}
131-
132-
return null;
126+
return $this->lastEventId = $this->getClient()->captureMessage($message, $level, $this->getScope(), $hint);
133127
}
134128

135129
/**
136130
* {@inheritdoc}
137131
*/
138132
public function captureException(\Throwable $exception, ?EventHint $hint = null): ?EventId
139133
{
140-
$client = $this->getClient();
141-
142-
if ($client !== null) {
143-
return $this->lastEventId = $client->captureException($exception, $this->getScope(), $hint);
144-
}
145-
146-
return null;
134+
return $this->lastEventId = $this->getClient()->captureException($exception, $this->getScope(), $hint);
147135
}
148136

149137
/**
150138
* {@inheritdoc}
151139
*/
152140
public function captureEvent(Event $event, ?EventHint $hint = null): ?EventId
153141
{
154-
$client = $this->getClient();
155-
156-
if ($client !== null) {
157-
return $this->lastEventId = $client->captureEvent($event, $hint, $this->getScope());
158-
}
159-
160-
return null;
142+
return $this->lastEventId = $this->getClient()->captureEvent($event, $hint, $this->getScope());
161143
}
162144

163145
/**
164146
* {@inheritdoc}
165147
*/
166148
public function captureLastError(?EventHint $hint = null): ?EventId
167149
{
168-
$client = $this->getClient();
169-
170-
if ($client !== null) {
171-
return $this->lastEventId = $client->captureLastError($this->getScope(), $hint);
172-
}
173-
174-
return null;
150+
return $this->lastEventId = $this->getClient()->captureLastError($this->getScope(), $hint);
175151
}
176152

177153
/**
@@ -183,7 +159,7 @@ public function captureCheckIn(string $slug, CheckInStatus $status, $duration =
183159
{
184160
$client = $this->getClient();
185161

186-
if ($client === null) {
162+
if ($client instanceof NoOpClient) {
187163
return null;
188164
}
189165

@@ -211,7 +187,8 @@ public function addBreadcrumb(Breadcrumb $breadcrumb): bool
211187
{
212188
$client = $this->getClient();
213189

214-
if ($client === null) {
190+
// No point in storing breadcrumbs if the client will never send them
191+
if ($client instanceof NoOpClient) {
215192
return false;
216193
}
217194

@@ -234,9 +211,8 @@ public function addBreadcrumb(Breadcrumb $breadcrumb): bool
234211

235212
public function addAttachment(Attachment $attachment): bool
236213
{
237-
$client = $this->getClient();
238-
239-
if ($client === null) {
214+
// No point in storing attachments if the client will never send them
215+
if ($this->getClient() instanceof NoOpClient) {
240216
return false;
241217
}
242218

@@ -250,13 +226,7 @@ public function addAttachment(Attachment $attachment): bool
250226
*/
251227
public function getIntegration(string $className): ?IntegrationInterface
252228
{
253-
$client = $this->getClient();
254-
255-
if ($client !== null) {
256-
return $client->getIntegration($className);
257-
}
258-
259-
return null;
229+
return $this->getClient()->getIntegration($className);
260230
}
261231

262232
/**
@@ -267,11 +237,10 @@ public function getIntegration(string $className): ?IntegrationInterface
267237
public function startTransaction(TransactionContext $context, array $customSamplingContext = []): Transaction
268238
{
269239
$transaction = new Transaction($context, $this);
270-
$client = $this->getClient();
271-
$options = $client !== null ? $client->getOptions() : null;
272-
$logger = $options !== null ? $options->getLoggerOrNullLogger() : new NullLogger();
240+
$options = $this->getClient()->getOptions();
241+
$logger = $options->getLoggerOrNullLogger();
273242

274-
if ($options === null || !$options->isTracingEnabled()) {
243+
if (!$options->isTracingEnabled()) {
275244
$transaction->setSampled(false);
276245

277246
$logger->warning(\sprintf('Transaction [%s] was started but tracing is not enabled.', (string) $transaction->getTraceId()), ['context' => $context]);

src/State/HubAdapter.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public static function getInstance(): self
5353
/**
5454
* {@inheritdoc}
5555
*/
56-
public function getClient(): ?ClientInterface
56+
public function getClient(): ClientInterface
5757
{
5858
return SentrySdk::getCurrentHub()->getClient();
5959
}

src/State/HubInterface.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ interface HubInterface
2323
/**
2424
* Gets the client bound to the top of the stack.
2525
*/
26-
public function getClient(): ?ClientInterface;
26+
public function getClient(): ClientInterface;
2727

2828
/**
2929
* Gets the ID of the last captured event.

0 commit comments

Comments
 (0)