Skip to content

Commit e0ce070

Browse files
authored
Add distributed tracing support for the Symfony Cache component (#477)
1 parent 8e6cf4d commit e0ce070

File tree

18 files changed

+473
-5
lines changed

18 files changed

+473
-5
lines changed

.github/workflows/tests.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ jobs:
108108
restore-keys: ${{ runner.os }}-${{ matrix.php }}-composer-${{ matrix.dependencies }}-
109109

110110
- name: Remove optional packages
111-
run: composer remove doctrine/dbal doctrine/doctrine-bundle symfony/messenger symfony/twig-bundle --dev --no-update
111+
run: composer remove doctrine/dbal doctrine/doctrine-bundle symfony/messenger symfony/twig-bundle symfony/cache --dev --no-update
112112

113113
- name: Install highest dependencies
114114
run: composer update --no-progress --no-interaction --prefer-dist

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
- Add support for distributed tracing of Twig template rendering (#430)
77
- Add support for distributed tracing of SQL queries while using Doctrine DBAL (#426)
88
- Add support for distributed tracing when running a console command (#455)
9-
- Added missing `capture-soft-fails` config schema option (#417)
9+
- Add support for distributed tracing of cache pools (#)
1010
- Deprecate the `Sentry\SentryBundle\EventListener\ConsoleCommandListener` class in favor of its parent class `Sentry\SentryBundle\EventListener\ConsoleListener` (#429)
1111
- Lower the required version of `symfony/psr-http-message-bridge` to allow installing it on a project that uses Symfony `3.4.x` components only (#480)
1212

composer.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
"phpstan/phpstan-phpunit": "^0.12",
4646
"phpunit/phpunit": "^8.5||^9.0",
4747
"symfony/browser-kit": "^3.4.44||^4.4.20||^5.0.11",
48+
"symfony/cache": "^3.4.44||^4.4.20||^5.0.11",
4849
"symfony/dom-crawler": "^3.4.44||^4.4.20||^5.0.11",
4950
"symfony/framework-bundle": "^3.4.44||^4.4.20||^5.0.11",
5051
"symfony/messenger": "^4.4.20||^5.0.11",
@@ -57,7 +58,8 @@
5758
"suggest": {
5859
"monolog/monolog": "Allow sending log messages to Sentry by using the included Monolog handler.",
5960
"doctrine/doctrine-bundle": "Allow distributed tracing of database queries using Sentry.",
60-
"symfony/twig-bundle": "Allow distributed tracing of Twig template rendering using Sentry."
61+
"symfony/twig-bundle": "Allow distributed tracing of Twig template rendering using Sentry.",
62+
"symfony/cache": "Allow distributed tracing of cache pools using Sentry."
6163
},
6264
"autoload": {
6365
"files": [

psalm-baseline.xml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<files psalm-version="4.6.1@e93e532e4eaad6d68c4d7b606853800eaceccc72">
2+
<files psalm-version="4.7.0@d4377c0baf3ffbf0b1ec6998e8d1be2a40971005">
33
<file src="src/EventListener/ConsoleCommandListener.php">
44
<InvalidExtendClass occurrences="1">
55
<code>ConsoleListener</code>
66
</InvalidExtendClass>
7-
<MethodSignatureMismatch occurrences="1"/>
7+
<MethodSignatureMismatch occurrences="1">
8+
<code>public function __construct(HubInterface $hub, bool $captureErrors = true)</code>
9+
</MethodSignatureMismatch>
10+
</file>
11+
<file src="src/Tracing/Cache/TraceableCacheAdapterTrait.php">
12+
<InvalidReturnType occurrences="1">
13+
<code>getItems</code>
14+
</InvalidReturnType>
815
</file>
916
</files>
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Sentry\SentryBundle\DependencyInjection\Compiler;
6+
7+
use Symfony\Component\Cache\Adapter\TagAwareAdapterInterface;
8+
use Symfony\Component\DependencyInjection\ChildDefinition;
9+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
10+
use Symfony\Component\DependencyInjection\ContainerBuilder;
11+
use Symfony\Component\DependencyInjection\Reference;
12+
13+
final class CacheTracingPass implements CompilerPassInterface
14+
{
15+
/**
16+
* {@inheritdoc}
17+
*/
18+
public function process(ContainerBuilder $container): void
19+
{
20+
if (!$container->getParameter('sentry.tracing.cache.enabled')) {
21+
return;
22+
}
23+
24+
foreach ($container->findTaggedServiceIds('cache.pool') as $serviceId => $tags) {
25+
$cachePoolDefinition = $container->getDefinition($serviceId);
26+
27+
if ($cachePoolDefinition->isAbstract()) {
28+
continue;
29+
}
30+
31+
if (is_subclass_of($cachePoolDefinition->getClass(), TagAwareAdapterInterface::class)) {
32+
$traceableCachePoolDefinition = new ChildDefinition('sentry.tracing.traceable_tag_aware_cache_adapter');
33+
} else {
34+
$traceableCachePoolDefinition = new ChildDefinition('sentry.tracing.traceable_cache_adapter');
35+
}
36+
37+
$traceableCachePoolDefinition->setDecoratedService($serviceId);
38+
$traceableCachePoolDefinition->replaceArgument(1, new Reference($serviceId . '.traceable.inner'));
39+
40+
$container->setDefinition($serviceId . '.traceable', $traceableCachePoolDefinition);
41+
}
42+
}
43+
}

src/DependencyInjection/Configuration.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
1414
use Symfony\Component\Config\Definition\ConfigurationInterface;
1515
use Symfony\Component\Messenger\MessageBusInterface;
16+
use Symfony\Contracts\Cache\CacheInterface;
1617

1718
final class Configuration implements ConfigurationInterface
1819
{
@@ -163,6 +164,9 @@ private function addDistributedTracingSection(ArrayNodeDefinition $rootNode): vo
163164
->arrayNode('twig')
164165
->{class_exists(TwigBundle::class) ? 'canBeDisabled' : 'canBeEnabled'}()
165166
->end()
167+
->arrayNode('cache')
168+
->{interface_exists(CacheInterface::class) ? 'canBeDisabled' : 'canBeEnabled'}()
169+
->end()
166170
->end()
167171
->end()
168172
->end();

src/DependencyInjection/SentryExtension.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
use Symfony\Component\DependencyInjection\Reference;
3636
use Symfony\Component\ErrorHandler\Error\FatalError;
3737
use Symfony\Component\HttpKernel\DependencyInjection\ConfigurableExtension;
38+
use Symfony\Contracts\Cache\CacheInterface;
3839

3940
final class SentryExtension extends ConfigurableExtension
4041
{
@@ -68,6 +69,7 @@ protected function loadInternal(array $mergedConfig, ContainerBuilder $container
6869
$this->registerTracingConfiguration($container, $mergedConfig['tracing']);
6970
$this->registerDbalTracingConfiguration($container, $mergedConfig['tracing']);
7071
$this->registerTwigTracingConfiguration($container, $mergedConfig['tracing']);
72+
$this->registerCacheTracingConfiguration($container, $mergedConfig['tracing']);
7173
}
7274

7375
/**
@@ -214,6 +216,21 @@ private function registerTwigTracingConfiguration(ContainerBuilder $container, a
214216
}
215217
}
216218

219+
/**
220+
* @param array<string, mixed> $config
221+
*/
222+
private function registerCacheTracingConfiguration(ContainerBuilder $container, array $config): void
223+
{
224+
$isConfigEnabled = $this->isConfigEnabled($container, $config)
225+
&& $this->isConfigEnabled($container, $config['cache']);
226+
227+
if ($isConfigEnabled && !interface_exists(CacheInterface::class)) {
228+
throw new LogicException('Cache tracing support cannot be enabled because the symfony/cache Composer package is not installed.');
229+
}
230+
231+
$container->setParameter('sentry.tracing.cache.enabled', $isConfigEnabled);
232+
}
233+
217234
/**
218235
* @param string[] $integrations
219236
* @param array<string, mixed> $config

src/Resources/config/schema/sentry-1.0.xsd

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@
8585
<xsd:choice maxOccurs="unbounded">
8686
<xsd:element name="dbal" type="tracing-dbal" minOccurs="0" maxOccurs="1" />
8787
<xsd:element name="twig" type="tracing-twig" minOccurs="0" maxOccurs="1" />
88+
<xsd:element name="cache" type="tracing-cache" minOccurs="0" maxOccurs="1" />
8889
</xsd:choice>
8990

9091
<xsd:attribute name="enabled" type="xsd:boolean" default="true"/>
@@ -101,4 +102,8 @@
101102
<xsd:complexType name="tracing-twig">
102103
<xsd:attribute name="enabled" type="xsd:boolean" />
103104
</xsd:complexType>
105+
106+
<xsd:complexType name="tracing-cache">
107+
<xsd:attribute name="enabled" type="xsd:boolean" />
108+
</xsd:complexType>
104109
</xsd:schema>

src/Resources/config/services.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,16 @@
102102
<tag name="twig.extension" />
103103
</service>
104104

105+
<service id="sentry.tracing.traceable_cache_adapter" class="Sentry\SentryBundle\Tracing\Cache\TraceableCacheAdapter" abstract="true">
106+
<argument type="service" id="Sentry\State\HubInterface" />
107+
<argument /> <!-- $decoratedAdapter -->
108+
</service>
109+
110+
<service id="sentry.tracing.traceable_tag_aware_cache_adapter" class="Sentry\SentryBundle\Tracing\Cache\TraceableTagAwareCacheAdapter" abstract="true">
111+
<argument type="service" id="Sentry\State\HubInterface" />
112+
<argument /> <!-- $decoratedAdapter -->
113+
</service>
114+
105115
<service id="Sentry\Integration\RequestFetcherInterface" class="Sentry\SentryBundle\Integration\RequestFetcher">
106116
<argument type="service" id="Symfony\Component\HttpFoundation\RequestStack" />
107117
<argument type="service" id="Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface" on-invalid="null" />

src/SentryBundle.php

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

55
namespace Sentry\SentryBundle;
66

7+
use Sentry\SentryBundle\DependencyInjection\Compiler\CacheTracingPass;
78
use Sentry\SentryBundle\DependencyInjection\Compiler\DbalTracingPass;
89
use Symfony\Component\DependencyInjection\ContainerBuilder;
910
use Symfony\Component\HttpKernel\Bundle\Bundle;
@@ -17,5 +18,6 @@ public function build(ContainerBuilder $container): void
1718
parent::build($container);
1819

1920
$container->addCompilerPass(new DbalTracingPass());
21+
$container->addCompilerPass(new CacheTracingPass());
2022
}
2123
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Sentry\SentryBundle\Tracing\Cache;
6+
7+
use Sentry\State\HubInterface;
8+
use Symfony\Component\Cache\Adapter\AdapterInterface;
9+
use Symfony\Component\Cache\PruneableInterface;
10+
use Symfony\Component\Cache\ResettableInterface;
11+
use Symfony\Contracts\Cache\CacheInterface;
12+
13+
/**
14+
* This implementation of a cache adapter supports the distributed tracing
15+
* feature of Sentry.
16+
*/
17+
final class TraceableCacheAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface
18+
{
19+
/**
20+
* @phpstan-use TraceableCacheAdapterTrait<AdapterInterface>
21+
*/
22+
use TraceableCacheAdapterTrait;
23+
24+
/**
25+
* @param HubInterface $hub The current hub
26+
* @param AdapterInterface $decoratedAdapter The decorated cache adapter
27+
*/
28+
public function __construct(HubInterface $hub, AdapterInterface $decoratedAdapter)
29+
{
30+
$this->hub = $hub;
31+
$this->decoratedAdapter = $decoratedAdapter;
32+
}
33+
}

0 commit comments

Comments
 (0)