Zeta Components - high quality PHP components

eZ Components - Debug

Introduction

The Debug component provides an API to log and time debug events. This component depends mainly on the EventLog component. The functionality of the Debug component is divided into two parts:

Writing a debug message is almost the same as writing a message with the EventLog component. However, there is one major distinction: messages written with the EventLog component are intended to be written to a storage element (such as a log file or database). Messages written with the Debug component are usually directly formatted and displayed. Note that the Debug::log() method has a slightly different signature than the EventLog::log() method.

Timing information is captured by starting and stopping timers using the public methods from ezcDebug. The timing information is stored in a structure with raw data. This structure should be formatted and displayed at the end of the script.

The Debug summary output can be formatted with an implementation from ezcDebugOutputFormatter. The default, and currently only, formatter is ezcDebugHtmlFormatter. This HTML formatter transforms the raw log messages and raw timing information into a HTML string for display.

Class overview

The following classes are the most important to use, extend or implement:

ezcDebug
This provides the public API for writing Debug messages and capturing timing information.
ezcDebugOptions
Allows you to switch on debug stack traces and to configure their appearance.
ezcDebugOutputFormatter
ezcDebugOutputFormatter provides an interface for the debug output format. New implementations can format the raw log messages and timing information to any output format.
ezcDebugHtmlFormatter
ezcDebugHtmlFormatter is an implementation of the ezcDebugOutputFormatter interface. This formatter reads the raw log and timing information and returns it as an HTML string. This string can be output directly to an HTML page.

See the API documentation for more information.

Usage

Writing a log message to file

The following script writes a message to the Debug component. At the end of the script, the log message is formatted and printed.

  1. <?php
  2. require_once 'tutorial_autoload.php';
  3. date_default_timezone_set"UTC" );
  4. // Get the one and only instance of the ezcDebug.
  5. $debug ezcDebug::getInstance();
  6. // Write a log message with verbosity 1.
  7. $debug->log"Connecting with the Payment server");  
  8. $debug->log"Connected with the Payment server"2, array( "source" => "shop""category" => "payment" ) );  
  9. // Get HTML output.
  10. $output $debug->generateOutput();
  11. echo $output;
  12. ?>

Writing log messages is almost the same as writing them to the EventLog component. As a matter of fact, the EventLog component is internally used by Debug.

Further information about writing log messages can be found in the EventLog component.

Timers

The timers from ezcDebug can be used for two purposes:

Both methods are executed with ezcDebug::startTimer(), ezcDebug::stopTimer() and ezcDebug::switchTimer(). The next script demonstrates the usage of these methods:

  1. <style type="text/css">@import url("example_stylesheet.txt");</style>
  2. <?php
  3. require_once 'tutorial_autoload.php';
  4. date_default_timezone_set"UTC" );
  5. // Get the one and only instance of the ezcDebug.
  6. $debug ezcDebug::getInstance();
  7. // Start the accumulator.
  8. $debug->startTimer"Program runtime""Accumulators" );
  9. $debug->switchTimer"Start""Program runtime" );
  10. // Measure the time of writing "hello world".
  11. // The name of the timer is: "Hello world" and it will be placed in the group: "output". 
  12. $debug->startTimer ("Hello world""output" );
  13. echo "Hello world<br/>";
  14. $debug->stopTimer"Hello world" );
  15. // Replace the "Start" timer for "Half the way".
  16. $debug->switchTimer"Half the way""Start" );
  17. // Measure the time of writing "cruel world".
  18. $debug->startTimer"Goodbye cruel world""output" );
  19. echo "Goodbye cruel world<br/>";
  20. $debug->stopTimer"Goodbye cruel world" );
  21. // Stop the last timer.
  22. $debug->switchTimer"Stop""Half the way" );
  23. $debug->stopTimer"Stop" );
  24. // Get HTML output.
  25. $output $debug->generateOutput();
  26. echo "<br/><br/>";
  27. echo $output;
  28. ?>

The output is as follows (if the CSS stylesheet is used that is available through "Example Stylesheet" in the menu):

The output has two groups: output and accumulators. There are two timers in the "output" group: "Hello world" and "Goodbye cruel world".

The "accumulators" group has one timer called "Program runtime". This timer took a total of 0.00034 seconds. In this timer are several "switch timers". These show the time since the "Program runtime" was started.

Recursive timers

You can also time repeating code blocks. For example, you can measure the time a PHP statement takes in a loop. The Debug timer will calculate the average time of the repeating statement and display it in the debug summary. See the next example:

  1. <style type="text/css">@import url("example_stylesheet.txt");</style>
  2. <?php
  3. require_once 'tutorial_autoload.php';
  4. date_default_timezone_set"UTC" );
  5. // Get the one and only instance of the ezcDebug.
  6. $debug ezcDebug::getInstance();
  7. // Start the accumulator.
  8. $debug->startTimer"Script runtime""Accumulators" );
  9. // Store the name of the accumulator.
  10. $accumulatorName "start";
  11. $debug->switchTimer$accumulatorName"Script runtime" );
  12. // Time the loop.
  13. $debug->startTimer "Five times Hello world""output" );
  14. for( $i 0$i 5$i++ )
  15. {
  16.     // Time the "Hello world" only.
  17.     $debug->startTimer "Hello world""output" );
  18.     echo "Hello world<br/>";
  19.     $debug->stopTimer"Hello world" );
  20.     // Store the accumulator.
  21.     $debug->switchTimer"After: hello world"$accumulatorName );
  22.     $accumulatorName "After: hello world"
  23. }
  24. $debug->stopTimer"Five times Hello world" );
  25. // Stop the accumulator
  26. $debug->switchTimer"stop"$accumulatorName );
  27. $debug->stopTimer"stop" );
  28. // Get HTML output.
  29. $output $debug->generateOutput();
  30. echo "<br/><br/>";
  31. echo $output;
  32. ?>

The resulting output is as follows (if the CSS stylesheet is used that is available through "Example Stylesheet" in the menu):

Stack traces

Sometimes it is useful to get a stack trace for log messages. To achieve this, there are 2 possibilities offered by the Debug component:

1) Global stack trace switch
  1. <?php
  2. require_once 'tutorial_autoload.php';
  3. $debug ezcDebug::getInstance();
  4. // Switch on global stack traces.
  5. $debug->options->stackTrace            true;
  6. // Configure stack trace appearance.
  7. $debug->options->stackTraceDepth       3;
  8. $debug->options->stackTraceMaxData     32;
  9. $debug->options->stackTraceMaxChildren 3;
  10. $debug->options->stackTraceMaxDepth    2;
  11. // ... somewhere else ...
  12. // Log with no explicit stacktrace indication
  13. ezcDebug::getInstance()->log(
  14.     'Function testThis() has been called.',
  15.     ezcLog::NOTICE,
  16.     array( 'additional' => 'info' )
  17. );
  18. // ... somewhere else ...
  19. // Print out log with stacktraces.
  20. $debug ezcDebug::getInstance();
  21. echo $debug->generateOutput();
  22. ?>

In this example, the debug options (see: ezcDebugOptions) are used to switch on stack traces globally. The effect is, that whenever a debug message is logged, a stack trace is logged in addition. When printing the debug information, stack traces in the manor of Xdebug are included in the output.

Beside the $stackTrace option itself, the appearance of the stack traces is configured. This configuration only takes effect, if Xdebug is not installed. In this case, an own implementation is used to retrieve stack traces that look almost exactly like the Xdebug version. If Xdebug is installed, its internal settings will be used.

The possible options for stack traces are:

$stackTraceDepth
Defines the number of nested function calls included in the trace (starting at the most recent one). This option also affects Xdebug generated stack traces. The default is 5.
$stackTraceMaxData
Maximum bytes of data to be dumped for variable values. The default is 512.
$stackTraceMaxChildren
Defines the maximum number of child elements that will be dumped for array and object structures. The default value is 128.
$stackTraceMaxDepth
Maximum level of iteration that is performed when dumping nested array or object structures.
2) Local stack trace switch

If stack traces are not desired with every log message, it is also possible to activate them when the log message is issued:

  1. <?php
  2. require_once 'tutorial_autoload.php';
  3. // ... inside some function...
  4. // Log with no explicit stacktrace indication
  5. ezcDebug::getInstance()->log(
  6.     'Function testThis() has been called.',
  7.     ezcLog::NOTICE,
  8.     array( 'additional' => 'info' ),
  9.     // Enable stack trace
  10.     true
  11. );
  12. // ... somewhere else ...
  13. // Print out log with stacktraces.
  14. $debug ezcDebug::getInstance();
  15. echo $debug->generateOutput();
  16. ?>