Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Code Igniter logging too much

In my CI config file I have this logging treshold set:

$config['log_threshold'] = 1;

In index.php, I have set the following error reporting:

error_reporting(E_ERROR);

My expectation is that this will log any CI errors that I log (using log_message('error','my error message')), as well as any PHP errors. However, I would expect that it will not log PHP notices, only errors. However, when I look at the log files, it seems to log PHP notices too:

ERROR - 2009-12-18 13:21:50—> Severity: Notice —> Undefined variable: pageindex /var/www/apps/OS4W/system/application/views/user/view.php 12
ERROR - 2009-12-18 13:21:50—> Severity: Notice —> Undefined variable: friendsmode /var/www/apps/OS4W/system/application/views/user/activitytable.php 207

Although the log lines start with “ERROR”, in reality this seems to be a PHP notice, kind of like a warning, that I do not want to log. How can I make sure only CI and PHP errors are logged, yet not PHP notices? I thought error_reporting(E_ERROR) would do just that?

like image 347
Fer Avatar asked Dec 18 '09 15:12

Fer


4 Answers

According to the PHP error reporting docs at http://us2.php.net/manual/en/errorfunc.configuration.php#ini.error-reporting

In PHP 4 and PHP 5 the default value is E_ALL & ~E_NOTICE. This setting does not show E_NOTICE level errors. You may want to show them during development.

I'd try changing your error_reporting() to "E_ALL & ~E_NOTICE" and see if that works.

Dana

Edit: Well, I spoke too soon. I tried this and it stopped the notice from showing up on screen, but still logged it to the log file.

Solution:

OK I think I figured this out. In the common.php file there's a function called "_exception_handler" that handles the logging process. It does some bitwise comparisons of the current severity level and the error_reporting level to see if it should log to the screen, but it does not do so for logging to the log file. IT just passes everything through except for E_STRICT messages which it tosses regardless.

What you can do is wrap the very last line in this function with the same IF statement they use for logging to the screen. So the entire function becomes:

function _exception_handler($severity, $message, $filepath, $line)
{   
 // We don't bother with "strict" notices since they will fill up
 // the log file with information that isn't normally very
 // helpful.  For example, if you are running PHP 5 and you
 // use version 4 style class functions (without prefixes
 // like "public", "private", etc.) you'll get notices telling
 // you that these have been deprecated.

if ($severity == E_STRICT)
{
    return;
}

$error =& load_class('Exceptions');

// Should we display the error?
// We'll get the current error_reporting level and add its bits
// with the severity bits to find out.  
if (($severity & error_reporting()) == $severity)
{
    $error->show_php_error($severity, $message, $filepath, $line);
}

// Should we log the error?  No?  We're done...
$config =& get_config();
if ($config['log_threshold'] == 0)
{
    return;
}

if (($severity & error_reporting()) == $severity)
{
    $error->log_exception($severity, $message, $filepath, $line);
}
}

and I think that will take care of it. Then you can use

error_reporting(E_ALL & ~E_NOTICE);

in your index.php. Of course we're editing the core here. Maybe there's a way to override instead?

Dana

like image 142
Dana Avatar answered Nov 17 '22 14:11

Dana


First of all, thank you all for thinking along. After considering your advise, I decided to patch the core of CI. Unfortunately, the core classes can be extended, but not the core itself. Therefore if you apply the same patch, be sure to document it.

Here goes. In system\application\config\config.php I added the following custom config setting right below the log_treshold setting:

/*
|--------------------------------------------------------------------------
| Error Logging Exclusions (custom config addition by Ferdy Christant)
|--------------------------------------------------------------------------
|
| By default, CI will log all PHP errors, whether it is a notice, warning
| or error. Or, by setting the above treshold to 0, it will log nothing
| In most cases, however, you will want to log PHP errors but not the notices
| In the array below, simply place the PHP error constant that you do NOT
| want to see logged. 
|
| For a live site you'll usually use the config as follow:
|
| $config['exclude_logging'] = array(E_STRICT,E_NOTICE);
|
*/

$config['exclude_logging'] = array(E_STRICT,E_NOTICE);

As the documentation explains, in this config array you put the PHP error types that you do NOT want to log.

Next, I have patched the core file (system/codeigniter/Common.php) and edited the function _exception_handler

There are two changes. First, I moved the config loading line to the top of the method, since I need it earlier. Find the line below and you will see $config =& get_config(); under it. Delete that.

I removed the // Should we log the error? No? We're done...

Second, the check for severity is modified to check for the array that we declared. Go to the top of the method and replace the if statement that checks $severity == E_STRICT with below:

$config =& get_config();
if (in_array($severity,$config['exclude_logging']))
{
return;
}

These patches allow for fine-grained control over PHP error logging. Normal CI logging will of course still work. As mentioned, the only downside is that this patches the core.

I hope this helps anyone. Thank you for thinking along!

like image 31
Fer Avatar answered Nov 17 '22 14:11

Fer


For anyone else that might come across this with CodeIgniter 2.0. The problem is still the same, but the solution is "easier".

You still have to modify a core file: /system/codeigniter/Common.php

Find the _exception_handler() function (should be at the bottom), and change this line:

if ($severity == E_STRICT) to this: if ($severity == E_STRICT OR $severity == E_NOTICE)

Funny how they think E_STRICT notices will fill up the log; but E_NOTICE won't. Or maybe it's good to punish people for not coding strictly and declaring all their variables before using them? :)

like image 6
drewjoh Avatar answered Nov 17 '22 13:11

drewjoh


try this, no need to patch CI core:

$hook['pre_controller'] = array(
    'class'    => 'MY_Commonfunction_hook',
    'function' => 'hook',
    'filename' => 'MY_Commonfunction_hook.php',
    'filepath' => 'hooks');

class MY_Commonfunction_hook {
    public function hook() {
        set_error_handler('_my_exception_handler');
    }
}

function _my_exception_handler($severity, $message, $filepath, $line) {
    if ($severity == E_STRICT) {
        return;
    }
    $_error = & load_class('Exceptions', 'core');
    if (($severity & error_reporting()) == $severity) {
        for ($i = ob_get_level(); $i > 0; $i--) {
            @ob_end_clean();
        }
        $_error->show_php_error($severity, $message, $filepath, $line);
    }
    if (config_item('log_threshold') == 0) {
        return;
    }
    if (($severity & error_reporting()) == $severity) {
        $_error->log_exception($severity, $message, $filepath, $line);
    }
}
like image 2
lsave Avatar answered Nov 17 '22 13:11

lsave