Commit d0556a13 by Qiang Xue

debug toolbar WIP

parent 5892b265
......@@ -16,32 +16,34 @@ use yii\log\Target;
*/
class LogTarget extends Target
{
/**
* @var Module
*/
public $module;
public $maxLogFiles = 20;
public function __construct($module, $config = array())
{
parent::__construct($config);
$this->module = $module;
}
/**
* Exports log messages to a specific destination.
* Child classes must implement this method.
* @param array $messages the messages to be exported. See [[Logger::messages]] for the structure
* of each message.
*/
public function export($messages)
public function export()
{
$path = Yii::$app->getRuntimePath() . '/debug';
if (!is_dir($path)) {
mkdir($path);
}
$file = $path . '/' . Yii::$app->getLog()->getTag() . '.log';
$data = array(
'messages' => $messages,
'_SERVER' => $_SERVER,
'_GET' => $_GET,
'_POST' => $_POST,
'_COOKIE' => $_COOKIE,
'_FILES' => empty($_FILES) ? array() : $_FILES,
'_SESSION' => empty($_SESSION) ? array() : $_SESSION,
'memory' => memory_get_peak_usage(),
'time' => microtime(true) - YII_BEGIN_TIME,
);
$tag = Yii::$app->getLog()->getTag();
$file = "$path/$tag.log";
$data = array();
foreach ($this->module->panels as $panel) {
$data[$panel->id] = $panel->save();
}
file_put_contents($file, json_encode($data));
}
......
......@@ -18,19 +18,28 @@ use yii\helpers\Html;
class Module extends \yii\base\Module
{
public $controllerNamespace = 'yii\debug\controllers';
public $panels;
/**
* @var array|Panel[]
*/
public $panels = array();
public function init()
{
parent::init();
Yii::$app->log->targets['debug'] = new LogTarget;
foreach (array_merge($this->corePanels(), $this->panels) as $id => $config) {
$config['id'] = $id;
$this->panels[$id] = Yii::createObject($config);
}
Yii::$app->getLog()->targets['debug'] = new LogTarget($this);
Yii::$app->getView()->on(View::EVENT_END_BODY, array($this, 'renderToolbar'));
}
public function beforeAction($action)
{
Yii::$app->getView()->off(View::EVENT_END_BODY, array($this, 'renderToolbar'));
unset(Yii::$app->log->targets['debug']);
unset(Yii::$app->getLog()->targets['debug']);
return parent::beforeAction($action);
}
......@@ -49,4 +58,19 @@ class Module extends \yii\base\Module
'style' => 'display: none',
));
}
protected function corePanels()
{
return array(
'config' => array(
'class' => 'yii\debug\panels\ConfigPanel',
),
'request' => array(
'class' => 'yii\debug\panels\RequestPanel',
),
'log' => array(
'class' => 'yii\debug\panels\LogPanel',
),
);
}
}
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\debug;
use yii\base\Component;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class Panel extends Component
{
public $id;
public $data;
public function getName()
{
return '';
}
public function getSummary()
{
return '';
}
public function getDetail()
{
return '';
}
public function save()
{
return null;
}
public function load($data)
{
$this->data = $data;
}
}
......@@ -9,6 +9,7 @@ namespace yii\debug\controllers;
use Yii;
use yii\web\Controller;
use yii\web\HttpException;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
......@@ -16,22 +17,48 @@ use yii\web\Controller;
*/
class DefaultController extends Controller
{
/** @var \yii\debug\Module */
public $module;
public $layout = 'main';
public function actionIndex($tag)
public function actionIndex($tag, $panel = null)
{
return $this->render('index');
$this->loadData($tag);
if (isset($this->module->panels[$panel])) {
$activePanel = $this->module->panels[$panel];
} else {
$activePanel = reset($this->module->panels);
}
return $this->render('index', array(
'tag' => $tag,
'panels' => $this->module->panels,
'activePanel' => $activePanel,
));
}
public function actionToolbar($tag)
{
$this->loadData($tag);
return $this->renderPartial('toolbar', array(
'panels' => $this->module->panels,
));
}
protected function loadData($tag)
{
$file = Yii::$app->getRuntimePath() . "/debug/$tag.log";
if (preg_match('/^[\w\-]+$/', $tag) && is_file($file)) {
$data = json_decode(file_get_contents($file), true);
$data['tag'] = $tag;
return $this->renderPartial('toolbar', $data);
foreach ($this->module->panels as $id => $panel) {
if (isset($data[$panel->id])) {
$panel->load($data[$panel->id]);
} else {
// remove the panel since it has not received any data
unset($this->module->panels[$id]);
}
}
} else {
return "Unable to find debug data tagged with '$tag'.";
throw new HttpException(404, "Unable to find debug data tagged with '$tag'.");
}
}
}
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\debug\panels;
use Yii;
use yii\debug\Panel;
use yii\helpers\Html;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class ConfigPanel extends Panel
{
public function getName()
{
return 'Config';
}
public function getSummary()
{
$link = Html::a('more details', array('index', 'tag' => $this->data['tag']));
return <<<EOD
<div class="yii-debug-toolbar-block">
PHP: {$this->data['phpVersion']},
Yii: {$this->data['phpVersion']},
$link
</div>
EOD;
}
public function getDetail()
{
return '<h2>Config</h2>';
}
public function save()
{
return array(
'tag' => Yii::$app->getLog()->getTag(),
'phpVersion' => PHP_VERSION,
'yiiVersion' => Yii::getVersion(),
);
}
}
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\debug\panels;
use Yii;
use yii\debug\Panel;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class LogPanel extends Panel
{
public function getName()
{
return 'Logs';
}
public function getSummary()
{
$count = count($this->data['messages']);
return <<<EOD
<div class="yii-debug-toolbar-block">
Log messages: $count
</div>
EOD;
}
public function getDetail()
{
return '<h2>Logs</h2>';
}
public function save()
{
return array(
'messages' => Yii::$app->getLog()->targets['debug']->messages,
);
}
}
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\debug\panels;
use yii\debug\Panel;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class RequestPanel extends Panel
{
public function getName()
{
return 'Request';
}
public function getSummary()
{
$memory = sprintf('%.2fMB', $this->data['memory'] / 1048576);
$time = sprintf('%.3fs', $this->data['time']);
return <<<EOD
<div class="yii-debug-toolbar-block">
Peak memory: $memory
</div>
<div class="yii-debug-toolbar-block">
Time spent: $time
</div>
EOD;
}
public function getDetail()
{
return '<h2>Request</h2>';
}
public function save()
{
return array(
'memory' => memory_get_peak_usage(),
'time' => microtime(true) - YII_BEGIN_TIME,
'SERVER' => $_SERVER,
'GET' => $_GET,
'POST' => $_POST,
'COOKIE' => $_COOKIE,
'FILES' => empty($_FILES) ? array() : $_FILES,
'SESSION' => empty($_SESSION) ? array() : $_SESSION,
);
}
}
here we are
<?php
use yii\helpers\Html;
/**
* @var \yii\base\View $this
* @var string $tag
* @var \yii\debug\Panel[] $panels
* @var \yii\debug\Panel $activePanel
*/
?>
<?php foreach ($panels as $panel): ?>
<?php echo Html::a(Html::encode($panel->getName()), array('debug/default/index', 'tag' => $tag, 'panel' => $panel->id)); ?><br>
<?php endforeach; ?>
<?php echo $activePanel->getDetail(); ?>
<?php use yii\helpers\Html;
echo Html::style("
<?php
/**
* @var \yii\base\View $this
* @var \yii\debug\Panel[] $panels
*/
?>
<style>
#yii-debug-toolbar {
position: fixed;
left: 0;
......@@ -17,24 +21,11 @@ echo Html::style("
.yii-debug-toolbar-block {
float: left;
margin: 0 10px;
");
?>
<div id="yii-debug-toolbar">
<div class="yii-debug-toolbar-block">
<?php echo Html::a('more details', array('index', 'tag' => $tag)); ?>
</div>
<div class="yii-debug-toolbar-block">
Peak memory: <?php echo sprintf('%.2fMB', $memory / 1048576); ?>
</div>
<div class="yii-debug-toolbar-block">
Time spent: <?php echo sprintf('%.3fs', $time); ?>
</div>
<div class="yii-debug-toolbar-block">
</div>
}
</style>
<div class="yii-debug-toolbar-block">
</div>
<div id="yii-debug-toolbar">
<?php foreach ($panels as $panel): ?>
<?php echo $panel->getSummary(); ?>
<?php endforeach; ?>
</div>
......@@ -72,16 +72,14 @@ class DbTarget extends Target
/**
* Stores log messages to DB.
* @param array $messages the messages to be exported. See [[Logger::messages]] for the structure
* of each message.
*/
public function export($messages)
public function export()
{
$tableName = $this->db->quoteTableName($this->logTable);
$sql = "INSERT INTO $tableName ([[level]], [[category]], [[log_time]], [[message]])
VALUES (:level, :category, :log_time, :message)";
$command = $this->db->createCommand($sql);
foreach ($messages as $message) {
foreach ($this->messages as $message) {
$command->bindValues(array(
':level' => $message[1],
':category' => $message[2],
......
......@@ -38,13 +38,11 @@ class EmailTarget extends Target
/**
* Sends log messages to specified email addresses.
* @param array $messages the messages to be exported. See [[Logger::messages]] for the structure
* of each message.
*/
public function export($messages)
public function export()
{
$body = '';
foreach ($messages as $message) {
foreach ($this->messages as $message) {
$body .= $this->formatMessage($message);
}
$body = wordwrap($body, 70);
......
......@@ -65,14 +65,12 @@ class FileTarget extends Target
/**
* Sends log messages to specified email addresses.
* @param array $messages the messages to be exported. See [[Logger::messages]] for the structure
* of each message.
* @throws InvalidConfigException if unable to open the log file for writing
*/
public function export($messages)
public function export()
{
$text = '';
foreach ($messages as $message) {
foreach ($this->messages as $message) {
$text .= $this->formatMessage($message);
}
if (($fp = @fopen($this->logFile, 'a')) === false) {
......
......@@ -124,7 +124,7 @@ class Logger extends Component
*/
public $messages = array();
/**
* @var array the log targets. Each array element represents a single [[Target|log target]] instance
* @var array|Target[] the log targets. Each array element represents a single [[Target|log target]] instance
* or the configuration for creating the log target instance.
*/
public $targets = array();
......
......@@ -68,18 +68,17 @@ abstract class Target extends Component
public $exportInterval = 1000;
/**
* @var array the messages that are retrieved from the logger so far by this log target.
* Please refer to [[Logger::messages]] for the details about the message structure.
*/
public $messages = array();
private $_levels = 0;
/**
* Exports log messages to a specific destination.
* Exports log [[messages]] to a specific destination.
* Child classes must implement this method.
* @param array $messages the messages to be exported. See [[Logger::messages]] for the structure
* of each message.
*/
abstract public function export($messages);
abstract public function export();
/**
* Processes the given log messages.
......@@ -97,7 +96,7 @@ abstract class Target extends Component
if (($context = $this->getContextMessage()) !== '') {
$this->messages[] = array($context, Logger::LEVEL_INFO, 'application', YII_BEGIN_TIME);
}
$this->export($this->messages);
$this->export();
$this->messages = array();
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment