Magento 1.7 Error Reporting – var/report vs. var/log/exception.log

errormagento-1.7

I'm trying to fully understand Magento's error handling.

I noticed that sometimes if a fatal error occurs, a report is created in var/report (and an email is sent – depending on configuration) and on other occasions an error message is logged in var/log/exception.log. This all happens on the same installation, so it can't be a configuration thing.

How does Magento decide where to store an error message?

Best Answer

So the default behavior for an uncatched error (when developer mode is deactivated) is to create a report. That ultimate catch is handled in the Mage.php:

public static function init($code = '', $type = 'store', $options = array(), $modules = array())
{
    try {
        self::setRoot();
        self::$_app     = new Mage_Core_Model_App();
        self::_setIsInstalled($options);
        self::_setConfigModel($options);

        if (!empty($modules)) {
            self::$_app->initSpecified($code, $type, $options, $modules);
        } else {
            self::$_app->init($code, $type, $options);
        }
    } catch (Mage_Core_Model_Session_Exception $e) {
        header('Location: ' . self::getBaseUrl());
        die;
    } catch (Mage_Core_Model_Store_Exception $e) {
        require_once(self::getBaseDir() . DS . 'errors' . DS . '404.php');
        die;
    } catch (Exception $e) {
        self::printException($e);
        die;
    }
}

If you dig deeper into printException you can see that it decides if dev mode is activated or not. If it's activated it'll just output the exception and in production mode prepare the data and include errors/report.php.

public static function printException(Exception $e, $extra = '')
{
    if (self::$_isDeveloperMode) {
        print '<pre>';

        if (!empty($extra)) {
            print $extra . "\n\n";
        }

        print $e->getMessage() . "\n\n";
        print $e->getTraceAsString();
        print '</pre>';
    } else {

        $reportData = array(
            !empty($extra) ? $extra . "\n\n" : '' . $e->getMessage(),
            $e->getTraceAsString()
        );

        // retrieve server data
        if (isset($_SERVER)) {
            if (isset($_SERVER['REQUEST_URI'])) {
                $reportData['url'] = $_SERVER['REQUEST_URI'];
            }
            if (isset($_SERVER['SCRIPT_NAME'])) {
                $reportData['script_name'] = $_SERVER['SCRIPT_NAME'];
            }
        }

        // attempt to specify store as a skin
        try {
            $storeCode = self::app()->getStore()->getCode();
            $reportData['skin'] = $storeCode;
        }
        catch (Exception $e) {}

        require_once(self::getBaseDir() . DS . 'errors' . DS . 'report.php');
    }

    die();
}

errors/reports.php itself just calls the processor and stores the report:

require_once 'processor.php';

$processor = new Error_Processor();

if (isset($reportData) && is_array($reportData)) {
    $processor->saveReport($reportData);
}

$processor->processReport();

So, but where is the exception.log coming from? That's written when Mage::logException is called:

public static function logException(Exception $e)
{
    if (!self::getConfig()) {
        return;
    }
    $file = self::getStoreConfig('dev/log/exception_file');
    self::log("\n" . $e->__toString(), Zend_Log::ERR, $file);
}

An that static function is manually called in over 100 plcaes over the Magento Core, especially when an exception is catched, should be logged, but not thrown to the top of Mage::init to continue the current process.