When developing modules, questions inevitably arise: why is the page generating slowly? Which SQL query is causing the bottleneck? Is the cache working correctly? To answer these questions, the Melbis platform is equipped with a built-in debugger that displays detailed statistics directly on the page — without any third-party tools.
The debugger is activated via URL: add the GET parameter
debug_on_KEY to any page address, where KEY is
the secret code defined in the MELBIS_DEBUG_CODE
configuration parameter (or via “Design →
Installation”, the “Debugger Password” field).
For example, if the code is pass:
https://site.com/?debug_on_pass
https://site.com/?topic_id=5&debug_on_pass
The debugger state is stored in the PHP session — once activated, it remains enabled as you navigate between pages of the site. This allows you to examine the behavior of different pages without manually adding the parameter to every URL.
To disable it — navigate to any page with the debug_off
parameter:
https://site.com/?debug_off
The
MELBIS()->DebugState()method allows you to check in module code whether the debugger is enabled, and output diagnostic data only in debug mode without affecting production:if ( MELBIS()->DebugState() ) { error_log('Variable value: ' . print_r($data, true)); }
At the very top is a brief summary of the current request:
| Parameter | Description |
|---|---|
| Cache | Whether caching is enabled (On / Off) |
| Compile | Total page generation time in seconds |
| SQL cnt/time | Number of SQL queries / total execution time |
| Load | Server load: 1 min / 5 min / 15 min |
| Memory peak/lim | Peak memory usage / PHP memory limit |
| Files | Number of included PHP files |
| Cache Base | Size of the base cache on disk |
| Cache Trick | Size of the Trick cache on disk |
Below the summary is a horizontal bar showing how page generation time was distributed across all modules. Each module is colored with several bands depending on how it was processed:
| Color | Execution Type | Description |
|---|---|---|
| Pink | Run Native | Module executed fully (cache was not used) |
| Yellow | Paste Lazy | Module loaded asynchronously (Lazy Loading) |
| Light Blue | Run Smart | Module executed early on Smart cache command |
| Orange | Cache Trick | Trick cache was served instead of execution |
| Light Green | Cache Base Pause | Cache is valid but still within the pause period |
| Green | Cache Base Valid | Cache is valid, retrieved from disk |
| Gray | Core | Core and framework overhead |
Hovering over a segment shows the module name, time, and percentage of total page time.
Detailed statistics for each module on the page. Columns:
| Column | Description |
|---|---|
| Module | Module name and its cache settings (Cache On/Off, Pause, Trick, Smart) |
| Paste Lazy | How many times the module was substituted as a Lazy placeholder |
| Run Native | How many times the module executed fully |
| Run Smart | How many times the module was launched early by Smart cache |
| Cache Trick | How many times the Trick cache was served |
| Cache Base Pause | How many times the cache was valid but in a pause state |
| Cache Base Valid | How many times the cache was retrieved from disk as valid |
| Total Call | Total number of module calls on the page |
| Total Time | Total module execution time |
| SQL in/total | SQL queries per single call / total across all calls |
| SQL time | Total SQL query execution time |
| SQL avg/max | Average and maximum time of a single SQL query |
| Content of query for max time | Text of the slowest SQL query with parameters |
Cells where actual execution or cache retrieval occurred are highlighted in the corresponding color — making it immediately clear how each module was processed.
The Summary row at the bottom shows totals across all modules on the page.
A section for detailed cache analysis of each module (displayed when caching is enabled). For each module, a header row is shown with the name, number of tracked tables, and number of calls on the page.
For each module call, the following is displayed:
Last update — the table that was modified most
recently among all dependent tables, with the modification timestamp.
Shows what potentially could have invalidated the cache. To the right is
the current server time (right now) so you can see the
actual difference.
Cache state — the cache status: whether it is enabled, the timeout, and the timestamps of the latest cache directories.
Cache load — how the result was obtained for this specific call:
Run Native — the module executed and the cache is being
created.Run Smart — the module executed early at the initiative
of Smart cache.Cache Base Valid — the cache is valid, retrieved from
disk. Shows the cache creation time and the table that determined its
validity.Cache Base Pause — the cache is valid due to the pause.
Shows the cache creation time, time until the pause ends
(ETA), and the deadline.Cache Trick — the Trick cache was served. The reason is
specified: server overload (High Server load) or long page
compile time (Long Page compile), the actual and allowed
values, and the age of the Trick cache.Run info — timing for the specific call: start time
(Start), end time (End), duration
(Run), and share of total page time (Part).
Below are the input parameters with which the module was called.
Cumulative cache operation statistics over the entire observation period (stored in APCu). Displayed if at least one module has Smart cache enabled. This is the data Smart cache uses to make decisions about early updates.
For each module — a row with its cache settings and seven statistics
columns in Cnt/Sum/Avg format (count / total /
average):
| Column | Description |
|---|---|
| Paste Lazy | Lazy call statistics |
| Run Native | Actual execution statistics |
| Run Smart | Early Smart launch statistics |
| Cache Base Valid | Valid cache delivery statistics |
| Cache Base Pause | Cache delivery in pause state statistics |
| Cache Trick | Trick cache usage statistics |
| Total Run + Cache | Total statistics for all calls (Cnt/Sum/Avg/Min/Max) |
Below the numbers for each column, a mini histogram is displayed (a bar proportional to the column maximum), allowing you to quickly spot anomalies and imbalances without scrutinizing the numbers.
The “Reset Module Smart Data” button in the IDE clears the accumulated statistics for a specific module.
RunTimeFor precise measurement of execution time for an arbitrary code section:
// Mark the start
$start = MELBIS()->RunTime();
// ... code to measure ...
// Get elapsed time
$elapsed = MELBIS()->RunTime($start);
if ( MELBIS()->DebugState() )
{
error_log("Discount calculation: {$elapsed}s");
}RunTime() without an argument returns the current
timestamp. RunTime($start) returns the difference between
the current time and $start.
When developing AJAX modules and web modules, standard debugging via browser output does not work — the result goes to JavaScript and is lost there. In such cases, it is convenient to save intermediate data to a file:
// Save the $data array to a dump.htm file next to the module's templates
MELBIS()->TplDumpVar('dump', $data);The file is created in the template directory of the current module. Remember to remove the call after debugging.
In addition to the visual panel, the platform provides programmatic access to module operation statistics. This is useful for automated monitoring: sending alerts on performance degradation, writing metrics to a database for subsequent analysis, or identifying problematic modules under real traffic conditions.
LogOn() / LogOff() —
enable and disable statistics collection. Unlike the visual debugger,
the Log API outputs nothing to the page and can be used in
production:
// In the root script, before Run():
MELBIS()->LogOn();
MELBIS()->Run($entry_point, $entry_param);
MELBIS()->Publish();
// After Run(), statistics are collected — ready for analysisLogUnitsList() — returns an array of
all modules involved in page generation:
$modules = MELBIS()->LogUnitsList();
// ['melbis_base_page' => true, 'melbis_cataloge' => true, ...]LogUnitStat($unitName) — returns
accumulated statistics for a module. Array keys:
| Key | Description |
|---|---|
run_cnt |
Number of actual module executions |
smart_cnt |
Number of Smart launches |
trick_cnt |
Number of Trick cache deliveries |
pause_cnt |
Number of cache deliveries from pause state |
valid_cnt |
Number of valid cache deliveries |
lazy_cnt |
Number of Lazy substitutions |
request |
Total number of calls |
total_time |
Total module execution time (seconds) |
query_count |
Number of SQL queries per single call |
query_count_total |
Total number of SQL queries |
query_sum_time |
Total SQL query execution time |
query_max_time |
Time of the slowest SQL query |
query_max_query |
Text of the slowest SQL query |
query_max_params |
Parameters of the slowest SQL query |
LogUnitProp($unitName) — returns the
module configuration: dependency tables, cache settings (Base, Trick,
Smart), entry_point and lazy_load flags, list
of included libraries, and registered callbacks.
Example: alert on module slowdown
MELBIS()->LogOn();
MELBIS()->Run($entry_point, $entry_param);
MELBIS()->Publish();
// Check each module
foreach ( MELBIS()->LogUnitsList() as $mod => $tmp )
{
$stat = MELBIS()->LogUnitStat($mod);
// Skip modules whose result was taken from cache
if ( ($stat['run_cnt'] ?? 0) == 0 ) continue;
// Alert if the module ran for more than 1 second
if ( ($stat['total_time'] ?? 0) > 1 )
{
$params = json_encode($stat['query_max_params'] ?? []);
error_log("[SLOW MODULE] {$mod} — {$stat['total_time']}s, "
. "SQL: {$stat['query_max_query']}, params: {$params}");
}
}Example: writing statistics to a database for long-term analysis
MELBIS()->LogOn();
MELBIS()->Run($entry_point, $entry_param);
MELBIS()->Publish();
foreach ( MELBIS()->LogUnitsList() as $mod => $tmp )
{
$stat = MELBIS()->LogUnitStat($mod);
if ( ($stat['run_cnt'] ?? 0) == 0 ) continue;
MELBIS()->SqlQuery(__LINE__,
"INSERT INTO {DBNICK}_log
SET name = :NAME, date_time = NOW(),
runtime = :RUNTIME, sql_time = :SQLTIME,
sql_count = :SQLCNT, sql_max = :SQLMAX,
sql_text = :SQLTEXT",
[
'name' => $mod,
'runtime' => $stat['total_time'],
'sqltime' => $stat['query_sum_time'] ?? 0,
'sqlcnt' => $stat['query_count_total'] ?? 0,
'sqlmax' => $stat['query_max_time'] ?? 0,
'sqltext' => $stat['query_max_query'] ?? '',
]
);
}By accumulating such data over several days, you can identify modules with systematically high resource consumption, find correlations between load and performance degradation, and make an informed decision about optimization.
Find a slow module. Check the summary line
(Compile) and the timeline — pink (Run Native)
segments with the greatest width indicate the longest executions. In the
“Page Modules” table, find the row with the maximum
Total Time and examine
Content of query for max time.
Verify that the cache is working correctly. In the
“Page Modules” table, most modules should have non-zero values in the
Cache Base Valid or Cache Base Pause columns.
In “Modules Details”, each call should show
Cache Base Valid or Cache Base Pause, not
Run Native.
Understand why the cache is being invalidated too
frequently. In “Modules Details”, look at the
Last update column — it shows which table was modified most
recently and at what time. If the cache is being invalidated by a table
that should not affect it, that table may be unnecessarily listed in the
module’s dependency list.
Evaluate Smart cache effectiveness. In “Cache Smart
Monitor”, the ratio of Run Smart to Run Native
shows how well Smart cache manages to update data in the background,
preventing a “cold” execution while visitors are active.
Check Trick cache triggering. In the “Page Modules”
table, the Cache Trick column should be non-zero only under
genuinely high load. If Trick is triggering constantly under normal
load, the thresholds in the module settings should be reviewed.