Domanda

I'm attempting to gather information when our sites encounter an internal server error. We have many applications that were never set up with proper error logging and when an issue occurs our clients don't give us the best information to work with. What I would like to do is that when a 500 happens, I would like to collect data about where the issue happened such as:

  • The page the user was on
  • Any data associated with the page ($_GET, $_POST, etc)

I've set up custom error pages on our server (IIS 7) with the following config:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <httpErrors errorMode="Custom">
            <remove statusCode="500" />
            <error statusCode="500" path="/error.php?code=500" responseMode="ExecuteURL" />
        </httpErrors>
    </system.webServer>
</configuration>

And on that page I'm just var_dump-ing $_POST and $_GET to see if anything in those gets through to the error page, but it doesn't. My goal on a 500 error would be:

  • Gather data about the page/user at time of error
  • Send email to support team about issue containing the gathered data

Is there any way to collect that data and have the custom error page see it?

error.php:

switch($ErrorCode){
    case '500':
         var_dump($_REQUEST, $_POST, $_GET);
         echo "internal server error";
         break;
}

In all cases $_POST is empty even though I submitted a form to get this error and $_GET contains this (which makes sense):

array(2) {
  ["code"]=>
  string(3) "500"
  ["500;http://icom-sbs/test_php"]=>
  string(0) ""
}

4/19 Update

I played with some ideas, and the main one being storing useful data in a session variable. I attempted to store some form data in a session variable on the test page that gives the error, but it never gets into the session. It seems like the server detects that an error will occur on the page so it never even executes any code on the page and immediately executes the error page.

È stato utile?

Soluzione

If your server started to interpret php file and after this 500 error occurred this means some fatal error happened in your code. It might be anything, from simple typo to execution time limit reached.

The best and only way to catch fatal errors in PHP is with register_shutdown_function. You should define it on top of your working file:

function handle_fatal() {
    $error = error_get_last(); // PHP 5.2+
    if($error !== NULL){
        $error_landing_page = '[FATAL] '.$error['message'].' in '.$error['file'].':'.$error['line'] . '<br/>GET:<br/>' . print_r($_GET, true) . '<br/>POST:<br/>' . print_r($_POST, true);
        // mail here if you need that and include $_GET, $_POST variables - this will be the last state before error occurred
        exit($error_landing_page);
    }
}

register_shutdown_function('handle_fatal');

Simple test case:

// put handling function at the very beginning
function handle_fatal() {/*...*/}
register_shutdown_function('handle_fatal');

// now do some logic
if($_GET['page'] == 'dupa'){
    $_POST['subpage'] = 1; // more and more logic
    $obj = new Dupa(); // class not found exception
}

This is what I get with my handle_fatal from example:

[FATAL] Class 'Dupa' not found in /var/www/index.php:22
GET:
Array ( [page] => dupa )
POST:
Array ( [subpage] => 1 ) 

After all you should know that catching such errors is not always best idea and you should be careful about it.

Altri suggerimenti

I think you need to log details at server level rather than at php level, since php might not even initialize when a 500 internal error occurs. If you are using apache you can check out

http://httpd.apache.org/docs/1.3/mod/mod_log_config.html#logformat

The error logs will definitely provide you request url, remote address and get params (query string). But I'm not sure about post data. May be you can make some changes to log format to dump entire headers and raw data at a certain level.

But I'm sure logging at php level will skip at certain times when the server actually gives up and php does not kick in...

Check the $_SERVER array if there is anything of interest.

I researched a bit and if you were using ASP, you would be able to get the error details in Server.GetLastError which leads me to believe that IIS might pass on the information through the $_SERVER array.

I believe that you can set up an custom error handler in PHP. The hard thing is that some errors may cause PHP to die and return an 500 without triggering the error handler. The plus side is that it should be easy to implement site wide without a lot of changes.

http://www.php.net/manual/en/function.set-error-handler.php

You should be able to find most of the relevant information in the $_SERVER global. You may also what to check out the debug_backtrace function that will give you a stack trace.

http://php.net/manual/en/function.debug-backtrace.php

Good luck

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top