Profiler.php

Go to the documentation of this file.
00001 <?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
00002 /**
00003  * CodeIgniter
00004  *
00005  * An open source application development framework for PHP 4.3.2 or newer
00006  *
00007  * @package             CodeIgniter
00008  * @author              ExpressionEngine Dev Team
00009  * @copyright   Copyright (c) 2008, EllisLab, Inc.
00010  * @license             http://codeigniter.com/user_guide/license.html
00011  * @link                http://codeigniter.com
00012  * @since               Version 1.0
00013  * @filesource
00014  */
00015 
00016 // ------------------------------------------------------------------------
00017 
00018 /**
00019  * CodeIgniter Profiler Class
00020  *
00021  * This class enables you to display benchmark, query, and other data
00022  * in order to help with debugging and optimization.
00023  *
00024  * Note: At some point it would be good to move all the HTML in this class
00025  * into a set of template files in order to allow customization.
00026  *
00027  * @package             CodeIgniter
00028  * @subpackage  Libraries
00029  * @category    Libraries
00030  * @author              ExpressionEngine Dev Team
00031  * @link                http://codeigniter.com/user_guide/general/profiling.html
00032  */
00033 class CI_Profiler {
00034 
00035         var $CI;
00036         
00037         function CI_Profiler()
00038         {
00039                 $this->CI =& get_instance();
00040                 $this->CI->load->language('profiler');
00041         }
00042         
00043         // --------------------------------------------------------------------
00044 
00045         /**
00046          * Auto Profiler
00047          *
00048          * This function cycles through the entire array of mark points and
00049          * matches any two points that are named identically (ending in "_start"
00050          * and "_end" respectively).  It then compiles the execution times for
00051          * all points and returns it as an array
00052          *
00053          * @access      private
00054          * @return      array
00055          */
00056         function _compile_benchmarks()
00057         {
00058                 $profile = array();
00059                 foreach ($this->CI->benchmark->marker as $key => $val)
00060                 {
00061                         // We match the "end" marker so that the list ends
00062                         // up in the order that it was defined
00063                         if (preg_match("/(.+?)_end/i", $key, $match))
00064                         {                       
00065                                 if (isset($this->CI->benchmark->marker[$match[1].'_end']) AND isset($this->CI->benchmark->marker[$match[1].'_start']))
00066                                 {
00067                                         $profile[$match[1]] = $this->CI->benchmark->elapsed_time($match[1].'_start', $key);
00068                                 }
00069                         }
00070                 }
00071 
00072                 // Build a table containing the profile data.
00073                 // Note: At some point we should turn this into a template that can
00074                 // be modified.  We also might want to make this data available to be logged
00075         
00076                 $output  = "\n\n";
00077                 $output .= '<fieldset style="border:1px solid #990000;padding:6px 10px 10px 10px;margin:0 0 20px 0;background-color:#eee">';
00078                 $output .= "\n";
00079                 $output .= '<legend style="color:#990000;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_benchmarks').'&nbsp;&nbsp;</legend>';
00080                 $output .= "\n";                        
00081                 $output .= "\n\n<table cellpadding='4' cellspacing='1' border='0' width='100%'>\n";
00082                 
00083                 foreach ($profile as $key => $val)
00084                 {
00085                         $key = ucwords(str_replace(array('_', '-'), ' ', $key));
00086                         $output .= "<tr><td width='50%' style='color:#000;font-weight:bold;background-color:#ddd;'>".$key."&nbsp;&nbsp;</td><td width='50%' style='color:#990000;font-weight:normal;background-color:#ddd;'>".$val."</td></tr>\n";
00087                 }
00088                 
00089                 $output .= "</table>\n";
00090                 $output .= "</fieldset>";
00091                 
00092                 return $output;
00093         }
00094         
00095         // --------------------------------------------------------------------
00096 
00097         /**
00098          * Compile Queries
00099          *
00100          * @access      private
00101          * @return      string
00102          */     
00103         function _compile_queries()
00104         {
00105                 $dbs = array();
00106                 
00107                 // Let's determine which databases are currently connected to
00108                 foreach (get_object_vars($this->CI) as $CI_object)
00109                 {
00110                         if ( is_subclass_of(get_class($CI_object), 'CI_DB') )
00111                         {
00112                                 $dbs[] = $CI_object;
00113                         }
00114                 }
00115                                         
00116                 if (count($dbs) == 0)
00117                 {
00118                         $output  = "\n\n";
00119                         $output .= '<fieldset style="border:1px solid #0000FF;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee">';
00120                         $output .= "\n";
00121                         $output .= '<legend style="color:#0000FF;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_queries').'&nbsp;&nbsp;</legend>';
00122                         $output .= "\n";                
00123                         $output .= "\n\n<table cellpadding='4' cellspacing='1' border='0' width='100%'>\n";
00124                         $output .="<tr><td width='100%' style='color:#0000FF;font-weight:normal;background-color:#eee;'>".$this->CI->lang->line('profiler_no_db')."</td></tr>\n";
00125                         $output .= "</table>\n";
00126                         $output .= "</fieldset>";
00127                         
00128                         return $output;
00129                 }
00130                 
00131                 // Load the text helper so we can highlight the SQL
00132                 $this->CI->load->helper('text');
00133 
00134                 // Key words we want bolded
00135                 $highlight = array('SELECT', 'DISTINCT', 'FROM', 'WHERE', 'AND', 'LEFT&nbsp;JOIN', 'ORDER&nbsp;BY', 'GROUP&nbsp;BY', 'LIMIT', 'INSERT', 'INTO', 'VALUES', 'UPDATE', 'OR', 'HAVING', 'OFFSET', 'NOT&nbsp;IN', 'IN', 'LIKE', 'NOT&nbsp;LIKE', 'COUNT', 'MAX', 'MIN', 'ON', 'AS', 'AVG', 'SUM', '(', ')');
00136 
00137                 $output  = "\n\n";
00138                         
00139                 foreach ($dbs as $db)
00140                 {
00141                         $output .= '<fieldset style="border:1px solid #0000FF;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee">';
00142                         $output .= "\n";
00143                         $output .= '<legend style="color:#0000FF;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_database').':&nbsp; '.$db->database.'&nbsp;&nbsp;&nbsp;'.$this->CI->lang->line('profiler_queries').': '.count($this->CI->db->queries).'&nbsp;&nbsp;&nbsp;</legend>';
00144                         $output .= "\n";                
00145                         $output .= "\n\n<table cellpadding='4' cellspacing='1' border='0' width='100%'>\n";
00146                 
00147                         if (count($db->queries) == 0)
00148                         {
00149                                 $output .= "<tr><td width='100%' style='color:#0000FF;font-weight:normal;background-color:#eee;'>".$this->CI->lang->line('profiler_no_queries')."</td></tr>\n";
00150                         }
00151                         else
00152                         {                               
00153                                 foreach ($db->queries as $key => $val)
00154                                 {                                       
00155                                         $time = number_format($db->query_times[$key], 4);
00156 
00157                                         $val = highlight_code($val, ENT_QUOTES);
00158         
00159                                         foreach ($highlight as $bold)
00160                                         {
00161                                                 $val = str_replace($bold, '<strong>'.$bold.'</strong>', $val);  
00162                                         }
00163                                         
00164                                         $output .= "<tr><td width='1%' valign='top' style='color:#990000;font-weight:normal;background-color:#ddd;'>".$time."&nbsp;&nbsp;</td><td style='color:#000;font-weight:normal;background-color:#ddd;'>".$val."</td></tr>\n";
00165                                 }
00166                         }
00167                         
00168                         $output .= "</table>\n";
00169                         $output .= "</fieldset>";
00170                         
00171                 }
00172                 
00173                 return $output;
00174         }
00175 
00176         
00177         // --------------------------------------------------------------------
00178 
00179         /**
00180          * Compile $_GET Data
00181          *
00182          * @access      private
00183          * @return      string
00184          */     
00185         function _compile_get()
00186         {       
00187                 $output  = "\n\n";
00188                 $output .= '<fieldset style="border:1px solid #cd6e00;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee">';
00189                 $output .= "\n";
00190                 $output .= '<legend style="color:#cd6e00;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_get_data').'&nbsp;&nbsp;</legend>';
00191                 $output .= "\n";
00192                                 
00193                 if (count($_GET) == 0)
00194                 {
00195                         $output .= "<div style='color:#cd6e00;font-weight:normal;padding:4px 0 4px 0'>".$this->CI->lang->line('profiler_no_get')."</div>";
00196                 }
00197                 else
00198                 {
00199                         $output .= "\n\n<table cellpadding='4' cellspacing='1' border='0' width='100%'>\n";
00200                 
00201                         foreach ($_GET as $key => $val)
00202                         {
00203                                 if ( ! is_numeric($key))
00204                                 {
00205                                         $key = "'".$key."'";
00206                                 }
00207                         
00208                                 $output .= "<tr><td width='50%' style='color:#000;background-color:#ddd;'>&#36;_GET[".$key."]&nbsp;&nbsp; </td><td width='50%' style='color:#cd6e00;font-weight:normal;background-color:#ddd;'>";
00209                                 if (is_array($val))
00210                                 {
00211                                         $output .= "<pre>" . htmlspecialchars(stripslashes(print_r($val, true))) . "</pre>";
00212                                 }
00213                                 else
00214                                 {
00215                                         $output .= htmlspecialchars(stripslashes($val));
00216                                 }
00217                                 $output .= "</td></tr>\n";
00218                         }
00219                         
00220                         $output .= "</table>\n";
00221                 }
00222                 $output .= "</fieldset>";
00223 
00224                 return $output; 
00225         }
00226         
00227         // --------------------------------------------------------------------
00228         
00229         /**
00230          * Compile $_POST Data
00231          *
00232          * @access      private
00233          * @return      string
00234          */     
00235         function _compile_post()
00236         {       
00237                 $output  = "\n\n";
00238                 $output .= '<fieldset style="border:1px solid #009900;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee">';
00239                 $output .= "\n";
00240                 $output .= '<legend style="color:#009900;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_post_data').'&nbsp;&nbsp;</legend>';
00241                 $output .= "\n";
00242                                 
00243                 if (count($_POST) == 0)
00244                 {
00245                         $output .= "<div style='color:#009900;font-weight:normal;padding:4px 0 4px 0'>".$this->CI->lang->line('profiler_no_post')."</div>";
00246                 }
00247                 else
00248                 {
00249                         $output .= "\n\n<table cellpadding='4' cellspacing='1' border='0' width='100%'>\n";
00250                 
00251                         foreach ($_POST as $key => $val)
00252                         {
00253                                 if ( ! is_numeric($key))
00254                                 {
00255                                         $key = "'".$key."'";
00256                                 }
00257                         
00258                                 $output .= "<tr><td width='50%' style='color:#000;background-color:#ddd;'>&#36;_POST[".$key."]&nbsp;&nbsp; </td><td width='50%' style='color:#009900;font-weight:normal;background-color:#ddd;'>";
00259                                 if (is_array($val))
00260                                 {
00261                                         $output .= "<pre>" . htmlspecialchars(stripslashes(print_r($val, true))) . "</pre>";
00262                                 }
00263                                 else
00264                                 {
00265                                         $output .= htmlspecialchars(stripslashes($val));
00266                                 }
00267                                 $output .= "</td></tr>\n";
00268                         }
00269                         
00270                         $output .= "</table>\n";
00271                 }
00272                 $output .= "</fieldset>";
00273 
00274                 return $output; 
00275         }
00276         
00277         // --------------------------------------------------------------------
00278         
00279         /**
00280          * Show query string
00281          *
00282          * @access      private
00283          * @return      string
00284          */     
00285         function _compile_uri_string()
00286         {       
00287                 $output  = "\n\n";
00288                 $output .= '<fieldset style="border:1px solid #000;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee">';
00289                 $output .= "\n";
00290                 $output .= '<legend style="color:#000;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_uri_string').'&nbsp;&nbsp;</legend>';
00291                 $output .= "\n";
00292                 
00293                 if ($this->CI->uri->uri_string == '')
00294                 {
00295                         $output .= "<div style='color:#000;font-weight:normal;padding:4px 0 4px 0'>".$this->CI->lang->line('profiler_no_uri')."</div>";
00296                 }
00297                 else
00298                 {
00299                         $output .= "<div style='color:#000;font-weight:normal;padding:4px 0 4px 0'>".$this->CI->uri->uri_string."</div>";                               
00300                 }
00301                 
00302                 $output .= "</fieldset>";
00303 
00304                 return $output; 
00305         }
00306 
00307         // --------------------------------------------------------------------
00308         
00309         /**
00310          * Show the controller and function that were called
00311          *
00312          * @access      private
00313          * @return      string
00314          */     
00315         function _compile_controller_info()
00316         {       
00317                 $output  = "\n\n";
00318                 $output .= '<fieldset style="border:1px solid #995300;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee">';
00319                 $output .= "\n";
00320                 $output .= '<legend style="color:#995300;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_controller_info').'&nbsp;&nbsp;</legend>';
00321                 $output .= "\n";
00322                 
00323                 $output .= "<div style='color:#995300;font-weight:normal;padding:4px 0 4px 0'>".$this->CI->router->fetch_class()."/".$this->CI->router->fetch_method()."</div>";                                
00324 
00325                 
00326                 $output .= "</fieldset>";
00327 
00328                 return $output; 
00329         }
00330         // --------------------------------------------------------------------
00331         
00332         /**
00333          * Compile memory usage
00334          *
00335          * Display total used memory
00336          *
00337          * @access      public
00338          * @return      string
00339          */
00340         function _compile_memory_usage()
00341         {
00342                 $output  = "\n\n";
00343                 $output .= '<fieldset style="border:1px solid #5a0099;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee">';
00344                 $output .= "\n";
00345                 $output .= '<legend style="color:#5a0099;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_memory_usage').'&nbsp;&nbsp;</legend>';
00346                 $output .= "\n";
00347                 
00348                 if (function_exists('memory_get_usage') && ($usage = memory_get_usage()) != '')
00349                 {
00350                         $output .= "<div style='color:#5a0099;font-weight:normal;padding:4px 0 4px 0'>".number_format($usage).' bytes</div>';
00351                 }
00352                 else
00353                 {
00354                         $output .= "<div style='color:#5a0099;font-weight:normal;padding:4px 0 4px 0'>".$this->CI->lang->line('profiler_no_memory_usage')."</div>";                             
00355                 }
00356                 
00357                 $output .= "</fieldset>";
00358 
00359                 return $output;
00360         }
00361 
00362         // --------------------------------------------------------------------
00363         
00364         /**
00365          * Run the Profiler
00366          *
00367          * @access      private
00368          * @return      string
00369          */     
00370         function run()
00371         {
00372                 $output = "<div id='codeigniter_profiler' style='clear:both;background-color:#fff;padding:10px;'>";
00373 
00374                 $output .= $this->_compile_uri_string();
00375                 $output .= $this->_compile_controller_info();
00376                 $output .= $this->_compile_memory_usage();
00377                 $output .= $this->_compile_benchmarks();
00378                 $output .= $this->_compile_get();
00379                 $output .= $this->_compile_post();
00380                 $output .= $this->_compile_queries();
00381 
00382                 $output .= '</div>';
00383 
00384                 return $output;
00385         }
00386 
00387 }
00388 
00389 // END CI_Profiler class
00390 
00391 /* End of file Profiler.php */
00392 /* Location: ./system/libraries/Profiler.php */