3

I've researched different methods and directives including:

  • auto_prepend_file
  • .user.ini files
  • getcwd()
  • debug_backtrace()

And I can't seem to find a way to change the path of the error_log to log in the same path as the file being included/required.

For example, say index.php has the line:

include('subdir/file.php');

If subdir/file.php has a syntax error, forcing php to create subdir/error_log, rather than the default behavior of creating error_log in the same path as index.php, auto_prepend_file suffers from this same limitation as it prepends the specified file before the first script called, rather than each file included.

I've looked around and can't seem to find a legitimate way to do this. I understand the implications of performance overhead by doing this, and plan to only use it for development purposes. I believe this can help isolate errors rather than using stack traces such as debug_backtrace(), as I can use a terminal script to show the last error logs by last modified, and find the offending files much quicker than reading through a massive error log.

My goal is ultimately not to have these files appear at all, obviously, as debugging already existing sites and having to go through a 10GB error logs or tail/multitailing it can be somewhat cumbersome. I'm trying to devise this method so errors can be isolated by path. Any suggestions?

hakre
  • 193,403
  • 52
  • 435
  • 836
DWils
  • 390
  • 1
  • 4
  • 16
  • I'm not sure if your idea turns out well in practice but including a file must not mean that the working directory changes. The only chance I see is that you create your own error handling function (http://php.net/set_error_handler) that looks into the backtrace for the file of the error (take care that some errors are not within a file but "nowhere" so you need to look for the *last* file) and then log into that directory (http://php.net/error_log). You register that handler in your *`auto_prepend_file`*. – hakre Sep 10 '13 at 05:53
  • *"10GB error logs"* - you need to fix a different problem first, e.g. logrotate this big ball first. also for a short moment if the sheer amount of messages is overwhelming, do not log repeating errors: http://stackoverflow.com/q/1964732/367456 (might not help you, just saying) – hakre Sep 10 '13 at 05:58
  • I like the idea of not logging repeated errors. I have come across some Magento and Wordpress sites that already exist, so typically if I find a large error log I would rename it (as most people would) and grab the new one that appears. However in the context of php, where everything is included at runtime unless cached already, this may not help, if I'm correct, it would only stop repeated errors from happening on the same request, and would not prune the log each time to see if an error exists. Am I assuming correctly? – DWils Sep 10 '13 at 06:19
  • Your first suggestion of custom error logging seems more appropriate for this scenario. I could use debug_backtrace and get the 'file' value from the array, use a regex on it to eliminate the actual file name and just use the path to use with ini_set('error_log',$error_path) – DWils Sep 10 '13 at 06:20
  • well, a regex seems wrong, there is `dirname()` for example. the backtrace is here: http://php.net/debug_backtrace - and the second comment wasn't a suggestion how to do what you ask for more that you have quite a problem already if the error log is that huge. you need to fix some errors first. – hakre Sep 10 '13 at 06:20
  • agreed, some of the projects our company has taken on have been insane when these huge logs already exist, so I was mostly looking for a way to sort those out effectively, so we can create more effective use case scenarios in the future. When we jump into a site to fix one problem and all these other issues already exist (especially warnings and depreciation notices), it can take a lot more time. Thanks for pointing me in the right direction, I've started to create a file I can include at the top of code stacks to override for specific cases. – DWils Sep 10 '13 at 07:05

1 Answers1

2

Based on hakre's suggestions above, I've created this script, to be included at the top of any php script:

(also here is a gist I made of this file if you wish to fork/download it: view on github )

<?
function custom_error_debug($errno, $errstr, $errfile, $errline, $errvars) {
  $message = "";
  $message .= "[ " . date('Y-m-d h-i-s') . " ] Error: [$errno] $errstr on line $errline of $errfile ";

  //Dump all info to browser!
  //WARNING: Leave this commented except for extreme cases where you need to see all variables in use!
  //Using this will cause excessive processing time, and RAM. Use only as needed!
  /*if (!empty($errvars)) {
     echo $message . PHP_EOL . "Variables in use: <pre>";print_r($errvars); echo "</pre>";
     //WARNING: not ending execution here may cause the browser to overload on larger frameworks, comment out at your own risk!
     die();
  }*/

  //get the directory of the offending file, put a log in that path, and separate them by end of line, append to file
  file_put_contents ( dirname($errfile) . "/php_errors.log", $message . PHP_EOL, FILE_APPEND );

  //Dump all variables to file as well, (MAY CAUSE LARGE FILES, read above)
  //file_put_contents ( dirname($errfile) . "/php_errors.log", $errvars . PHP_EOL, FILE_APPEND );

  //Optionally end script execution
  //die();
}
set_error_handler('custom_error_debug');
?>
DWils
  • 390
  • 1
  • 4
  • 16