Skip to content

Commit b5bd18a

Browse files
committed
Implementation of optional sentry tracing with twig
1 parent d526d9d commit b5bd18a

File tree

17 files changed

+269
-1
lines changed

17 files changed

+269
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## Unreleased
44

5+
- Add support for distributed tracing of Twig template rendering (#430)
56
- Add support for distributed tracing of SQL queries while using Doctrine DBAL (#426)
67
- Added missing `capture-soft-fails` config schema option (#417)
78
- Deprecate the `Sentry\SentryBundle\EventListener\ConsoleCommandListener` class in favor of its parent class `Sentry\SentryBundle\EventListener\ConsoleListener` (#429)

composer.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,14 @@
5050
"symfony/monolog-bundle": "^3.4",
5151
"symfony/phpunit-bridge": "^5.0",
5252
"symfony/polyfill-php80": "^1.22",
53+
"symfony/twig-bundle": "^3.4.44||^4.4.12||^5.0.11",
5354
"symfony/yaml": "^3.4.44||^4.4.11||^5.0.11",
5455
"vimeo/psalm": "^4.3"
5556
},
5657
"suggest": {
5758
"monolog/monolog": "Allow sending log messages to Sentry by using the included Monolog handler.",
58-
"doctrine/doctrine-bundle": "Allow distributed tracing of database queries using Sentry."
59+
"doctrine/doctrine-bundle": "Allow distributed tracing of database queries using Sentry.",
60+
"symfony/twig-bundle": "Allow distributed tracing of twig template rendering using Sentry."
5961
},
6062
"autoload": {
6163
"files": [

src/DependencyInjection/Configuration.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,9 @@ private function addDistributedTracingSection(ArrayNodeDefinition $rootNode): vo
163163
->end()
164164
->end()
165165
->end()
166+
->arrayNode('twig')
167+
->canBeEnabled()
168+
->end()
166169
->end()
167170
->end()
168171
->end();

src/DependencyInjection/SentryExtension.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Sentry\Options;
1717
use Sentry\SentryBundle\EventListener\ErrorListener;
1818
use Sentry\SentryBundle\EventListener\MessengerListener;
19+
use Sentry\SentryBundle\Tracing\Twig\TwigTracingExtension;
1920
use Sentry\SentryBundle\SentryBundle;
2021
use Sentry\SentryBundle\Tracing\Doctrine\DBAL\ConnectionConfigurator;
2122
use Sentry\SentryBundle\Tracing\Doctrine\DBAL\TracingDriverMiddleware;
@@ -62,6 +63,7 @@ protected function loadInternal(array $mergedConfig, ContainerBuilder $container
6263
$this->registerErrorListenerConfiguration($container, $mergedConfig);
6364
$this->registerMessengerListenerConfiguration($container, $mergedConfig['messenger']);
6465
$this->registerTracingConfiguration($container, $mergedConfig['tracing']);
66+
$this->registerTracingTwigExtensionConfiguration($container, $mergedConfig['tracing']);
6567
}
6668

6769
/**
@@ -173,6 +175,18 @@ private function registerTracingConfiguration(ContainerBuilder $container, array
173175
}
174176
}
175177

178+
/**
179+
* @param array<string, mixed> $config
180+
*/
181+
private function registerTracingTwigExtensionConfiguration(ContainerBuilder $container, array $config): void
182+
{
183+
$isConfigEnabled = $this->isConfigEnabled($container, $config['twig']);
184+
185+
if (!$isConfigEnabled) {
186+
$container->removeDefinition(TwigTracingExtension::class);
187+
}
188+
}
189+
176190
/**
177191
* @param string[] $integrations
178192
* @param array<string, mixed> $config

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
<xsd:complexType name="tracing">
8585
<xsd:choice maxOccurs="unbounded">
8686
<xsd:element name="dbal" type="tracing-dbal" minOccurs="0" maxOccurs="1" />
87+
<xsd:element name="twig" type="tracing-twig" minOccurs="0" maxOccurs="1" />
8788
</xsd:choice>
8889
</xsd:complexType>
8990

@@ -94,4 +95,7 @@
9495

9596
<xsd:attribute name="enabled" type="xsd:boolean" />
9697
</xsd:complexType>
98+
<xsd:complexType name="tracing-twig">
99+
<xsd:attribute name="enabled" type="xsd:boolean" />
100+
</xsd:complexType>
97101
</xsd:schema>

src/Resources/config/services.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,11 @@
7373
<argument type="service" id="Sentry\SentryBundle\Tracing\Doctrine\DBAL\TracingDriverMiddleware" />
7474
</service>
7575

76+
<service id="Sentry\SentryBundle\Tracing\Twig\TwigTracingExtension" class="Sentry\SentryBundle\Tracing\Twig\TwigTracingExtension">
77+
<argument type="service" id="Sentry\State\HubInterface" />
78+
<tag name="twig.extension" />
79+
</service>
80+
7681
<service id="Sentry\Integration\RequestFetcherInterface" class="Sentry\SentryBundle\Integration\RequestFetcher">
7782
<argument type="service" id="Symfony\Component\HttpFoundation\RequestStack" />
7883
<argument type="service" id="Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface" on-invalid="null" />
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Sentry\SentryBundle\Tracing\Twig;
6+
7+
use Sentry\State\HubInterface;
8+
use Sentry\Tracing\SpanContext;
9+
use SplObjectStorage;
10+
use Twig\Extension\AbstractExtension;
11+
use Twig\Profiler\NodeVisitor\ProfilerNodeVisitor;
12+
use Twig\Profiler\Profile;
13+
14+
final class TwigTracingExtension extends AbstractExtension
15+
{
16+
/**
17+
* @var HubInterface The current hub
18+
*/
19+
private $hub;
20+
21+
/**
22+
* @var SplObjectStorage<object, \Sentry\Tracing\Span>
23+
*/
24+
private $events;
25+
26+
/**
27+
* @param HubInterface $hub The current hub
28+
*/
29+
public function __construct(HubInterface $hub)
30+
{
31+
$this->hub = $hub;
32+
$this->events = new SplObjectStorage();
33+
}
34+
35+
/**
36+
* @param Profile $profile
37+
*/
38+
public function enter(Profile $profile): void
39+
{
40+
$transaction = $this->hub->getTransaction();
41+
42+
if (null === $transaction || !$profile->isTemplate()) {
43+
return;
44+
}
45+
46+
$spanContext = new SpanContext();
47+
$spanContext->setOp('twig.template');
48+
$spanContext->setDescription($profile->getName());
49+
50+
$this->events[$profile] = $transaction->startChild($spanContext);
51+
}
52+
53+
/**
54+
* @param Profile $profile
55+
*/
56+
public function leave(Profile $profile): void
57+
{
58+
if (empty($this->events[$profile]) || !$profile->isTemplate()) {
59+
return;
60+
}
61+
62+
$this->events[$profile]->finish();
63+
unset($this->events[$profile]);
64+
}
65+
66+
public function getNodeVisitors(): array
67+
{
68+
return [new ProfilerNodeVisitor(static::class)];
69+
}
70+
}

src/aliases.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
use Sentry\SentryBundle\EventListener\ErrorListenerExceptionEvent;
1515
use Sentry\SentryBundle\EventListener\RequestListenerControllerEvent;
1616
use Sentry\SentryBundle\EventListener\RequestListenerRequestEvent;
17+
use Sentry\SentryBundle\EventListener\RequestListenerResponseEvent;
18+
use Sentry\SentryBundle\EventListener\RequestListenerTerminateEvent;
1719
use Sentry\SentryBundle\EventListener\SubRequestListenerRequestEvent;
1820
use Sentry\SentryBundle\Tracing\Doctrine\DBAL\Compatibility\DriverInterface;
1921
use Sentry\SentryBundle\Tracing\Doctrine\DBAL\Compatibility\ExceptionConverterDriverInterface;

tests/DependencyInjection/ConfigurationTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ public function testProcessConfigurationWithDefaultConfiguration(): void
4141
'enabled' => false,
4242
'connections' => class_exists(DoctrineBundle::class) ? ['%doctrine.default_connection%'] : [],
4343
],
44+
'twig' => [
45+
'enabled' => false,
46+
],
4447
],
4548
];
4649

tests/DependencyInjection/Fixtures/php/full.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,8 @@
4747
'enabled' => false,
4848
'connections' => ['default'],
4949
],
50+
'twig' => [
51+
'enabled' => false
52+
],
5053
],
5154
]);

0 commit comments

Comments
 (0)