diff --git a/module/VuFind/src/VuFind/Bootstrap.php b/module/VuFind/src/VuFind/Bootstrap.php index c3720110bb08c5c89376b8727581181681379d0a..13376f31fd6821fe9fa0f1ce723141b22e819a51 100644 --- a/module/VuFind/src/VuFind/Bootstrap.php +++ b/module/VuFind/src/VuFind/Bootstrap.php @@ -327,9 +327,21 @@ class Bootstrap * * @return void */ - protected function initLog() + protected function initErrorLogging() { - // TODO: We need to figure out how to capture exceptions to the log -- the - // logic found in 2.0alpha's ErrorController needs a new home in 2.0beta. + $callback = function($event) { + $sm = $event->getApplication()->getServiceManager(); + if ($sm->has('Logger')) { + $log = $sm->get('Logger'); + if (is_callable(array($log, 'logException'))) { + $exception = $event->getParam('exception'); + $server = $event->getRequest()->getServer(); + if (!empty($exception)) { + $log->logException($exception, $server); + } + } + } + }; + $this->events->attach('dispatch.error', $callback); } } \ No newline at end of file diff --git a/module/VuFind/src/VuFind/Log/Logger.php b/module/VuFind/src/VuFind/Log/Logger.php index c3b3f220fcaaaaeac788006251529956c785b621..bdd8ba1ff5ea5a81e347584486f7a64ede813a38 100644 --- a/module/VuFind/src/VuFind/Log/Logger.php +++ b/module/VuFind/src/VuFind/Log/Logger.php @@ -251,4 +251,99 @@ class Logger extends BaseLogger implements ServiceLocatorAwareInterface { return $this->serviceLocator; } + + /** + * Add a message as a log entry + * + * @param int $priority Priority + * @param mixed $message Message + * @param array|Traversable $extra Extras + * + * @return Logger + */ + public function log($priority, $message, $extra = array()) + { + // Special case to handle arrays of messages (for multi-verbosity-level + // logging, not supported by base class): + if (is_array($message)) { + $timestamp = new \DateTime(); + foreach ($this->writers->toArray() as $writer) { + $writer->write(array( + 'timestamp' => $timestamp, + 'priority' => (int) $priority, + 'priorityName' => $this->priorities[$priority], + 'message' => $message, + 'extra' => $extra + )); + } + return $this; + } + return parent::log($priority, $message, $extra); + } + + /** + * Log an exception triggered by ZF2 for administrative purposes. + * + * @param \Exception $error Exception to log + * @param \Zend\Stdlib\Parameters $server Server metadata + * + * @return void + */ + public function logException($error, $server) + { + // We need to build a variety of pieces so we can supply + // information at five different verbosity levels: + $baseError = $error->getMessage(); + $referer = $server->get('HTTP_REFERER', 'none'); + $basicServer + = '(Server: IP = ' . $server->get('REMOTE_ADDR') . ', ' + . 'Referer = ' . $referer . ', ' + . 'User Agent = ' + . $server->get('HTTP_USER_AGENT') . ', ' + . 'Request URI = ' + . $server->get('REQUEST_URI') . ')'; + $detailedServer = "\nServer Context:\n" + . print_r($server->toArray(), true); + $basicBacktrace = $detailedBacktrace = "\nBacktrace:\n"; + if (is_array($error->getTrace())) { + foreach ($error->getTrace() as $line) { + if (!isset($line['file'])) { + $line['file'] = 'unlisted file'; + } + if (!isset($line['line'])) { + $line['line'] = 'unlisted'; + } + $basicBacktraceLine = $detailedBacktraceLine = $line['file'] . + ' line ' . $line['line'] . ' - ' . + (isset($line['class'])? 'class = '.$line['class'].', ' : '') + . 'function = ' . $line['function']; + $basicBacktrace .= "{$basicBacktraceLine}\n"; + if (!empty($line['args'])) { + $args = array(); + foreach ($line['args'] as $i => $arg) { + $val = is_object($arg) + ? get_class($arg) . ' Object' + : is_array($arg) + ? count($arg) . '-element Array' + : $arg; + $args[] = $i . ' = ' . $val; + } + $detailedBacktraceLine .= ', args: ' . implode(', ', $args); + } else { + $detailedBacktraceLine .= ', args: none.'; + } + $detailedBacktrace .= "{$detailedBacktraceLine}\n"; + } + } + + $errorDetails = array( + 1 => $baseError, + 2 => $baseError . $basicServer, + 3 => $baseError . $basicServer . $basicBacktrace, + 4 => $baseError . $detailedServer . $basicBacktrace, + 5 => $baseError . $detailedServer . $detailedBacktrace + ); + + $this->log(BaseLogger::CRIT, $errorDetails); + } }