You are here

TwigTracingExtension.php in Raven: Sentry Integration 3.x

Namespace

Drupal\raven\Twig

File

src/Twig/TwigTracingExtension.php
View source
<?php

declare (strict_types=1);
namespace Drupal\raven\Twig;

use Drupal\Core\Config\ConfigFactoryInterface;
use Sentry\SentrySdk;
use Sentry\Tracing\SpanContext;
use Twig\Extension\AbstractExtension;
use Twig\Profiler\NodeVisitor\ProfilerNodeVisitor;
use Twig\Profiler\Profile;

/**
 * Provides Twig performance tracing.
 */
class TwigTracingExtension extends AbstractExtension {

  /**
   * Config factory.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $configFactory;

  /**
   * The currently active spans.
   *
   * @var \SplObjectStorage
   */
  private $spans;

  /**
   * Extension constructor.
   */
  public function __construct(ConfigFactoryInterface $config_factory) {
    $this->configFactory = $config_factory;
    $this->spans = new \SplObjectStorage();
  }

  /**
   * This method is called before execution.
   *
   * @param \Twig\Profiler\Profile $profile
   *   The profiling data.
   */
  public function enter(Profile $profile) : void {
    if (!$this->configFactory
      ->get('raven.settings')
      ->get('twig_tracing') || !class_exists(SentrySdk::class)) {
      return;
    }
    $transaction = SentrySdk::getCurrentHub()
      ->getTransaction();
    if (NULL === $transaction) {
      return;
    }
    $spanContext = new SpanContext();
    $spanContext
      ->setOp('twig.render');
    $spanContext
      ->setDescription($this
      ->getSpanDescription($profile));
    $this->spans[$profile] = $transaction
      ->startChild($spanContext);
  }

  /**
   * This method is called when execution is finished.
   *
   * @param \Twig\Profiler\Profile $profile
   *   The profiling data.
   */
  public function leave(Profile $profile) : void {
    if (!isset($this->spans[$profile])) {
      return;
    }
    $this->spans[$profile]
      ->finish();
    unset($this->spans[$profile]);
  }

  /**
   * {@inheritdoc}
   */
  public function getNodeVisitors() : array {
    return [
      new ProfilerNodeVisitor(self::class),
    ];
  }

  /**
   * Gets a short description for the span.
   *
   * @param \Twig\Profiler\Profile $profile
   *   The profiling data.
   */
  private function getSpanDescription(Profile $profile) : string {
    switch (TRUE) {
      case $profile
        ->isRoot():
        return $profile
          ->getName();
      case $profile
        ->isTemplate():
        return $profile
          ->getTemplate();
      default:
        return sprintf('%s::%s(%s)', $profile
          ->getTemplate(), $profile
          ->getType(), $profile
          ->getName());
    }
  }

}

Classes

Namesort descending Description
TwigTracingExtension Provides Twig performance tracing.