DebugExecutionTime.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. <?php
  2. /* usage 1 - log to memory and print report:
  3. Lib::loadClass('DebugExecutionTime');
  4. $dbgExecTime = new DebugExecutionTime();
  5. $dbgExecTime->activate();
  6. $dbgExecTime->log('start');
  7. ...
  8. $dbgExecTime->log('end');
  9. $dbgExecTime->printDebug();
  10. */
  11. /* usage 2 - log to file:
  12. Lib::loadClass('DebugExecutionTime');
  13. $dbgExecTime = new DebugExecutionTime();
  14. $dbgExecTime->setLogFile('UNIQ_FILE_NAME', $format = 'csv'); // $format: 'csv', 'json'
  15. $dbgExecTime->logToFile('start');
  16. ...
  17. $dbgExecTime->logToFile('end');
  18. */
  19. class DebugExecutionTime {
  20. private $_log = array();
  21. private $_logByGroups = array();
  22. private $_isActive = false;
  23. private $_lastTime = 0;
  24. private $_logFile = null;
  25. private $_logFormat = null;
  26. public function __construct() {
  27. $this->_log = array();
  28. }
  29. public function activate() {
  30. $this->_isActive = true;
  31. }
  32. public function setLogFile($fileName, $format = 'csv') { // @param $format = 'csv', 'json'
  33. if (!file_exists($fileName)) @touch($fileName);
  34. if (!file_exists($fileName)) return; // log error?
  35. $this->_logFile = $fileName;
  36. switch ($format) {
  37. case 'json'; $this->_logFormat = 'json'; break;
  38. default: $this->_logFormat = 'csv';
  39. }
  40. }
  41. public function logToFile($msg) {
  42. if (!$this->_logFile) return;
  43. static $_idRequest = null;
  44. static $_lastMicroTime = null;
  45. // $timeDiff = (!$lastTime)
  46. // ? ''
  47. // : V::milisecondsStringDiff($dbg['date'], $lastTime); // TODO: $dbg['date'] - $lastTime;
  48. $microTime = date("Y-m-d H:i:s") . substr((string)microtime(), 1, 6);
  49. $info = [
  50. 'date' => $microTime,
  51. 'diff' => ($_lastMicroTime) ? V::milisecondsStringDiff($microTime, $_lastMicroTime) : '',
  52. 'req' => $_idRequest,
  53. 'mem' => memory_get_usage(true),
  54. 'msg' => $msg,
  55. ];
  56. $_lastMicroTime = $microTime;
  57. if (null === $_idRequest && 'csv' === $this->_logFormat) {
  58. error_log(
  59. implode("\t", array_keys($info)) . "\n"
  60. , 3
  61. , $this->_logFile
  62. );
  63. }
  64. if (null === $_idRequest) {
  65. $_idRequest = substr(md5(date("Y-m-d") . Request::getUserIp() . V::get('REQUEST_TIME', '', $_SERVER)), 0, 6);
  66. $info['req'] = $_idRequest;
  67. }
  68. switch ($this->_logFormat) {
  69. case 'csv': {
  70. error_log(
  71. implode("\t", array_values($info)) . "\n"
  72. , 3
  73. , $this->_logFile
  74. );
  75. } break;
  76. case 'json': {
  77. error_log(
  78. json_encode($info) . "\n"
  79. , 3
  80. , $this->_logFile
  81. );
  82. } break;
  83. }
  84. }
  85. /*
  86. * @param $msg string or NULL (NULL to log only group stats)
  87. */
  88. public function log($msg, $groups = array()) {
  89. if (!$this->_isActive) return;
  90. $curTime = microtime(true);
  91. $execTime = (!$this->_lastTime)? 0 : $curTime - $this->_lastTime;
  92. $this->_lastTime = $curTime;
  93. $this->_log[] = array($msg, $execTime);
  94. foreach ($groups as $group) {
  95. if (!array_key_exists($group, $this->_logByGroups)) $this->_logByGroups[$group] = 0;
  96. $this->_logByGroups[$group] += $execTime;
  97. }
  98. }
  99. public function getLastExecTime() {
  100. if (!$this->_isActive) return null;
  101. $logTotal = count($this->_log);
  102. if ($logTotal < 2) return null;
  103. return $this->_log[$logTotal - 1][1];
  104. }
  105. public function getTotalExecTime() {
  106. if (!$this->_isActive) return null;
  107. $logTotal = count($this->_log);
  108. if ($logTotal < 2) return null;
  109. $sumExecTime = 0;
  110. foreach ($this->_log as $log) $sumExecTime += $log[1];
  111. return $sumExecTime;
  112. }
  113. public function printDebug() {
  114. if (!$this->_isActive) return;
  115. $sumExecTime = 0;
  116. foreach ($this->_log as $log) $sumExecTime += $log[1];
  117. ?>
  118. <table>
  119. <tr>
  120. <td style="vertical-align:top;">
  121. <div style="max-height:300px;overflow:auto">
  122. <table style="text-align:left;" border="1" cellspacing="0" cellpadding="1">
  123. <thead>
  124. <tr>
  125. <th>msg</th>
  126. <th>time</th>
  127. </tr>
  128. </thead>
  129. <tfoot>
  130. <th style="text-align:right">total:</th>
  131. <th style="font-family:monospace;text-align:right;font-weight:bold;"><?php echo number_format($sumExecTime, 6); ?></th>
  132. </tfoot>
  133. <tbody>
  134. <?php foreach ($this->_log as $log) : ?>
  135. <?php if (null === $log[0]) continue; ?>
  136. <tr>
  137. <td><?php echo $log[0]; ?></td>
  138. <td style="font-family:monospace;text-align:right;"><?php echo number_format($log[1], 6); ?></td>
  139. </tr>
  140. <?php endforeach; ?>
  141. </tbody>
  142. </table>
  143. </div>
  144. </td>
  145. <td style="vertical-align:top;">
  146. <?php if (!empty($this->_logByGroups)) : ?>
  147. <table style="text-align:left;" border="1" cellspacing="0" cellpadding="1">
  148. <thead>
  149. <tr>
  150. <th>group</th>
  151. <th>time</th>
  152. <th>time left</th>
  153. <th>time %</th>
  154. </tr>
  155. </thead>
  156. <tbody>
  157. <?php foreach ($this->_logByGroups as $group => $execTime) : ?>
  158. <tr>
  159. <th><?php echo $group; ?></th>
  160. <td style="font-family:monospace;text-align:right;"><?php echo number_format($execTime, 6); ?></td>
  161. <td style="font-family:monospace;text-align:right;"><?php echo number_format($sumExecTime - $execTime, 6); ?></td>
  162. <td style="font-family:monospace;text-align:right;"><?php echo (!$execTime)? 0 : round($execTime * 100 / $sumExecTime); ?>%</td>
  163. </tr>
  164. <?php endforeach; ?>
  165. </tbody>
  166. </table>
  167. <?php endif; ?>
  168. </td>
  169. </tr>
  170. </table>
  171. <?php
  172. }
  173. }