seth: Error-Logs und Email-Benachrichtigung

Beitrag lesen

gudn tach!

fehlermeldungen werden bei mir immer in ein logfile auf dem server geschrieben.
zusaetzlich lasse ich mir bei einem fehler eine e-mail schicken und setze direkt danach ein flag (in form einer datei).
bei jeder (weiteren) fehlermeldung wird ueberprueft, ob das flag gesetzt wurde. falls es gesetzt wurde, wird die e-mail-benachrichtigung nicht durchgefuehrt.

Und ich nehme an, du loggst trotzdem in der Zwischenzeit auftretende Fehler ohne Aussortieren; allerdings ohne Email-Benachrichtigung.

ja, das wollte ich eigentlich damit ausdruecken. sorry, dass es nicht klar rueberkam.

Das spart zumindest schonmal einen komplizierten Unterbau, um z.B. vor dem Loggen/Mailsenden zu überprüfen, ob _dieser_ Fehler in den letzten x Sekunden schon einmal auftrat.

ja. allerdings wird ohne diese pruefung das error-log-file bei gewissen attacken ziemlich schnell ziemlich gross. insofern kann eine solche abfrage trotzdem noch sinnvoll sein.

Klingt ganz praktisch. :-)

fuer meine beduerfnisse ist es das bisher auch.

link zum thema bzgl. php: http://www.php.net/manual/en/ref.errorfunc.php (das beispiel "Example 1. Using error handling in a script" ist toll.)

Wenn ich das richtig sehe allerdings komplett ohne einen Mechanismus, der Massenmails an den Admin verhindert, falls ein kritischer Fehler bestehen bleibt.

ja, schon. aber die umbauten, die ich im vorigen posting beschrieben hatte, bauen darauf auf und sind dann nicht mehr viele. ich haenge mal diesem posting scriptauszuege an, die ich in einem projekt verwende.

fuer perl habe ich auf die schnelle nur das hier gefunden.

Da geht es ja eher um die Architektur des Programms, um mit Exceptions den Fehler bis zur geeigneten Stelle "durchzureichen", nicht um die eigentliche Fehlerbehandlung.

ja.

so, und nun das error-handling-zeugs fuer php 4 und 5. vielleicht hat ja noch jemand verbesserungsvorschlaege oder findet sogar luecken/fehler:

jede datei des projektes beginnt mit

<?php  
require('foodir/error_handling.php');

(je nach projektstruktur besser: require_once())

ausser die datei "error_handling.php", welche sich in irgendeinem verzeichnis "foodir" befindet.

englische kommentare sollen erlaeutern, was passiert. deutsche kommentare beschreiben, was an der jeweiligen stelle getan werden sollte, was ich jedoch nicht explizit hinschreibe, z.b. weil es das script hier unuebersichtlich machen wuerde.

<?php  
// error_handling.php  
  
// setze $debugging_mode=1, falls scripts (auf lokalem server) auf fehler untersucht werden sollen, sonst 0;  
  
// set error reporting  
if($debugging_mode){  
  error_reporting(E_ALL | (defined('E_STRICT')? E_STRICT : 0));  
}else error_reporting(0);  
  
// own error handling  
function userErrorHandler($errno, $errmsg, $filename, $linenum, $vars){  
  // timestamp for the error entry  
  $errortime=date('Y-m-d\TH:i:s');  
  // define an assoc array of error strings  
  $errortype=array(  
    E_ERROR           => 'error',  
    E_WARNING         => 'warning',  
    E_PARSE           => 'parsing error',  
    E_NOTICE          => 'notice',  
    E_CORE_ERROR      => 'core error',  
    E_CORE_WARNING    => 'core warning',  
    E_COMPILE_ERROR   => 'compile error',  
    E_COMPILE_WARNING => 'compile warning',  
    E_USER_ERROR      => 'user error',  
    E_USER_WARNING    => 'user warning',  
    E_USER_NOTICE     => 'user notice');  
  if(defined('E_STRICT')) // because in php prior to version 5 not defined  
    $errortype[E_STRICT]='runtime notice';  
  // table head of logged data  
  $err_h_arr=array('errortime', 'errortype', 'filename', 'linenum', 'errmsg',  
    'REMOTE_ADDR:REMOTE_PORT', 'HTTP_USER_AGENT', 'REQUEST_URI', 'STATUS',  
    'HTTP_REFERER', 'REQUEST_METHOD', '_GET', '_POST');  
  // data to log  
  $err_array=array($errortime, $errortype[$errno], $filename, $linenum, $errmsg);  
  // fuelle $err_array mit dem rest $err_array[]=... (siehe tabellenkopf $err_h_arr)  
  $err='"'.implode('"; "', $err_array).'"'."\n";  
  
  // write error information to error log and set new_error flag  
  $err_file_path='foodir/error.log';  
  // first line = table head  
  if(!file_exists($err_file_path) || filesize($err_file_path)===0){  
    $file_handle=fopen($err_file_path, 'w');  
      fwrite($file_handle, '"'.implode('"; "', $err_h_arr).'"'."\n");  
    fclose($file_handle);  
  }  
  // write errormessage to file  
  error_log($err, 3, $err_file_path);  
  // set new_error flag  
  $flag=0;  
  $flag_file_path='foodir/new_error.flag';  
  if(file_exists($flag_file_path)){  
    $file_handle=fopen($flag_file_path, 'r');  
      $flag=fgetc($file_handle); // read '0' or '1' or false  
    fclose($file_handle);  
  }  
  $file_handle=fopen($flag_file_path, 'w');  
    fwrite($file_handle, '1');  
  fclose($file_handle);  
  
  // send error information by mail  
  if(!$debugging_mode && $flag!=='1'){  
    $headers='From: err_handling_script@'.$_SERVER['SERVER_NAME']."\r\n".  
      'X-Mailer: PHP/'.phpversion();  
    error_log($err, 1, $meine_adresse, $headers);  
  }  
  
  if($errno & (E_USER_ERROR | E_ERROR)){  
    echo '<div>ein fehler ist aufgetreten</div>';  
    echo '<div>der administrator wurde benachrichtigt</div>';  
    die;  
  }  
}  
  
$old_error_handler = set_error_handler('userErrorHandler');  
//eof

und das viele-gleiche-errors-gar-nicht-erst-mitloggen, koennte man nun bewerkstelligen, indem man prueft, ob die aktuelle fehler-ip-adresse und die des letzten eintrages in error.log gleich sind, ob die fehlermeldung die gleiche ist und ob auch der fehler in der gleichen datei an der gleichen stelle aufgetreten ist.

falls allerdings abwechselnd irgendwelche warnings gefolgt von errors erscheinen koennen, kann man ja z.b. die letzten 10 eintraege durchforsten, wenn sie nicht aelter als z.b. 5 minuten sind.

prost
seth