开发者

PHP: How do we log errors that happen?

开发者 https://www.devze.com 2022-12-21 12:51 出处:网络
For example, if we try to get to some api but fail开发者_运维知识库, or try to connect to our database but also fail.There are several ways to deal with this:

For example, if we try to get to some api but fail开发者_运维知识库, or try to connect to our database but also fail.


There are several ways to deal with this:

  • Bubble the error into your server log file
  • Write the error to a text file
  • Store the errors in a database table


You can user PHP Error Handling. See set_error_handler


php error handling is tricky, and there are many points to take into account. In php, we have 3 types of errors:

  • Fatal errors, like calling an undefined function. There's not much you can do about them. At least, set display_errors=0, log_errors=1 in php.ini, so that they won't be displayed. Better yet, write a petition on bugs.php.net and demand eliminating fatals altogether. Fatal errors are such a shame!

  • "Normal" warnings and notices. The best is to convert them into exceptions, see example #1

  • Exceptions - the funny part. You can catch them in your code when appropriate + install a generic exception handler as a last chance option to log the error and tell users that something wrong is happened.


There is a default function of PHP to log errors; error_log

Example from PHP.net:

<?php
// Send notification through the server log if we can not
// connect to the database.
if (!Ora_Logon($username, $password)) {
    error_log("Oracle database not available!", 0);
}

// Notify administrator by email if we run out of FOO
if (!($foo = allocate_new_foo())) {
    error_log("Big trouble, we're all out of FOOs!", 1,
               "operator@example.com");
}

// another way to call error_log():
error_log("You messed up!", 3, "/var/tmp/my-errors.log");
?>


Be aware of extensive logging. Especially on productive Systems.

  • If you just try to handle programming errors, first you should raise a debug mode flag in your code. strict php handling is also very helpful. (set in php.ini or by your apache vhost settings).

  • dont try browser/screen debugging. as mentioned in other postings. set diplay_errors=0 and log_errors=1 in your php ini (or set it by your apache vhost settings)

  • then open a console window and do: tail -f

    on your php_error.log (path is set in php.ini or by apache vhost settings)

  • if you use a framework. use the framework debugging tools (cake)

  • if you have your own framework/or just code. You probably should write an own exception handler class with debug capabilities.

example:

class MyFactory{
    public static function getLogger(){
        return new MyLogger();
    }
}

class ExampleExceptionWithLogging extends Exception{

    public __construct ($message=''){
        MyFactory::getLogger()->exception($message,$this->getTrace());
    }

}

class MyLogger{

    /**
    * @var string $logfile
    **/
    protected $logFile = '/var/log/php_error.log';

    /**
     * @param string $message
     * @param array $stackTrace
     **/
    public function exception($message,$stackTrace){
        $prefix = '[EXCEPTION] ';
        $this->writeOut($prefix.$message.' '.print_r($stackTrace,TRUE));
    }

    /** 
     * writes $value to given Logfile.
     * @param string $value
     * @param string|NULL $logFile FileName with full path
     */
    protected function writeOut($value,$logFile = NULL){
        if(is_null($logFile)){
                $logFile = $this->logFile;
        }
        error_log($value,3,$logFile);
    }
}

Usage: throw new ExampleExceptionWithLogging('Sample Message');


There are 3 issues here:

  1. redirecting the program flow to the error handling

  2. Capturing information relevant to resolving the error

  3. Making that information available to the relevant parties

As others have said, (1) can be dealt with using set_error_handler(), note that you can instantiate your own customer errors within your code, e.g.

if (!$_SESSION['authenticated_user']) {
    $login="<a href='/login.php'>login</a>";
    trigger_error("Not authorized please $login", E_USER_WARNING);
}

The established practice for capturing information is the stack trace - and this is indeed available in PHP, however this is a static snapshot of the state of the PHP code at the point the error occurred - if you've tested your code properly, then the fault likely has nothing to do with your PHP code. Its a good indicator of where you should try to fix your code, but not a good indicator of what you need to fix. The stacktrace is still a useful tool, but it was often the only tool for programs which were running for any length of time, other than recording detailled logs of what the program did in the run up to the error. As well as an obvious performance hit, wading through several megabytes of logfiles looking for an error can be like looking for a needle in a haystack. However since PHP programs usually just generate a web page the exit, this presents the opportunity to accumulate the detailled log of events in a PHP variable, then you can choose to write the variable to a file only once an error occurs.

Like most things about programming, there is a trade-off here - if an error has happenned that you didn't expect/ plan for, how do you know that you're error handling is going to work?

In terms of making the data available, you probably should not record it in a database - chances are your program may have failed because the database isn't working properly - error handling must be very, very robust. Dumping it into a uniquely named file is a good approach which avoids the file contention problems you'd have with appending to a consolidated log file. Or use the syslog facility. You might even email a copy of the error out (but again this is relying on another complex subsystem).

HTH

C.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号