├── modman ├── app ├── code │ └── community │ │ └── Aleron75 │ │ └── Magemonolog │ │ ├── Model │ │ ├── HandlerWrapper │ │ │ ├── HandlerInterface.php │ │ │ ├── NewRelicHandler.php │ │ │ ├── NativeMailHandler.php │ │ │ ├── StreamHandler.php │ │ │ └── AbstractHandler.php │ │ └── Logwriter.php │ │ ├── Helper │ │ └── Data.php │ │ └── etc │ │ └── config.xml └── etc │ └── modules │ └── Aleron75_Magemonolog.xml ├── composer.json └── README.md /modman: -------------------------------------------------------------------------------- 1 | # Aleron75_Magemonolog definition 2 | app/etc/modules/*.xml app/etc/modules/ 3 | app/code/community/Aleron75/* app/code/community/Aleron75/ 4 | -------------------------------------------------------------------------------- /app/code/community/Aleron75/Magemonolog/Model/HandlerWrapper/HandlerInterface.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | true 6 | community 7 | 8 | 9 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aleron75/magemonolog", 3 | "description": "A Magento extension to transparently use Monolog as logging library.", 4 | "type": "magento-module", 5 | "license": "OSL-3.0", 6 | "authors": [ 7 | { 8 | "name": "Alessandro Ronchi", 9 | "email": "aleron75@gmail.com" 10 | } 11 | ], 12 | "require": { 13 | "magento-hackathon/magento-composer-installer": "*", 14 | "firegento/psr0autoloader": "*", 15 | "monolog/monolog": "*" 16 | }, 17 | "repositories": [ 18 | { 19 | "type": "composer", 20 | "url": "http://packages.firegento.com" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /app/code/community/Aleron75/Magemonolog/Model/HandlerWrapper/NewRelicHandler.php: -------------------------------------------------------------------------------- 1 | _validateArgs($args); 11 | $this->_handler = new NewRelicHandler( 12 | $args['level'], 13 | $args['bubble'], 14 | $args['appname'] 15 | ); 16 | } 17 | 18 | protected function _validateArgs(array &$args) 19 | { 20 | parent::_validateArgs($args); 21 | 22 | // Appname 23 | $appname = ''; 24 | if (isset($args['appname'])) 25 | { 26 | $appname = trim($args['appname']); 27 | } 28 | $args['appname'] = $appname; 29 | } 30 | } -------------------------------------------------------------------------------- /app/code/community/Aleron75/Magemonolog/Model/HandlerWrapper/NativeMailHandler.php: -------------------------------------------------------------------------------- 1 | _validateArgs($args); 11 | $this->_handler = new NativeMailerHandler( 12 | $args['to'], 13 | $args['subject'], 14 | $args['from'], 15 | $args['level'], 16 | $args['bubble'], 17 | $args['maxColumnWidth'] 18 | ); 19 | } 20 | 21 | protected function _validateArgs(array &$args) 22 | { 23 | parent::_validateArgs($args); 24 | 25 | // To 26 | $args['to'] = array_map('trim', explode(',', $args['to'])); 27 | 28 | // Subject 29 | $args['subject'] = trim($args['subject']); 30 | 31 | // From 32 | $args['from'] = trim($args['from']); 33 | 34 | // Max Column Width 35 | $maxColumnWidth = null; 36 | if (isset($args['maxColumnWidth']) && is_numeric($args['maxColumnWidth'])) 37 | { 38 | $maxColumnWidth = filter_var($args['maxColumnWidth'], FILTER_VALIDATE_INT); 39 | } 40 | $args['maxColumnWidth'] = $maxColumnWidth; 41 | } 42 | } -------------------------------------------------------------------------------- /app/code/community/Aleron75/Magemonolog/Model/HandlerWrapper/StreamHandler.php: -------------------------------------------------------------------------------- 1 | _validateArgs($args); 11 | $this->_handler = new StreamHandler( 12 | $args['stream'], 13 | $args['level'], 14 | $args['bubble'], 15 | $args['filePermission'], 16 | $args['useLocking'] 17 | ); 18 | } 19 | 20 | protected function _validateArgs(array &$args) 21 | { 22 | parent::_validateArgs($args); 23 | 24 | // Stream 25 | $file = Mage::getStoreConfig('dev/log/file'); 26 | if (isset($args['stream'])) 27 | { 28 | $file = $args['stream']; 29 | } 30 | $logDir = Mage::getBaseDir('var') . DS . 'log'; 31 | $logFile = $logDir . DS . $file; 32 | $args['stream'] = $logFile; 33 | 34 | // File Permission 35 | $filePermission = null; 36 | if (isset($args['filePermission']) && is_numeric($args['filePermission'])) 37 | { 38 | $filePermission = filter_var($args['filePermission'], FILTER_VALIDATE_INT); 39 | } 40 | $args['filePermission'] = $filePermission; 41 | 42 | // Use Locking 43 | $useLocking = false; 44 | if (isset($args['useLocking'])) 45 | { 46 | $useLocking = filter_var($args['useLocking'], FILTER_VALIDATE_BOOLEAN); 47 | } 48 | $args['useLocking'] = $useLocking; 49 | } 50 | } -------------------------------------------------------------------------------- /app/code/community/Aleron75/Magemonolog/Model/HandlerWrapper/AbstractHandler.php: -------------------------------------------------------------------------------- 1 | _handler; 48 | } 49 | 50 | /** 51 | * @param \Monolog\Formatter\FormatterInterface $formatter 52 | */ 53 | public function setFormatter(\Monolog\Formatter\FormatterInterface $formatter) 54 | { 55 | if ($this->_handler) { 56 | $this->_handler->setFormatter($formatter); 57 | } 58 | } 59 | 60 | } -------------------------------------------------------------------------------- /app/code/community/Aleron75/Magemonolog/etc/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 0.3.0 6 | 7 | 8 | 9 | 10 | 11 | Aleron75_Magemonolog_Model 12 | 13 | 14 | 15 | 16 | Aleron75_Magemonolog_Helper 17 | 18 | 19 | 20 | 21 | Aleron75_Magemonolog_Model_Logwriter 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 1 30 | 31 | magemonolog.log 32 | DEBUG 33 | true 34 | null 35 | false 36 | 37 | 38 | LogstashFormatter 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 0 50 | 51 | dummy@example.com 52 | Log 53 | dummy@example.com 54 | ERROR 55 | true 56 | 70 57 | 58 | 59 | 60 | 0 61 | 62 | ERROR 63 | true 64 | ***your app name here*** 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /app/code/community/Aleron75/Magemonolog/Model/Logwriter.php: -------------------------------------------------------------------------------- 1 | _logFile = $logFile; 27 | 28 | // Force autoloading 29 | Mage::dispatchEvent('add_spl_autoloader'); 30 | 31 | // Initialize level mapping only after the Logger class is loaded 32 | $this->__initLevelMapping(); 33 | 34 | $this->_logger = new Logger('monolog'); 35 | 36 | $handlers = Mage::getStoreConfig('magemonolog/handlers'); 37 | 38 | if (!is_null($handlers) && is_array($handlers)) 39 | { 40 | foreach ($handlers as $handlerModel => $handlerValues) 41 | { 42 | $isActive = Mage::getStoreConfigFlag('magemonolog/handlers/'.$handlerModel.'/active'); 43 | if (!$isActive) 44 | { 45 | continue; 46 | } 47 | 48 | $args = array(); 49 | if (array_key_exists('params', $handlerValues)) 50 | { 51 | $args = $handlerValues['params']; 52 | if (!empty($this->_logFile)){ 53 | $logFileParts = explode(DS,$this->_logFile); 54 | $args['stream'] = array_pop($logFileParts); 55 | } 56 | } 57 | 58 | $handlerWrapper = Mage::getModel('aleron75_magemonolog/handlerWrapper_'.$handlerModel, $args); 59 | 60 | if (array_key_exists('formatter', $handlerValues) 61 | && array_key_exists('class', $handlerValues['formatter'])) 62 | { 63 | $class = new ReflectionClass('\\Monolog\Formatter\\'.$handlerValues['formatter']['class']); 64 | $formatter = $class->newInstanceArgs($handlerValues['formatter']['args']); 65 | $handlerWrapper->setFormatter($formatter); 66 | } 67 | 68 | $this->_logger->pushHandler($handlerWrapper->getHandler()); 69 | } 70 | } 71 | } 72 | 73 | /** 74 | * Initialize the array used to map Zend's log levels into Monolog's 75 | */ 76 | private function __initLevelMapping() 77 | { 78 | $this->_levelMap = array( 79 | Zend_Log::EMERG => Logger::EMERGENCY, 80 | Zend_Log::ALERT => Logger::ALERT, 81 | Zend_Log::CRIT => Logger::CRITICAL, 82 | Zend_Log::ERR => Logger::ERROR, 83 | Zend_Log::WARN => Logger::WARNING, 84 | Zend_Log::NOTICE => Logger::NOTICE, 85 | Zend_Log::INFO => Logger::INFO, 86 | Zend_Log::DEBUG => Logger::DEBUG, 87 | ); 88 | } 89 | 90 | /** 91 | * Write a message using Monolog. 92 | * 93 | * @param array $event event data 94 | * @return void 95 | */ 96 | protected function _write($event) 97 | { 98 | $level = $this->_levelMap[$event['priority']]; 99 | $message = $event['message']; 100 | $this->_logger->addRecord($level, $message); 101 | } 102 | 103 | /** 104 | * Create a new instance of Aleron75_Magemonolog_Model_Logwriter 105 | * 106 | * @param array|Zend_Config $config 107 | * @return Aleron75_Magemonolog_Model_Logwriter 108 | * @throws Zend_Log_Exception 109 | */ 110 | static public function factory($config) 111 | { 112 | return new self(self::_parseConfig($config)); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | magemonolog 2 | =========== 3 | 4 | Facts 5 | ----- 6 | Version: 0.2.2 7 | Developed (and tested) on Magento CE v 1.8.1.0 8 | 9 | Introduction 10 | ------------ 11 | 12 | A Magento extension which provides a custom writer model to transparently use 13 | Monolog as logging library. 14 | 15 | The following Monolog's Handlers are supported at the moment: 16 | 17 | * `StreamHandler` - writes to file 18 | * `NativeMailHandler` - sends each log entry via email 19 | * `NewRelicHandler` - logs in NewRelic app 20 | 21 | Installation 22 | ------------ 23 | 24 | You can install this extension in several ways: 25 | 26 | **Download** 27 | 28 | Download the full package, copy the content of the `app` directory 29 | in your Magento base directory; pay attention not to overwrite 30 | the `app` folder, only merge its contents into existing directory; 31 | 32 | **Modman** 33 | 34 | Install modman Module Manager: https://github.com/colinmollenhour/modman 35 | 36 | After having installed modman on your system, you can clone this module on your 37 | Magento base directory by typing the following command: 38 | 39 | $ modman init 40 | $ modman clone git@github.com:aleron75/magemonolog.git 41 | 42 | **Composer** 43 | 44 | Install composer: http://getcomposer.org/download/ 45 | 46 | Install Magento Composer: https://github.com/magento-hackathon/magento-composer-installer 47 | 48 | Type the following command: 49 | 50 | $ php composer.phar require aleron75/magemonolog:dev-master 51 | 52 | or 53 | 54 | $ composer require aleron75/magemonolog:dev-master 55 | 56 | **Common tasks** 57 | 58 | After installation: 59 | 60 | * if you have cache enabled, disable or refresh it; 61 | * if you have compilation enabled, disable it or recompile the code base. 62 | 63 | Usage example 64 | ------------- 65 | Once installed, the module automatically replaces the default Magento Log Writer 66 | with Monolog's StreamHandler. 67 | 68 | This is obtained through the following config node in `config.xml`: 69 | 70 | 71 | 72 | 73 | 74 | Aleron75_Magemonolog_Model_Logwriter 75 | 76 | 77 | 78 | 79 | 80 | which instructs Magento to use a custom log writer class when logging via the 81 | `Mage::log()` native static function. 82 | 83 | The configured `Aleron75_Magemonolog_Model_Logwriter` class is a wrapper for 84 | Monolog and allows to use Monolog's Handlers. 85 | 86 | Monolog's Handlers are configured in the `config.xml` through the following 87 | config node: 88 | 89 | 90 | 91 | 92 | 93 | 94 | 1 95 | 96 | magemonolog.log 97 | DEBUG 98 | true 99 | null 100 | false 101 | 102 | 103 | 104 | 0 105 | 106 | dummy@example.com 107 | Log 108 | dummy@example.com 109 | ERROR 110 | true 111 | 70 112 | 113 | 114 | 115 | 0 116 | 117 | ERROR 118 | true 119 | ***your app name here*** 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | It is assumed you know Monolog's Handlers to understand the meaning of `params` 128 | node. 129 | 130 | Multiple Log Handlers can be activated at the same time with different log 131 | filter level; this way, for example, it is possible to log any message into a 132 | file and only serious errors via e-mail. 133 | 134 | You can also use Monolog's Formatters like shown below: 135 | 136 | 137 | 138 | 139 | 140 | 141 | 1 142 | 143 | magemonolog.log 144 | DEBUG 145 | true 146 | null 147 | false 148 | 149 | 150 | LogstashFormatter 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | The `` tag should contain proper Formatter's contructor arguments. Arguments' tag name is not important, values 166 | are passed to Formatter's constructor in the exact order the constructor requires them. You should consult Formatter's 167 | constructor signature to know which are its arguments, their meaning and their order. 168 | 169 | Closing words 170 | ------------- 171 | Any feedback is appreciated. 172 | 173 | This extension is published under the [Open Software License (OSL 3.0)](http://opensource.org/licenses/OSL-3.0). 174 | 175 | Any contribution or feedback is extremely appreciated. 176 | --------------------------------------------------------------------------------