2011-06-06 9 views
23

aka, Buscando controlador de errores genéricos error de PHP (ΟΚ utilizar comercialmente)La gran teoría unificada de manejar

dudo que soy el mejor programador PHP alrededor, por lo que, aunque no tengo mi propio controlador de error genérico para set_error_handler(), me pregunté qué harían otros y si hay un "mejor" (lo siento si eso suena subjetivo; solo quiero destacar los enfoques generales (pero incluso la etiqueta de "mejores prácticas" se ha eliminado de SO)).

Para ser objetivo al respecto, esto es lo que creo que es necesario. Por favor corrígeme si estoy equivocado &, si es así, pídeme un buen código.

  • Quiero capturar la mayor cantidad de información posible, sin saber cuál fue el error.

  • por lo que, por ejemplo, tiene sentido volcar la pila de llamadas.

  • y $_GET, $_POST y $_SESSION.

  • y quiero que la pila de llamadas & Globals a ser bastante-impresos

  • Quiero un poco de diseño 'texto plano', no CSS & de fantasía JS para expandir/contraer la información. Es posible que mis usuarios tengan que cortar/pegar en el correo electrónico o incluso imprimir el fax &.

  • Me gustaría poder agregar un encabezado de mi propio diseño, preferiblemente como un parámetro, pero puedo piratear el código si es necesario. El encabezado puede incluir la versión del programa, la marca de tiempo, etc. (y, en mi caso, tengo una pista de auditoría, por lo que puedo incluir las últimas acciones del usuario, lo que llevó a la falla).

  • algunos usuarios pueden permitir que mi código envíe automáticamente el informe por correo electrónico, algunos pueden desear obtener una vista previa forst & por correo electrónico y algunos pueden no querer que envíe un correo electrónico.

+3

Epic question title, +1. –

+1

No importa cuál sea la pregunta, prefiero ese brillante título. – sepehr

+2

A partir de PHP 7, los errores de PHP antiguos se tratarán como excepciones, permitiendo 'try ... catch', etc. Eso debería hacer que el error de PHP se maneje un billón de veces mejor (y con suerte desterrará a ese molesto operador' @ 'una vez y para todos). – Simba

Respuesta

28

Sugiero que vaya a la forma de "Excepciones".

excepciones Throw cuando hay un error del usuario, y se puede convertir en errores de PHP excepciones, como este:

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

Aunque que este tipo de comportamiento funciona mejor en un tipo de programación orientada a objetos medio ambiente. Si usted no tiene un único punto de entrada (como un FrontController), también puede capturar las excepciones sueltos con esto:

function myException($exception) 
{ 
    echo "<b>Exception:</b> " , $exception->getMessage(); 
} 

set_exception_handler('myException'); 

depuración simple con excepciones sería algo un poco como esto:

function parseException($e) { 
    $result = 'Exception: "'; 
    $result .= $e->getMessage(); 
    $trace = $e->getTrace(); 
    foreach (range(0, 10) as $i) { 
     $result .= '" @ '; 
     if (!isset($trace[$i])) { 
      break; 
     } 
     if (isset($trace[$i]['class'])) { 
      $result .= $trace[$i]['class']; 
      $result .= '->'; 
     } 
     $result .= $trace[$i]['function']; 
     $result .= '(); '; 
     $result .= $e->getFile() . ':' . $e->getLine() . "\n\n"; 
    } 

    return $result; 
} 

A partir de ahí, evaluar los globos terráqueos, etc. es un paseo por el parque. Puede buscar inspiración en Symfony Framework Debug Toolbar, que ofrece muchas de estas solicitudes.

+0

Me gusta eso, realmente no estaba pensando en excepciones, más como problemas de base de datos (pero supongo que también pueden ser excepciones), o errores de codificación (valor predeterminado: "elemento de cambio desconocido") y similares. Si llegamos a un acuerdo debería abarcar todos estos. – Mawg

+0

Lo bueno de esto es que en su desarrollo puede agregar soporte granular para diferentes tipos de errores. Por ejemplo, en mi entorno de ajax es muy fácil propagar cualquier tipo de error al usuario. Hace mi vida mucho más fácil. – Arend

+0

+1 Esto es muy parecido a lo que hago, así que naturalmente me gusta. – Wiseguy

3

No es una buena idea exponer todos los errores que se manejan al usuario final.

1) expone la estructura interna de su código - OK, por lo que debe ser seguro incluso cuando un posible atacante tiene el código fuente completo - pero no tiene sentido hacerles la vida más fácil.

2) ¿De verdad cree que el usuario final copiará concienzudamente toda la información y se la enviará de vuelta?

3) abruma al usuario con mucha información que no le importa.

La forma en que los manejo es capturar tanta información como el lado práctico del servidor (y escribirla en un archivo plano cuando ocurre un error) luego proporcionar un mensaje de error significativo al usuario incluyendo una referencia simple donde puedo encontrar el error en los registros. Para sistemas a gran escala, también recomendaría capturar una huella digital del error (por ejemplo, los últimos 6 dígitos del hash md5 del seguimiento de la pila) para permitir que un servicio de ayuda administre y clasifique múltiples incidentes informados de la misma falla subyacente.

Recuerde que con PHP todos los datos se borran cuando finaliza la secuencia de comandos. Si estaba escribiendo una aplicación Java o un programa en C, entonces realmente no desea acumular datos constantemente, por lo que las únicas opciones son escribir entradas de depuración/información en un registro, luego, una vez que se produce un error, escriba un seguimiento de la pila al registro. Pero con PHP para páginas web, generalmente guardo un registro de estas en una variable de PHP, luego lo escribo en un archivo cuando ocurre un error junto con un seguimiento de la pila (o cuando el script se completa y configuro una bandera) en el código, por ejemplo, a través de la sesión, para analizar cómo se comporta en escenarios sin errores).

Cuantos detalles graba usted, generalmente registro todos los puntos de entrada y salida, y cualquier consulta SQL.

p. Ej.

function logit($msg) 
{ 
    global $runlog; 
    static $basetime; 
    if (!$basetime) $basetime=time(); 
    $runlog.="+" . time()-$basetime . "s : " . $msg . "\n"; 
} 
+0

¿Hay alguna razón por la que escribirías ejecuciones en un archivo plano en lugar de la base de datos? – JamesHalsall

+4

@Jaitsu ¿Qué sucede si el error se está conectando a la base de datos? – jbarlow

+0

@jbarlow, por supuesto que es una buena situación ideal para notificar a alguien con gracia a través de correo electrónico (su aplicación sería hacia abajo), acabo de encontrar almacenar en una tabla de base más fácil de ordenar a través de, por ejemplo ...si un usuario ha reportado un problema al usar una página en particular, almaceno REQUEST_URI junto con los detalles del error y puedo realizar una consulta – JamesHalsall

13

No puedo creer que esto no se haya sugerido todavía.

En mi empresa solo usamos Exceptions con un controlador de error personalizado. El gestor de errores compilará un mensaje de depuración con:

  • GET, POST, cookies, sesión, GLOBALS
  • Un rastro
  • un mensaje de error (ya sea el mensaje de la excepción o la advertencia, sí también debería detectar advertencias, incluso errores de STRICTness).

A continuación, se envía a continuación el mensaje a un servidor monitoreo, si esto falla, se intentará enviar un correo electrónico, lo que falla, se intentará registro a una base de datos (y si eso falla, se registrará en un archivo ). Si el error es un error "fatal" en el sentido de que no se puede garantizar su salida, puede optar por arrojar un encabezado 500 e imprimir un mensaje "¡Vaya!" Predeterminado.

Le aconsejaría que siempre informe automáticamente todos los errores. Los únicos errores que no desea conocer son errores causados ​​por entradas erróneas por parte del usuario. En ese caso, los errores deberían presentarse al usuario de alguna manera. Descubrí que para cada excepción puede identificar si esto es un error en su sistema o un error de un usuario.Por ejemplo: vincular a una página, y luego eliminar la página (esto causará un 404). No quiere saber sobre el 404, pero su cliente sí.

La razón por la que siempre quieres saber sobre todos los errores es simple. Si su sistema tiene un error, no lo sabrá a menos que se encuentre con usted o que su cliente lo informe (lo cual casi nunca lo hace). Solíamos tener un sistema que era bueno para ocultar todos los errores y era super buggy. Comenzamos a exponer todos los errores y, dos años después, es una aplicación muy estable.

Adicionalmente. Hay un truco que puede usar para atrapar molestos Fatal Errors. Puede usar register_shutdown_handler para registrar una función que siempre se ejecutará después de que su script PHP haya finalizado. Luego puede usar error_get_last para verificar si hay un error fatal. A continuación, puede repetir los pasos anteriores para que sepa el error. Esto funciona, lo uso todo el tiempo.

Para redondearlo. Lo que elija para informar los errores no tiene nada que ver con lo que verá el usuario de su aplicación. Puedes elegir darle un informe de error e incluso podrías pedirle retroalimentación en ese momento. Pero la mayoría de las veces solo hay un error en su sistema por lo que el usuario no puede hacer mucho con él.

+1

+1 para el registro seguro de respaldo. Si pudiera preguntar, he estado pensando mucho sobre ese tipo de sistema, ¿cómo diseñó el servicio de monitoreo? ¿Está en el nivel de syslog, un servicio de mensajería o algo escrito en php? – Arend

+2

En realidad, solo llama a un servicio web con una solicitud HTTP. Entonces, es un sistema de monitoreo muy activo, funciona muy bien. – Halcyon

+0

+1 suena bien. ¿Algún código de inspección o punteros para algunos, ya que no puedes publicar el código de tu empresa? – Mawg

Cuestiones relacionadas