Skip to content

Instantly share code, notes, and snippets.

@chrisbloom7
Created March 4, 2011 05:08
Show Gist options
  • Save chrisbloom7/854208 to your computer and use it in GitHub Desktop.
Save chrisbloom7/854208 to your computer and use it in GitHub Desktop.
Some standard debugging functions I use in almost every project. Include this file after the main config file has been loaded.
<?php
// This should probably be ported to a custom class...
// DEBUGGING - set to TRUE to force debugging or comment out to use dynamic
// debugging. The debugging behaviour is unreliable if this is set to FALSE
// define("X_GLOBAL_DEBUG", TRUE);
// LOG_DIR needs to be defined here rather than in the local config file because we
// may need access to it from pages where the local conf hasn't been loaded yet.
define('LOG_DIR', dirname(__FILE__) . '/../../logs');
// Define debugging levels. Set constant X_LOGVAR_LEVEL to one of these integer
// values in the main config file.
define('X_LOGVAR_NONE', 0);
define('X_LOGVAR_ERROR', 1);
define('X_LOGVAR_WARNING', 2);
define('X_LOGVAR_INFO', 3);
// Override error logging defaults
ini_set('error_log', LOG_DIR . '/php_error.log');
ini_set('log_errors', 'On');
ini_set('html_errors', 'Off');
ini_set('display_errors', 'Off');
// Setup stricter error reporting if necessary
if ((defined('X_GLOBAL_DEBUG') && X_GLOBAL_DEBUG == true) //Forced debugging via constant
|| (isset($_REQUEST['X_GLOBAL_DEBUG']) && $_REQUEST['X_GLOBAL_DEBUG'] == 'foo') //Dynamic debugging via request parameter or cookie
) {
error_reporting(E_ALL);
if (!defined('X_GLOBAL_DEBUG')) {
define('X_GLOBAL_DEBUG', true);
}
} else {
error_reporting(E_ALL ^ E_NOTICE);
if (!defined('X_GLOBAL_DEBUG')) {
define('X_GLOBAL_DEBUG', false);
}
}
// Custom error reporting with backtrace
function log_error_backtrace($errno, $errstr, $errfile, $errline, $errcontext)
{
if (!(error_reporting() & $errno)) return;
switch ($errno) {
case E_WARNING:
case E_USER_WARNING:
case E_STRICT:
case E_NOTICE:
case E_USER_NOTICE:
$type = 'warning';
$fatal = false;
break;
default:
$type = 'fatal error';
$fatal = true;
break;
}
$log = array();
foreach (array_reverse(debug_backtrace()) as $item) {
$log[] = (isset($item['file']) ? $item['file'] : '<unknown file>') . ' ' . (isset($item['line']) ? $item['line'] : '<unknown line>') . ' calling ' . $item['function'] . '()';
}
LOGVAR($log, 'Backtrace from ' . $type . ' \'' . $errstr . '\' at ' . $errfile . ' ' . $errline, X_LOGVAR_ERROR);
if (X_GLOBAL_DEBUG || ini_get('display_errors')) {
PRINTVAR($log, 'Backtrace from ' . $type . ' \'' . $errstr . '\' at ' . $errfile . ' ' . $errline, (php_sapi_name() == 'cli'));
}
if ($fatal) exit(1);
}
// Comment out next line to disable custom error handler
set_error_handler('log_error_backtrace');
// Set X_GLOBAL_DEBUG_PLAIN to true if we are in a command-line-only environment
if (!isset($X_GLOBAL_DEBUG_PLAIN)) {
$X_GLOBAL_DEBUG_PLAIN = false;
}
// The functions
function GETVAR($var, $label = "")
{
$output = "<pre style=\"border: 1px solid #999; background-color: #f7f7f7; color: #000; overflow: auto; width: auto; text-align: left; padding: 1em;\">" . ((strlen(trim($label))) ? htmlentities($label) . "\n===================\n" : "") . htmlentities(print_r($var, true)) . "</pre>";
return $output;
}
function GETVARPLAIN($var, $label = "")
{
$output = '' . ((strlen(trim($label))) ? $label . "\n===================\n" : "") . print_r($var, true) . "\n\n";
return $output;
}
function PRINTVAR($var, $label = "", $plain = false)
{
global $X_GLOBAL_DEBUG_PLAIN;
print (($plain || $X_GLOBAL_DEBUG_PLAIN) ? GETVARPLAIN($var, $label) : GETVAR($var, $label));
}
function PRINTVARD($var, $label = "", $plain = false)
{
global $X_GLOBAL_DEBUG_PLAIN;
die(($plain || $X_GLOBAL_DEBUG_PLAIN) ? GETVARPLAIN($var, $label) : GETVAR($var, $label));
}
function LOGVAR($var, $label = "", $level = X_LOGVAR_INFO, $group = false)
{
if (!defined('X_LOGVAR_LEVEL')) {
if (X_GLOBAL_DEBUG) {
$X_LOGVAR_LEVEL = X_LOGVAR_INFO;
} else {
$X_LOGVAR_LEVEL = X_LOGVAR_WARNING;
}
} else {
$X_LOGVAR_LEVEL = X_LOGVAR_LEVEL;
}
if (X_GLOBAL_DEBUG) {
PRINTVAR($var, $label);
} elseif (intval($level) > $X_LOGVAR_LEVEL) {
return;
} else {
$message = GETVARPLAIN($var, $label);
if (X_LOGVAR_USE_DATABASE) {
debug_log_to_database($message, $level, ($group) ? $group : 'debug');
}
else {
$uri = $_SERVER['REQUEST_URI'];
if (!empty($_SERVER['QUERY_STRING'])) $uri.= '?' . $_SERVER['QUERY_STRING'];
$data = sprintf("[%s] Request URI: %s\n-------------------------------------------------\n%s", gmdate('d-M-Y H:i:s') . ' GMT', $uri, $message);
debug_write_log(($group) ? $group : 'debug', $data);
}
}
}
function LOGVARD($var, $label = "", $group = false)
{
if (X_GLOBAL_DEBUG) {
PRINTVARD($var, $label);
} else {
LOGVAR($var, $label, 99, $group);
PRINTVARD('A fatal error has occured and has been logged.');
}
}
function debug_write_log($logfile, $data)
{
$filename = sprintf("%s/%s.%s.%s.log", LOG_DIR, $logfile, date('Y-m-d'), str_replace('.', '_', $_SERVER['SERVER_ADDR']));
$fp = @fopen($filename, 'a+b');
if ($fp === false || !is_writeable($filename)) {
PRINTVARD('Could not open log file for writing');
}
fwrite($fp, $data);
fclose($fp);
}
/**
* To enable tracking of data across requests, add the following to your config file:
*
// Though not neccessarily a configurable option, this is the best place to include this
// so that we have access to the COOKIE_HOST constant.
if (empty($_COOKIE['x_logvar_id']) && !headers_sent()) {
$x_logvar_id = base_convert(mt_rand(0, 0x38E38E3), 10, 36) . '-' . microtime(TRUE);
setcookie("x_logvar_id", $x_logvar_id, 0, '/', '' . COOKIE_HOST, FALSE);
setcookie("x_logvar_id", $x_logvar_id, 0, '/', '.' . COOKIE_HOST, FALSE);
}
*/
function debug_log_to_database($message, $level, $group) {
$log_data = array(
'message' => $message,
'level' => $level,
'group' => $group,
'timestamp' => gmdate('Y-m-d H:i:s'),
'request_environment' => GETVARPLAIN(array(
'SERVER' => $_SERVER,
'GET' => $_GET,
'POST' => $_POST,
'FILES' => $_FILES,
'COOKIE' => $_COOKIE,
'SESSION' => $_SESSION,
'REQUEST' => $_REQUEST,
'ENV' => $_ENV
)),
'remote_address' => ((!empty($_SERVER['REMOTE_ADDR'])) ? $_SERVER['REMOTE_ADDR'] : ''),
'uri' => ((!empty($_SERVER['REQUEST_URI'])) ? $_SERVER['REQUEST_URI'] : ''),
'server_address' => ((!empty($_SERVER['SERVER_ADDR'])) ? $_SERVER['SERVER_ADDR'] : ''),
'x_logvar_id' => ((!empty($_COOKIE['x_logvar_id'])) ? $_COOKIE['x_logvar_id'] : '')
);
if (function_exists('some_insert_function')) {
/**
* Add code to insert the $log_data array into the database. If we were using ADOdb, it might
* look like this:
*
global $ADODB_QUOTE_FIELDNAMES;
$old_ADODB_QUOTE_FIELDNAMES = $ADODB_QUOTE_FIELDNAMES;
// Make sure ADOdb quotes the field names
$ADODB_QUOTE_FIELDNAMES = TRUE;
some_insert_function('_debug_log', $log_data);
$ADODB_QUOTE_FIELDNAMES = $old_ADODB_QUOTE_FIELDNAMES;
unset($old_ADODB_QUOTE_FIELDNAMES);
*/
}
// If all else fails:
else {
debug_write_log($group, $log_data);
}
}
$X_GLOBAL_BENCHMARK_LAST_TIME = $X_GLOBAL_BENCHMARK_TIME = microtime(true);
function benchmark($label = false, $save_to_log = false, $group = false)
{
if (!$label) {
$trace = debug_backtrace();
if (isset($trace[1]))
{
$label = (empty($trace[1]['function'])) ? '' : "{$trace[1]['function']}::";
$label .= "{$trace[0]['file']}::{$trace[0]['line']}";
}
}
$btime = microtime(true);
LOGVAR(array(
'benchmark' => $btime - $GLOBALS['X_GLOBAL_BENCHMARK_TIME'],
'delta' => $btime - $GLOBALS['X_GLOBAL_BENCHMARK_LAST_TIME']
), $label, X_LOGVAR_INFO, $group);
if ($save_to_log) {
debug_write_log(($group) ? $group : 'benchmark', sprintf("[%s]\t%s\t%s\n", $label, gmdate('d-M-Y H:i:s') , $btime - $GLOBALS['X_GLOBAL_BENCHMARK_TIME']));
}
$GLOBALS['X_GLOBAL_BENCHMARK_LAST_TIME'] = $btime;
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment