cache_metrics-2.0.0/src/CacheBackendWrapper.php
src/CacheBackendWrapper.php
<?php
namespace Drupal\cache_metrics;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Symfony\Component\HttpFoundation\RequestStack;
/**
* Wraps an existing cache backend to track calls to the cache backend.
*
* Inspired by webprofiler module.
*/
class CacheBackendWrapper implements CacheBackendInterface, CacheTagsInvalidatorInterface {
const EVENT_NAME = 'CacheGet';
/**
* The wrapped cache backend.
*
* @var \Drupal\Core\Cache\CacheBackendInterface
*/
protected $cacheBackend;
/**
* The name of the wrapped cache bin.
*
* @var string
*/
protected $bin;
/**
* Request stack.
*
* @var \Symfony\Component\HttpFoundation\RequestStack
*/
protected $requestStack;
/**
* Account Interface.
*
* @var \Drupal\Core\Session\AccountProxyInterface
*/
protected $currentUser;
/**
* Constructs a new CacheBackendWrapper.
*
* @param \Drupal\Core\Cache\CacheBackendInterface $cacheBackend
* The wrapped cache backend.
* @param string $bin
* The name of the wrapped cache bin.
* @param \Drupal\Core\Session\AccountProxyInterface $currentUser
* The current user service.
* @param \Symfony\Component\HttpFoundation\RequestStack $requestStack
* The request stack service.
*/
public function __construct(CacheBackendInterface $cacheBackend, $bin, AccountProxyInterface $currentUser, RequestStack $requestStack) {
$this->cacheBackend = $cacheBackend;
$this->bin = $bin;
$this->currentUser = $currentUser;
$this->requestStack = $requestStack;
}
/**
* {@inheritdoc}
*/
public function get($cid, $allow_invalid = FALSE) {
$cache = $this->cacheBackend->get($cid, $allow_invalid);
$hit = $cache !== FALSE;
$attributes = $this->buildAttributes($cid, $hit, $cache, FALSE);
$this->record($attributes);
return $cache;
}
/**
* {@inheritdoc}
*/
public function getMultiple(&$cids, $allow_invalid = FALSE) {
$cidsCopy = $cids;
// Perform the actual fetch.
$cache = $this->cacheBackend->getMultiple($cids, $allow_invalid);
// Record an event for each cid that was requested.
foreach ($cidsCopy as $cid) {
$hit = !in_array($cid, $cids);
$cacheItem = $cache[$cid] ?? NULL;
$attributes = $this->buildAttributes($cid, $hit, $cacheItem, TRUE);
$this->record($attributes);
}
return $cache;
}
/**
* {@inheritdoc}
*/
public function set($cid, $data, $expire = Cache::PERMANENT, array $tags = []) {
return $this->cacheBackend->set($cid, $data, $expire, $tags);
}
/**
* {@inheritdoc}
*/
public function setMultiple(array $items) {
return $this->cacheBackend->setMultiple($items);
}
/**
* {@inheritdoc}
*/
public function delete($cid) {
return $this->cacheBackend->delete($cid);
}
/**
* {@inheritdoc}
*/
public function deleteMultiple(array $cids) {
return $this->cacheBackend->deleteMultiple($cids);
}
/**
* {@inheritdoc}
*/
public function deleteAll() {
return $this->cacheBackend->deleteAll();
}
/**
* {@inheritdoc}
*/
public function invalidate($cid) {
return $this->cacheBackend->invalidate($cid);
}
/**
* {@inheritdoc}
*/
public function invalidateMultiple(array $cids) {
return $this->cacheBackend->invalidateMultiple($cids);
}
/**
* {@inheritdoc}
*/
public function invalidateTags(array $tags) {
if ($this->cacheBackend instanceof CacheTagsInvalidatorInterface) {
$this->cacheBackend->invalidateTags($tags);
}
}
/**
* {@inheritdoc}
*/
public function invalidateAll() {
return $this->cacheBackend->invalidateAll();
}
/**
* {@inheritdoc}
*/
public function garbageCollection() {
return $this->cacheBackend->garbageCollection();
}
/**
* {@inheritdoc}
*/
public function removeBin() {
return $this->cacheBackend->removeBin();
}
/**
* Record the event.
*
* @param array $attributes
* The array of attributes values.
*/
protected function record(array $attributes) {
newrelic_record_custom_event(self::EVENT_NAME, $attributes);
}
/**
* Build the attributes array for sending to New Relic.
*/
protected function buildAttributes(mixed $cid, bool $hit, $cache, bool $isMultiple): array {
$request = $this->requestStack->getCurrentRequest();
$attributes = [
// Not possible to measure duration for getMultiple().
'duration' => NULL,
'cid' => $cid,
'bin' => $this->bin,
'hit' => (int) $hit,
'miss' => (int) !$hit,
'expire' => $hit ? $cache->expire : NULL,
'tags' => $hit ? implode(' ', $cache->tags) : NULL,
'isMultiple' => $isMultiple,
'uri' => $request ? $request->getBaseUrl() . $request->getPathInfo(
) : NULL,
// Acquia https://docs.acquia.com/acquia-cloud/develop/env-variable.
'request_id' => getenv('HTTP_X_REQUEST_ID'),
// A Cloudflare header.
'cf_ray' => $request ? $request->headers->get('CF-RAY') : NULL,
'username' => $this->currentUser->getAccountName(),
];
return $attributes;
}
}
