/** * Handler to catch uncaught exception. * @param \Exception * @return void * @internal */ public static function _exceptionHandler(\Exception $exception) { if (!headers_sent()) { // for PHP < 5.2.4 $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1'; $code = isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE ') !== FALSE ? 503 : 500; header("{$protocol} {$code}", TRUE, $code); } try { if (self::$productionMode) { try { self::log($exception, self::ERROR); } catch (\Exception $e) { echo 'FATAL ERROR: unable to log error'; } if (self::$consoleMode) { echo "ERROR: the server encountered an internal error and was unable to complete your request.\n"; } elseif (self::isHtmlMode()) { require __DIR__ . '/templates/error.phtml'; } } else { if (self::$consoleMode) { // dump to console echo "{$exception}\n"; if ($file = self::log($exception)) { echo "(stored in {$file})\n"; if (self::$browser) { exec(self::$browser . ' ' . escapeshellarg($file)); } } } elseif (self::isHtmlMode()) { // dump to browser self::$blueScreen->render($exception); if (self::$bar) { self::$bar->render(); } } elseif (!self::fireLog($exception)) { // AJAX or non-HTML mode $file = self::log($exception, self::ERROR); if (!headers_sent()) { header("X-Nette-Error-Log: {$file}"); } } } foreach (self::$onFatalError as $handler) { call_user_func($handler, $exception); } } catch (\Exception $e) { if (self::$productionMode) { echo self::isHtmlMode() ? '<meta name=robots content=noindex>FATAL ERROR' : 'FATAL ERROR'; } else { echo "FATAL ERROR: thrown ", get_class($e), ': ', $e->getMessage(), "\nwhile processing ", get_class($exception), ': ', $exception->getMessage(), "\n"; } } self::$enabled = FALSE; // un-register shutdown function exit(254); }
/** * Handler to catch uncaught exception. * @param \Exception * @return void * @internal */ public static function _exceptionHandler(\Exception $exception) { if (!headers_sent()) { // for PHP < 5.2.4 header('HTTP/1.1 500 Internal Server Error'); } try { if (self::$productionMode) { try { self::log($exception, self::ERROR); } catch (\Exception $e) { echo 'FATAL ERROR: unable to log error'; } if (self::$consoleMode) { echo "ERROR: the server encountered an internal error and was unable to complete your request.\n"; } elseif (self::isHtmlMode()) { require __DIR__ . '/templates/error.phtml'; } } else { if (self::$consoleMode) { // dump to console echo "{$exception}\n"; } elseif (self::isHtmlMode()) { // dump to browser self::$blueScreen->render($exception); if (self::$bar) { self::$bar->render(); } } elseif (!self::fireLog($exception, self::ERROR)) { // AJAX or non-HTML mode self::log($exception); } } foreach (self::$onFatalError as $handler) { call_user_func($handler, $exception); } } catch (\Exception $e) { if (self::$productionMode) { echo self::isHtmlMode() ? '<meta name=robots content=noindex>FATAL ERROR' : 'FATAL ERROR'; } else { echo "FATAL ERROR: thrown ", get_class($e), ': ', $e->getMessage(), "\nwhile processing ", get_class($exception), ': ', $exception->getMessage(), "\n"; } } self::$enabled = FALSE; // un-register shutdown function exit(255); }
/** * @return BlueScreen */ public static function getBlueScreen() { if (!self::$blueScreen) { self::$blueScreen = new BlueScreen(); self::$blueScreen->collapsePaths[] = dirname(__DIR__); self::$blueScreen->addPanel(function ($e) { if ($e instanceof Nette\Templating\FilterException) { return array('tab' => 'Template', 'panel' => '<p><b>File:</b> ' . Helpers::editorLink($e->sourceFile, $e->sourceLine) . '</p>' . ($e->sourceLine ? BlueScreen::highlightFile($e->sourceFile, $e->sourceLine) : '')); } elseif ($e instanceof Nette\Utils\NeonException && preg_match('#line (\\d+)#', $e->getMessage(), $m)) { if ($item = Helpers::findTrace($e->getTrace(), 'Nette\\DI\\Config\\Adapters\\NeonAdapter::load')) { return array('tab' => 'NEON', 'panel' => '<p><b>File:</b> ' . Helpers::editorLink($item['args'][0], $m[1]) . '</p>' . BlueScreen::highlightFile($item['args'][0], $m[1])); } elseif ($item = Helpers::findTrace($e->getTrace(), 'Nette\\Utils\\Neon::decode')) { return array('tab' => 'NEON', 'panel' => BlueScreen::highlightPhp($item['args'][0], $m[1])); } } }); } return self::$blueScreen; }
/** * Handler to catch uncaught exception. * @param \Exception * @return void * @internal */ public static function _exceptionHandler(\Exception $exception) { if (!headers_sent()) { // for PHP < 5.2.4 header('HTTP/1.1 500 Internal Server Error'); } $htmlMode = !self::$ajaxDetected && !preg_match('#^Content-Type: (?!text/html)#im', implode("\n", headers_list())); try { if (self::$productionMode) { self::log($exception, self::ERROR); if (self::$consoleMode) { echo "ERROR: the server encountered an internal error and was unable to complete your request.\n"; } elseif ($htmlMode) { require __DIR__ . '/templates/error.phtml'; } } else { if (self::$consoleMode) { // dump to console echo "{$exception}\n"; } elseif ($htmlMode) { // dump to browser self::$blueScreen->render($exception); if (self::$bar) { self::$bar->render(); } } elseif (!self::fireLog($exception, self::ERROR)) { // AJAX or non-HTML mode self::log($exception); } } foreach (self::$onFatalError as $handler) { call_user_func($handler, $exception); } } catch (\Exception $e) { echo "\nNette\\Debug FATAL ERROR: thrown ", get_class($e), ': ', $e->getMessage(), "\nwhile processing ", get_class($exception), ': ', $exception->getMessage(), "\n"; } self::$enabled = FALSE; // un-register shutdown function exit(255); }
/** * Logs message or exception to file (if not disabled) and sends email notification (if enabled). * * @param string|Exception * @param int one of constant Debugger::INFO, WARNING, ERROR (sends email), CRITICAL (sends email) * * @return string logged error filename */ public static function log($message, $priority = self::INFO) { if (self::$logDirectory === false) { return; } elseif (!self::$logDirectory) { throw new Nette\InvalidStateException('Logging directory is not specified in Nette\\Diagnostics\\Debugger::$logDirectory.'); } if ($message instanceof \Exception) { $exception = $message; $message = ($message instanceof Nette\FatalErrorException ? 'Fatal error: ' . $exception->getMessage() : get_class($exception) . ": " . $exception->getMessage()) . " in " . $exception->getFile() . ":" . $exception->getLine(); $hash = md5($exception); $exceptionFilename = "exception-" . @date('Y-m-d-H-i-s') . "-{$hash}.html"; foreach (new \DirectoryIterator(self::$logDirectory) as $entry) { if (strpos($entry, $hash)) { $exceptionFilename = $entry; $saved = true; break; } } } self::$logger->log(array(@date('[Y-m-d H-i-s]'), trim($message), self::$source ? ' @ ' . self::$source : null, !empty($exceptionFilename) ? ' @@ ' . $exceptionFilename : null), $priority); if (!empty($exceptionFilename)) { $exceptionFilename = self::$logDirectory . '/' . $exceptionFilename; if (empty($saved) && ($logHandle = @fopen($exceptionFilename, 'w'))) { ob_start(); // double buffer prevents sending HTTP headers in some PHP ob_start(function ($buffer) use($logHandle) { fwrite($logHandle, $buffer); }, 4096); self::$blueScreen->render($exception); ob_end_flush(); ob_end_clean(); fclose($logHandle); } return strtr($exceptionFilename, '\\/', DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR); } }
static function _init() { self::$time = isset($_SERVER['REQUEST_TIME_FLOAT']) ? $_SERVER['REQUEST_TIME_FLOAT'] : microtime(TRUE); self::$consoleMode = PHP_SAPI === 'cli'; self::$productionMode = self::DETECT; if (self::$consoleMode) { self::$source = empty($_SERVER['argv']) ? 'cli' : 'cli: ' . implode(' ', $_SERVER['argv']); } else { self::$ajaxDetected = isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest'; if (isset($_SERVER['REQUEST_URI'])) { self::$source = (isset($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'], 'off') ? 'https://' : 'http://') . (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : (isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : '')) . $_SERVER['REQUEST_URI']; } } self::$logger = new Logger(); self::$logDirectory =& self::$logger->directory; self::$email =& self::$logger->email; self::$mailer =& self::$logger->mailer; self::$emailSnooze =& Logger::$emailSnooze; self::$fireLogger = new FireLogger(); self::$blueScreen = new BlueScreen(); self::$blueScreen->addPanel(function ($e) { if ($e instanceof Nette\Templating\FilterException) { return array('tab' => 'Template', 'panel' => '<p><b>File:</b> ' . Helpers::editorLink($e->sourceFile, $e->sourceLine) . ' <b>Line:</b> ' . ($e->sourceLine ? $e->sourceLine : 'n/a') . '</p>' . ($e->sourceLine ? BlueScreen::highlightFile($e->sourceFile, $e->sourceLine) : '')); } elseif ($e instanceof Nette\Utils\NeonException && preg_match('#line (\\d+)#', $e->getMessage(), $m)) { if ($item = Helpers::findTrace($e->getTrace(), 'Nette\\Config\\Adapters\\NeonAdapter::load')) { return array('tab' => 'NEON', 'panel' => '<p><b>File:</b> ' . Helpers::editorLink($item['args'][0], $m[1]) . ' <b>Line:</b> ' . $m[1] . '</p>' . BlueScreen::highlightFile($item['args'][0], $m[1])); } elseif ($item = Helpers::findTrace($e->getTrace(), 'Nette\\Utils\\Neon::decode')) { return array('tab' => 'NEON', 'panel' => BlueScreen::highlightPhp($item['args'][0], $m[1])); } } }); self::$bar = new Bar(); self::$bar->addPanel(new DefaultBarPanel('time')); self::$bar->addPanel(new DefaultBarPanel('memory')); self::$bar->addPanel(self::$errorPanel = new DefaultBarPanel('errors')); self::$bar->addPanel(self::$dumpPanel = new DefaultBarPanel('dumps')); }
/** * Extend debugger bluescreen * * @param mixed $exception Exception * * @return array */ public static function renderException($exception) { if ($exception instanceof \UniMapper\Exception\EntityException && $exception->getEntityPath() !== false) { $link = Helpers::editorLink($exception->getEntityPath(), $exception->getEntityLine()); $code = BlueScreen::highlightFile($exception->getEntityPath(), $exception->getEntityLine()); return ["tab" => "Entity", "panel" => $link . "\n" . $code]; } elseif ($exception instanceof \UniMapper\Exception\InvalidArgumentException && $exception->getValue() !== null) { return ["tab" => "Value given", "panel" => self::dump($exception->getValue())]; } elseif ($exception instanceof \UniMapper\Exception\AdapterException && $exception->getQuery() !== null) { return ["tab" => "Query", "panel" => self::dump($exception->getQuery())]; } }
/** * Logs error into database, URL is generated automatically * @param string $lstErrorTpName * @param string $message * @param string $insProcessId * @return \Nette\Database\Table\ActiveRow */ public function logError($message, $lstErrorTpName = null, $insProcessId = 'Logger::logError()') { $file_content = null; $now = new \DateTime(); if ($message instanceof \Exception) { $lstErrorTpName = $lstErrorTpName ?: 'exception'; $exception = $message; $message = ($message instanceof Nette\FatalErrorException ? 'Fatal error: ' . $exception->getMessage() : get_class($exception) . ": " . $exception->getMessage()) . ($exception->getCode() ? " #" . $exception->getCode() : ''); // Check if this exception has been submitted recently $isReported = $this->logErrorEntity->getTable()->where("message", $message)->where("reported_flag", 0)->where("ins_dt >= ?", $now->modify('-3 hours'))->fetch(); if (!$isReported) { $blueScreen = new ND\BlueScreen(); ob_start(); ob_start(); $blueScreen->render($exception); $file_content = ob_get_contents(); ob_end_clean(); ob_end_clean(); } } else { $isReported = $this->logErrorEntity->getTable()->where("message", $message)->where("reported_flag", 0)->where("url", $this->httpRequest->getUrl())->where("ins_dt >= ?", $now->modify('-3 hours'))->fetch(); } $lstErrorTpName = $lstErrorTpName ?: 'error'; if ($isReported) { $isReportedArray = $isReported->toArray(); $cnt = 1 + $isReportedArray['occured_cnt']; $isReported->update(array("occured_cnt" => $cnt, "upd_process_id" => "REPEATED_EXCEPTION_OCCURENCE")); return $isReported; } $logVisitId = $this->lastLogVisitRow ? $this->lastLogVisitRow->id : -1; $errorTp = $this->getErrorTpByName($lstErrorTpName); return $this->logErrorEntity->insert(array("error_tp_id" => $errorTp->id, "message" => $message, "file_content" => $file_content, "url" => $this->httpRequest->getUrl(), "log_visit_id" => $logVisitId, "post_query" => $this->createQueryString($this->httpRequest->getPost()), "ins_dt" => new \DateTime(), "ins_process_id" => $insProcessId)); }
static function _init() { self::$time = microtime(TRUE); self::$consoleMode = PHP_SAPI === 'cli'; self::$productionMode = self::DETECT; if (self::$consoleMode) { self::$source = empty($_SERVER['argv']) ? 'cli' : 'cli: ' . implode(' ', $_SERVER['argv']); } else { self::$ajaxDetected = isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest'; if (isset($_SERVER['REQUEST_URI'])) { self::$source = (isset($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'], 'off') ? 'https://' : 'http://') . (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : (isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : '')) . $_SERVER['REQUEST_URI']; } } self::$logger = new Logger(); self::$logDirectory =& self::$logger->directory; self::$email =& self::$logger->email; self::$mailer =& self::$logger->mailer; self::$emailSnooze =& Logger::$emailSnooze; self::$fireLogger = new FireLogger(); self::$blueScreen = new BlueScreen(); self::$blueScreen->addPanel(function ($e) { if ($e instanceof Nette\Templating\FilterException) { return array('tab' => 'Template', 'panel' => '<p><b>File:</b> ' . Helpers::editorLink($e->sourceFile, $e->sourceLine) . ' <b>Line:</b> ' . ($e->sourceLine ? $e->sourceLine : 'n/a') . '</p>' . ($e->sourceLine ? '<pre>' . BlueScreen::highlightFile($e->sourceFile, $e->sourceLine) . '</pre>' : '')); } }); self::$bar = new Bar(); self::$bar->addPanel(new DefaultBarPanel('time')); self::$bar->addPanel(new DefaultBarPanel('memory')); self::$bar->addPanel(self::$errorPanel = new DefaultBarPanel('errors')); self::$bar->addPanel(self::$dumpPanel = new DefaultBarPanel('dumps')); }