Permalink
Browse files

Many improvements:

- better way of merging similar errors & error context detection
- Debug_ErrorHook_Listener::triggerException() method to log & mail exceptions keeping their stacktraces
- incresed no-dups delay; count of errors happened between mails is included to mails
- tabs to spaces :-)
  • Loading branch information...
1 parent 173f188 commit 2822de9dae20215ec9ce1b1a1f8911585804b6b5 Dmitry committed Feb 22, 2013
@@ -14,13 +14,13 @@ class Debug_ErrorHook_Catcher
"E_USER_ERROR", "E_USER_WARNING", "E_USER_NOTICE", "E_STRICT",
"E_RECOVERABLE_ERROR", "E_DEPRECATED", "E_USER_DEPRECATED",
);
-
+
public function __construct()
{
$this->_prevHdl = set_error_handler(array($this, "_handleNotice"));
register_shutdown_function(array($this, "_handleFatal"));
}
-
+
public function remove()
{
restore_error_handler();
@@ -33,19 +33,34 @@ public function addNotifier(Debug_ErrorHook_INotifier $notifier)
{
$this->_notifiers[] = $notifier;
}
-
- public function _handleNotice($errno, $errstr, $errfile, $errline)
+
+ public function triggerException(Exception $e, $msg = null)
+ {
+ return $this->_handleNonFatal(
+ E_USER_ERROR,
+ "exception '" . get_class($e) . "' with message: '" . ($msg !== null? $msg : $e->getMessage()) . "'",
+ $e->getFile(), $e->getLine(),
+ $e->getTrace()
+ );
+ }
+
+ private function _handleNonFatal($errno, $errstr, $errfile, $errline, $trace)
{
if (!($errno & error_reporting())) {
return $this->_callPrevHdl($errno, $errstr, $errfile, $errline);
}
- $trace = debug_backtrace();
- array_shift($trace);
if ($this->_notify($errno, $errstr, $errfile, $errline, $trace) === false) {
return $this->_callPrevHdl($errno, $errstr, $errfile, $errline, $trace);
}
}
-
+
+ public function _handleNotice($errno, $errstr, $errfile, $errline)
+ {
+ $trace = debug_backtrace();
+ array_shift($trace);
+ return $this->_handleNonFatal($errno, $errstr, $errfile, $errline, $trace);
+ }
+
public function _handleFatal()
{
$error = error_get_last();
@@ -54,7 +69,7 @@ public function _handleFatal()
}
$this->_notify($error['type'], $error['message'], $error['file'], $error['line'], null);
}
-
+
/**
* Processes a notification.
*
@@ -87,7 +102,7 @@ private function _notify($errno, $errstr, $errfile, $errline, $trace)
}
return false;
}
-
+
private function _callPrevHdl()
{
if ($this->_prevHdl) {
@@ -5,15 +5,17 @@
*/
interface Debug_ErrorHook_INotifier
{
- /**
- * Called when an error occurred.
- *
- * @param string $errno
- * @param string $errstr
- * @param string $errfile
- * @param string $errline
- * @param array $trace
- * @return void
- */
- public function notify($errno, $errstr, $errfile, $errline, $trace);
+ /**
+ * Called when an error occurred.
+ *
+ * @param string $errno
+ * @param string $errstr
+ * @param string $errfile
+ * @param string $errline
+ * @param array $trace
+ * @param string $hash
+ * @param string $prependText
+ * @return void
+ */
+ public function notify($errno, $errstr, $errfile, $errline, $trace, $hash = null, $prependText = null);
}
@@ -13,14 +13,14 @@
class Debug_ErrorHook_Listener
{
- private $_catcher = null;
-
- /**
- * Creates a new listener object.
- * When this object is destroyed, all hooks are removed.
- *
- * @return Debug_ErrorHook_Listener
- */
+ private $_catcher = null;
+
+ /**
+ * Creates a new listener object.
+ * When this object is destroyed, all hooks are removed.
+ *
+ * @return Debug_ErrorHook_Listener
+ */
public function __construct()
{
$this->_catcher = new Debug_ErrorHook_Catcher();
@@ -35,7 +35,7 @@ public function __destruct()
{
$this->_catcher->remove();
}
-
+
/**
* Adds a new notifier to the list. Notifiers are called in case
* of notices and even fatal errors.
@@ -45,6 +45,18 @@ public function __destruct()
*/
public function addNotifier(Debug_ErrorHook_INotifier $notifier)
{
- $this->_catcher->addNotifier($notifier);
+ $this->_catcher->addNotifier($notifier);
+ }
+
+ /**
+ * Works like trigger_error, but allows to pass stacktrace
+ * from the specified exception.
+ *
+ * @param Exception $e
+ * @param string $msg
+ */
+ public function triggerException(Exception $e, $msg = null)
+ {
+ $this->_catcher->triggerException($e, $msg);
}
}
@@ -11,50 +11,55 @@
class Debug_ErrorHook_MailNotifier extends Debug_ErrorHook_TextNotifier
{
- private $_to;
- private $_charset;
- private $_whatToSend;
- private $_subjPrefix;
-
- public function __construct($to, $whatToSend, $subjPrefix = "[ERROR] ", $charset = "UTF-8")
- {
+ private $_to;
+ private $_from;
+ private $_charset;
+ private $_whatToSend;
+ private $_subjPrefix;
+
+ public function __construct($to, $whatToSend, $subjPrefix = "[ERROR] ", $charset = "UTF-8", $from = null)
+ {
parent::__construct($whatToSend);
- $this->_to = $to;
- $this->_subjPrefix = $subjPrefix;
- $this->_charset = $charset;
- }
-
+ $this->_to = $to;
+ $this->_from = $from? $from : $to;
+ $this->_subjPrefix = $subjPrefix;
+ $this->_charset = $charset;
+ }
+
protected function _notifyText($subject, $body)
{
- $this->_mail(
- $this->_to,
- $this->_encodeMailHeader($this->_subjPrefix . $subject),
- $body,
- join("\r\n", array(
- "From: {$this->_to}",
- "Content-Type: text/plain; charset={$this->_charset}"
- ))
- );
+ $msgId = md5(__CLASS__ . $this->_to . $this->_from . $this->_subjPrefix . $subject) . "@errorhook";
+ $this->_mail(
+ $this->_to,
+ $this->_encodeMailHeader($this->_subjPrefix . $subject),
+ $body,
+ join("\r\n", array(
+ "From: {$this->_from}",
+ "Content-Type: text/plain; charset={$this->_charset}",
+ "Message-Id: <$msgId>",
+ "In-Reply-To: <$msgId>",
+ ))
+ );
}
-
+
protected function _mail()
{
- $args = func_get_args();
- @call_user_func_array("mail", $args);
+ $args = func_get_args();
+ @call_user_func_array("mail", $args);
}
-
+
private function _encodeMailHeader($header)
{
return preg_replace_callback(
'/((?:^|>)\s*)([^<>]*?[^\w\s.][^<>]*?)(\s*(?:<|$))/s',
- array(__CLASS__, '_encodeMailHeaderCallback'),
+ array($this, '_encodeMailHeaderCallback'),
$header
);
}
- private function _encodeMailHeaderCallback($p)
+ public function _encodeMailHeaderCallback($p)
{
- $encoding = $this->_charset;
+ $encoding = $this->_charset;
return $p[1] . "=?$encoding?B?" . base64_encode($p[2]) . "?=" . $p[3];
}
}
Oops, something went wrong.

0 comments on commit 2822de9

Please sign in to comment.