Skip to content

Commit

Permalink
NEW TemplateCache tab (showing partial caching hits/misses) added (#78)
Browse files Browse the repository at this point in the history
  • Loading branch information
fspringveldt authored and robbieaverill committed Jul 25, 2017
1 parent 856f7c4 commit 9f8837a
Show file tree
Hide file tree
Showing 10 changed files with 234 additions and 2 deletions.
8 changes: 8 additions & 0 deletions README.md
Expand Up @@ -27,6 +27,7 @@ composer require --dev lekoala/silverstripe-debugbar
* [Database profiling](#database-profiling)
* [System logs and messages](#system-logs-and-messages)
* [Template use](#template-use)
* [Partial caching hits and misses](#partial-caching-hits-and-misses)
* [Environment and other information](#environment-and-other-information)
* [Helper methods](#helper-methods)
* [Configuration options](#configuration-options)
Expand Down Expand Up @@ -107,6 +108,13 @@ This will only be populated when you are flushing your cache (`?flush=1`). When

![Templates](docs/_images/templates.png)

### Partial caching hits and misses
The "TemplateCache" tab shows how effective your chosen partial cache key is (e.g. `<% cached 'navigation', $LastEdited %>...<% end_cached %>`). It does
this by indicating whether a key has hit a cache or not.

![Partial caching](docs/_images/templateCache.png)


### Environment and other information

There is a variety of other useful information available via various tabs and indicators on the debug bar. See the screenshot below, and the arrows explained in order from left to right:
Expand Down
13 changes: 13 additions & 0 deletions _config/debugbar.yml
Expand Up @@ -45,6 +45,19 @@ SilverStripe\Core\Injector\Injector:
properties:
Middlewares:
DebugBarMiddleware: %$DebugBarMiddleware
Psr\SimpleCache\CacheInterface.backend:
factory: SilverStripe\Core\Cache\CacheFactory
constructor:
namespace: "cacheblock"
defaultLifetime: 600
Psr\SimpleCache\CacheInterface.cacheblock: %$Psr\SimpleCache\CacheInterface.proxied
Psr\SimpleCache\CacheInterface.proxied:
class: SilverStripe\Core\Injector\AopProxyService
properties:
proxied: %$Psr\SimpleCache\CacheInterface.backend
afterCall:
get:
- %$LeKoala\DebugBar\Aspect\CacheAfterCallAspect

SilverStripe\Admin\LeftAndMain:
extensions:
Expand Down
29 changes: 29 additions & 0 deletions code/Aspects/CacheAfterCallAspect.php
@@ -0,0 +1,29 @@
<?php

namespace LeKoala\DebugBar\Aspect;

use LeKoala\DebugBar\Collector\PartialCacheCollector;
use SilverStripe\Core\Convert;
use SilverStripe\Core\Injector\AfterCallAspect;

class CacheAfterCallAspect implements AfterCallAspect
{
/**
* Logs all hits/misses after a CacheInterface::get call is made.
*
* {@inheritdoc}
*/
public function afterCall($proxied, $method, $args, $result)
{
$message = (empty($result)) ? "Missed: {$args[0]}" : "Hit: {$args[0]}";
$result = preg_replace('/\s+/', ' ', trim($result));
$result = Convert::raw2att($result);
PartialCacheCollector::addTemplateCache(
$message,
array(
'cache_result' =>
array('result' => $result)
)
);
}
}
78 changes: 78 additions & 0 deletions code/Collector/PartialCacheCollector.php
@@ -0,0 +1,78 @@
<?php

namespace LeKoala\DebugBar\Collector;

use DebugBar\DataCollector\DataCollector;
use DebugBar\DataCollector\Renderable;

/**
* Collects data about the partial cache hits and misses during a SilverStripe request
*/
class PartialCacheCollector extends DataCollector implements Renderable
{
/**
* Contains a list of all partial caches found.
* @var array
*/
protected static $templateCache = [];

public function getName()
{
return 'partial-cache';
}

public function collect()
{
$result = self::getTemplateCache();
return [
'count' => count($result),
'calls' => $result
];
}

public function getWidgets()
{
$widgets = [
'Partial Cache' => [
'icon' => 'asterisk',
'widget' => 'PhpDebugBar.Widgets.ConfigWidget',
'map' => 'partial-cache.calls',
'default' => '{}'
]
];
if (count(self::getTemplateCache()) > 0) {
$widgets['Partial Cache:badge'] = [
'map' => 'partial-cache.count',
'default' => 0
];
}

return $widgets;
}

/**
* @return array
*/
public static function getTemplateCache()
{
return (self::$templateCache) ?: [];
}

/**
* Adds an item to the templateCache array
* @param string $key
* @param array $item
*/
public static function addTemplateCache($key, $item)
{
self::$templateCache[$key] = $item;
}

/**
* @param array $templateCache
*/
public static function setTemplateCache($templateCache)
{
self::$templateCache = $templateCache;
}
}
3 changes: 1 addition & 2 deletions code/Collector/SilverStripeCollector.php
Expand Up @@ -10,7 +10,6 @@
use SilverStripe\Admin\LeftAndMain;
use SilverStripe\Control\Controller;
use SilverStripe\Control\Cookie;
use SilverStripe\Control\Session;
use SilverStripe\Core\Convert;
use SilverStripe\i18n\i18n;
use SilverStripe\Security\Member;
Expand Down Expand Up @@ -235,7 +234,7 @@ public function getWidgets()
'templates:badge' => array(
'map' => "$name.templates.count",
'default' => 0
),
)
);

if (!empty(self::$debug)) {
Expand Down
2 changes: 2 additions & 0 deletions code/DebugBar.php
Expand Up @@ -12,6 +12,7 @@
use Exception;
use LeKoala\DebugBar\Collector\ConfigCollector;
use LeKoala\DebugBar\Collector\DatabaseCollector;
use LeKoala\DebugBar\Collector\PartialCacheCollector;
use LeKoala\DebugBar\Collector\SilverStripeCollector;
use LeKoala\DebugBar\Collector\TimeDataCollector;
use LeKoala\DebugBar\Messages\LogFormatter;
Expand Down Expand Up @@ -171,6 +172,7 @@ public static function initDebugBar()
// Add the config collector
$debugbar->addCollector(new ConfigCollector);
}
$debugbar->addCollector(new PartialCacheCollector);

// Since we buffer everything, why not enable all dev options ?
if (self::config()->auto_debug) {
Expand Down
Binary file added docs/_images/templateCache.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions javascript/config/widget.js
Expand Up @@ -35,6 +35,11 @@

$.each(args, function(key, result) {
var heading = key;

if (result === null) {
return true;
}

if (parseInt(result.calls) > 1) {
heading += ' <span class="phpdebugbar-badge">' + result.calls + '</span>';
}
Expand Down
30 changes: 30 additions & 0 deletions tests/Aspects/CacheAfterCallAspectTest.php
@@ -0,0 +1,30 @@
<?php

namespace LeKoala\DebugBar\Test\Aspect;

use LeKoala\DebugBar\Aspect\CacheAfterCallAspect;
use LeKoala\DebugBar\Collector\PartialCacheCollector;
use Psr\SimpleCache\CacheInterface;
use SilverStripe\Core\Injector\AopProxyService;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Dev\SapphireTest;

class CacheAfterCallAspectTest extends SapphireTest
{
/**
* Tests if an entry was added to PartialCacheCollector::$template_cache_info array
*/
public function testAfterCall()
{
$proxy = new AopProxyService();
$aspect = new CacheAfterCallAspect();
$proxy->afterCall = array(
'get' => $aspect
);
$count = count(PartialCacheCollector::getTemplateCache());
$proxy->proxied = Injector::inst()->get(CacheInterface::class . '.backend');
$cacheKey = 'myCacheKey';
$proxy->get($cacheKey);
$this->assertCount($count + 1, PartialCacheCollector::getTemplateCache());
}
}
68 changes: 68 additions & 0 deletions tests/Collector/PartialCacheCollectorTest.php
@@ -0,0 +1,68 @@
<?php

namespace LeKoala\DebugBar\Test\Collector;

use LeKoala\DebugBar\Collector\PartialCacheCollector;
use SilverStripe\Dev\SapphireTest;

class PartialCacheCollectorTest extends SapphireTest
{
/**
* @var PartialCacheCollector
*/
private $collector;

protected function setUp()
{
parent::setUp();
$this->collector = new PartialCacheCollector();
}

public function testGetName()
{
$this->assertNotEmpty($this->collector->getName());
}

/**
* Tests that the tab is returned and that the badge is optional
*/
public function testGetWidgets()
{
PartialCacheCollector::setTemplateCache(array());
$widgets = $this->collector->getWidgets();
$this->assertArrayHasKey('Partial Cache', $widgets);
$this->assertArrayNotHasKey('Partial Cache:badge', $widgets);

PartialCacheCollector::addTemplateCache('test', array('test'));
$this->assertArrayHasKey('Partial Cache:badge', $this->collector->getWidgets());
}

/**
* Tests that an array is returned with specific indexes set
*/
public function testCollect()
{
$result = $this->collector->collect();
$this->assertArrayHasKey('count', $result);
$this->assertArrayHasKey('calls', $result);
}

/**
* Tests that adding an item to the cache increases its count
*/
public function testAddTemplateCache()
{
$count = count(PartialCacheCollector::getTemplateCache());
PartialCacheCollector::addTemplateCache('test1234', array('test'));
$this->assertCount($count + 1, PartialCacheCollector::getTemplateCache());
}

/**
* Tests that the setter works
*/
public function testSetTemplateCache()
{
PartialCacheCollector::setTemplateCache(array());
$this->assertCount(0, PartialCacheCollector::getTemplateCache());
}
}

0 comments on commit 9f8837a

Please sign in to comment.