Skip to content

Commit

Permalink
Merge pull request #245 from getsentry/add-class_serializers-option
Browse files Browse the repository at this point in the history
Add class_serializers option
  • Loading branch information
Jean85 committed Sep 23, 2019
2 parents 4f4dcf0 + df3905e commit 5b8b5de
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 31 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -6,7 +6,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## [Unreleased]
- Add forward compatibility with Symfony 5 (#235, thanks to @garak)
- Fix Hub initialization for `ErrorListener` (#243, thanks to @teohhanhui)
- Fix compatibility with sentry/sentry 2.2+ (#244)
- Add support for `class_serializers` option (#245)

## 3.1.0 - 2019-07-02
- Add support for Symfony 2.8 (#233, thanks to @nocive)
Expand Down
22 changes: 19 additions & 3 deletions src/DependencyInjection/Configuration.php
Expand Up @@ -57,6 +57,11 @@ public function getConfigTreeBuilder(): TreeBuilder
if (PrettyVersions::getVersion('sentry/sentry')->getPrettyVersion() !== '2.0.0') {
$optionsChildNodes->booleanNode('capture_silenced_errors');
}
if ($this->classSerializersAreSupported()) {
$optionsChildNodes->arrayNode('class_serializers')
->defaultValue([])
->prototype('scalar');
}
$optionsChildNodes->integerNode('context_lines')
->min(0)
->max(99);
Expand All @@ -80,13 +85,13 @@ public function getConfigTreeBuilder(): TreeBuilder
->prototype('scalar')
->validate()
->ifTrue(function ($value): bool {
if (! is_string($value)) {
if (! is_string($value) && '' != $value) {
return true;
}

return '@' !== substr($value, 0, 1);
return '@' !== $value[0];
})
->thenInvalid('Expecting service reference, got %s');
->thenInvalid('Expecting service reference, got "%s"');
$optionsChildNodes->scalarNode('logger');
$optionsChildNodes->integerNode('max_breadcrumbs')
->min(1);
Expand Down Expand Up @@ -163,4 +168,15 @@ private function isNotAValidCallback(): \Closure
return true;
};
}

private function classSerializersAreSupported(): bool
{
try {
new Options(['class_serializers' => []]);

return true;
} catch (\Throwable $throwable) {
return false;
}
}
}
31 changes: 17 additions & 14 deletions src/DependencyInjection/SentryExtension.php
Expand Up @@ -14,7 +14,6 @@
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Loader;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
Expand Down Expand Up @@ -97,11 +96,22 @@ private function passConfigurationToOptions(ContainerBuilder $container, array $
}

if (\array_key_exists('before_send', $processedOptions)) {
$this->mapCallableValue($options, 'setBeforeSendCallback', $processedOptions['before_send']);
$beforeSendCallable = $this->valueToCallable($processedOptions['before_send']);
$options->addMethodCall('setBeforeSendCallback', [$beforeSendCallable]);
}

if (\array_key_exists('before_breadcrumb', $processedOptions)) {
$this->mapCallableValue($options, 'setBeforeBreadcrumbCallback', $processedOptions['before_breadcrumb']);
$beforeBreadcrumbCallable = $this->valueToCallable($processedOptions['before_breadcrumb']);
$options->addMethodCall('setBeforeBreadcrumbCallback', [$beforeBreadcrumbCallable]);
}

if (\array_key_exists('class_serializers', $processedOptions)) {
$classSerializers = [];
foreach ($processedOptions['class_serializers'] as $class => $serializer) {
$classSerializers[$class] = $this->valueToCallable($serializer);
}

$options->addMethodCall('setClassSerializers', [$classSerializers]);
}

if (\array_key_exists('integrations', $processedOptions)) {
Expand All @@ -114,20 +124,13 @@ private function passConfigurationToOptions(ContainerBuilder $container, array $
}
}

/**
* @param Definition $options
* @param string $method
* @param callable|string $optionValue
*/
private function mapCallableValue(Definition $options, string $method, $optionValue): void
private function valueToCallable($value)
{
if (is_string($optionValue) && 0 === strpos($optionValue, '@')) {
$beforeSend = new Reference(substr($optionValue, 1));
} else {
$beforeSend = $optionValue;
if (is_string($value) && 0 === strpos($value, '@')) {
return new Reference(substr($value, 1));
}

$options->addMethodCall($method, [$beforeSend]);
return $value;
}

/**
Expand Down
1 change: 0 additions & 1 deletion src/EventListener/ConsoleListener.php
Expand Up @@ -3,7 +3,6 @@
namespace Sentry\SentryBundle\EventListener;

use Sentry\SentryBundle\SentryBundle;
use Sentry\State\Hub;
use Sentry\State\HubInterface;
use Sentry\State\Scope;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
Expand Down
1 change: 0 additions & 1 deletion src/EventListener/RequestListener.php
Expand Up @@ -3,7 +3,6 @@
namespace Sentry\SentryBundle\EventListener;

use Sentry\SentryBundle\SentryBundle;
use Sentry\State\Hub;
use Sentry\State\HubInterface;
use Sentry\State\Scope;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
Expand Down
32 changes: 32 additions & 0 deletions test/BaseTestCase.php
@@ -0,0 +1,32 @@
<?php

namespace Sentry\SentryBundle\Test;

use PHPUnit\Framework\TestCase;
use Sentry\Options;
use Sentry\SentryBundle\Test\DependencyInjection\ConfigurationTest;

abstract class BaseTestCase extends TestCase
{
public const SUPPORTED_SENTRY_OPTIONS_COUNT = 23;

protected function classSerializersAreSupported(): bool
{
try {
new Options(['class_serializers' => []]);

return true;
} catch (\Throwable $throwable) {
return false;
}
}

protected function getSupportedOptionsCount(): int
{
if ($this->classSerializersAreSupported()) {
return ConfigurationTest::SUPPORTED_SENTRY_OPTIONS_COUNT + 1;
}

return ConfigurationTest::SUPPORTED_SENTRY_OPTIONS_COUNT;
}
}
29 changes: 22 additions & 7 deletions test/DependencyInjection/ConfigurationTest.php
Expand Up @@ -3,23 +3,21 @@
namespace Sentry\SentryBundle\Test\DependencyInjection;

use Jean85\PrettyVersions;
use PHPUnit\Framework\TestCase;
use Sentry\Options;
use Sentry\SentryBundle\DependencyInjection\Configuration;
use Sentry\SentryBundle\Test\BaseTestCase;
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use Symfony\Component\Config\Definition\Processor;
use Symfony\Component\HttpKernel\Kernel;

class ConfigurationTest extends TestCase
class ConfigurationTest extends BaseTestCase
{
public const SUPPORTED_SENTRY_OPTIONS_COUNT = 23;

public function testDataProviderIsMappingTheRightNumberOfOptions(): void
{
$providerData = $this->optionValuesProvider();
$supportedOptions = \array_unique(\array_column($providerData, 0));

$expectedCount = self::SUPPORTED_SENTRY_OPTIONS_COUNT;
$expectedCount = $this->getSupportedOptionsCount();

if (PrettyVersions::getVersion('sentry/sentry')->getPrettyVersion() !== '2.0.0') {
++$expectedCount;
Expand All @@ -38,7 +36,7 @@ public function testInvalidDataProviderIsMappingTheRightNumberOfOptions(): void
$supportedOptions = \array_unique(\array_column($providerData, 0));

$this->assertCount(
self::SUPPORTED_SENTRY_OPTIONS_COUNT,
$this->getSupportedOptionsCount(),
$supportedOptions,
'Provider for invalid configuration options mismatch: ' . PHP_EOL . print_r($supportedOptions, true)
);
Expand Down Expand Up @@ -76,6 +74,10 @@ public function testConfigurationDefaults(): void
$expectedDefaults['options']['in_app_exclude'][1] = '%kernel.project_dir%/vendor';
}

if ($this->classSerializersAreSupported()) {
$expectedDefaults['options']['class_serializers'] = [];
}

$this->assertEquals($expectedDefaults, $processed);
$this->assertArrayNotHasKey('server_name', $processed['options'], 'server_name has to be fetched at runtime, not before (see #181)');
}
Expand Down Expand Up @@ -127,6 +129,10 @@ public function optionValuesProvider(): array
$options[] = ['capture_silenced_errors', true];
}

if ($this->classSerializersAreSupported()) {
$options[] = ['class_serializers', ['count']];
}

return $options;
}

Expand All @@ -144,7 +150,7 @@ public function testInvalidValues(string $option, $value): void

public function invalidValuesProvider(): array
{
return [
$values = [
['attach_stacktrace', 'string'],
['before_breadcrumb', 'this is not a callable'],
['before_breadcrumb', [$this, 'is not a callable']],
Expand Down Expand Up @@ -184,6 +190,15 @@ public function invalidValuesProvider(): array
['server_name', []],
['tags', 'invalid-unmapped-tag'],
];

if ($this->classSerializersAreSupported()) {
$values[] = ['class_serializers', 'this is not a callable'];
$values[] = ['class_serializers', [$this, 'is not a callable']];
$values[] = ['class_serializers', false];
$values[] = ['class_serializers', -1];
}

return $values;
}

private function processConfiguration(array $values): array
Expand Down
25 changes: 20 additions & 5 deletions test/DependencyInjection/SentryExtensionTest.php
Expand Up @@ -3,12 +3,12 @@
namespace Sentry\SentryBundle\Test\DependencyInjection;

use Jean85\PrettyVersions;
use PHPUnit\Framework\TestCase;
use Sentry\Breadcrumb;
use Sentry\Event;
use Sentry\Integration\IntegrationInterface;
use Sentry\Options;
use Sentry\SentryBundle\DependencyInjection\SentryExtension;
use Sentry\SentryBundle\Test\BaseTestCase;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\ContainerBuilder;
Expand All @@ -17,7 +17,7 @@
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Kernel;

class SentryExtensionTest extends TestCase
class SentryExtensionTest extends BaseTestCase
{
private const OPTIONS_TEST_PUBLIC_ALIAS = 'sentry.options.public_alias';

Expand All @@ -27,10 +27,10 @@ public function testDataProviderIsMappingTheRightNumberOfOptions(): void
$supportedOptions = \array_unique(\array_column($providerData, 0));

// subtracted one is `integration`, which cannot be tested with the provider
$expectedCount = ConfigurationTest::SUPPORTED_SENTRY_OPTIONS_COUNT - 1;
$expectedCount = $this->getSupportedOptionsCount();

if (PrettyVersions::getVersion('sentry/sentry')->getPrettyVersion() !== '2.0.0') {
++$expectedCount;
if (PrettyVersions::getVersion('sentry/sentry')->getPrettyVersion() === '2.0.0') {
--$expectedCount;
}

$this->assertCount(
Expand Down Expand Up @@ -138,6 +138,16 @@ public function optionsValueProvider(): array
$options[] = ['capture_silenced_errors', true, 'shouldCaptureSilencedErrors'];
}

if ($this->classSerializersAreSupported()) {
$options['class_serializer'] = [
'class_serializers',
[
self::class => __NAMESPACE__ . '\mockClassSerializer',
],
'getClassSerializers',
];
}

return $options;
}

Expand Down Expand Up @@ -375,6 +385,11 @@ function mockBeforeBreadcrumb(Breadcrumb $breadcrumb): ?Breadcrumb
return null;
}

function mockClassSerializer($object)
{
return ['value' => 'serialized_class'];
}

class CallbackMock
{
public static function callback()
Expand Down

0 comments on commit 5b8b5de

Please sign in to comment.