views:

1201

answers:

4

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?

+1  A: 

You need just one underscore in the error_reporting method call that PHP doesn't report those notices:

error_reporting(E_ERROR);

Code Igniter will treat any error from PHP (whether it's a notice, warning, or fatal error, etc.) as an error in your CI logs.

Edit: Nevermind, just saw your comment. Not sure what's going on with your error reporting.

Coomer
Your answer still is interesting, specifically where you say "Code Igniter will treat any error from PHP (whether it's a notice, warning, or fatal error, etc.) as an error in your CI logs.". Am I crazy or is this highly undesired behavior of CI? This kind of make it an all or nothing deal: Either log a ton or log nothing at all, not even an error. Correct me if I'm wrong but it seems that CI this way severely handicaps PHP's error reporting.
Ferdy
This is set with a config option, everything or nothing is incorrect. Where did you hear this?
Phil Sturgeon
I did not "hear" this, I know it. I have tested and debugged it and that is how CI works. The config option you talk about controls CI errors, not PHP errors. It will either log all PHP errors or none at all. CI errors you can control using that config setting.
Ferdy
+1  A: 

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

Dana
For normal PHP, I think this is correct, but I think Code Igniter sees all PHP errors (whether a notice or actual error) as the same and will log all or nothing.
Ferdy
Yeah, I've been playing with it this morning. Tried changing it at the server level but CI ignores those. Can't see any way around it except maybe digging into CI core.
Dana
Ferdy
Dana
A: 

I've always just modified that logging library of CodeIgniter. Ferdy is correct when he says CI will log either everything or nothing. It's very undesired.

Zack
Thanks for confirming!
Ferdy
+1  A: 

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). There are two changes. First, I moved the config loading line to the top of the method, since I need it earlier. Second, the check for severity is modified to check for the array that we declared:

$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!

Ferdy
Thanks for sharing this Ferdy!
Dana