I've just discovered that my application is logging Notices in debug.log instead of error.log. All notices seem to be prefixed with "Debug: ", e.g.:
2014-07-25 14:10:50 Debug: Notice (8):
Debug is set to 0 in core.php. I'm using a custom error handler, configured in core.php:
Configure::write('Error', array(
'handler' => 'MyErrorHandler::handleError',
'level' => E_ALL & ~E_DEPRECATED & ~E_STRICT,
'trace' => true,
'api' => false
));
I have this in bootstrap.php:
App::uses('MyErrorHandler', 'Lib');
App::uses('CakeLog', 'Log');
CakeLog::config('debug', array(
'engine' => 'FileLog',
'types' => array('info', 'debug'),
'file' => 'debug',
));
CakeLog::config('error', array(
'engine' => 'FileLog',
'types' => array('warning', 'error', 'critical', 'alert', 'emergency', 'notice'),
'file' => 'error',
));
If I move 'debug' from the debug config to the error config, debug messages go to error.log, but then so does the output from Debugger:log().
The issue seems to be that the notices are being prefixed with "Debug". Any ideas?
Update See answer from @ndm Here is the code I used in my custom mapErrorCode function to help resolve this:
case E_NOTICE:
case E_USER_NOTICE:
$error = 'Notice';
$levels = array_flip(CakeLog::levels());
$log = ( isset($levels['notice']) ? $levels['notice'] : LOG_NOTICE );
The problem
As mentioned in my comment, this behavior is caused by
LOG_DEBUGandLOG_NOTICEholding the same value (6) on Windows systems, some people in the PHP team thought it might be funny to handle the OS differences (Windows doesn't have that many levels) exposed at user level, instead of translating the values internally.https://bugs.php.net/bug.php?id=18090
Internally
CakeLoguses an error type (string) to error level (int) map, which is being flipped to create a map to retrieve the type by level, and so you'll end up with a map that looks likewhich will cause
LOG_DEBUG,LOG_NOTICEandLOG_INFOlevels to be treated asdebugtypes, as they are all holding the value6.A possible workaround
Working around this problem should be possible, but it might have some caveats. You could override the levels in
CakeLogusingCakeLog::levels()so that the types have individual levels:would result in a map like
Finally you'd need to use a custom error handler which maps the error codes to the proper levels, see
ErrorHandler::mapErrorCode(), by default notices are mapped toLOG_NOTICE(6), which you'd want to be5instead.The problem with that might be
While this might work for PHP errors (like for example notices about undefined variables and the like) that are flowing through the error handler, and custom calls to
CakeLog::write()where you are explicitly passing the appropriate level, you may run into problems where the core or a plugin callsCakeLog::write()and passes hard-codedLOG_*constants, which would most likely cause the types to be written into the wrong log again.However as far as I can tell the only place where such calls to
CakeLog::write()appear in the core (yet), is in the error handler, so overriding this might do it for now.