Вопрос по php – Регистрация ошибок, плавно

37

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

try {
     //try a database connection...

} catch (PDOException $e) {
    error_log($e->getMessage(), 3, "/var/tmp/my-errors.log");

}

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

<?php

function legit() {
    try {
        if (1 == 1) {
            throw new Exception('There was an error here');
        }
    } catch (Exception $e) {
        throw new Exception('throw the error to the try-catch outside the function...');
    }

}

try {
    legit();
} catch (Exception $e) {
    echo 'error here' . $e->getMessage();

    //log it
}

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceededlog_errorsError: User Rate Limit Exceededtrigger_errorError: User Rate Limit Exceeded Tom van der Woerdt
Error: User Rate Limit Exceeded John

Ваш Ответ

11   ответов
3

Error: User Rate Limit Exceededtrigger_error()Error: User Rate Limit ExceededError: User Rate Limit ExceededError: User Rate Limit Exceeded

  1. this can be used as a standalone component, ZF is not a full-stack framework. You may copy only Zend_Loader and Zend_Log namespaces , instantiate Zend_Loader and use it. See below:

    require_once('Zend/Loader/Autoloader.php');
    
    $loader = Zend_Loader_Autoloader::getInstance();
    
    $logger = new Zend_Log();    
    $writer = new Zend_Log_Writer_Stream('php://output');
    
    $logger->addWriter($writer);    
    $logger->log('Informational message', Zend_Log::INFO);
    
  2. You were offered many logging libraries, but I believe that Zend team (founders of PHP lang) know what they do

  3. You may use any writers (database, STDOUT - see above, file, whatever, you may customize it to write your own to post log messages to a web service even)
  4. log levels
  5. may change log format (but the one that is out-of-box is great to my mind). The above example with standard formatter will produce something like this:

2012-05-07T23:57:23+03:00 INFO (6): Informational message

  1. just read the reference, it may be configured to catch php errors
Error: User Rate Limit Exceeded John
Error: User Rate Limit ExceededmonologError: User Rate Limit Exceededapache log4phpError: User Rate Limit Exceeded
3

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\Event;

$dispatcher = new EventDispatcher();

//register listeners
$dispatcher->addListener('application.log', function (Event $event) {
    //do anything you want
});

Error: User Rate Limit Exceeded

$dispatcher->dispatch(new GenericEvent('application.log', array('message' => 'some log', 'priority' => 'high'));

Error: User Rate Limit Exceeded

class LogEvent extends GenericEvent {
    public function __construct($message, $priority = 'INFO') {
        parent::__construct('application.log', array('message'=>$message,'priority'=>$priority));
    }
    public function getMessage() { return $this->getArgument('message'); }
    public function getPriority() { return $this->getArgument('priority'); }
}

// now raising LogEvent is much cleaner:
$dispatcher->dispatch(new LogEvent('some log'));

Error: User Rate Limit Exceeded

 class ExceptionEvent extends GenericEvent {
    public function __construct(Exception $cause) {
        parent::__construct('exception.event', array('cause' => $cause));
    }
 }

Error: User Rate Limit Exceeded

Advantages

  • you separate logging logic from your application
  • you can easily add and remove loggers in runtime
  • you can easily register as many loggers you want (i.e. DebugLogger which logs everything into text file, ErrorLogger which logs only errors to error_log, CriticalLogger which logs only critical errors on production environment and sends them by email to administrator, etc.)
  • you can use event dispatcher for more things than just logging (in fact for every job for which observer pattern is appropriate)
  • actual logger becomes nothing more than 'implementation detail' - it's so easy to replace that it doesn't matter where your logs go - you will be able to replace log destination at any time without having to refactor names of your methods, or changing anything in code.
  • it will be easy to implement complex log routing logic or globally change log format (by configuring loggers)
  • everything becomes even more flexible if you use dependency injection for both listeners (loggers) and dispatcher (into classes that notifies log event)

Actual Logging

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

0

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceededdate()Error: User Rate Limit Exceededtime()

Error: User Rate Limit Exceeded

function dlog($message,$type="php-dlog")
{
    if(!is_array($message)  )
        $message=trim($message);
    error_log(date("m/d/Y h:i:s").":".print_r($message,true)."\n",3, "/data/web/logs/$_SERVER[HTTP_HOST]-$type.log");
} 
0

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

define('ERRORLOG_PATH', '/var/tmp/my-errors.log');
function do_something($in)
{
    if (is_good($in))
    {
        try {
            return get_data($in);
        } catch (NoDataException $e) {
            // Since it's not too big a deal that nothing
            // was found, we just return false.
            return false;
        }
    } else {
        throw new InvalidArguementException('$in is not good');
    }
}

function get_data($data)
{
    if (!is_int($data))
    {
        InvalidArguementException('No');
    }
    $get = //do some getting.
    if (!$get)
    {
        throw new NoDataException('No data was found.');
    } else {
        return $get;
    }
}

try {
   do_something('value');
} catch (Exception $e) {
   error_log($e->getMessage(), 3, ERRORLOG_PATH);
   die ('Something went wrong :(');
}

Error: User Rate Limit ExceededNoDataExceptionError: User Rate Limit ExceededException.

Error: User Rate Limit ExceededExceptionError: User Rate Limit Exceededtry {}Error: User Rate Limit Exceededcatch {}Error: User Rate Limit Exceeded

Error: User Rate Limit Exceededset_error_handler()Error: User Rate Limit Exceeded

0

Error: User Rate Limit Exceeded

Error: User Rate Limit ExceededError: User Rate Limit ExceededError: User Rate Limit ExceededError: User Rate Limit ExceededError: User Rate Limit Exceeded

0

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded
Error: User Rate Limit ExceededMost important fatal errors would be logged in error log anywayError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
0

Error: User Rate Limit ExceededError: User Rate Limit Exceeded.

Error: User Rate Limit ExceededError: User Rate Limit ExceededError: User Rate Limit ExceededError: User Rate Limit Exceeded.

Error: User Rate Limit Exceeded

3

Error: User Rate Limit Exceeded

define('ERRORLOG_PATH', '/var/tmp/my-errors.log');

error_log($e->getMessage(), 3, ERRORLOG_PATH);

Error: User Rate Limit Exceedederror_logError: User Rate Limit Exceeded

Error: User Rate Limit Exceeded John
35

Error: User Rate Limit Exceeded

Preamble

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

Triggering errors

Error: User Rate Limit Exceeded

  1. Errors from PHP itself (e.g. using undefined variables) or internal functions (e.g. imagecreatefromjpeg could not open a file),
  2. Errors triggered by user code using trigger_error,

Error: User Rate Limit Exceededdisplay_errorsError: User Rate Limit Exceedederror_reportingError: User Rate Limit Exceededset_error_handlerError: User Rate Limit Exceeded

Throwing exceptions

Error: User Rate Limit Exceeded

  1. The code that handles them may be far removed from the place where they are thrown from. The variable state at the origin must be explicitly passed to the Exception constructor, otherwise you only have the stack trace.
  2. The code between the exception and the catch is skipped entirely, whereas after an error occurs (and it was not fatal) the code still continues.
  3. They can be extended from the main Exception class; this allows you to catch and handle specific exceptions but let others bubble down the stack until they're caught by other code. See also: http://www.php.net/manual/en/language.exceptions.php

Error: User Rate Limit Exceeded

Handling errors

Error: User Rate Limit Exceeded

function my_error_handler($errno, $errstr, $errfile = 'unknown', $errline = 0, array $errcontext = array())
{
    // $errcontext is very powerful, it gives you the variable state at the point of error; this can be a pretty big variable in certain cases, but it may be extremely valuable for debugging
    // if error_reporting() returns 0, it means the error control operator was used (@)
    printf("%s [%d] occurred in %s:%d\n%s\n", $errstr, $errno, $errfile, $errline, print_r($errcontext, true));

    // if necessary, you can retrieve the stack trace that led up to the error by calling debug_backtrace()

    // if you return false here, the standard PHP error reporting is performed
}

set_error_handler('my_error_handler');

Error: User Rate Limit ExceededErrorExceptionError: User Rate Limit Exceeded

function exception_error_handler($errno, $errstr, $errfile, $errline)
{
    throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
}

set_error_handler("exception_error_handler");

Handling exceptions

Error: User Rate Limit Exceeded

function insertRecord($user, $name)
{
    try {
        if (true) {
            throw new Exception('This exception should not be handled here');
        }
        // this code is not executed
        $this->db->insert('users', array('uid' => $user, 'name' => $name));
    } catch (PDOException $e) {
        // attempt to fix; an exception thrown here will cascade down
        throw $e; // rethrow exception

        // since PHP 5.3.0 you can also nest exceptions
        throw new Exception("Could not insert '$name'", -1, $e);
    } catch (WhatEverException $e) {
        // guess what, we can handle whatever too
    }
}

The slippery exception

Error: User Rate Limit Exceededset_exception_handler.

function my_exception_handler(Exception $exception)
{
    // do your stuff here, just don't throw another exception here
}

set_,exception_handler('my_exception_handler');

Error: User Rate Limit Exceeded

Logging the error / exception

Error: User Rate Limit ExceededError: User Rate Limit ExceededError: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

  1. Loggers - named entities that perform logging upon your behalf; they can be specific to a class in your project or shared as a common logger,
  2. Appenders - each log request can be sent to one or more destinations (email, database, text file) based on predefined conditions (such as log level),
  3. Levels - logs are classified from debug messages to fatal errors.

Error: User Rate Limit Exceeded

Logger::getLogger('main')->info('We have lift off');
Logger::getLogger('main')->warn('Rocket is a bit hot');
Logger::getLogger('main')->error('Houston, we have a problem');

Error: User Rate Limit Exceeded

  1. Collect all debug messages in a database for developers to look at; you might disable this on the production server,
  2. Collect warnings into a daily file that you might email at the end of the day,
  3. Have immediate emails sent on fatal errors.
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededstackoverflow.com/questions/12609104/catch-mysql-error-in-c
0

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

Error: User Rate Limit ExceededError: User Rate Limit ExceededError: User Rate Limit Exceeded

Error: User Rate Limit Exceeded
82

Error: User Rate Limit Exceedederror_logError: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

  1. Errors
    • Logging the error directly vs trigger_error and set_error_handler
    • Where good errors go bad - Fatal Errors.
  2. Exceptions
    • SPL
    • What to do with them?
  3. Code
    • Setup
    • Usage

TL;DRError: User Rate Limit Exceededtrigger_errorError: User Rate Limit Exceededset_error_handlerError: User Rate Limit Exceeded

1. Errors

Error: User Rate Limit Exceededtrigger_errorError: User Rate Limit Exceededset_error_handlerError: User Rate Limit Exceeded

Logging the error directly

Error: User Rate Limit Exceeded

Logger::getLogger('standard')->error('Ouch, this hurts');

Error: User Rate Limit Exceeded

    Class:  Logger
    Method: getLogger
    Return: Object with method 'error'

Error: User Rate Limit Exceeded

Error: User Rate Limit ExceededError: User Rate Limit Exceeded.

Error: User Rate Limit Exceededlogging the error directly is bad.

trigger_error to the rescue

Error: User Rate Limit Exceededtrigger_errorError: User Rate Limit ExceededError: User Rate Limit ExceededError: User Rate Limit ExceededE_USER_ERROR, E_USER_WARNINGError: User Rate Limit ExceededE_USER_NOTICEError: User Rate Limit Exceeded

Error: User Rate Limit Exceededtrigger_errorError: User Rate Limit Exceeded

Error Handler

Error: User Rate Limit Exceededset_error_handlerError: User Rate Limit ExceededfalseError: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded@Error: User Rate Limit ExceedederrnoError: User Rate Limit Exceedederror_reportingError: User Rate Limit Exceeded

When Good Errors go Bad - Fatal Errors

Error: User Rate Limit ExceededE_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNINGError: User Rate Limit Exceeded

call_this_function_that_obviously_does_not_exist_or_was_misspelt();

Error: User Rate Limit ExceededseriousError: User Rate Limit Exceededregister_shutdown_functionError: User Rate Limit Exceedederror_get_lastError: User Rate Limit Exceeded

2. Exceptions

Error: User Rate Limit Exceededtrigger_errorError: User Rate Limit Exceededthrow new ExceptionError: User Rate Limit Exceededset_exception_handlerError: User Rate Limit Exceeded

SPL

Error: User Rate Limit ExceededError: User Rate Limit ExceededError: User Rate Limit Exceededtrigger_errorError: User Rate Limit Exceeded

What to do with them?

Error: User Rate Limit Exceeded

  1. Catch it and fix it (the code then continues as if nothing bad happened).
  2. Catch it, append useful information and re-throw it.
  3. Let it bubble up to a higher level.

Error: User Rate Limit Exceededset_exception_handlerError: User Rate Limit ExceededcatchError: User Rate Limit Exceeded

3. Code

Setup

Error Handler

function errorHandler($errno , $errstr, $errfile, $errline, $errcontext)
{
    // Perform your error handling here, respecting error_reporting() and
    // $errno.  This is where you can log the errors.  The choice of logger
    // that you use is based on your preference.  So long as it implements
    // the observer pattern you will be able to easily add logging for any
    // type of output you desire.
}

$previousErrorHandler = set_error_handler('errorHandler');

Exception Handler

function exceptionHandler($e)
{
    // Perform your exception handling here.
}

$previousExceptionHandler = set_exception_handler('exceptionHandler');

Shutdown Function

function shutdownFunction()
{
    $err = error_get_last();

    if (!isset($err))
    {
        return;
    }

    $handledErrorTypes = array(
        E_USER_ERROR      => 'USER ERROR',
        E_ERROR           => 'ERROR',
        E_PARSE           => 'PARSE',
        E_CORE_ERROR      => 'CORE_ERROR',
        E_CORE_WARNING    => 'CORE_WARNING',
        E_COMPILE_ERROR   => 'COMPILE_ERROR',
        E_COMPILE_WARNING => 'COMPILE_WARNING');

    // If our last error wasn't fatal then this must be a normal shutdown.  
    if (!isset($handledErrorTypes[$err['type']]))
    {
        return;
    }

    if (!headers_sent())
    {
        header('HTTP/1.1 500 Internal Server Error');
    }

    // Perform simple logging here.
}

register_shutdown_function('shutdownFunction');

Usage

Errors

// Notices.
trigger_error('Disk space is below 20%.', E_USER_NOTICE);
trigger_error('Disk space is below 20%.'); // Defaults to E_USER_NOTICE

// Warnings.
fopen('BAD_ARGS'); // E_WARNING fopen() expects at least 2 parameters, 1 given
trigger_error('Warning, this mode could be dangerous', E_USER_WARNING);

// Fatal Errors.    
// This function has not been defined and so a fatal error is generated that
// does not reach the custom error handler.
this_function_has_not_been_defined();
// Execution does not reach this point.

// The following will be received by the custom error handler but is fatal.
trigger_error('Error in the code, cannot continue.', E_USER_ERROR);
// Execution does not reach this point.

Exceptions

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

try
{
    $value = code_that_can_generate_exception();
}
catch (Exception $e)
{
    // We decide to emit a notice here (a warning could also be used).
    trigger_error('We had to use the default value instead of ' .
                  'code_that_can_generate_exception\'s', E_USER_NOTICE);
    // Fix the exception.
    $value = DEFAULT_VALUE;
}

// Code continues executing happily here.

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceededcode_that_can_generate_exception()Error: User Rate Limit Exceeded$contextError: User Rate Limit Exceeded

try
{
    $context = 'foo';
    $value = code_that_can_generate_exception();
}
catch (Exception $e)
{
    // Raise another exception, with extra information and the existing
    // exception set as the previous exception. 
    throw new Exception('Context: ' . $context, 0, $e);
}

Error: User Rate Limit Exceeded

// Don't catch it.
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded John

Похожие вопросы