Skip to content

Commit c792525

Browse files
authored
Merge pull request #195 from getsentry/add-before-breadcrumb
Add before_breadcrumb
2 parents 4d952a7 + 74b16b9 commit c792525

File tree

4 files changed

+114
-23
lines changed

4 files changed

+114
-23
lines changed

src/DependencyInjection/Configuration.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,12 @@ public function getConfigTreeBuilder()
4646
$optionsNode
4747
->children()
4848
->booleanNode('attach_stacktrace')->end()
49-
// TODO -- before_breadcrumb
49+
->variableNode('before_breadcrumb')
50+
->validate()
51+
->ifTrue($this->isNotAValidCallback())
52+
->thenInvalid('Expecting callable or service reference, got %s')
53+
->end()
54+
->end()
5055
->variableNode('before_send')
5156
->validate()
5257
->ifTrue($this->isNotAValidCallback())

src/DependencyInjection/SentryExtension.php

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
1010
use Symfony\Component\Config\FileLocator;
1111
use Symfony\Component\DependencyInjection\ContainerBuilder;
12+
use Symfony\Component\DependencyInjection\Definition;
1213
use Symfony\Component\DependencyInjection\Loader;
1314
use Symfony\Component\DependencyInjection\Reference;
1415
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
@@ -86,14 +87,27 @@ private function passConfigurationToOptions(ContainerBuilder $container, array $
8687
}
8788

8889
if (\array_key_exists('before_send', $processedOptions)) {
89-
$optionValue = $processedOptions['before_send'];
90-
if (is_string($optionValue) && 0 === strpos($optionValue, '@')) {
91-
$beforeSend = new Reference(substr($optionValue, 1));
92-
} else {
93-
$beforeSend = $optionValue;
94-
}
90+
$this->mapCallableValue($options, 'setBeforeSendCallback', $processedOptions['before_send']);
91+
}
9592

96-
$options->addMethodCall('setBeforeSendCallback', [$beforeSend]);
93+
if (\array_key_exists('before_breadcrumb', $processedOptions)) {
94+
$this->mapCallableValue($options, 'setBeforeBreadcrumbCallback', $processedOptions['before_breadcrumb']);
9795
}
9896
}
97+
98+
/**
99+
* @param Definition $options
100+
* @param string $method
101+
* @param callable|string $optionValue
102+
*/
103+
private function mapCallableValue(Definition $options, string $method, $optionValue): void
104+
{
105+
if (is_string($optionValue) && 0 === strpos($optionValue, '@')) {
106+
$beforeSend = new Reference(substr($optionValue, 1));
107+
} else {
108+
$beforeSend = $optionValue;
109+
}
110+
111+
$options->addMethodCall($method, [$beforeSend]);
112+
}
99113
}

test/DependencyInjection/ConfigurationTest.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
class ConfigurationTest extends TestCase
1313
{
14-
public const SUPPORTED_SENTRY_OPTIONS_COUNT = 20;
14+
public const SUPPORTED_SENTRY_OPTIONS_COUNT = 21;
1515

1616
public function testDataProviderIsMappingTheRightNumberOfOptions(): void
1717
{
@@ -84,6 +84,7 @@ public function optionValuesProvider(): array
8484
{
8585
return [
8686
['attach_stacktrace', true],
87+
['before_breadcrumb', 'count'],
8788
['before_send', 'count'],
8889
['context_lines', 4],
8990
['context_lines', 99],
@@ -126,6 +127,10 @@ public function invalidValuesProvider(): array
126127
{
127128
return [
128129
['attach_stacktrace', 'string'],
130+
['before_breadcrumb', 'this is not a callable'],
131+
['before_breadcrumb', [$this, 'is not a callable']],
132+
['before_breadcrumb', false],
133+
['before_breadcrumb', -1],
129134
['before_send', 'this is not a callable'],
130135
['before_send', [$this, 'is not a callable']],
131136
['before_send', false],

test/DependencyInjection/SentryExtensionTest.php

Lines changed: 81 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Sentry\SentryBundle\Test\DependencyInjection;
44

55
use PHPUnit\Framework\TestCase;
6+
use Sentry\Breadcrumb;
67
use Sentry\Event;
78
use Sentry\Options;
89
use Sentry\SentryBundle\DependencyInjection\SentryExtension;
@@ -89,6 +90,7 @@ public function optionsValueProvider(): array
8990
{
9091
return [
9192
['attach_stacktrace', true, 'shouldAttachStacktrace'],
93+
['before_breadcrumb', __NAMESPACE__ . '\mockBeforeBreadcrumb', 'getBeforeBreadcrumbCallback'],
9294
['before_send', __NAMESPACE__ . '\mockBeforeSend', 'getBeforeSendCallback'],
9395
['context_lines', 1],
9496
['default_integrations', false, 'hasDefaultIntegrations'],
@@ -153,7 +155,7 @@ public function testBeforeSendUsingServiceDefinition(): void
153155
{
154156
$container = $this->getContainer([
155157
'options' => [
156-
'before_send' => '@before_send',
158+
'before_send' => '@callable_mock',
157159
],
158160
]);
159161

@@ -166,13 +168,13 @@ public function testBeforeSendUsingServiceDefinition(): void
166168
'before_send closure has not been replaced, is the default one'
167169
);
168170
$this->assertEquals(
169-
CallbackMock::createBeforeSendCallback(),
171+
CallbackMock::createCallback(),
170172
$beforeSendCallback
171173
);
172174
}
173175

174176
/**
175-
* @dataProvider beforeSendDataProvider
177+
* @dataProvider scalarCallableDataProvider
176178
*/
177179
public function testBeforeSendUsingScalarCallable($scalarCallable): void
178180
{
@@ -196,26 +198,86 @@ public function testBeforeSendUsingScalarCallable($scalarCallable): void
196198
);
197199
}
198200

199-
public function beforeSendDataProvider(): array
201+
public function testBeforeSendWithInvalidServiceReference(): void
202+
{
203+
$container = $this->getContainer([
204+
'options' => [
205+
'before_send' => '@event_dispatcher',
206+
],
207+
]);
208+
209+
$this->expectException(\TypeError::class);
210+
211+
$this->getOptionsFrom($container)->getBeforeSendCallback();
212+
}
213+
214+
public function testBeforeBreadcrumbUsingServiceDefinition(): void
215+
{
216+
$container = $this->getContainer([
217+
'options' => [
218+
'before_breadcrumb' => '@callable_mock',
219+
],
220+
]);
221+
222+
$beforeBreadcrumbCallback = $this->getOptionsFrom($container)->getBeforeBreadcrumbCallback();
223+
$this->assertIsCallable($beforeBreadcrumbCallback);
224+
$defaultOptions = $this->getOptionsFrom($this->getContainer());
225+
$this->assertNotEquals(
226+
$defaultOptions->getBeforeBreadcrumbCallback(),
227+
$beforeBreadcrumbCallback,
228+
'before_breadcrumb closure has not been replaced, is the default one'
229+
);
230+
$this->assertEquals(
231+
CallbackMock::createCallback(),
232+
$beforeBreadcrumbCallback
233+
);
234+
}
235+
236+
/**
237+
* @dataProvider scalarCallableDataProvider
238+
*/
239+
public function testBeforeBreadcrumbUsingScalarCallable($scalarCallable): void
240+
{
241+
$container = $this->getContainer([
242+
'options' => [
243+
'before_breadcrumb' => $scalarCallable,
244+
],
245+
]);
246+
247+
$beforeBreadcrumbCallback = $this->getOptionsFrom($container)->getBeforeBreadcrumbCallback();
248+
$this->assertIsCallable($beforeBreadcrumbCallback);
249+
$defaultOptions = $this->getOptionsFrom($this->getContainer());
250+
$this->assertNotEquals(
251+
$defaultOptions->getBeforeBreadcrumbCallback(),
252+
$beforeBreadcrumbCallback,
253+
'before_breadcrumb closure has not been replaced, is the default one'
254+
);
255+
$this->assertEquals(
256+
$scalarCallable,
257+
$beforeBreadcrumbCallback
258+
);
259+
}
260+
261+
public function scalarCallableDataProvider(): array
200262
{
201263
return [
202-
[[CallbackMock::class, 'beforeSend']],
203-
[CallbackMock::class . '::beforeSend'],
264+
[[CallbackMock::class, 'callback']],
265+
[CallbackMock::class . '::callback'],
204266
[__NAMESPACE__ . '\mockBeforeSend'],
205267
];
206268
}
207269

208-
public function testBeforeSendWithInvalidServiceReference(): void
270+
public function testBeforeBreadcrumbWithInvalidServiceReference(): void
209271
{
210272
$container = $this->getContainer([
211273
'options' => [
212-
'before_send' => '@event_dispatcher',
274+
'before_breadcrumb' => '@event_dispatcher',
213275
],
214276
]);
215277

216278
$this->expectException(\TypeError::class);
217279

218-
$this->getOptionsFrom($container)->getBeforeSendCallback();
280+
$this->getOptionsFrom($container)->getBeforeBreadcrumbCallback();
219281
}
220282

221283
private function getContainer(array $configuration = []): Container
@@ -241,8 +303,8 @@ private function getContainer(array $configuration = []): Container
241303
$containerBuilder->setAlias(self::CONSOLE_LISTENER_TEST_PUBLIC_ALIAS, new Alias(ConsoleListener::class, true));
242304

243305
$beforeSend = new Definition('callable');
244-
$beforeSend->setFactory([CallbackMock::class, 'createBeforeSendCallback']);
245-
$containerBuilder->setDefinition('before_send', $beforeSend);
306+
$beforeSend->setFactory([CallbackMock::class, 'createCallback']);
307+
$containerBuilder->setDefinition('callable_mock', $beforeSend);
246308

247309
$extension = new SentryExtension();
248310
$extension->load(['sentry' => $configuration], $containerBuilder);
@@ -268,15 +330,20 @@ function mockBeforeSend(Event $event): ?Event
268330
return null;
269331
}
270332

333+
function mockBeforeBreadcrumb(Breadcrumb $breadcrumb): ?Breadcrumb
334+
{
335+
return null;
336+
}
337+
271338
class CallbackMock
272339
{
273-
public static function beforeSend(Event $event): ?Event
340+
public static function callback()
274341
{
275342
return null;
276343
}
277344

278-
public static function createBeforeSendCallback(): callable
345+
public static function createCallback(): callable
279346
{
280-
return [new self(), 'beforeSend'];
347+
return [new self(), 'callback'];
281348
}
282349
}

0 commit comments

Comments
 (0)