1
0

BxProfiler.php 25 KB

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