Here's debugger design we've planned together with @xepozz.
General idea is to separate data collection and data display. In Yii 2 it was not
split so design was not convenient for both APIs and displaying data from
multiple servers.
Collection goes to yiisoft/yii-debug,
API goes to yiisoft/yii-debug-api,
displaying goes to yiisoft/yii-debug-viewer.
Modules
Debugger is extendable via modules. Each module provides:
- One of multiple data collectors
- Debug viewer panel
- Debug toolbar panel (optionally)
Modules are distributed as packages named as yii-debug-<name>
.
Data collector
Collecting data
Debug data collector is modular and is using multiple application requests:
ApplicationStartup
, ApplicationShutdown
, BeforeRequest
and AfterRequest
.
On ApplicationStartup
each module may register its own listener for events
containing data it needs. When such event occurs, data is being collected.
On AfterRequest
and ApplicationShutdown
data is flushed and persisted.
As an alternative, on ApplicationStartup
any initialization could be done and at ApplicationShutdown
data could be collected directly from service without using events.
An interface for collector:
interface DebugDataCollectorInterface
{
public function startup(): void;
public function shutdown(): void;
public function flush(): array;
}
As an extra idea we may implement a decorator for DI container that would return service proxies that may record data.
Data collected
Besides module-specific data, all modules write common information about the data
collected:
- Date and time of occurence.
- A set of tags such as "application ID" or "server".
The following collectors are planned:
- EventsCollector
- ReqeustCollector
- ResponseCollector
- LogCollector
- ViewsCollector
- RoutesCollector
- FrameworkInfoCollector
- ComposerCollector
- DIContainerCollector
Storing data
Data persistence happens via an interface. Default implementation wites to files.
For the case of multiple servers storage should be switched to a shared one.
interface DebugDataStoreInterface
{
public function persist(DebugDataInterface $data): void;
public function list();
public function read(): DebugDataInterface;
}
interface DebugDataInterface
{
public function get(string $key);
}
Displaying data
Data collected during current request is displayed in a debug toolbar in form
of a very short summary. Previously collected data along with details could
be viewed via debug viewer.
Debug toolbar is implemented as middleware that adds extra HTML / JS code to
each page. For what to append it is querying all modules for an instance of
DebugToolbarPanelInterface
:
interface DebugToolbarPanelInterface
{
public function render(): string;
}
Debug viewer panel is implemented as another interface:
interface DebugViewerPanelInterface
{
public static function name(): string;
public function render(): string;
}
When debug viewer is getting a list of panels, it is querying name()
from each
module. When rendering a panel, render()
method is used.
There should be a view when all data collected is listed. There we should be able to filter by data tag.
Implementation plan
References
- #28 - Multi server support for debug panel
- #27 - Export/Import results
- #26 - Separate debugging and showing results
- #25 - Standalone debug application
- #24 - Allow debugging console application