BxProfiler.php 25 KB

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