Using Log4php in Magento Applications

    Magento is without a doubt an outstanding system for building e-commerce applications. The principles laid down in its architecture made it possible not only to take the first place in the rating in its class of web applications and hold it for many years, but, more importantly, to form an eco-system of developers around itself, creating extensions for the main functionality that satisfy the most exotic requirements users. But what I strongly greatly lacking in Magento during the first "approach to the projectile," so it is a system-level logging Log4php . Therefore, the first extension that was made for Magento is the “wrapper” for Log4php. Under the cut is a description of how we use this “wrapper” in our Magento projects.


    “Wrap” for “Wrap”


    To reduce the dependence of our other modules on Praxigento_Log, each of our modules contains its own logger, which, depending on the configuration of the Magento application, uses either the "native" Magento-logger or Log4php if the Praxigento_Log module is installed.

    Here is the code for this wrapper
    class Praxigento_Module_Logger
    {
        private static $_isLog4phpUsed = null;
        private $_loggerLog4php;
        private $_name;
        function __construct($name)
        {
            /**
             * switch off/on error reporting to prevent messages like
             * "ERR (3): Warning: include(Praxigento\Log\Logger.php): failed to open stream: No such file or directory"
             * in case of Praxigento_Log module is not used.
             */
            $level = error_reporting(0);
            self::$_isLog4phpUsed = class_exists('Praxigento_Log_Logger', true);
            error_reporting($level);
            if (self::$_isLog4phpUsed) {
                $this->_loggerLog4php = Praxigento_Log_Logger::getLogger($name);
            } else {
                $this->_name = is_object($name) ? get_class($name) : (string)$name;
            }
        }
        /**
         * Override getter to use '$log = Praxigento_Log_Logger::getLogger($this)' form in Mage classes.
         */
        public static function getLogger($name)
        {
            $class = __CLASS__;
            return new $class($name);
        }
        public function debug($message, $throwable = null)
        {
            $this->doLog($message, $throwable, 'debug', Zend_Log::INFO);
        }
        /**
         * Internal dispatcher for the called log method.
         */
        private function doLog($message, $throwable, $log4phpMethod, $zendLevel)
        {
            if (self::$_isLog4phpUsed) {
                $this->_loggerLog4php->$log4phpMethod($message, $throwable);
            } else {
                Mage::log($this->_name . ': ' . $message, $zendLevel);
                if ($throwable instanceof Exception) {
                    Mage::logException($throwable);
                }
            }
        }
        public function error($message, $throwable = null)
        {
            $this->doLog($message, $throwable, 'error', Zend_Log::ERR);
        }
        public function fatal($message, $throwable = null)
        {
            $this->doLog($message, $throwable, 'fatal', Zend_Log::CRIT);
        }
        public function info($message, $throwable = null)
        {
            $this->doLog($message, $throwable, 'info', Zend_Log::NOTICE);
        }
        public function trace($message, $throwable = null)
        {
            $this->doLog($message, $throwable, 'trace', Zend_Log::DEBUG);
        }
        public function warn($message, $throwable = null)
        {
            $this->doLog($message, $throwable, 'warn', Zend_Log::WARN);
        }
    }
    



    This code is identical for all our modules (except for the name of the class itself) and allows you to use logging regardless of whether the application has the Praxigento_Log module or not. Here is a call example:

            $log = Praxigento_Module_Logger::getLogger(__CLASS__);
            $log->trace('trace level message');
            $log->debug('debug level message');
            $log->info('info level message');
            $log->warn('warn level message');
            $log->error('error level message');
            $log->fatal('fatal level message');
    


    And here are the logs themselves with the Praxigento_Log module (Log4php framework):
    2015/06/25 09:59:55,973 TRACE P\B\T\L\UnitTest: trace level message
    2015/06/25 09:59:55,973 DEBUG P\B\T\L\UnitTest: debug level message
    2015/06/25 09:59:55,974 INFO P\B\T\L\UnitTest: info level message
    2015/06/25 09:59:55,974 WARN P\B\T\L\UnitTest: warn level message
    2015/06/25 09:59:55,975 ERROR P\B\T\L\UnitTest: error level message
    2015/06/25 09:59:55,975 FATAL P\B\T\L\UnitTest: fatal level message
    


    ... and in its absence (Zend_Log framework, var / log / system.log file):
    2015-06-25T10:07:00+00:00 DEBUG (7): Praxigento_Bonus_Test_Logger_UnitTest: trace level message
    2015-06-25T10:07:00+00:00 INFO (6): Praxigento_Bonus_Test_Logger_UnitTest: debug level message
    2015-06-25T10:07:00+00:00 NOTICE (5): Praxigento_Bonus_Test_Logger_UnitTest: info level message
    2015-06-25T10:07:00+00:00 WARN (4): Praxigento_Bonus_Test_Logger_UnitTest: warn level message
    2015-06-25T10:07:00+00:00 ERR (3): Praxigento_Bonus_Test_Logger_UnitTest: error level message
    2015-06-25T10:07:00+00:00 CRIT (2): Praxigento_Bonus_Test_Logger_UnitTest: fatal level message
    


    Log4php Configuration


    Magento specifies the path to the Log4php configuration file :
    image
    in which all logging parameters are configured.

    Configuration example
    
        
         TRACE -> DEBUG -> INFO -> WARN -> ERROR -> FATAL -> OFF
                Available appenders:
                    http://logging.apache.org/log4php/docs/appenders.html
                    appenders/LoggerAppenderMemory
                Available layouts:
                    http://logging.apache.org/log4php/docs/layouts.html
        -->



    Bonuses Log4php



    Record Source


    When creating a logger, the name of the class in which this logger is used is used:
            $log = Praxigento_Module_Logger::getLogger(__CLASS__);
    

    as a result, in the logs you can distinguish messages of one class from messages of another. So for the Praxigento_Bonus_Test_Logger_UnitTest class, the message in the log will look something like this (depends on the logging settings):
    2015/06/25 09:59:55,973 TRACE P\B\T\L\UnitTest: trace level message
    

    which is convenient when you need to select messages from a particular class in the general stream:
    $ cat  ./var/log/old/log4php.log_20150623 | grep 'P\\B\\T\\L\\UnitTest'
    


    Differentiation by logging level and source


    Depending on the level selected in the configuration file, you can detail the output to the log depending on the load or in the event of a failure in the application. And you can pour in a separate log all messages from any class or group of classes:


    Email Alerts


    In case of errors (fatal, error, warn levels), you can send the corresponding log entries by email:


    In-memory logging


    An additional LoggerAppenderMemory class has been added to the original Log4php upders in the module, which allows access to logs from the Magento application:


    $log = Praxigento_Module_Logger::getLogger(__CLASS__);
    $log->debug('...');
    $debugLog = LoggerAppenderMemory::getEventsAsArray();
    




    In our applications, we use a similar approach if you have to start tasks from the admin panel, which are usually performed via cron. The list of log entries is simply displayed in the web interface with the required level of detail:


    Installation


    At the moment, we are using Composer to deploy our Magento projects , so a description of the installation is given for this method. Installation of the module is also possible through Magento Connect (there it goes under the previous name - Nmmlm_Log).

    To connect the module through Composer, you need to specify in the composer.json file:
    {
      "require": {
        "praxigento/mage_ext_log4php": "*"
      },
      "repositories": [
        {
          "type": "vcs",
          "url": "https://github.com/praxigento/mage_ext_log4php"
        }
      ]
    }
    


    You can also download the source code of the module, unzip it and copy the contents from the ./src/ directory to the root directory of your Magento application.

    Also popular now: