Skip to content

Commit 008fb7d

Browse files
authored
Fix for default integrations not disabled (#327)
* Fix for default integrations not disabled * Add tests * Add changelog entry * Do not use `expectNotToPerformAssertions` (yet)
1 parent d6aa3aa commit 008fb7d

File tree

3 files changed

+84
-13
lines changed

3 files changed

+84
-13
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## Unreleased
44

5+
- Fix for default integrations not disabled (#327)
6+
57
## 1.6.1
68

79
- Fix queue events with missing handler suffix (#322)

src/Sentry/Laravel/ServiceProvider.php

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,12 @@ protected function configureAndRegisterClient(): void
101101
$basePath = base_path();
102102
$userConfig = $this->getUserConfig();
103103

104-
// We do not want this setting to hit our main client because it's Laravel specific
105104
unset(
105+
// We do not want this setting to hit our main client because it's Laravel specific
106106
$userConfig['breadcrumbs'],
107-
// this is kept for backwards compatibilty and can be dropped in a breaking release
107+
// We resolve the integrations through the container later, so we initially do not pass it to the SDK yet
108+
$userConfig['integrations'],
109+
// This is kept for backwards compatibilty and can be dropped in a future breaking release
108110
$userConfig['breadcrumbs.sql_bindings']
109111
);
110112

@@ -114,10 +116,7 @@ protected function configureAndRegisterClient(): void
114116
'prefixes' => [$basePath],
115117
'in_app_exclude' => ["{$basePath}/vendor"],
116118
],
117-
$userConfig,
118-
[
119-
'integrations' => $this->getIntegrations(),
120-
]
119+
$userConfig
121120
);
122121

123122
$clientBuilder = ClientBuilder::create($options);
@@ -135,13 +134,19 @@ protected function configureAndRegisterClient(): void
135134

136135
$options = $clientBuilder->getOptions();
137136

138-
if ($options->hasDefaultIntegrations()) {
139-
$integrations = $options->getIntegrations();
137+
$userIntegrations = $this->resolveIntegrationsFromUserConfig();
138+
139+
$options->setIntegrations(static function (array $integrations) use ($options, $userIntegrations) {
140+
$allIntegrations = array_merge($integrations, $userIntegrations);
141+
142+
if (!$options->hasDefaultIntegrations()) {
143+
return $allIntegrations;
144+
}
140145

141146
// Remove the default error and fatal exception listeners to let Laravel handle those
142147
// itself. These event are still bubbling up through the documented changes in the users
143148
// `ExceptionHandler` of their application or through the log channel integration to Sentry
144-
$options->setIntegrations(array_filter($integrations, static function (SdkIntegration\IntegrationInterface $integration): bool {
149+
return array_filter($allIntegrations, static function (SdkIntegration\IntegrationInterface $integration): bool {
145150
if ($integration instanceof SdkIntegration\ErrorListenerIntegration) {
146151
return false;
147152
}
@@ -155,8 +160,8 @@ protected function configureAndRegisterClient(): void
155160
}
156161

157162
return true;
158-
}));
159-
}
163+
});
164+
});
160165

161166
$hub = new Hub($clientBuilder->getClient());
162167

@@ -185,7 +190,7 @@ protected function hasDsnSet(): bool
185190
*
186191
* @return array
187192
*/
188-
private function getIntegrations(): array
193+
private function resolveIntegrationsFromUserConfig(): array
189194
{
190195
$integrations = [new Integration];
191196

@@ -195,7 +200,13 @@ private function getIntegrations(): array
195200
if ($userIntegration instanceof SdkIntegration\IntegrationInterface) {
196201
$integrations[] = $userIntegration;
197202
} elseif (\is_string($userIntegration)) {
198-
$integrations[] = $this->app->make($userIntegration);
203+
$resolvedIntegration = $this->app->make($userIntegration);
204+
205+
if (!($resolvedIntegration instanceof SdkIntegration\IntegrationInterface)) {
206+
throw new \RuntimeException('Sentry integrations should a instance of `\Sentry\Integration\IntegrationInterface`.');
207+
}
208+
209+
$integrations[] = $resolvedIntegration;
199210
} else {
200211
throw new \RuntimeException('Sentry integrations should either be a container reference or a instance of `\Sentry\Integration\IntegrationInterface`.');
201212
}

test/Sentry/IntegrationsOptionTest.php

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
namespace Sentry\Laravel\Tests;
44

55
use Sentry\Integration\IntegrationInterface;
6+
use Sentry\Integration\ErrorListenerIntegration;
7+
use Sentry\Integration\ExceptionListenerIntegration;
8+
use Sentry\Integration\FatalErrorListenerIntegration;
69

710
class IntegrationsOptionTest extends SentryLaravelTestCase
811
{
@@ -50,6 +53,7 @@ public function testCustomIntegrationByInstance()
5053

5154
/**
5255
* Throws \ReflectionException in <=5.8 and \Illuminate\Contracts\Container\BindingResolutionException since 6.0
56+
*
5357
* @expectedException \Exception
5458
*/
5559
public function testCustomIntegrationThrowsExceptionIfNotResolvable()
@@ -73,6 +77,60 @@ static function () {
7377
],
7478
]);
7579
}
80+
81+
public function testDisabledIntegrationsAreNotPresent()
82+
{
83+
$integrations = $this->getHubFromContainer()->getClient()->getOptions()->getIntegrations();
84+
85+
foreach ($integrations as $integration) {
86+
$this->ensureIsNotDisabledIntegration($integration);
87+
}
88+
89+
$this->assertTrue(true, 'Not all disabled integrations are actually disabled.');
90+
}
91+
92+
public function testDisabledIntegrationsAreNotPresentWithCustomIntegrations()
93+
{
94+
$this->resetApplicationWithConfig([
95+
'sentry.integrations' => [
96+
new IntegrationsOptionTestIntegrationStub,
97+
],
98+
]);
99+
100+
$integrations = $this->getHubFromContainer()->getClient()->getOptions()->getIntegrations();
101+
102+
$found = false;
103+
104+
foreach ($integrations as $integration) {
105+
$this->ensureIsNotDisabledIntegration($integration);
106+
107+
if ($integration instanceof IntegrationsOptionTestIntegrationStub) {
108+
$found = true;
109+
}
110+
}
111+
112+
$this->assertTrue($found, 'No IntegrationsOptionTestIntegrationStub found in final integrations enabled');
113+
}
114+
115+
/**
116+
* Make sure the passed integration is not one of the disabled integrations.
117+
*
118+
* @param \Sentry\Integration\IntegrationInterface $integration
119+
*/
120+
private function ensureIsNotDisabledIntegration(IntegrationInterface $integration)
121+
{
122+
if ($integration instanceof ErrorListenerIntegration) {
123+
$this->fail('Should not have ErrorListenerIntegration registered');
124+
}
125+
126+
if ($integration instanceof ExceptionListenerIntegration) {
127+
$this->fail('Should not have ExceptionListenerIntegration registered');
128+
}
129+
130+
if ($integration instanceof FatalErrorListenerIntegration) {
131+
$this->fail('Should not have FatalErrorListenerIntegration registered');
132+
}
133+
}
76134
}
77135

78136
class IntegrationsOptionTestIntegrationStub implements IntegrationInterface

0 commit comments

Comments
 (0)