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;
}
};