diff --git a/README.md b/README.md
index 61f88ea..7a34d3c 100644
--- a/README.md
+++ b/README.md
@@ -46,9 +46,22 @@ sentry:
# Trace 10% of requests
traces_sample_rate: 0.1
-# Optional: Report scheduled tasks status to Sentry. See https://docs.sentry.io/product/crons/ for more information and check pricing before enabling this feature.
frosh_sentry:
+ # Optional: Report scheduled tasks status to Sentry. See https://docs.sentry.io/product/crons/ for more information and check pricing before enabling this feature.
report_scheduled_tasks: false
+ storefront:
+ # optional: if you want track errors occurs within the browser (javascript/cors/csp)
+ enabled: true
+ # optional: if you want record the user sessions. Please aware the GDPR.
+ replay_recording:
+ enabled: true
+ sample_rate: 0.1
+ # optional: if you want measure the performance within the browser
+ tracing:
+ enabled: true
+ sample_rate: 0.1
+ # you should always specify a sdk version. If you do not provide any version, a hard-coded version got used. We try to keep the version up to date with the latest version, but cause the fast release-line of the javascript SDK it is recommend to update the version number regularly.
+ javascript_sdk_version: "8.26.0"
```
### Pictures
diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php
index 06de471..7a975c3 100644
--- a/src/DependencyInjection/Configuration.php
+++ b/src/DependencyInjection/Configuration.php
@@ -15,10 +15,29 @@ public function getConfigTreeBuilder(): TreeBuilder
$treeBuilder = new TreeBuilder('frosh_sentry');
$rootNode = $treeBuilder->getRootNode();
- $rootNode
+ // @formatter:off
+ $rootNode // @phpstan-ignore-line
->children()
->booleanNode('report_scheduled_tasks')->defaultFalse()->end()
+ ->arrayNode('storefront')
+ ->children()
+ ->booleanNode('enabled')->defaultFalse()->end()
+ ->arrayNode('replay_recording')
+ ->children()
+ ->booleanNode('enabled')->defaultFalse()->end()
+ ->floatNode('sample_rate')->defaultValue(0.1)->end()
+ ->end()
+ ->end()
+ ->arrayNode('tracing')
+ ->children()
+ ->booleanNode('enabled')->defaultFalse()->end()
+ ->floatNode('sample_rate')->defaultValue(0.1)->end()
+ ->end()
+ ->end()
+ ->scalarNode('javascript_sdk_version')->defaultValue('8.26.0')->end()
+ ->end()
->end();
+ // @formatter:on
return $treeBuilder;
}
diff --git a/src/Resources/config/services.xml b/src/Resources/config/services.xml
new file mode 100644
index 0000000..a9cdc69
--- /dev/null
+++ b/src/Resources/config/services.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Resources/views/storefront/layout/meta.html.twig b/src/Resources/views/storefront/layout/meta.html.twig
new file mode 100644
index 0000000..4411310
--- /dev/null
+++ b/src/Resources/views/storefront/layout/meta.html.twig
@@ -0,0 +1,7 @@
+{% sw_extends '@Storefront/storefront/layout/meta.html.twig' %}
+
+{% block layout_head_javascript_feature %}
+ {% sw_include '@ShopwareSentryBundle/storefront/sentry.html.twig' %}
+
+ {{ parent() }}
+{% endblock %}
diff --git a/src/Resources/views/storefront/sentry.html.twig b/src/Resources/views/storefront/sentry.html.twig
new file mode 100644
index 0000000..b54b8b8
--- /dev/null
+++ b/src/Resources/views/storefront/sentry.html.twig
@@ -0,0 +1,37 @@
+{% if sentry %}
+ {% block sentry %}
+
+
+ {% endblock %}
+{% endif %}
diff --git a/src/ShopwareSentryBundle.php b/src/ShopwareSentryBundle.php
index f620b9b..0b26259 100644
--- a/src/ShopwareSentryBundle.php
+++ b/src/ShopwareSentryBundle.php
@@ -8,11 +8,11 @@
use Frosh\SentryBundle\Listener\FixRequestUrlListener;
use Frosh\SentryBundle\Listener\SalesChannelContextListener;
use Frosh\SentryBundle\Subscriber\ScheduledTaskSubscriber;
+use Shopware\Core\Framework\Bundle;
use Shopware\Core\System\SalesChannel\Event\SalesChannelContextCreatedEvent;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
use Symfony\Component\DependencyInjection\Reference;
-use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Sentry\State\HubInterface;
@@ -20,6 +20,8 @@ class ShopwareSentryBundle extends Bundle
{
public function build(ContainerBuilder $container): void
{
+ parent::build($container);
+
$container
->register(SalesChannelContextListener::class)
->addTag('kernel.event_listener', ['event' => SalesChannelContextCreatedEvent::class, 'method' => '__invoke'])
diff --git a/src/Subscriber/StorefrontPageSubscriber.php b/src/Subscriber/StorefrontPageSubscriber.php
new file mode 100644
index 0000000..b07deae
--- /dev/null
+++ b/src/Subscriber/StorefrontPageSubscriber.php
@@ -0,0 +1,73 @@
+ 'onRender',
+ ];
+ }
+
+ public function onRender(StorefrontRenderEvent $event): void
+ {
+ if ($this->sentryOptions->getDsn() == null
+ || !$this->container->getParameter('frosh_sentry.storefront.enabled')
+ ) {
+ return;
+ }
+
+ $jsSdkVersion = $this->container->getParameter('frosh_sentry.storefront.javascript_sdk_version');
+ if (!is_string($jsSdkVersion)) {
+ return;
+ }
+
+ $isReplayRecordingEnabled = $this->container->getParameter('frosh_sentry.storefront.replay_recording.enabled');
+ $isPerformanceTracingEnabled = $this->container->getParameter('frosh_sentry.storefront.tracing.enabled');
+
+ if ($isReplayRecordingEnabled && $isPerformanceTracingEnabled) {
+ $jsFile = 'bundle.tracing.replay.min.js';
+ } elseif ($isReplayRecordingEnabled && !$isPerformanceTracingEnabled) {
+ $jsFile = 'bundle.replay.min.js';
+ } elseif (!$isReplayRecordingEnabled && $isPerformanceTracingEnabled) {
+ $jsFile = 'bundle.tracing.min.js';
+ } elseif (!$isReplayRecordingEnabled && !$isPerformanceTracingEnabled) {
+ $jsFile = 'bundle.min.js';
+ } else {
+ // this case should never happen
+ return;
+ }
+
+ $replaySample = $this->container->getParameter('frosh_sentry.storefront.replay_recording.sample_rate');
+ $tracingSample = $this->container->getParameter('frosh_sentry.storefront.tracing.sample_rate');
+
+ $event->setParameter('sentry', [
+ 'dsn' => $this->sentryOptions->getDsn(),
+ 'javascript_src' => sprintf("https://browser.sentry-cdn.com/%s/%s", $jsSdkVersion, $jsFile),
+ 'replay_recording' => [
+ 'enabled' => $isReplayRecordingEnabled,
+ 'sample_rate' => is_float($replaySample) ? $replaySample : 0.1,
+ ],
+ 'tracing' => [
+ 'enabled' => $isPerformanceTracingEnabled,
+ 'sample_rate' => is_float($tracingSample) ? $tracingSample : 0.1,
+ ],
+ 'release' => $this->sentryOptions->getRelease(),
+ 'environment' => $this->sentryOptions->getEnvironment(),
+ ]);
+ }
+}