handle = fopen($fileName, 'r'); if (!$this->handle) { throw new Exception("Can't open '$fileName'"); } $header1 = fgets($this->handle); $header2 = fgets($this->handle); if (!preg_match('@Version: [23].*@', $header1) || !preg_match('@File format: [2-4]@', $header2)) { throw new Exception("This file is not an Xdebug trace file made with format option '1' and version 2 to 4."); } } public function parse() { $c = 0; $size = fstat($this->handle); $size = $size['size']; $read = 0; while (!feof($this->handle)) { $buffer = fgets($this->handle, 4096); $read += strlen($buffer); $this->parseLine($buffer); $c++; } } function parseLine($line) { $parts = explode("\t", $line); if (count($parts) < 5) { return; } $funcNr = (int) $parts[1]; $type = $parts[2]; switch ($type) { case '0': // Function enter $this->functions[$funcNr] = array(); $this->functions[$funcNr]['depth'] = (int) $parts[0]; $this->functions[$funcNr]['time.enter'] = $parts[3]; $this->functions[$funcNr]['memory.enter'] = $parts[4]; $this->functions[$funcNr]['name'] = $parts[5]; $this->functions[$funcNr]['internal'] = !(bool) $parts[6]; $this->functions[$funcNr]['file'] = $parts[8]; $this->functions[$funcNr]['line'] = $parts[9]; if ($parts[7]) { $this->functions[$funcNr]['params'] = array($parts[7]); } else { $this->functions[$funcNr]['params'] = array_slice($parts, 11); } // these are set later $this->functions[$funcNr]['time.exit'] = ''; $this->functions[$funcNr]['memory.exit'] = ''; $this->functions[$funcNr]['time.diff'] = ''; $this->functions[$funcNr]['memory.diff'] = ''; $this->functions[$funcNr]['return'] = ''; break; case '1': // Function exit $this->functions[$funcNr]['time.exit'] = $parts[3]; $this->functions[$funcNr]['memory.exit'] = $parts[4]; $this->functions[$funcNr]['time.diff'] = $this->functions[$funcNr]['time.exit'] - $this->functions[$funcNr]['time.enter']; $this->functions[$funcNr]['memory.diff'] = $this->functions[$funcNr]['memory.exit'] - $this->functions[$funcNr]['memory.enter']; break; case 'R'; // Function return $this->functions[$funcNr]['return'] = $parts[5]; break; } } function getTrace() { return $this->functions; } function getTraceHTML() { ob_start(); echo '
'; echo '
Function Call
'; echo '
'; echo 'File:Line'; echo 'ΔTime'; echo 'ΔMemory'; echo 'Time'; echo '
'; echo '
'; $level = 0; foreach ($this->functions as $func) { // depth wrapper if ($func['depth'] > $level) { for ($i = $level; $i < $func['depth']; $i++) { echo '
'; } } elseif ($func['depth'] < $level) { for ($i = $func['depth']; $i < $level; $i++) { echo '
'; } } $level = $func['depth']; $class = 'f'; if ($func['internal']) { $class .= ' i'; } echo '
'; echo '
'; echo '' . htmlspecialchars($func['name']) . ''; echo '(' . htmlspecialchars(join(",", $func['params'])) . ') '; if ($func['return'] !== '') { echo '→ ' . htmlspecialchars($func['return']) . ''; } echo '
'; echo '
'; echo ''.htmlspecialchars(basename($func['file']).':'.$func['line']).''; echo '' . sprintf('%f', $func['time.diff']) . ''; echo '' . sprintf('%d', $func['memory.diff']) . ''; echo '' . sprintf('%f', $func['time.enter']) . ''; echo '
'; echo '
'; } if ($level > 0) { for ($i = 0; $i < $level; $i++) { echo ''; } } $html = ob_get_contents(); ob_end_clean(); return $html; } }