Skip to content
This repository was archived by the owner on Sep 6, 2021. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Currently, the following panels have been written and are working:
* A list of superglobals
* Application settings
* SQL queries including time to execute and param bindings
* Cache requests including time
* Logging output via Yii built-in logging


Expand All @@ -35,6 +36,7 @@ For use [yii-debug-toolbar](/malyshev/yii-debug-toolbar/) need to specify new `r
'class'=>'ext.yii-debug-toolbar.YiiDebugToolbarRoute',
// Access is restricted by default to the localhost
//'ipFilters'=>array('127.0.0.1','192.168.1.*', 88.23.23.0/24),
//'cookieFilters' => array('YiiDebagger123', 'yii-debug-toolbar'),
),
),
),
Expand All @@ -54,6 +56,22 @@ For use [yii-debug-toolbar](/malyshev/yii-debug-toolbar/) need to specify new `r
),
```


* To enable reports about cache usage you need to change application configuration like that
```php
<?php
//...
'cache'=>array(
'class' => 'ext.yii-debug-toolbar.YiiDebugCacheProxy',
'enableProfiling' => true,
'cache' => array(
'class' => 'system.caching.CFileCache', // or other cache class
//... any other valid settings for cache
),
),
```


## TODOs and BUGS

See: [issues](https://github.com/malyshev/yii-debug-toolbar/issues)
Expand All @@ -62,5 +80,7 @@ See: [issues](https://github.com/malyshev/yii-debug-toolbar/issues)
<img src="https://dl.dropboxusercontent.com/u/6067542/yii-debug-toolbar/screenshot_1.png" alt="Screenshot1" />
<img src="https://dl.dropboxusercontent.com/u/6067542/yii-debug-toolbar/screenshot_2.png" alt="Screenshot2" />
<img src="https://dl.dropboxusercontent.com/u/6067542/yii-debug-toolbar/screenshot_3.png" alt="Screenshot3" />
<img src="https://dl.dropboxusercontent.com/sh/09k0c42xasghu6c/Zq0WrQpxw5/screenshot_4.png" alt="Screenshot4" />
<img src="https://dl.dropboxusercontent.com/s/8l0ne92rgsfb3mj/screenshot_5.png" alt="Screenshot5" />


2 changes: 1 addition & 1 deletion YiiDebug.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public static function dump()
}
return;
} else if (empty($_SERVER['SERVER_ADDR']) || empty($_SERVER['REMOTE_ADDR']) || $_SERVER['SERVER_ADDR'] !== $_SERVER['REMOTE_ADDR']) {
return;
//return;
}

$backTrace = debug_backtrace();
Expand Down
267 changes: 267 additions & 0 deletions YiiDebugCacheProxy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
<?php
/**
* YiiDebugCacheProxy class file.
*
* @author Pavel Volyntsev <pavel.volyntsev@gmail.com>
*/

Yii::import('system.caching.CCache');

/**
* Class YiiDebugCacheProxy
*
* Class to profile cache requests
*
* @author Pavel Volyntsev <pavel.volyntsev@gmail.com>
* @version $Id$
* @package
*/
class YiiDebugCacheProxy extends CCache
{
/**
* @var boolean whether to enable profiling requests to cache.
* Defaults to false. This should be mainly enabled and used during development
* to find out the bottleneck of cache executions.
*/
public $enableProfiling = false;

/**
* Options to create cache component
*
* @var array
*/
public $cache;

/**
* memcache ONLY
*
* @var boolean whether to use memcached or memcache as the underlying caching extension.
* If true {@link http://pecl.php.net/package/memcached memcached} will be used.
* If false {@link http://pecl.php.net/package/memcache memcache}. will be used.
* Defaults to false.
*/
public $useMemcached=false;

/**
* memcache ONLY
* @var array list of memcache server configurations
*/
public $servers=array();

/**
* Cache component instance
*
* @var \CCache
*/
protected $_cacheProxy;

/**
* Cache usage statistics
*
* @var array
*/
protected $_stats = array(
'get' => 0, // read requests quantity
'get_time' => 0, // read time
'mget' => 0,
'mget_time' => 0,
'set' => 0, // write requests quantity
'add' => 0, // add requests quantity
'set_time' => 0, // write time
'delete' => 0, // delete requests quantity
'delete_time' => 0, // delete time
'flush' => 0,
'flush_time' => 0,
'hit' => 0, // read requests when data found
'miss' => 0, // read requests when no data found
'count' => 0, // total requests
'time' => 0, // total time
);

/**
* Key for profiling logs
*
* @var
*/
private $_logCategory;

const LOG_CATEGORY = 'system.caching.';

public function init()
{
parent::init();
$this->_logCategory = self::LOG_CATEGORY . get_class($this);
}

/**
* @return CCache
*/
protected function getCacheProxy()
{
if (is_null($this->_cacheProxy)) {
$this->_cacheProxy = Yii::createComponent($this->cache);
$this->_cacheProxy->init();
}

return $this->_cacheProxy;
}

/**
* @see \CCache::get
*
* @param string $id
*
* @return mixed
*/
public function get($id)
{
if ($this->enableProfiling) {
Yii::beginProfile(__METHOD__ . '("' . $id . '")', $this->_logCategory . '.get');
}
$value = $this->getCacheProxy()->get($id);
if ($this->enableProfiling) {
++$this->_stats['get'];
++$this->_stats['hit'];
if (false == $value) {
++$this->_stats['miss'];
}
Yii::endProfile(__METHOD__ . '("' . $id . '")', $this->_logCategory . '.get');
}

return $value;
}

/**
* @see \CCache::mget
*
* @param string[] $ids
*
* @return array
*/
public function mget($ids)
{
if ($this->enableProfiling) {
Yii::beginProfile(__METHOD__ . '("' . implode('","', $ids) . '")', $this->_logCategory . '.mget');
}
$value = $this->getCacheProxy()->mget($ids);
if ($this->enableProfiling) {
++$this->_stats['mget'];
++$this->_stats['hit'];
if (empty($value)) {
++$this->_stats['miss'];
}
Yii::endProfile(__METHOD__ . '("' . implode('","', $ids) . '")', $this->_logCategory . '.mget');
}

return $value;
}

/**
* @see \CCache::set
*
* @param string $id
* @param mixed $value
* @param int $expire
* @param null $dependency
*
* @return bool|mixed
*/
public function set($id, $value, $expire = 0, $dependency = null)
{
if ($this->enableProfiling) {
Yii::beginProfile(__METHOD__ . '("' . $id . '")', $this->_logCategory . '.set');
}
$returnValue = $this->getCacheProxy()->set($id, $value, $expire, $dependency);
if ($this->enableProfiling) {
++$this->_stats['set'];
Yii::endProfile(__METHOD__ . '("' . $id . '")', $this->_logCategory . '.set');
}

return $returnValue;
}

/**
* Stores a value identified by a key into cache if the cache does not contain this key.
* Nothing will be done if the cache already contains the key.
*
* @param string $id the key identifying the value to be cached
* @param mixed $value the value to be cached
* @param integer $expire the number of seconds in which the cached value will expire. 0 means never expire.
* @param ICacheDependency $dependency dependency of the cached item. If the dependency changes, the item is labeled invalid.
*
* @return boolean true if the value is successfully stored into cache, false otherwise
*/
public function add($id, $value, $expire = 0, $dependency = null)
{
if ($this->enableProfiling) {
Yii::beginProfile(__METHOD__ . '("' . $id . '")', $this->_logCategory . '.add');
}

$returnValue = $this->getCacheProxy()->add($id, $value, $expire, $dependency);

if ($this->enableProfiling) {
++$this->_stats['add'];
Yii::endProfile(__METHOD__ . '("' . $id . '")', $this->_logCategory . '.add');
}

return $returnValue;
}

/**
* @see \CCache::delete
*
* @param string $id
*
* @return bool
*/
public function delete($id)
{
if ($this->enableProfiling) {
Yii::beginProfile(__METHOD__ . '("' . $id . '")', $this->_logCategory . '.delete');
}
$value = $this->getCacheProxy()->delete($id);
if ($this->enableProfiling) {
++$this->_stats['delete'];
Yii::endProfile(__METHOD__ . '("' . $id . '")', $this->_logCategory . '.delete');
}

return $value;
}

/**
* @see \CCache::flush
* @return bool
*/
public function flush()
{
if ($this->enableProfiling) {
Yii::beginProfile(__METHOD__ . '()', $this->_logCategory . '.flush');
}
$value = $this->getCacheProxy()->flush();
if ($this->enableProfiling) {
++$this->_stats['flush'];
Yii::endProfile(__METHOD__ . '()', $this->_logCategory . '.flush');
}

return $value;
}

/**
* Returns the statistics about cache usage.
*
* @return array
*/
public function getStats()
{
$logger = Yii::getLogger();
$this->_stats['get_time'] = array_sum($logger->getProfilingResults(null, $this->_logCategory . '.get'));
$this->_stats['mget_time'] = array_sum($logger->getProfilingResults(null, $this->_logCategory . '.mget'));
$this->_stats['set_time'] = array_sum($logger->getProfilingResults(null, $this->_logCategory . '.set'));
$this->_stats['delete_time'] = array_sum($logger->getProfilingResults(null, $this->_logCategory . '.delete'));
$this->_stats['flush_time'] = array_sum($logger->getProfilingResults(null, $this->_logCategory . '.flush'));
$this->_stats['call'] = $this->_stats['get'] + $this->_stats['mget'] + $this->_stats['set'] + $this->_stats['delete'] + $this->_stats['flush'];
$this->_stats['time'] = $this->_stats['get_time'] + $this->_stats['mget_time'] + $this->_stats['set_time'] + $this->_stats['delete_time'] + $this->_stats['flush_time'];

return $this->_stats;
}
}
2 changes: 1 addition & 1 deletion YiiDebugToolbar.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ private function registerClientScripts()
{
$cs = Yii::app()->getClientScript()
->registerCoreScript('jquery');
$cs->registerCssFile($this->assetsUrl . '/main.css');
$cs->registerCssFile($this->assetsUrl . '/main.dark.css');

$cs->registerScriptFile($this->assetsUrl . '/main.js',
CClientScript::POS_END);
Expand Down
20 changes: 19 additions & 1 deletion YiiDebugToolbarRoute.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class YiiDebugToolbarRoute extends CLogRoute
'YiiDebugToolbarPanelViews',
'YiiDebugToolbarPanelSql',
'YiiDebugToolbarPanelLogging',
'YiiDebugToolbarPanelCache',
);

/**
Expand All @@ -35,6 +36,11 @@ class YiiDebugToolbarRoute extends CLogRoute
* - "*" for everything.
*/
public $ipFilters=array('127.0.0.1','::1');

/**
* The filters are given in an array
*/
public $cookieFilters=array('YiiDebagger123');

/**
* Whitelist for response content types. DebugToolbarRoute won't write any
Expand Down Expand Up @@ -114,7 +120,7 @@ public function init()

$this->enabled = strpos(trim($route, '/'), 'debug') !== 0;

$this->enabled && $this->enabled = ($this->allowIp(Yii::app()->request->userHostAddress)
$this->enabled && $this->enabled = (($this->allowIp(Yii::app()->request->userHostAddress) or $this->allowCookies())
&& !Yii::app()->getRequest()->getIsAjaxRequest() && (Yii::app() instanceof CWebApplication))
&& $this->checkContentTypeWhitelist();

Expand Down Expand Up @@ -211,6 +217,18 @@ private function checkContentTypeWhitelist()
return in_array( $contentType, $this->contentTypeWhitelist );
}

/**
* Checks to see if the user cookie is allowed by {@link cookieFilters}.
* @return boolean whether the user cookie is allowed by {@link cookieFilters}.
*/
protected function allowCookies() {
foreach ($this->cookieFilters as $filter) {
$filter = trim($filter);
if (isset($_COOKIE[$filter])) return true;
}
return false;
}

/**
* Checks to see if the user IP is allowed by {@link ipFilters}.
* @param string $ip the user IP
Expand Down
Loading