Welcome Guest, Not a member yet? Register   Sign In
Slow application, CodeIgniter Logs and Antivirus
#1

[eluser]tchule[/eluser]
Hello,

We have recently changed the antivirus we are using (from Norton to NOD32) and we have discovered that all our CodeIgniter applications were becoming very slow.

After some search, we've found out that the problem was that the Log class was opening and closing the log file for each line added, and the antivirus was scanning the file each time.

I'm done a very dirty hack that keep the file handler open between two logs, I'll post it here for info but it would be nice if a cleaner solution could be implemented in CodeIgniter.

Regards,

Code:
<?php if (!defined('BASEPATH'))
    exit('No direct script access allowed');
/**
* CodeIgniter
*
* An open source application development framework for PHP 4.3.2 or newer
*
* @package        CodeIgniter
* @author        ExpressionEngine Dev Team
* @copyright    Copyright (c) 2008, EllisLab, Inc.
* @license        http://ellislab.com/codeigniter/user-guide/license.html
* @link        http://codeigniter.com
* @since        Version 1.0
* @filesource
*/

// ------------------------------------------------------------------------

/**
* Logging Class
*
* @package        CodeIgniter
* @subpackage    Libraries
* @category    Logging
* @author        ExpressionEngine Dev Team
* @link        http://ellislab.com/codeigniter/user-guide/general/errors.html
*/
class CI_Log {

    var $log_path;
    var $_threshold = 1;
    var $_date_fmt = 'Y-m-d H:i:s';
    var $_enabled = TRUE;
    var $_levels = array('ERROR' => '1', 'DEBUG' => '2', 'INFO' => '3', 'ALL' => '4');
    var $currentDate;
    var $filehandler;

    /**
     * Constructor
     *
     * @access    public
     */
    function CI_Log() {
        $config =& get_config();

        $this->log_path = ($config['log_path'] != '') ? $config['log_path'] : BASEPATH.'logs/';

        if (!is_dir($this->log_path) OR !is_really_writable($this->log_path)) {
            $this->_enabled = FALSE;
        }

        if (is_numeric($config['log_threshold'])) {
            $this->_threshold = $config['log_threshold'];
        }

        if ($config['log_date_format'] != '') {
            $this->_date_fmt = $config['log_date_format'];
        }

        // Initialise the log file
        $this->createLogFile();
    }

    /**
     * Create a new log file.
     *
     * @return void
     */
    private function createLogFile() {
        $this->currentDate = date('Y-m-d'); // Store the date of the file
        $filepath = $this->log_path.'log-'.$this->currentDate.'.log';
        if (!$this->filehandler = @fopen($filepath, FOPEN_WRITE_CREATE)) {
            return FALSE;
        }
        @chmod($filepath, FILE_WRITE_MODE);
    }

    /**
     * Write Log File
     *
     * Generally this function will be called using the global log_message() function
     *
     * @access    public
     * @param    string    the error level
     * @param    string    the error message
     * @param    bool    whether the error is a native PHP error
     * @return    bool
     */
    function write_log($level = 'error', $msg, $php_error = FALSE) {
        if ($this->_enabled === FALSE) {
            return FALSE;
        }

        $level = strtoupper($level);

        if (!isset($this->_levels[$level]) OR ($this->_levels[$level] > $this->_threshold)) {
            return FALSE;
        }

        if ($this->currentDate != date('Y-m-d')) {
            // Re-initialise the log file because we have changed the date
            $this->createLogFile();
        }

        $message = $level.' '.(($level == 'INFO') ? ' -' : '-').' '.date($this->_date_fmt).' --> '.$msg."\n";

        fwrite($this->filehandler, $message);

        return TRUE;
    }

    /**
     * Class destructor.
     */
    public function __destruct() {
        fclose($this->filehandler);
    }

}
#2

[eluser]InsiteFX[/eluser]
You should be extending the class not modifing it!

What's going to happen when you move to CodeIgniter 2.0?

Enjoy
InsiteFX
#3

[eluser]antonagestam[/eluser]
I solved it in a very similar way. Guess it's kinda ugly too:

Code:
<?php
    /*
     * My try to make the log less memory eating
     */
    class CI_Log
    {
        private $filepath;
        private $fp;
        private $state=TRUE;
        
        var $log_path;
        var $_threshold    = 1;
        var $_date_fmt    = 'Y-m-d H:i:s';
        var $_enabled    = TRUE;
        var $_levels    = array('ERROR' => '1', 'DEBUG' => '2',  'INFO' => '3', 'ALL' => '4');
        
        function CI_Log()
        {
            $config =& get_config();
            
            $this->log_path = ($config['log_path'] != '') ? $config['log_path'] : BASEPATH.'logs/';
            
            if ( ! is_dir($this->log_path) OR ! is_really_writable($this->log_path))
            {
                $this->_enabled = FALSE;
            }
            
            if (is_numeric($config['log_threshold']))
            {
                $this->_threshold = $config['log_threshold'];
            }
                
            if ($config['log_date_format'] != '')
            {
                $this->_date_fmt = $config['log_date_format'];
            }
            
            if( $this->_enabled === FALSE )
            {
                return;
            }
            else
            {
                $this->filepath = $this->log_path.'log-'.date('Y-m-d').EXT;
                    
                if ( ! $this->fp = @fopen($this->filepath, FOPEN_WRITE_CREATE))
                {
                    $this->state = FALSE;
                    return;
                }
            }
        }
        
        function write_log($level = 'error', $msg, $php_error = FALSE)
        {
            if( $this->state === TRUE )
            {
                if ($this->_enabled === FALSE)
                {
                    return FALSE;
                }
            
                $level = strtoupper($level);
                
                if ( ! isset($this->_levels[$level]) OR ($this->_levels[$level] > $this->_threshold))
                {
                    return FALSE;
                }
            
                $message  = '';
                
                if ( ! file_exists($this->filepath))
                {
                    $message .= "<"."?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed'); ?".">\n\n";
                }
                
                $message .= $level.' '.(($level == 'INFO') ? ' -' : '-').' '.date($this->_date_fmt). ' --&gt; '.$msg."\n";
                
                flock($this->fp, LOCK_EX);
                fwrite($this->fp, $message);
                flock($this->fp, LOCK_UN);
                        
                return TRUE;
            }
            else
            {
                trigger_error("Could not open log file",E_USER_ERROR);
            }
        }
        
        function __destruct()
        {
            $this->write_log('debug','<strong>Log class uninitialized</strong>');
            fclose($this->fp);
            @chmod($this->filepath, FILE_WRITE_MODE);
        }
    }
#4

[eluser]WanWizard[/eluser]
Isn't it a lot easier to tell your virus scanner not to scan c:\www\codeigniter\data\logs\*.log (or whatever your path is)?
#5

[eluser]pickupman[/eluser]
[quote author="WanWizard" date="1274368197"]Isn't it a lot easier to tell your virus scanner not to scan c:\www\codeigniter\data\logs\*.log (or whatever your path is)?[/quote]
I agree. If you are running ant-vir on your server, you should only be scanning those folders in which might be accepting user input (./uploads folder). Hopefully your own system files should not contain viruses since they are your files.
#6

[eluser]antonagestam[/eluser]
Well I don't think my problem was that my virus scanner scanned through the files. But all the logging just took a lot of time. It might be because I have a slow pc.




Theme © iAndrew 2016 - Forum software by © MyBB