BxProfiler.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  1. <?php defined('BX_DOL') or die('hack attempt');
  2. /**
  3. * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
  4. * CC-BY License - http://creativecommons.org/licenses/by/3.0/
  5. *
  6. * @defgroup Profiler Profiler
  7. * @ingroup DolphinModules
  8. *
  9. * @{
  10. */
  11. define ('BX_PROFILER', true);
  12. define ('BX_PROFILER_DISPLAY', 1);
  13. require_once(BX_DIRECTORY_PATH_MODULES . 'boonex/profiler/install/config.php');
  14. $GLOBALS['bx_profiler_module'] = array (
  15. 'title' => $aConfig['title'],
  16. 'vendor' => $aConfig['vendor'],
  17. 'path' => $aConfig['home_dir'],
  18. 'uri' => $aConfig['home_uri'],
  19. 'class_prefix' => $aConfig['class_prefix'],
  20. 'db_prefix' => $aConfig['db_prefix'],
  21. );
  22. bx_import('BxDolStudioTemplate');
  23. bx_import('Template', $GLOBALS['bx_profiler_module']);
  24. bx_import('Config', $GLOBALS['bx_profiler_module']);
  25. class BxProfiler extends BxDol {
  26. protected $oConfig, $oTemplate;
  27. protected $aConf = array ();
  28. protected $_iTimeStart = 0;
  29. protected $_aQueries = array();
  30. protected $_sQueryIndex = 0;
  31. protected $_aModules = array();
  32. protected $_aModulesNames = array();
  33. protected $_aModulesLevel = 0;
  34. protected $_aInjections = array();
  35. protected $_sInjectionIndex = 0;
  36. protected $_sLogDateFormat = "Y-m-d H:i:s";
  37. protected $_sLogMaxArgLength = 64;
  38. protected $_sLogFilename = 64;
  39. function __construct($iTimeStart) {
  40. parent::__construct();
  41. $this->oConfig = new BxProfilerConfig ($GLOBALS['bx_profiler_module']);
  42. $this->oTemplate = new BxProfilerTemplate ($this->oConfig);
  43. $this->oTemplateAdmin = BxDolStudioTemplate::getInstance();
  44. $aCss = array (
  45. BX_DOL_URL_MODULES . 'boonex/profiler/template/css/profiler.css',
  46. BX_DOL_URL_PLUGINS_PUBLIC . 'jush/jush.css',
  47. );
  48. $aJs = array (
  49. 'jquery.tablesorter.min.js',
  50. BX_DOL_URL_MODULES . 'boonex/profiler/js/profiler.js',
  51. BX_DOL_URL_PLUGINS_PUBLIC . 'jush/jush.js',
  52. );
  53. foreach ($aCss as $sCssUrl) {
  54. $this->oTemplate->addCss($sCssUrl);
  55. $this->oTemplateAdmin->addCss($sCssUrl);
  56. }
  57. foreach ($aJs as $sJsUrl) {
  58. $this->oTemplate->addJs($sJsUrl);
  59. $this->oTemplateAdmin->addJs($sJsUrl);
  60. }
  61. if (getParam ('bx_profiler_long_sql_queries_log'))
  62. $this->aConf['long_query'] = getParam ('bx_profiler_long_sql_queries_time');
  63. if (getParam ('bx_profiler_long_module_query_log'))
  64. $this->aConf['long_module'] = getParam ('bx_profiler_long_module_query_time');
  65. if (getParam ('bx_profiler_long_page_log'))
  66. $this->aConf['long_page'] = getParam ('bx_profiler_long_page_time');
  67. $this->_iTimeStart = $iTimeStart;
  68. }
  69. // output profiler debug panel
  70. function output () {
  71. $iPageTIme = $this->_getCurrentDelay ();
  72. if (isset($this->aConf['long_page']) && $iPageTIme > $this->aConf['long_page'])
  73. $this->logPageOpen ($iPageTIme);
  74. switch (getParam('bx_profiler_show_debug_panel')) {
  75. case 'all':
  76. break;
  77. case 'admins':
  78. if (!$GLOBALS['logged']['admin'])
  79. return;
  80. break;
  81. case 'none':
  82. default:
  83. return;
  84. }
  85. $sContentType = $this->_getHeaderContentType();
  86. if ('text/html' == $sContentType) {
  87. echo $this->_plankMain ();
  88. echo $this->_plankMenus ();
  89. echo $this->_plankTemplates ();
  90. echo $this->_plankInjections ();
  91. echo $this->_plankPagesBlocks ();
  92. echo $this->_plankSql ();
  93. echo $this->_plankModules ();
  94. }
  95. }
  96. function _logBegin ($s) {
  97. $sDate = date ($this->_sLogDateFormat);
  98. return "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" . $sDate . " " . $s . "\n" .
  99. "User ID: " . $_COOKIE['memberID'] . "\n" .
  100. "User role: " . ($GLOBALS['logged']['admin'] ? 'admin' : ($GLOBALS['logged']['member'] ? 'member' : 'guest')) . "\n";
  101. }
  102. function _logEnd () {
  103. return "\n";
  104. }
  105. function _appendToLog ($s) {
  106. $f = fopen ( BX_DIRECTORY_PATH_ROOT . 'logs/bx_profiler.log', 'a');
  107. if (!$f)
  108. return;
  109. fwrite($f, $s);
  110. fclose($f);
  111. }
  112. function logSqlQuery ($iTime, $aSqlQuery, &$res) {
  113. $s = $this->_logBegin ('LONG SQL QUERY: ' . $aSqlQuery['time']);
  114. $s .= "Rows: " . $aSqlQuery['rows'] . "\n";
  115. $s .= "Affected: " . $aSqlQuery['affected'] . "\n";
  116. $s .= "Query: " . $aSqlQuery['sql'] . "\n";
  117. if (getParam('bx_profiler_long_sql_queries_debug'))
  118. $s .= "Backtrace: \n" . $this->_debugBackTrace (3);
  119. $s .= $this->_logEnd();
  120. $this->_appendToLog ($s);
  121. }
  122. function logModuleQuery ($iTime, $aModuleQuery) {
  123. $s = $this->_logBegin ('LONG MODULE QUERY: ' . $aModuleQuery['time']);
  124. $s .= "Module name: " . $aModuleQuery['name'] . "\n";
  125. $s .= "Query type: " . $aModuleQuery['type'] . "\n";
  126. $s .= "Class/file: " . $aModuleQuery['class/file'] . "\n";
  127. $s .= "Method: " . $aModuleQuery['method'] . "\n";
  128. if (getParam('bx_profiler_long_module_query_debug'))
  129. $s .= "Backtrace: \n" . $this->_debugBackTrace (3);
  130. $s .= $this->_logEnd();
  131. $this->_appendToLog ($s);
  132. }
  133. function logPageOpen ($iTime) {
  134. $s = $this->_logBegin ('LONG PAGE OPEN: ' . $this->_formatTime($iTime, 5));
  135. $s .= "Request method: " . $_SERVER['REQUEST_METHOD'] . "\n";
  136. $s .= "Query string: " . $_SERVER['QUERY_STRING'] . "\n";
  137. $s .= "Request URI: " . $_SERVER['REQUEST_URI'] . "\n";
  138. $s .= "Script name: " . $_SERVER['SCRIPT_NAME'] . "\n";
  139. $s .= "PHP self: " . $_SERVER['PHP_SELF'] . "\n";
  140. if (getParam('bx_profiler_long_page_debug'))
  141. $s .= "All server vars: \n" . print_r ($_SERVER, true);
  142. $s .= $this->_logEnd();
  143. $this->_appendToLog ($s);
  144. }
  145. function beginModule($sType, $sHash, &$aModule, $sClassFile, $sMethod = '' ) {
  146. ++$this->_aModulesLevel;
  147. $this->_aModulesNames[$aModule['title']] = isset($this->_aModulesNames[$aModule['title']]) ? $this->_aModulesNames[$aModule['title']] + 1 : 1;
  148. $this->_aModules[$sHash] = array (
  149. 'name' => str_repeat("--", $this->_aModulesLevel-1) . $aModule['title'],
  150. 'type' => $sType,
  151. 'class/file' => $sClassFile,
  152. 'method' => $sMethod,
  153. 'begin' => microtime (),
  154. 'time' => -1,
  155. );
  156. }
  157. function endModule($sType, $sHash) {
  158. --$this->_aModulesLevel;
  159. $iTime = $this->_calcTime ($this->_aModules[$sHash]['begin']);
  160. unset ($this->_aModules[$sHash]['begin']);
  161. $this->_aModules[$sHash]['time'] = $this->_formatTime($iTime, 5);
  162. $this->_aModules[$sHash]['raw_time'] = $iTime;
  163. if (isset($this->aConf['long_module']) && $iTime > $this->aConf['long_module'])
  164. $this->logModuleQuery ($iTime, $this->_aModules[$sHash]);
  165. }
  166. function beginInjection ($sId) {
  167. $this->_sInjectionIndex = $sId;
  168. $this->_aInjections[$sId]['begin'] = microtime ();
  169. }
  170. function endInjection ($sId, $aInjection) {
  171. if (!isset($this->_aInjections[$sId]))
  172. return;
  173. $iTime = $this->_calcTime ($this->_aInjections[$sId]['begin']);
  174. unset ($this->_aInjections[$sId]['begin']);
  175. $this->_aInjections[$sId]['name'] = isset($aInjection['name']) ? $aInjection['name'] : 'no-name';
  176. $this->_aInjections[$sId]['key'] = $aInjection['key'];
  177. $this->_aInjections[$sId]['replace'] = $aInjection['replace'] ? 'yes' : 'no';
  178. $this->_aInjections[$sId]['time'] = $this->_formatTime($iTime, 5);
  179. $this->_aInjections[$sId]['raw_time'] = $iTime;
  180. }
  181. function beginPageBlock ($sName, $iBlockId) {
  182. $this->_sPageBlockIndex = $iBlockId;
  183. $this->_aPagesBlocks[$this->_sPageBlockIndex]['name'] = $sName;
  184. $this->_aPagesBlocks[$this->_sPageBlockIndex]['begin'] = microtime ();
  185. }
  186. function endPageBlock ($iBlockId, $isEmpty, $isCached) {
  187. if (!$this->_sPageBlockIndex)
  188. return;
  189. $iTime = $this->_calcTime ($this->_aPagesBlocks[$this->_sPageBlockIndex]['begin']);
  190. unset ($this->_aPagesBlocks[$this->_sPageBlockIndex]['begin']);
  191. $this->_aPagesBlocks[$this->_sPageBlockIndex]['cached'] = $isCached ? 'yes' : 'no';
  192. $this->_aPagesBlocks[$this->_sPageBlockIndex]['empty'] = $isEmpty ? 'yes' : 'no';
  193. $this->_aPagesBlocks[$this->_sPageBlockIndex]['time'] = $this->_formatTime($iTime, 5);
  194. $this->_aPagesBlocks[$this->_sPageBlockIndex]['raw_time'] = $iTime;
  195. }
  196. function beginPage ($sName) {
  197. $this->_sPageIndex = md5 ($sName.time().rand());
  198. $this->_aPages[$this->_sPageIndex]['name'] = $sName;
  199. $this->_aPages[$this->_sPageIndex]['begin'] = microtime ();
  200. }
  201. function endPage (&$sContent) {
  202. if (!$this->_sPageIndex || !isset($this->_aPages[$this->_sPageIndex]['begin']))
  203. return;
  204. $iTime = $this->_calcTime ($this->_aPages[$this->_sPageIndex]['begin']);
  205. unset ($this->_aPages[$this->_sPageIndex]['begin']);
  206. $this->_aPages[$this->_sPageIndex]['time'] = $this->_formatTime($iTime, 5);
  207. $this->_aPages[$this->_sPageIndex]['raw_time'] = $iTime;
  208. }
  209. function beginTemplate ($sName, $sRand) {
  210. $this->_aTemplateIndexes[$sName.$sRand] = 1;
  211. $this->_aTemplates[$sName.$sRand]['name'] = $sName;
  212. $this->_aTemplates[$sName.$sRand]['begin'] = microtime ();
  213. }
  214. function endTemplate ($sName, $sRand, &$sContent, $isCached) {
  215. if (!isset($this->_aTemplateIndexes[$sName.$sRand]))
  216. return;
  217. $iTime = $this->_calcTime ($this->_aTemplates[$sName.$sRand]['begin']);
  218. unset ($this->_aTemplates[$sName.$sRand]['begin']);
  219. $this->_aTemplates[$sName.$sRand]['cached'] = $isCached ? 'yes' : 'no';
  220. $this->_aTemplates[$sName.$sRand]['time'] = $this->_formatTime($iTime, 5);
  221. $this->_aTemplates[$sName.$sRand]['raw_time'] = $iTime;
  222. }
  223. function beginQuery ($sSql) {
  224. $this->_sQueryIndex = md5 ($sSql.time().rand());
  225. $this->_aQueries[$this->_sQueryIndex]['sql'] = $sSql;
  226. $this->_aQueries[$this->_sQueryIndex]['begin'] = microtime ();
  227. }
  228. function endQuery (&$res) {
  229. if (!$this->_sQueryIndex)
  230. return;
  231. $iTime = $this->_calcTime ($this->_aQueries[$this->_sQueryIndex]['begin']);
  232. unset ($this->_aQueries[$this->_sQueryIndex]['begin']);
  233. $this->_aQueries[$this->_sQueryIndex]['time'] = $this->_formatTime($iTime, 5);
  234. $this->_aQueries[$this->_sQueryIndex]['raw_time'] = $iTime;
  235. $this->_aQueries[$this->_sQueryIndex]['rows'] = $res ? BxDolDb::getInstance()->getNumRows($res) : '';
  236. $this->_aQueries[$this->_sQueryIndex]['affected'] = $res ? BxDolDb::getInstance()->getAffectedRows($res) : '';
  237. if (isset($this->aConf['long_query']) && $iTime > $this->aConf['long_query'])
  238. $this->logSqlQuery ($iTime, $this->_aQueries[$this->_sQueryIndex], $res);
  239. }
  240. function beginMenu ($sName) {
  241. $this->_aMenus[$sName]['name'] = $sName;
  242. $this->_aMenus[$sName]['begin'] = microtime ();
  243. }
  244. function endMenu ($sName) {
  245. if (!isset($this->_aMenus[$sName]))
  246. return;
  247. $iTime = $this->_calcTime ($this->_aMenus[$sName]['begin']);
  248. unset ($this->_aMenus[$sName]['begin']);
  249. $this->_aMenus[$sName]['time'] = $this->_formatTime($iTime, 5);
  250. $this->_aMenus[$sName]['raw_time'] = $iTime;
  251. }
  252. function _getCurrentDelay () {
  253. $i1 = explode(' ', microtime ());
  254. $i2 = explode(' ', $this->_iTimeStart);
  255. return ($i1[0]+$i1[1]) - ($i2[0]+$i2[1]);
  256. }
  257. function _plankMain () {
  258. $sTime = $this->_formatTime($this->_getCurrentDelay ());
  259. if (function_exists('memory_get_usage'))
  260. $sMemory = $this->_formatBytes(memory_get_usage(true)) . ' of ' . ini_get('memory_limit') . ' allowed';
  261. return $this->oTemplate->plank(
  262. $this->oTemplate->nameValue('Time:', $sTime) .
  263. (function_exists('memory_get_usage') ? $this->oTemplate->nameValue('Memory:', $sMemory) : '') .
  264. $this->oTemplate->nameValue('PHP:', phpversion()) .
  265. $this->oTemplate->nameValue('SAPI:', php_sapi_name()) .
  266. $this->oTemplate->nameValue('OS:', php_uname('s r m'))
  267. );
  268. }
  269. function _plankTemplates () {
  270. if (empty($GLOBALS['bx_profiler']->_aPages) && empty($GLOBALS['bx_profiler']->_aTemplates))
  271. return;
  272. $sPages = '';
  273. if (!empty($GLOBALS['bx_profiler']->_aPages)) {
  274. $iTimePages = 0;
  275. foreach ($GLOBALS['bx_profiler']->_aPages as $k => $r) {
  276. if (!isset($r['raw_time']))
  277. continue;
  278. $iTimePages += $r['raw_time'];
  279. unset ($GLOBALS['bx_profiler']->_aPages[$k]['raw_time']);
  280. }
  281. $sPages = count($GLOBALS['bx_profiler']->_aPages) . ' (' . $this->_formatTime($iTimePages, 3) . ')';
  282. }
  283. $sTemplatesCached = '';
  284. $sTemplatesNotCached = '';
  285. if ($GLOBALS['bx_profiler']->_aTemplates) {
  286. $iTimeTemplatesCached = 0;
  287. $iTimeTemplatesNotCached = 0;
  288. $sTemplatesCached = 0;
  289. $sTemplatesNotCached = 0;
  290. foreach ($GLOBALS['bx_profiler']->_aTemplates as $k => $r) {
  291. if (!isset($r['raw_time']))
  292. continue;
  293. if ('yes' == $r['cached']) {
  294. $iTimeTemplatesCached += $r['raw_time'];
  295. ++$sTemplatesCached;
  296. } else {
  297. $iTimeTemplatesNotCached += $r['raw_time'];
  298. ++$sTemplatesNotCached;
  299. }
  300. unset ($GLOBALS['bx_profiler']->_aTemplates[$k]['raw_time']);
  301. }
  302. if ($sTemplatesCached)
  303. $sTemplatesCached .= ' (' . $this->_formatTime($iTimeTemplatesCached, 3) . ')';
  304. if ($sTemplatesNotCached)
  305. $sTemplatesNotCached .= ' (' . $this->_formatTime($iTimeTemplatesNotCached, 3) . ')';
  306. }
  307. return $this->oTemplate->plank(
  308. ($sPages ? $this->oTemplate->nameValue('Pages:', $sPages) : '') .
  309. ($sTemplatesCached ? $this->oTemplate->nameValue('Templates Cached:', $sTemplatesCached) : '') .
  310. ($sTemplatesNotCached ? $this->oTemplate->nameValue('Templates Not Cached:', $sTemplatesNotCached) : ''),
  311. $this->oTemplate->table($GLOBALS['bx_profiler']->_aTemplates)
  312. );
  313. }
  314. function _plankInjections () {
  315. if (!$GLOBALS['bx_profiler']->_aInjections)
  316. return;
  317. $iTimeInjections = 0;
  318. foreach ($GLOBALS['bx_profiler']->_aInjections as $k => $r) {
  319. if (!isset($r['raw_time']))
  320. continue;
  321. $iTimeInjections += $r['raw_time'];
  322. unset ($GLOBALS['bx_profiler']->_aInjections[$k]['raw_time']);
  323. }
  324. $sInjections = count($GLOBALS['bx_profiler']->_aInjections) . ' injection (' . $this->_formatTime($iTimeInjections, 3) . ')';
  325. return $this->oTemplate->plank(
  326. $this->oTemplate->nameValue('Injections:', $sInjections),
  327. $this->oTemplate->table($GLOBALS['bx_profiler']->_aInjections)
  328. );
  329. }
  330. function _plankPagesBlocks () {
  331. if (empty($GLOBALS['bx_profiler']->_aPagesBlocks))
  332. return;
  333. $iTimeBlocks = 0;
  334. $iTimeBlocksCached = 0;
  335. $iTimeBlocksNotCached = 0;
  336. $iTimeBlocksEmpty = 0;
  337. $iTimeBlocksNotEmpty = 0;
  338. $iCountBlocksCached = 0;
  339. $iCountBlocksNotCached = 0;
  340. $iCountBlocksEmpty = 0;
  341. $iCountBlocksNotEmpty = 0;
  342. foreach ($GLOBALS['bx_profiler']->_aPagesBlocks as $k => $r) {
  343. if (!isset($r['raw_time']))
  344. continue;
  345. $iTimeBlocks += $r['raw_time'];
  346. if ($r['cached'] == 'yes') {
  347. $iTimeBlocksCached += $r['raw_time'];
  348. ++$iCountBlocksCached;
  349. } else {
  350. $iTimeBlocksNotCached += $r['raw_time'];
  351. ++$iCountBlocksNotCached;
  352. }
  353. if ($r['empty'] == 'yes') {
  354. $iTimeBlocksEmpty += $r['raw_time'];
  355. ++$iCountBlocksEmpty;
  356. } else {
  357. $iTimeBlocksNotEmpty += $r['raw_time'];
  358. ++$iCountBlocksNotEmpty;
  359. }
  360. unset ($GLOBALS['bx_profiler']->_aPagesBlocks[$k]['raw_time']);
  361. }
  362. $sBlocks = count($GLOBALS['bx_profiler']->_aPagesBlocks) . ' (' . $this->_formatTime($iTimeBlocks, 3) . ')';
  363. if ($iCountBlocksCached)
  364. $sBlocksCached = $iCountBlocksCached . ' (' . $this->_formatTime($iTimeBlocksCached, 3) . ')';
  365. if ($iCountBlocksNotCached)
  366. $sBlocksNotCached = $iCountBlocksNotCached . ' (' . $this->_formatTime($iTimeBlocksNotCached, 3) . ')';
  367. if ($iCountBlocksEmpty)
  368. $sBlocksEmpty = $iCountBlocksEmpty . ' (' . $this->_formatTime($iTimeBlocksEmpty, 3) . ')';
  369. if ($iCountBlocksNotEmpty)
  370. $sBlocksNotEmpty = $iCountBlocksNotEmpty . ' (' . $this->_formatTime($iTimeBlocksNotEmpty, 3) . ')';
  371. return $this->oTemplate->plank(
  372. $this->oTemplate->nameValue('Pages Blocks:', $sBlocks) .
  373. ($iCountBlocksCached ? $this->oTemplate->nameValue('Cached:', $sBlocksCached) : '') .
  374. ($iCountBlocksNotCached ? $this->oTemplate->nameValue('Not Cached:', $sBlocksNotCached) : '') .
  375. ($iCountBlocksEmpty ? $this->oTemplate->nameValue('Empty:', $sBlocksEmpty) : '') .
  376. ($iCountBlocksNotEmpty ? $this->oTemplate->nameValue('Not Empty:', $sBlocksNotEmpty) : ''),
  377. $this->oTemplate->table($GLOBALS['bx_profiler']->_aPagesBlocks)
  378. );
  379. }
  380. function _plankMenus () {
  381. if (empty($GLOBALS['bx_profiler']->_aMenus))
  382. return;
  383. $iTimeMenus = 0;
  384. foreach ($GLOBALS['bx_profiler']->_aMenus as $k => $r) {
  385. if (!isset($r['raw_time']))
  386. continue;
  387. $iTimeMenus += $r['raw_time'];
  388. unset ($GLOBALS['bx_profiler']->_aMenus[$k]['raw_time']);
  389. }
  390. $sMenus = count($GLOBALS['bx_profiler']->_aMenus) . ' menus (' . $this->_formatTime($iTimeMenus, 3) . ')';
  391. return $this->oTemplate->plank(
  392. $this->oTemplate->nameValue('Menus:', $sMenus),
  393. $this->oTemplate->table($GLOBALS['bx_profiler']->_aMenus)
  394. );
  395. }
  396. function _plankSql () {
  397. if (empty($GLOBALS['bx_profiler']->_aQueries))
  398. return;
  399. $iTimeQueries = 0;
  400. foreach ($GLOBALS['bx_profiler']->_aQueries as $k => $r) {
  401. if (!isset($r['raw_time']))
  402. continue;
  403. $iTimeQueries += $r['raw_time'];
  404. unset ($GLOBALS['bx_profiler']->_aQueries[$k]['raw_time']);
  405. }
  406. $sQueries = count($GLOBALS['bx_profiler']->_aQueries) . ' queries (' . $this->_formatTime($iTimeQueries, 3) . ')';
  407. return $this->oTemplate->plank(
  408. $this->oTemplate->nameValue('SQL:', $sQueries),
  409. $this->oTemplate->table($GLOBALS['bx_profiler']->_aQueries, 'sql')
  410. );
  411. }
  412. function _plankModules () {
  413. if (empty($GLOBALS['bx_profiler']->_aModules))
  414. return;
  415. $iTimeModules = 0;
  416. foreach ($GLOBALS['bx_profiler']->_aModules as $k => $r) {
  417. if (!isset($r['raw_time']))
  418. continue;
  419. $iTimeModules += $r['raw_time'];
  420. unset ($GLOBALS['bx_profiler']->_aModules[$k]['raw_time']);
  421. }
  422. $sModules = count($GLOBALS['bx_profiler']->_aModulesNames) . ' modules loaded';
  423. $sModulesQueries = count($GLOBALS['bx_profiler']->_aModules) . ' modules queries (' . $this->_formatTime($iTimeModules, 3) . ')';
  424. return $this->oTemplate->plank(
  425. $this->oTemplate->nameValue('Modules:', $sModules) .
  426. $this->oTemplate->nameValue('Modules Queries:', $sModulesQueries),
  427. $this->oTemplate->table($GLOBALS['bx_profiler']->_aModules)
  428. );
  429. }
  430. function _formatTime ($i, $iPrecision = 3) {
  431. return round($i, $iPrecision) . ' sec';
  432. }
  433. function _formatBytes ($i) {
  434. if ($i > 1024*1024)
  435. return round($i/1024/1024, 1) . 'M';
  436. elseif ($i > 1024)
  437. return round($i/1024, 1) . 'K';
  438. else
  439. return $i . 'B';
  440. }
  441. function _isProfilerDisabled() {
  442. if (isset($GLOBALS['bx_profiler_disable']) || isset($_GET['bx_profiler_disable']))
  443. return true;
  444. if (
  445. preg_match('/gzip_loader\.php/', $_SERVER['PHP_SELF']) ||
  446. preg_match('/get_rss_feed\.php/', $_SERVER['PHP_SELF']) ||
  447. preg_match('/fields\.parse\.php/', $_SERVER['PHP_SELF']) ||
  448. preg_match('/flash/', $_SERVER['PHP_SELF']) ||
  449. preg_match('/forum/', $_SERVER['PHP_SELF'])
  450. )
  451. return true;
  452. return false;
  453. }
  454. function _calcTime ($begin) {
  455. $i1 = explode(' ', microtime ());
  456. $i2 = explode(' ', $begin);
  457. return ($i1[0]+$i1[1]) - ($i2[0]+$i2[1]);
  458. }
  459. function _debugPrintArray ($mixed) {
  460. $sArgs .= 'Array(';
  461. foreach ($mixed as $mixed2)
  462. $sArgs .= (is_object($mixed2) ? $this->_debugPrintObject($mixed2) : $this->_debugPrintAny($mixed2)) . ',';
  463. $sArgs = substr($sArgs, 0, -1);
  464. $sArgs .= ')';
  465. return $sArgs;
  466. }
  467. function _debugPrintObject ($mixed) {
  468. return get_class($mixed) . ' instance';
  469. }
  470. function _debugPrintAny ($mixed) {
  471. if (is_string)
  472. return "'" . (strlen($mixed) > $this->_sLogMaxArgLength ? substr($mixed, 0, $this->_sLogMaxArgLength) . '...' : $mixed) . "'";
  473. else
  474. return $mixed;
  475. }
  476. function _debugBackTrace ($iShifts = 0) {
  477. $a = debug_backtrace();
  478. while (--$iShifts > -1)
  479. array_shift($a);
  480. $s = '';
  481. foreach ($a as $r) {
  482. $sArgs = '';
  483. foreach ($r['args'] as $mixed) {
  484. switch (true) {
  485. case is_array($mixed):
  486. $sArgs .= $this->_debugPrintArray($mixed);
  487. break;
  488. case is_object($mixed):
  489. $sArgs .= $this->_debugPrintObject($mixed);
  490. break;
  491. default:
  492. $sArgs .= $this->_debugPrintAny($mixed);
  493. }
  494. $sArgs .= ',';
  495. }
  496. $sArgs = substr($sArgs, 0, -1);
  497. $s .= "--------------------------------------\n";
  498. $s .= "{$r['line']} {$r['file']}\n";
  499. $s .= "{$r['class']}{$r['type']}{$r['function']} ({$sArgs});\n";
  500. }
  501. return $s;
  502. }
  503. function _getHeaderContentType() {
  504. $aHeaders = headers_list();
  505. foreach ($aHeaders as $s) {
  506. $a = explode(':', $s);
  507. if (isset($a[0]) && isset($a[1]) && 'content-type' == strtolower(trim($a[0]))) {
  508. $aa = explode(';', $a[1]);
  509. return strtolower(trim($aa[0]));
  510. }
  511. }
  512. return false;
  513. }
  514. }
  515. $GLOBALS['bx_profiler'] = new BxProfiler(BX_DOL_START);
  516. if (!$GLOBALS['bx_profiler']->_isProfilerDisabled())
  517. register_shutdown_function (array ($GLOBALS['bx_profiler'], 'output'));
  518. /** @} */