Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Future add data source #489

Open
wants to merge 31 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
fe7b7fc
Future add data source (#1)
evgenybukharev Jun 23, 2022
c95f6cc
add data storage
evgenybukharev Jun 23, 2022
d7a8ed1
add data storage
evgenybukharev Jun 23, 2022
593157b
add data storage
evgenybukharev Jun 23, 2022
e8a6dfb
codestyle fix
evgenybukharev Jul 5, 2022
f1480b0
restore
evgenybukharev Jul 5, 2022
d946f93
Merge remote-tracking branch 'yiisoft/master'
evgenybukharev Jan 27, 2023
8c2d360
fix
evgenybukharev Jan 27, 2023
f464387
fix
evgenybukharev Jan 27, 2023
4af6b3b
fix
evgenybukharev Jan 27, 2023
abbf63b
fix
evgenybukharev Jan 27, 2023
8215da0
Merge remote-tracking branch 'origin/master' into future_add_data_source
evgenybukharev Jan 27, 2023
5516465
add yii\helpers\IpHelper
evgenybukharev Jan 27, 2023
ae8afbf
fix syntax error, unexpected 'class' (T_CLASS), expecting identifier …
evgenybukharev Jan 27, 2023
7ecfedc
fix syntax error, unexpected 'class' (T_CLASS), expecting identifier …
evgenybukharev Jan 27, 2023
f6c8f54
fix syntax error, unexpected 'class' (T_CLASS), expecting identifier …
evgenybukharev Jan 27, 2023
36a7605
add data storage info to CHANGELOG and README
evgenybukharev Jan 27, 2023
274a9d6
recover merge bugs
evgenybukharev Jan 28, 2023
a4c1775
codestyle
evgenybukharev Jan 28, 2023
6ca168f
recover merge bugs
evgenybukharev Jan 28, 2023
d259c64
add Instance::ensure
evgenybukharev Jan 28, 2023
6ea0f29
refactor if/else
evgenybukharev Jan 28, 2023
9946fa2
add Instance::ensure
evgenybukharev Jan 28, 2023
61b3ff0
make CacheDataStorage properties
evgenybukharev Feb 16, 2023
309ddf7
Update CHANGELOG.md
samdark Feb 20, 2023
0d8759b
Merge remote-tracking branch 'yiisoft/master'
evgenybukharev Apr 6, 2023
72488bc
Fix isset data exceptions
evgenybukharev Apr 6, 2023
98eb846
Merge branch 'master' into future_add_data_source
evgenybukharev Apr 6, 2023
611eed6
Merge branch 'master' into future_add_data_source
samdark Feb 20, 2024
cdb69db
Update CHANGELOG.md
samdark Feb 27, 2024
e7d9eaf
Update CHANGELOG.md
samdark Feb 27, 2024
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Yii Framework 2 debug extension Change Log
2.1.26 under development
------------------------

- Enh #489: Adds data storage functionality that allows you to replace file storage with any available storage (evgenybukharev)
- Enh #430: Allow to configure toolbar position via `Module::$toolbarPosition` property (sasha-x)
- Bug #528: Fix `yii\debug\Panel::getTraceLine()` to handle backtrace for internal PHP functions (zymeli)

Expand Down
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,28 @@ You will see a debugger toolbar showing at the bottom of every page of your appl
You can click on the toolbar to see more detailed debug information.


Data Storage
-----

You can save debug data in any storage, for this you need to implement the yii\debug\components\data\DataStorage interface, and configure the module.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
You can save debug data in any storage, for this you need to implement the yii\debug\components\data\DataStorage interface, and configure the module.
You can save debug data in any storage, for this you need to implement the `yii\debug\components\data\DataStorage` interface, and configure the module.

Solves the problem of correct operation of the debug panel in case the application is located on several servers.

```php
return [
'bootstrap' => ['debug'],
'modules' => [
'debug' => [
'class' => 'yii\debug\Module',
'dataStorageConfig'=>[
'class'=>'yii\debug\components\data\CacheDataStorage',
],
],
// ...
],
...
];
```

Open Files in IDE
-----

Expand Down
128 changes: 8 additions & 120 deletions src/LogTarget.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,14 @@ public function __construct($module, $config = [])
/**
* Exports log messages to a specific destination.
* Child classes must implement this method.
* @throws \yii\base\Exception
*/
public function export()
{
$path = $this->module->dataPath;
FileHelper::createDirectory($path, $this->module->dirMode);

$summary = $this->collectSummary();
$dataFile = "$path/{$this->tag}.data";

$data = [];
$exceptions = [];

foreach ($this->module->panels as $id => $panel) {
try {
$panelData = $panel->save();
Expand All @@ -71,47 +68,25 @@ public function export()
$data['summary'] = $summary;
$data['exceptions'] = $exceptions;

file_put_contents($dataFile, serialize($data));
if ($this->module->fileMode !== null) {
@chmod($dataFile, $this->module->fileMode);
}

$indexFile = "$path/index.data";
$this->updateIndexFile($indexFile, $summary);
$this->module->getDataStorage()->setData($this->tag, $data);
}

/**
* @see DefaultController
* @return array
* @see DefaultController
*/
public function loadManifest()
{
$indexFile = $this->module->dataPath . '/index.data';

$content = '';
$fp = @fopen($indexFile, 'r');
if ($fp !== false) {
@flock($fp, LOCK_SH);
$content = fread($fp, filesize($indexFile));
@flock($fp, LOCK_UN);
fclose($fp);
}

if ($content !== '') {
return array_reverse(unserialize($content), true);
}

return [];
return $this->module->getDataStorage()->getDataManifest();
}

/**
* @see DefaultController
* @return array
* @see DefaultController
*/
public function loadTagToPanels($tag)
{
$dataFile = $this->module->dataPath . "/$tag.data";
$data = unserialize(file_get_contents($dataFile));
$data = $this->module->getDataStorage()->getData($tag);
$exceptions = $data['exceptions'];
foreach ($this->module->panels as $id => $panel) {
if (isset($data[$id])) {
Expand All @@ -124,57 +99,18 @@ public function loadTagToPanels($tag)
$panel->setError($exceptions[$id]);
}
}
$this->module->getDataStorage()->setData($this->tag, $data);

return $data;
samdark marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* Updates index file with summary log data
*
* @param string $indexFile path to index file
* @param array $summary summary log data
* @throws \yii\base\InvalidConfigException
*/
private function updateIndexFile($indexFile, $summary)
{
if (!@touch($indexFile) || ($fp = @fopen($indexFile, 'r+')) === false) {
throw new InvalidConfigException("Unable to open debug data index file: $indexFile");
}
@flock($fp, LOCK_EX);
$manifest = '';
while (($buffer = fgets($fp)) !== false) {
$manifest .= $buffer;
}
if (!feof($fp) || empty($manifest)) {
// error while reading index data, ignore and create new
$manifest = [];
} else {
$manifest = unserialize($manifest);
}

$manifest[$this->tag] = $summary;
$this->gc($manifest);

ftruncate($fp, 0);
rewind($fp);
fwrite($fp, serialize($manifest));

@flock($fp, LOCK_UN);
@fclose($fp);

if ($this->module->fileMode !== null) {
@chmod($indexFile, $this->module->fileMode);
}
}

/**
* Processes the given log messages.
* This method will filter the given messages with [[levels]] and [[categories]].
* And if requested, it will also export the filtering result to specific medium (e.g. email).
* @param array $messages log messages to be processed. See [[\yii\log\Logger::messages]] for the structure
* of each message.
* @param bool $final whether this method is called at the end of the current application
* @throws \yii\base\Exception
*/
public function collect($messages, $final)
{
Expand All @@ -184,54 +120,6 @@ public function collect($messages, $final)
}
}

/**
* Removes obsolete data files
* @param array $manifest
*/
protected function gc(&$manifest)
{
if (count($manifest) > $this->module->historySize + 10) {
$n = count($manifest) - $this->module->historySize;
foreach (array_keys($manifest) as $tag) {
$file = $this->module->dataPath . "/$tag.data";
@unlink($file);
if (isset($manifest[$tag]['mailFiles'])) {
foreach ($manifest[$tag]['mailFiles'] as $mailFile) {
@unlink(Yii::getAlias($this->module->panels['mail']->mailPath) . "/$mailFile");
}
}
unset($manifest[$tag]);
if (--$n <= 0) {
break;
}
}
$this->removeStaleDataFiles($manifest);
}
}

/**
* Remove staled data files i.e. files that are not in the current index file
* (may happen because of corrupted or rotated index file)
*
* @param array $manifest
* @since 2.0.11
*/
protected function removeStaleDataFiles($manifest)
{
$storageTags = array_map(
function ($file) {
return pathinfo($file, PATHINFO_FILENAME);
},
FileHelper::findFiles($this->module->dataPath, ['except' => ['index.data']])
);

$staledTags = array_diff($storageTags, array_keys($manifest));

foreach ($staledTags as $tag) {
@unlink($this->module->dataPath . "/$tag.data");
}
}

/**
* Collects summary data of current request.
* @return array
Expand Down
55 changes: 29 additions & 26 deletions src/Module.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,22 @@
use Yii;
use yii\base\Application;
use yii\base\BootstrapInterface;
use yii\helpers\Html;
use yii\helpers\IpHelper;
use yii\base\InvalidConfigException;
use yii\debug\components\data\DataStorage;
use yii\di\Instance;
use yii\helpers\Json;
use yii\helpers\Url;
use yii\web\ForbiddenHttpException;
use yii\helpers\IpHelper;
use yii\web\Response;
use yii\helpers\Html;
use yii\helpers\Url;
use yii\web\View;
use yii\web\ForbiddenHttpException;

/**
* The Yii Debug Module provides the debug toolbar and debugger
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
* @since 2.0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @since 2.0
* @since 2.0

*/
class Module extends \yii\base\Module implements BootstrapInterface
{
Expand Down Expand Up @@ -76,30 +79,20 @@ class Module extends \yii\base\Module implements BootstrapInterface
* @since 2.0.7
*/
public $defaultPanel = 'log';

/**
* @var string the directory storing the debugger data files. This can be specified using a path alias.
*/
public $dataPath = '@runtime/debug';
/**
* @var int the permission to be set for newly created debugger data files.
* This value will be used by PHP [[chmod()]] function. No umask will be applied.
* If not set, the permission will be determined by the current environment.
* @since 2.0.6
*/
public $fileMode;
/**
* @var int the permission to be set for newly created directories.
* This value will be used by PHP [[chmod()]] function. No umask will be applied.
* Defaults to 0775, meaning the directory is read-writable by owner and group,
* but read-only for other users.
* @since 2.0.6
* @var DataStorage
*/
public $dirMode = 0775;
private $dataStorage;

/**
* @var int the maximum number of debug data files to keep. If there are more files generated,
* the oldest ones will be removed.
* Config options by DataStorage
* @var string[]
*/
public $historySize = 50;
public $dataStorageConfig = [
'class' => 'yii\debug\components\data\FileDataStorage',
];

/**
* @var int the debug bar default height, as a percentage of the total screen height
* @since 2.1.1
Expand All @@ -117,6 +110,7 @@ class Module extends \yii\base\Module implements BootstrapInterface
* You may want to enable the debug logs if you want to investigate how the debug module itself works.
*/
public $enableDebugLogs = false;

/**
* @var bool whether to disable IP address restriction warning triggered by checkAccess function
* @since 2.0.14
Expand Down Expand Up @@ -226,7 +220,8 @@ public static function setYiiLogo($logo)
public function init()
{
parent::init();
$this->dataPath = Yii::getAlias($this->dataPath);

$this->dataStorage = Instance::ensure($this->dataStorageConfig + ['module' => $this],'yii\debug\components\data\DataStorage');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
$this->dataStorage = Instance::ensure($this->dataStorageConfig + ['module' => $this],'yii\debug\components\data\DataStorage');
$this->dataStorage = Instance::ensure($this->dataStorageConfig + ['module' => $this], 'yii\debug\components\data\DataStorage');


$this->initPanels();
}
Expand Down Expand Up @@ -490,6 +485,14 @@ protected function corePanels()
return $corePanels;
}

/**
* @return DataStorage
*/
public function getDataStorage()
{
return $this->dataStorage;
}

/**
* {@inheritdoc}
* @since 2.0.7
Expand Down
Loading
Loading