PageRenderTime 44ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/bonfire/application/libraries/Profiler.php

https://github.com/seandowney/Bonfire
PHP | 524 lines | 303 code | 88 blank | 133 comment | 42 complexity | e6f05e09eb07cf91c1566f4f5bcf7098 MD5 | raw file
  1. <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
  2. /**
  3. * CodeIgniter
  4. *
  5. * An open source application development framework for PHP 5.1.6 or newer
  6. *
  7. * @package CodeIgniter
  8. * @author ExpressionEngine Dev Team
  9. * @copyright Copyright (c) 2008 - 2011, EllisLab, Inc.
  10. * @license http://codeigniter.com/user_guide/license.html
  11. * @link http://codeigniter.com
  12. * @since Version 1.0
  13. * @filesource
  14. */
  15. // ------------------------------------------------------------------------
  16. /**
  17. * CodeIgniter Profiler Class
  18. *
  19. * This class enables you to display benchmark, query, and other data
  20. * in order to help with debugging and optimization.
  21. *
  22. * Note: At some point it would be good to move all the HTML in this class
  23. * into a set of template files in order to allow customization.
  24. *
  25. * @package CodeIgniter
  26. * @subpackage Libraries
  27. * @category Libraries
  28. * @author ExpressionEngine Dev Team
  29. * @link http://codeigniter.com/user_guide/general/profiling.html
  30. */
  31. class CI_Profiler {
  32. var $CI;
  33. protected $_available_sections = array(
  34. 'benchmarks',
  35. 'get',
  36. 'memory_usage',
  37. 'post',
  38. 'uri_string',
  39. 'controller_info',
  40. 'queries',
  41. 'http_headers',
  42. 'config',
  43. 'files',
  44. 'console',
  45. 'userdata'
  46. );
  47. protected $_sections = array(); // Stores _compile_x() results
  48. // --------------------------------------------------------------------
  49. public function __construct($config = array())
  50. {
  51. $this->CI =& get_instance();
  52. $this->CI->load->language('profiler');
  53. // default all sections to display
  54. foreach ($this->_available_sections as $section)
  55. {
  56. if ( ! isset($config[$section]))
  57. {
  58. $this->_compile_{$section} = TRUE;
  59. }
  60. }
  61. // Make sure the Console is loaded.
  62. if (!class_exists('Console'))
  63. {
  64. $this->CI->load->library('Console');
  65. }
  66. $this->set_sections($config);
  67. }
  68. // --------------------------------------------------------------------
  69. /**
  70. * Set Sections
  71. *
  72. * Sets the private _compile_* properties to enable/disable Profiler sections
  73. *
  74. * @param mixed
  75. * @return void
  76. */
  77. public function set_sections($config)
  78. {
  79. foreach ($config as $method => $enable)
  80. {
  81. if (in_array($method, $this->_available_sections))
  82. {
  83. $this->_compile_{$method} = ($enable !== FALSE) ? TRUE : FALSE;
  84. }
  85. }
  86. }
  87. // --------------------------------------------------------------------
  88. /**
  89. * Auto Profiler
  90. *
  91. * This function cycles through the entire array of mark points and
  92. * matches any two points that are named identically (ending in "_start"
  93. * and "_end" respectively). It then compiles the execution times for
  94. * all points and returns it as an array
  95. *
  96. * @return array
  97. */
  98. protected function _compile_benchmarks()
  99. {
  100. $profile = array();
  101. $output = array();
  102. foreach ($this->CI->benchmark->marker as $key => $val)
  103. {
  104. // We match the "end" marker so that the list ends
  105. // up in the order that it was defined
  106. if (preg_match("/(.+?)_end/i", $key, $match))
  107. {
  108. if (isset($this->CI->benchmark->marker[$match[1].'_end']) AND isset($this->CI->benchmark->marker[$match[1].'_start']))
  109. {
  110. $profile[$match[1]] = $this->CI->benchmark->elapsed_time($match[1].'_start', $key);
  111. }
  112. }
  113. }
  114. // Build a table containing the profile data.
  115. // Note: At some point we might want to make this data available to be logged.
  116. foreach ($profile as $key => $val)
  117. {
  118. $key = ucwords(str_replace(array('_', '-'), ' ', $key));
  119. $output[$key] = $val;
  120. }
  121. return $output;
  122. }
  123. // --------------------------------------------------------------------
  124. /**
  125. * Compile Queries
  126. *
  127. * @return string
  128. */
  129. protected function _compile_queries()
  130. {
  131. $dbs = array();
  132. $output = array();
  133. $output['duplicates'] = 0;
  134. // Let's determine which databases are currently connected to
  135. foreach (get_object_vars($this->CI) as $CI_object)
  136. {
  137. if (is_object($CI_object) && is_subclass_of(get_class($CI_object), 'CI_DB') )
  138. {
  139. $dbs[] = $CI_object;
  140. }
  141. }
  142. if (count($dbs) == 0)
  143. {
  144. return $this->CI->lang->line('profiler_no_db');
  145. }
  146. // Load the text helper so we can highlight the SQL
  147. $this->CI->load->helper('text');
  148. // Key words we want bolded
  149. $highlight = array('SELECT', 'DISTINCT', 'FROM', 'WHERE', 'AND', 'LEFT&nbsp;JOIN', 'ORDER&nbsp;BY', 'GROUP&nbsp;BY', 'LIMIT', 'INSERT', 'INTO', 'VALUES', 'UPDATE', 'OR&nbsp;', 'HAVING', 'OFFSET', 'NOT&nbsp;IN', 'IN', 'LIKE', 'NOT&nbsp;LIKE', 'COUNT', 'MAX', 'MIN', 'ON', 'AS', 'AVG', 'SUM', '(', ')');
  150. foreach ($dbs as $db)
  151. {
  152. if (count($db->queries) == 0)
  153. {
  154. $output = $this->CI->lang->line('profiler_no_queries');
  155. }
  156. else
  157. {
  158. foreach ($db->queries as $key => $val)
  159. {
  160. // duplicates?
  161. if (in_array($val, $output))
  162. {
  163. $output['duplicates']++;
  164. }
  165. $time = number_format($db->query_times[$key], 4);
  166. $output[$time] = $val;
  167. }
  168. }
  169. }
  170. return $output;
  171. }
  172. // --------------------------------------------------------------------
  173. /**
  174. * Compile $_GET Data
  175. *
  176. * @return string
  177. */
  178. protected function _compile_get()
  179. {
  180. $output = array();
  181. if (count($_GET) == 0)
  182. {
  183. $output = $this->CI->lang->line('profiler_no_get');
  184. }
  185. else
  186. {
  187. foreach ($_GET as $key => $val)
  188. {
  189. if ( ! is_numeric($key))
  190. {
  191. $key = "'".$key."'";
  192. }
  193. $output .= "<tr><td style='width:50%;color:#000;background-color:#ddd;padding:5px'>&#36;_GET[".$key."]&nbsp;&nbsp; </td><td style='width:50%;padding:5px;color:#cd6e00;font-weight:normal;background-color:#ddd;'>";
  194. if (is_array($val))
  195. {
  196. $output['&#36;_GET['. $key .']'] = "<pre>" . htmlspecialchars(stripslashes(print_r($val, true))) . "</pre>";
  197. }
  198. else
  199. {
  200. $output['&#36;_GET['. $key .']'] = htmlspecialchars(stripslashes($val));
  201. }
  202. }
  203. }
  204. return $output;
  205. }
  206. // --------------------------------------------------------------------
  207. /**
  208. * Compile $_POST Data
  209. *
  210. * @return string
  211. */
  212. protected function _compile_post()
  213. {
  214. $output = array();
  215. if (count($_POST) == 0)
  216. {
  217. $output = $this->CI->lang->line('profiler_no_post');
  218. }
  219. else
  220. {
  221. foreach ($_POST as $key => $val)
  222. {
  223. if ( ! is_numeric($key))
  224. {
  225. $key = "'".$key."'";
  226. }
  227. if (is_array($val))
  228. {
  229. $output['&#36;_POST['. $key .']'] = '<pre>'. htmlspecialchars(stripslashes(print_r($val, TRUE))) . '</pre>';
  230. }
  231. else
  232. {
  233. $output['&#36;_POST['. $key .']'] = htmlspecialchars(stripslashes($val));
  234. }
  235. }
  236. }
  237. return $output;
  238. }
  239. // --------------------------------------------------------------------
  240. /**
  241. * Show query string
  242. *
  243. * @return string
  244. */
  245. protected function _compile_uri_string()
  246. {
  247. if ($this->CI->uri->uri_string == '')
  248. {
  249. $output = $this->CI->lang->line('profiler_no_uri');
  250. }
  251. else
  252. {
  253. $output = $this->CI->uri->uri_string;
  254. }
  255. return $output;
  256. }
  257. // --------------------------------------------------------------------
  258. /**
  259. * Show the controller and function that were called
  260. *
  261. * @return string
  262. */
  263. protected function _compile_controller_info()
  264. {
  265. $output = $this->CI->router->fetch_class()."/".$this->CI->router->fetch_method();
  266. return $output;
  267. }
  268. // --------------------------------------------------------------------
  269. /**
  270. * Compile memory usage
  271. *
  272. * Display total used memory
  273. *
  274. * @return string
  275. */
  276. protected function _compile_memory_usage()
  277. {
  278. if (function_exists('memory_get_usage') && ($usage = memory_get_usage()) != '')
  279. {
  280. $output = number_format($usage) .' bytes';
  281. }
  282. else
  283. {
  284. $output = $this->CI->lang->line('profiler_no_memory_usage');
  285. }
  286. return $output;
  287. }
  288. // --------------------------------------------------------------------
  289. /**
  290. * Compile header information
  291. *
  292. * Lists HTTP headers
  293. *
  294. * @return string
  295. */
  296. protected function _compile_http_headers()
  297. {
  298. $output = array();
  299. foreach (array('HTTP_ACCEPT', 'HTTP_USER_AGENT', 'HTTP_CONNECTION', 'SERVER_PORT', 'SERVER_NAME', 'REMOTE_ADDR', 'SERVER_SOFTWARE', 'HTTP_ACCEPT_LANGUAGE', 'SCRIPT_NAME', 'REQUEST_METHOD',' HTTP_HOST', 'REMOTE_HOST', 'CONTENT_TYPE', 'SERVER_PROTOCOL', 'QUERY_STRING', 'HTTP_ACCEPT_ENCODING', 'HTTP_X_FORWARDED_FOR') as $header)
  300. {
  301. $val = (isset($_SERVER[$header])) ? $_SERVER[$header] : '';
  302. $output[$header] = $val;
  303. }
  304. return $output;
  305. }
  306. // --------------------------------------------------------------------
  307. /**
  308. * Compile config information
  309. *
  310. * Lists developer config variables
  311. *
  312. * @return string
  313. */
  314. protected function _compile_config()
  315. {
  316. $output = array();
  317. foreach ($this->CI->config->config as $config=>$val)
  318. {
  319. if (is_array($val))
  320. {
  321. $val = print_r($val, TRUE);
  322. }
  323. $output[$config] = htmlspecialchars($val);
  324. }
  325. return $output;
  326. }
  327. // --------------------------------------------------------------------
  328. public function _compile_files()
  329. {
  330. $files = get_included_files();
  331. sort($files);
  332. return $files;
  333. }
  334. //--------------------------------------------------------------------
  335. public function _compile_console()
  336. {
  337. $logs = Console::get_logs();
  338. if ($logs['console'])
  339. {
  340. foreach ($logs['console'] as $key => $log)
  341. {
  342. if ($log['type'] == 'log')
  343. {
  344. $logs['console'][$key]['data'] = print_r($log['data'], true);
  345. }
  346. elseif ($log['type'] == 'memory')
  347. {
  348. $logs['console'][$key]['data'] = $this->get_file_size($log['data']);
  349. }
  350. }
  351. }
  352. //echo '<pre>'; print_r($logs); echo '</pre>';
  353. return $logs;
  354. }
  355. //--------------------------------------------------------------------
  356. function _compile_userdata()
  357. {
  358. $output = array();
  359. $compiled_userdata = $this->CI->session->all_userdata();
  360. if (count($compiled_userdata))
  361. {
  362. foreach ($compiled_userdata as $key => $val)
  363. {
  364. if (is_numeric($key))
  365. {
  366. $output[$key] = "'$val'";
  367. }
  368. if (is_array($val))
  369. {
  370. $output[$key] = htmlspecialchars(stripslashes(print_r($val, true)));
  371. }
  372. else
  373. {
  374. $output[$key] = htmlspecialchars(stripslashes($val));
  375. }
  376. }
  377. }
  378. return $output;
  379. }
  380. //--------------------------------------------------------------------
  381. public static function get_file_size($size, $retstring = null) {
  382. // adapted from code at http://aidanlister.com/repos/v/function.size_readable.php
  383. $sizes = array('bytes', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
  384. if ($retstring === null) { $retstring = '%01.2f %s'; }
  385. $lastsizestring = end($sizes);
  386. foreach ($sizes as $sizestring) {
  387. if ($size < 1024) { break; }
  388. if ($sizestring != $lastsizestring) { $size /= 1024; }
  389. }
  390. if ($sizestring == $sizes[0]) { $retstring = '%01d %s'; } // Bytes aren't normally fractional
  391. return sprintf($retstring, $size, $sizestring);
  392. }
  393. //--------------------------------------------------------------------
  394. /**
  395. * Run the Profiler
  396. *
  397. * @return string
  398. */
  399. public function run()
  400. {
  401. $this->CI->load->helper('language');
  402. $fields_displayed = 0;
  403. foreach ($this->_available_sections as $section)
  404. {
  405. if ($this->_compile_{$section} !== FALSE)
  406. {
  407. $func = "_compile_{$section}";
  408. $this->_sections[$section] = $this->{$func}();
  409. $fields_displayed++;
  410. }
  411. }
  412. // Has the user created an override in application/views?
  413. if (is_file(APPPATH .'views/profiler_template'.EXT))
  414. {
  415. $output = $this->CI->load->view('profiler_template', array('sections' => $this->_sections), true);
  416. }
  417. else
  418. {
  419. // Load the view from system/views
  420. $orig_view_path = $this->CI->load->_ci_view_path;
  421. $this->CI->load->_ci_view_path = BASEPATH .'views/';
  422. //echo $this->CI->load->_ci_view_path;
  423. $output = $this->CI->load->_ci_load(array(
  424. '_ci_view' => 'profiler_template',
  425. '_ci_vars' => array('sections' => $this->_sections),
  426. '_ci_return' => true,
  427. ));
  428. $this->CI->load->_ci_view_path = $orig_view_path;
  429. }
  430. return $output;
  431. }
  432. }
  433. // END CI_Profiler class
  434. //--------------------------------------------------------------------
  435. /* End of file Profiler.php */
  436. /* Location: ./system/libraries/Profiler.php */