Search Results for "Rolling File"

Novembro 26th 2008

Rolling File utilizando Zend_Log

Alguém já se perguntou porque diabos o Zend_Log não divide os arquivos de logs em vários arquivos? Para quem utiliza ou já utilizou o Log4PHP sabe do que estou falando. Aquela história, o arquivo de log ultrapassou 1MB por ex., é gerado um novo arquivo com o mesmo nome com um sufixo .1 (ex.: aplicacao.log.1) com os logs antigos, e os novos logs são inseridor no arquivo aplicacao.log.

Pois é, dei uma pesquisada sobre isso, alguns dizem que essa funcionalidade não é função do log... que existem outras aplicações que fazem isso... etc,etc. A questão é que isto não foi inserido no framework.

Discução: http://framework.zend.com/issues/browse/ZF-263

Então resolvi fazer uma classe para tratar isso, andei olhando como o Log4PHP faz, e adaptei para o Zend_Log.

PHP:
  1. <?php
  2.  
  3. require_once 'Zend/Log/Writer/Abstract.php';
  4. require_once 'Zend/Log/Formatter/Simple.php';
  5.  
  6. /**
  7.  * @package    Log
  8.  * @author     Diego Tremper <diegotremper@gmail.com>
  9.  */
  10. class Log_Writer_Rolling_File extends Zend_Log_Writer_Abstract {
  11.    
  12.     /**
  13.      * Holds the PHP stream to log to.
  14.      * @var null|stream
  15.      */
  16.     protected $_stream = null;
  17.    
  18.     /**
  19.      * default 1MB
  20.      */
  21.     protected $fileMaxSize = 1048576;
  22.    
  23.     protected $maxFiles = 10;
  24.    
  25.     protected $_filename = null;
  26.    
  27.     /**
  28.      * Class Constructor
  29.      *
  30.      * @param  streamOrUrl     Stream or URL to open as a stream
  31.      * @param  mode            Mode, only applicable if a URL is given
  32.      */
  33.     public function __construct($streamOrUrl, $mode = 'a') {
  34.         if (is_resource ( $streamOrUrl )) {
  35.             $stream_data = stream_get_meta_data ( $streamOrUrl );
  36.            
  37.             if (get_resource_type ( $streamOrUrl ) != 'plainfile') {
  38.                 require_once 'Zend/Log/Exception.php';
  39.                 throw new Zend_Log_Exception ( 'Resource is not a plainfile' );
  40.             }
  41.            
  42.             if ($mode != 'a') {
  43.                 require_once 'Zend/Log/Exception.php';
  44.                 throw new Zend_Log_Exception ( 'Mode cannot be changed on existing streams' );
  45.             }
  46.            
  47.             $filename = $stream_data ['uri'];
  48.             $this->_stream = $streamOrUrl;
  49.         } else {
  50.             if (! $this->_stream = @fopen ( $streamOrUrl, $mode, false )) {
  51.                 $msg = "\"$streamOrUrl\" cannot be opened with mode \"$mode\"";
  52.                 require_once 'Zend/Log/Exception.php';
  53.                 throw new Zend_Log_Exception ( $msg );
  54.             }
  55.            
  56.             $filename = $streamOrUrl;
  57.         }
  58.        
  59.         $this->_fileName = $filename;
  60.        
  61.         fseek ( $this->_stream, filesize ( $this->_fileName ) - 1 );
  62.        
  63.         $this->_formatter = new Zend_Log_Formatter_Simple ( );
  64.     }
  65.    
  66.     /**
  67.      * @return int
  68.      */
  69.     public function getFileMaxSize() {
  70.         return $this->fileMaxSize;
  71.     }
  72.    
  73.     /**
  74.      * Set the maximum size that the output file is allowed to reach
  75.      * before being rolled over to backup files.
  76.      *
  77.      * The maxFileSize option takes an long integer in the range 0 - 2^63.
  78.      * You can specify the value with the suffixes "KB", "MB" or "GB"
  79.      * so that the integer is interpreted being expressed respectively
  80.      * in kilobytes, megabytes or gigabytes. For example, the value "10KB"
  81.      * will be interpreted as 10240.
  82.      *
  83.      * @param int|string $fileMaxSize
  84.      */
  85.     public function setFileMaxSize($fileMaxSize) {
  86.         if (is_string($fileMaxSize)) {
  87.             $this->fileMaxSize = $this->_convertMaxFileSize($fileMaxSize);
  88.         } else {
  89.             $this->fileMaxSize = $fileMaxSize;
  90.         }
  91.     }
  92.    
  93.     /**
  94.      * @return int
  95.      */
  96.     public function getMaxFiles() {
  97.         return $this->maxFiles;
  98.     }
  99.    
  100.     /**
  101.      * @param int $maxFiles
  102.      */
  103.     public function setMaxFiles($maxFiles) {
  104.         $this->maxFiles = $maxFiles;
  105.     }
  106.    
  107.     /**
  108.      * Close the stream resource.
  109.      *
  110.      * @return void
  111.      */
  112.     public function shutdown() {
  113.         if (is_resource ( $this->_stream )) {
  114.             fclose ( $this->_stream );
  115.         }
  116.     }
  117.    
  118.     /**
  119.      * Write a message to the log.
  120.      *
  121.      * @param  array  $event  event data
  122.      * @return void
  123.      */
  124.     protected function _write($event) {
  125.         $line = $this->_formatter->format ( $event );
  126.        
  127.         if (false === @fwrite ( $this->_stream, $line )) {
  128.             require_once 'Zend/Log/Exception.php';
  129.             throw new Zend_Log_Exception ( "Unable to write to stream" );
  130.         }
  131.        
  132.         if (ftell ( $this->_stream )> $this->fileMaxSize)
  133.             $this->_rollOver ();
  134.     }
  135.    
  136.     protected function _rollOver() {
  137.         if ($this->maxFiles> 0) {
  138.             $file = $this->_fileName . '.' . $this->maxFiles;
  139.            
  140.             if (is_writable ( $file ))
  141.                 unlink ( $file );
  142.            
  143.             for($i = $this->maxFiles - 1; $i>= 1; $i --) {
  144.                 $file = $this->_fileName . '.' . $i;
  145.                 if (is_readable ( $file )) {
  146.                     $target = $this->_fileName . '.' . ($i + 1);
  147.                     rename ( $file, $target );
  148.                 }
  149.             }
  150.            
  151.             $target = $this->_fileName . '.1';
  152.            
  153.             $this->shutdown ();
  154.            
  155.             rename ( $this->_fileName, $target );
  156.         }
  157.        
  158.         $this->__construct ( $this->_fileName, 'w' );
  159.     }
  160.    
  161.     /**
  162.      * Convert maxFileSize value
  163.      *
  164.      * @param mixed $value
  165.      */
  166.     private function _convertMaxFileSize($value) {
  167.         $maxFileSize = null;
  168.         $numpart = substr ( $value, 0, strlen ( $value ) - 2 );
  169.         $suffix = strtoupper ( substr ( $value, - 2 ) );
  170.        
  171.         switch ($suffix) {
  172.             case 'KB' :
  173.                 $maxFileSize = ( int ) (( int ) $numpart * 1024);
  174.                 break;
  175.             case 'MB' :
  176.                 $maxFileSize = ( int ) (( int ) $numpart * 1024 * 1024);
  177.                 break;
  178.             case 'GB' :
  179.                 $maxFileSize = ( int ) (( int ) $numpart * 1024 * 1024 * 1024);
  180.                 break;
  181.             default :
  182.                 require_once 'Zend/Log/Exception.php';
  183.                 throw new Zend_Log_Exception ( 'Invalid size' );
  184.         }
  185.        
  186.         return $maxFileSize;
  187.     }
  188.  
  189. }

Para testar:

PHP:
  1. <?php
  2.  
  3. require 'Zend/Log.php';
  4. require 'Log/Writer/Rolling/File.php';
  5.  
  6. $writer = new Log_Writer_Rolling_File('aplicacao.log');
  7. $writer->setFileMaxSize("10KB");
  8. $writer->setMaxFiles(10);
  9. $logger = new Zend_Log($writer);
  10.  
  11. for ($i=0; $i<1000; $i++) {
  12.     $logger->debug('Este é um debug para teste de rolling file utilizando zend_log : ' . $i);
  13. }

Para quem quiser os arquivos, segue o link: rolling_file_zend_log.

[]s

No Comments yet »