Debugging Tools

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.

Enabling the Debugger

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));
}

Debugger Panel

Summary Line

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

Timeline

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.


“Page Modules” Table

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.


“Modules Details” Table

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 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.


“Cache Smart Monitor” Table

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.


Tool: RunTime

For 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.


Tool: Debugging via File Dump

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.


Programmatic Statistics Collection (Log API)

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 analysis

LogUnitsList() — 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.


Practical Scenarios

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.