vendor/symfony/cache/Adapter/TraceableAdapter.php line 172

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <fabien@symfony.com>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace Symfony\Component\Cache\Adapter;
  11. use Psr\Cache\CacheItemInterface;
  12. use Symfony\Component\Cache\CacheItem;
  13. use Symfony\Component\Cache\PruneableInterface;
  14. use Symfony\Component\Cache\ResettableInterface;
  15. use Symfony\Contracts\Cache\CacheInterface;
  16. use Symfony\Contracts\Service\ResetInterface;
  17. /**
  18.  * An adapter that collects data about all cache calls.
  19.  *
  20.  * @author Aaron Scherer <aequasi@gmail.com>
  21.  * @author Tobias Nyholm <tobias.nyholm@gmail.com>
  22.  * @author Nicolas Grekas <p@tchwork.com>
  23.  */
  24. class TraceableAdapter implements AdapterInterfaceCacheInterfacePruneableInterfaceResettableInterface
  25. {
  26.     protected $pool;
  27.     private array $calls = [];
  28.     public function __construct(AdapterInterface $pool)
  29.     {
  30.         $this->pool $pool;
  31.     }
  32.     public function get(string $key, callable $callbackfloat $beta null, array &$metadata null): mixed
  33.     {
  34.         if (!$this->pool instanceof CacheInterface) {
  35.             throw new \BadMethodCallException(sprintf('Cannot call "%s::get()": this class doesn\'t implement "%s".'get_debug_type($this->pool), CacheInterface::class));
  36.         }
  37.         $isHit true;
  38.         $callback = function (CacheItem $itembool &$save) use ($callback, &$isHit) {
  39.             $isHit $item->isHit();
  40.             return $callback($item$save);
  41.         };
  42.         $event $this->start(__FUNCTION__);
  43.         try {
  44.             $value $this->pool->get($key$callback$beta$metadata);
  45.             $event->result[$key] = get_debug_type($value);
  46.         } finally {
  47.             $event->end microtime(true);
  48.         }
  49.         if ($isHit) {
  50.             ++$event->hits;
  51.         } else {
  52.             ++$event->misses;
  53.         }
  54.         return $value;
  55.     }
  56.     public function getItem(mixed $key): CacheItem
  57.     {
  58.         $event $this->start(__FUNCTION__);
  59.         try {
  60.             $item $this->pool->getItem($key);
  61.         } finally {
  62.             $event->end microtime(true);
  63.         }
  64.         if ($event->result[$key] = $item->isHit()) {
  65.             ++$event->hits;
  66.         } else {
  67.             ++$event->misses;
  68.         }
  69.         return $item;
  70.     }
  71.     public function hasItem(mixed $key): bool
  72.     {
  73.         $event $this->start(__FUNCTION__);
  74.         try {
  75.             return $event->result[$key] = $this->pool->hasItem($key);
  76.         } finally {
  77.             $event->end microtime(true);
  78.         }
  79.     }
  80.     public function deleteItem(mixed $key): bool
  81.     {
  82.         $event $this->start(__FUNCTION__);
  83.         try {
  84.             return $event->result[$key] = $this->pool->deleteItem($key);
  85.         } finally {
  86.             $event->end microtime(true);
  87.         }
  88.     }
  89.     public function save(CacheItemInterface $item): bool
  90.     {
  91.         $event $this->start(__FUNCTION__);
  92.         try {
  93.             return $event->result[$item->getKey()] = $this->pool->save($item);
  94.         } finally {
  95.             $event->end microtime(true);
  96.         }
  97.     }
  98.     public function saveDeferred(CacheItemInterface $item): bool
  99.     {
  100.         $event $this->start(__FUNCTION__);
  101.         try {
  102.             return $event->result[$item->getKey()] = $this->pool->saveDeferred($item);
  103.         } finally {
  104.             $event->end microtime(true);
  105.         }
  106.     }
  107.     public function getItems(array $keys = []): iterable
  108.     {
  109.         $event $this->start(__FUNCTION__);
  110.         try {
  111.             $result $this->pool->getItems($keys);
  112.         } finally {
  113.             $event->end microtime(true);
  114.         }
  115.         $f = function () use ($result$event) {
  116.             $event->result = [];
  117.             foreach ($result as $key => $item) {
  118.                 if ($event->result[$key] = $item->isHit()) {
  119.                     ++$event->hits;
  120.                 } else {
  121.                     ++$event->misses;
  122.                 }
  123.                 yield $key => $item;
  124.             }
  125.         };
  126.         return $f();
  127.     }
  128.     public function clear(string $prefix ''): bool
  129.     {
  130.         $event $this->start(__FUNCTION__);
  131.         try {
  132.             if ($this->pool instanceof AdapterInterface) {
  133.                 return $event->result $this->pool->clear($prefix);
  134.             }
  135.             return $event->result $this->pool->clear();
  136.         } finally {
  137.             $event->end microtime(true);
  138.         }
  139.     }
  140.     public function deleteItems(array $keys): bool
  141.     {
  142.         $event $this->start(__FUNCTION__);
  143.         $event->result['keys'] = $keys;
  144.         try {
  145.             return $event->result['result'] = $this->pool->deleteItems($keys);
  146.         } finally {
  147.             $event->end microtime(true);
  148.         }
  149.     }
  150.     public function commit(): bool
  151.     {
  152.         $event $this->start(__FUNCTION__);
  153.         try {
  154.             return $event->result $this->pool->commit();
  155.         } finally {
  156.             $event->end microtime(true);
  157.         }
  158.     }
  159.     public function prune(): bool
  160.     {
  161.         if (!$this->pool instanceof PruneableInterface) {
  162.             return false;
  163.         }
  164.         $event $this->start(__FUNCTION__);
  165.         try {
  166.             return $event->result $this->pool->prune();
  167.         } finally {
  168.             $event->end microtime(true);
  169.         }
  170.     }
  171.     /**
  172.      * @return void
  173.      */
  174.     public function reset()
  175.     {
  176.         if ($this->pool instanceof ResetInterface) {
  177.             $this->pool->reset();
  178.         }
  179.         $this->clearCalls();
  180.     }
  181.     public function delete(string $key): bool
  182.     {
  183.         $event $this->start(__FUNCTION__);
  184.         try {
  185.             return $event->result[$key] = $this->pool->deleteItem($key);
  186.         } finally {
  187.             $event->end microtime(true);
  188.         }
  189.     }
  190.     /**
  191.      * @return array
  192.      */
  193.     public function getCalls()
  194.     {
  195.         return $this->calls;
  196.     }
  197.     /**
  198.      * @return void
  199.      */
  200.     public function clearCalls()
  201.     {
  202.         $this->calls = [];
  203.     }
  204.     public function getPool(): AdapterInterface
  205.     {
  206.         return $this->pool;
  207.     }
  208.     /**
  209.      * @return TraceableAdapterEvent
  210.      */
  211.     protected function start(string $name)
  212.     {
  213.         $this->calls[] = $event = new TraceableAdapterEvent();
  214.         $event->name $name;
  215.         $event->start microtime(true);
  216.         return $event;
  217.     }
  218. }
  219. /**
  220.  * @internal
  221.  */
  222. class TraceableAdapterEvent
  223. {
  224.     public string $name;
  225.     public float $start;
  226.     public float $end;
  227.     public array|bool $result;
  228.     public int $hits 0;
  229.     public int $misses 0;
  230. }