3 // @author Matt Todd <matt@matttoddphoto.com>
5 // @desc Handles various aspects of debugging, such as logging, asserting,
6 // default exception handlers or verbose exception handlers,
7 // and potentially suppoting breakpoints/interactive
8 // inspection during runtime
9 // @requires stdexception.php (StdException class)
10 // @refer_to http://www.php.net/manual/en/function.proc-open.php for
11 // breakpoint/interactive inspection during runtime
12 // @refer_to http://www.php.net/manual/en/function.assert.php for
13 // assertions and peculiarities therein
14 // @refer_to http://www.php.net/manual/en/function.apd-breakpoint.php
16 include_once('stdexception.php');
19 class Debug
extends Canvas
{
21 public static function __set($name, $value) {
22 $GLOBALS["debug"][$name] = $value;
24 public static function __get($strName) {
25 return $GLOBALS["debug"][$name];
29 // Debug::log($message, $type = 'general', $level = 'general', $from = null);
30 public static function log($message, $type = 'general', $level = 'notice', $from = null) {
31 // handle logging the $message (possibly formatting)
33 // configuration values
34 $env = Config2
::$environment;
35 $log_config = Config2
::$config['logging'];
36 $dir = Config2
::$config['directories']['logs'];
37 $filename = "{$env}.log";
38 if($filename == '.log') $filename = 'system.log';
39 $log_level = $log_config['log_level'];
40 $log_separately = $log_config['log_separately']; // array of types of messages to log separetely (in their own logs)
41 $always_log = $log_config['always_log']; // array of types of messages to always log
43 // handle default values (convention over configuration)
44 if(empty($dir)) $dir = 'logs/'; // default logging directory
45 if(empty($log_level)) $log_level = 'notice'; // default log level
46 if(empty($always_log)) $always_log = array();
47 if(empty($log_separately)) $log_separately = array();
48 // make sure logging is supposed to happen for this event
49 // if($env == 'production') return; // should logging be skipped in the production environment?
50 if(self
::log_level($level) >= self
::log_level($log_level) ||
in_array($type, $always_log) ||
in_array($type, $log_separately)) {
51 if(in_array($type, $log_separately)) $filename = "{$type}.log";
53 if(!in_array($type, $always_log)) return;
57 if(empty($log_config['log_format']))
58 $log_format = "%s (%s:%s)%s %s\n";
60 $log_format = $log_config['log_format'];
62 // changes if it was set
63 if(!empty($from)) $from = " [{$from}]";
65 $log_file = new FSFile(FSFile
::build_path($dir, $filename));
66 $date = date("Y-m-d H:i:s"); // alternatively // date("c");
67 $log_file->write(sprintf($log_format, $date, $type, $level, $from, $message));
69 private static function log_level($level) {
70 // determines the log level value (a numerical index) for each logging level
71 // used to determine if logging of the specified level should be skipped or not
73 // log levels and their numerical index
83 // return numerical index
84 // return 0 if it's not in the array of predefined levels
85 return (array_key_exists($level, $log_levels)) ?
$log_levels[$level] : 0;
88 public static function assert($expression, $value) {
89 if($expression == $value) return true; // assertion was successful
90 else throw new AssertionException($expression); // assertion did not succeed and must be handled
92 // if $expression is a boolean value, return it
93 // if not, evaluate it and then return that value
94 // if no value returned by expression, return null value
96 // refer to http://www.php.net/manual/en/function.assert.php
99 public static function breakpoint() {
100 // refer to http://www.php.net/manual/en/function.proc-open.php to possibly implement
101 // and also http://www.php.net/manual/en/function.apd-breakpoint.php
104 // standard/verbose exception handlers
105 public static function generic_exception_handler($e) {
106 // handle generic exception
107 $exception_type = get_class($e);
108 $e_dump = print_r($e, true);
112 <title>Exception: {$exception_type}</title>
115 <h1>Internal Exception!</h1>
116 <p>{$e->getMessage()}</p>
124 public static function verbose_exception_handler($e) {
125 // verbosely evaluate the exception and return/print the evaluation for inspection during development
127 public static function minimal_exception_handler($e) {
128 // give as little error information as possible (reserved primarily for the production environment for unhandled exceptions, a bad thing to begin with)
132 public static function timing($component) {
133 if(empty($GLOBALS['debug']['timing'][$component])) {
135 $GLOBALS['debug']['timing'][$component] = microtime(true);
138 $time = microtime(true) - $GLOBALS['debug']['timing'][$component];
139 Debug
::log("took $time seconds...", 'bebug:timing', 'warn', $component);
144 class DebugException
extends StdException
{} // hopefully won't ever need to be used, but you never know
145 class AssertionException
extends StdException
{} // an assertion failure exception