In PHP ist ja so ziemlich alles erforscht, wie man mit Exceptions und Errors umzugehen hat. In Javascript wird das Thema aber sehr stiefmütterlich behandelt. Hier mal ein Ansatz, um JS-Fehler effektiv tracken und loggen zu können.
E.js
var E = { //true: errors via alert / false: errors are being logged debugMode:false, //processes errors handle: function(sev,msg) { if (E.debugMode) { alert("Error ("+sev+") with message: " + msg); } else { var img=new Image(); img.src="errorlogger.php?sev="+encodeURIComponent(sev)+ "&msg="+encodeURIComponent(msg)+ "&url="+encodeURIComponent(document.URL); } } } //error has not been caught and forwarded to "errorhandler" manually -> windowerror window.onerror=function(msg,url,line) { E.handle(1,'Uncaught error:'+msg+" in "+url+", line "+line); return true; //continue }
In dieser Javascript-Datei geht die eigentliche Magie ab. Mittels des debugMode wird bestimmt, ob der Fehler ausgegeben oder geloggt wird. Im „Log“-Fall wird ein Image erzeugt (was natürlich nicht sichtbar ist), das die URL der Errorlog-Datei hat. Sollte ein Fehler auftreten (window.error), so wird dieser an den Errorhandler weitergereicht.
errorlogger.php
<?php error_log(date("d.m.Y H:i:s")." (JS) -> ".$_GET['msg']." (Severity: ".$_GET['sev']."): ".$_GET['url']."\n",3,"error.log"); ?>
Ultrasimpel. Die übergebenen Log-Parameter werden per error_log an eine Datei error.log appended. Wichtig: Per htaccess / httpd.conf den Aufruf der errorlog-Datei per Web verbieten.
Einbindung im HTML
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <script src="e.js"></script> <script> function divide(d1,d2) { if (d2==0) { throw new Error("Div by 0 is illegal."); } return d1/d2; } try { divide(3,0); } catch (ex) { E.handle(1,ex); } //does not exist -> window.error xyz(); </script> </head> <body> </body> </html>
So könnte das dann aussehen. in der divide-Funktion wird ein Error geworfen, der dann im try/catch Block aufgefangen und an den Errorhandler weitergegeben wird. Beim Aufruf von xyz() springt die window.onerror Funktion ein und bringt darüber auch wieder den Errorhandler ins Spiel.
Die Errorlog-Datei sieht nach Aufruf des obigen HTMLs im Browser dann so aus:
Habe mir mal erlaubt deine Arbeit etwas zu optimieren. Aber danke für den Denkansatz.
Mit freundlichen Grüßen
Kubitza Adrian
//Erstellt 17.11.2011 Adrian Kubitza
//Changelog:
// 17.11.2011 Adrian Kubitza Logfunktion ohne Ajax unterstützung (new Image() funktion genutzt)
// 17.11.2011 Adrian Kubitza debugModus Funktion entweder Alert-Ausgabe oder in Logdatei
// 17.11.2011 Adrian Kubitza Integration von Ajax in die Funktion this.logThis(param1, param2)
// 18.11.2011 Adrian Kubitza Ausgliederung der Ajax-Funktionen in die Klasse AjaxSendParameter(param1, param2)
// 18.11.2011 Adrian Kubitza Code Optimierungen, this.alert.errorString(param1, param2) und this.send.errorString(param1, param2)
// 18.11.2011 Adrian Kubitza Exception Handler: Exception konnte nicht an Server gesendet werden
var ErrorLogger=function(pDebugMode, pErrorPhpScript){
//DebugModus empfiehlt sich für die Entwicklung, da dort die Fehler via Alert ausgegeben werden
//DebugModus ist normal deaktviert == false
this.debugMode = pDebugMode || false;
//Es kan ein alternatives PHP-Script als Parameter Übergeben werden fuer besondere Protokoll eintraege,
//ansonsten wird ihr ein Standartscript eingetragen
this.errorPhpScript = pErrorPhpScript || 'error.php';
//Stellt Funktion bereit zum erstellen einem String der via Alert ausgegeben werden kann
this.alert={
errorString: function (sev, msg){ return "Es ist ein Fehler aufgetreten: " + sev + " Fehler Nachricht: " + msg;}
};
//Stellt eine Funktion bereit, mit der eine Parameter Kette erstellt wird VAR1=WERT1&VAR2=WERT2&VAR(n)=WERT(n)
this.send={
errorString: function (sev, msg){ return 'sev=' + encodeURIComponent(sev) + '&msg=' + encodeURIComponent(msg) + '&url=' + encodeURIComponent(document.URL);}
};
//Funktion zum protokollieren der Fehler DEBUGMODUS = true -> alert DEBUGMODUS = false -> senden PHP-Script
this.logThis=function(sev,msg){
if(this.debugMode){
alert(this.alert.errorString(sev,msg));
}else{
var ajaxSend = new AjaxSendParameter(this.errorPhpScript, this.send.errorString(sev, msg));
if(ajaxSend.postParameterToPhp() != true){
throw new Error('Exception konnte nicht an Server gesendet werden.');
}
}
}
};
Und Ihr die Ajax-Klasse die man noch braucht:
//Erstellt 18.11.2011 Adrian Kubitza
//Cangelog:
// 18.11.2011 Adrian Kubitza Erstellung der Klasse und Funktion this.postParameterToPhp()
// 18.11.2011 Adrian Kubitza Erstellung der LeerenFunktion this.getParameterToPhp();
var AjaxSendParameter=function(pPhpScript, pParameter){
this.phpScript=pPhpScript;
this.parameter=pParameter;
this.xmlhttp=new XMLHttpRequest();
this.postParameterToPhp=function(){
this.xmlhttp.open('POST', this.phpScript, true);
this.xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
this.xmlhttp.setRequestHeader("Content-length", this.parameter.length);
this.xmlhttp.setRequestHeader("Connection", "close");
this.xmlhttp.send(this.parameter);
return true;
}
this.getParamterToPhp=function(){
return false;
}
};