2013-04-08 4 views
8

Ich möchte die user_id der Person, die eine Anfrage stellt, und den Methodennamen jeder Methode, die für eine JavaScript-Klasse aufgerufen wird, protokollieren. Zum Beispiel:Wie kann ich jeden Methodenaufruf in node.js protokollieren, ohne überall Debug-Zeilen hinzufügen zu müssen?

35 - log_in 
35 - list_of_other_users 
78 - log_in 
35 - send_message_to_user 
35 - connect_to_redis 
78 - list_of_other_users 

Da alles async ist, könnten die Benutzer 35 und 78 zur gleichen Zeit Dinge tun. Ich möchte also sicherstellen, dass jede Log-Zeile mit ihrer Benutzer-ID beginnt, damit ich sie grepen kann und nur die Aktivität eines Benutzers gleichzeitig sehe.

Gibt es einen super cleveren Weg, dies zu tun, ohne Logger-Anweisungen zu jeder Methode hinzuzufügen?

+0

Mögliche Duplikat [Wie Debuggen ich Node.js Anwendungen?] (Http://stackoverflow.com/questions/1911015/how-do-i-debug-node-js- Anwendungen) – Sylar

Antwort

2

Ich vermute, das ist eine Web-App, in diesem Fall, wenn Sie connect verwenden, können Sie eine Logger-Middleware verwenden, die den Benutzer und den URL-Pfad protokolliert, was wahrscheinlich ausreichend ist. Andernfalls müssen Sie einige Metaprogrammierungen durchführen, um die einzelnen Funktionen in einer Wrapper-Funktion für die Protokollierung einzubinden.

function logCall(realFunc, instance) { 
    return function() { 
     log.debug('User: ' + instance.user_id + ' method ' + realFunc.name); 
     return realFunc.apply(instance, arguments); 
    }; 
} 

Damit dies funktioniert, müssen Ihre Klassenmethoden Funktionen genannt werden, nicht anonym.

function sendMessage() { 
    //code to send message 
    //can use `this` to access instance properties 
} 
function MyClass(userId) { 
    this.userId = userId; //or whatever 
    this.sendMessage = logCall(sendMessage, this); 
    //repeat above line for each instance method you want instrumented for logging 
} 
4

Dies ist eine Alternative, nicht ganz sicher, wie zuverlässig es aber ist, fühlt es sich ein bisschen falsch:

(function() { 
    var oldCall = Function.prototype.call; 
    var newCall = function(self) { 
    Function.prototype.call = oldCall; 
    console.log('Function called:', this.name); 
    var args = Array.prototype.slice.call(arguments, 1); 
    Function.prototype.call = newCall; 
    this.apply(self, args); 
    } 
    Function.prototype.call = newCall; 
})(); 

Wie Sie sehen können, ist es überschreibt die call Funktion - das schafft ein kleines Problem Wenn Sie versuchen, console.log() aufzurufen, müssen Sie die Funktion zurück austauschen. Aber es scheint zu funktionieren!

do -> 
    oldCall = Function::call 
    newCall = (self) -> 
    Function::call = oldCall 
    console.log "Function called: #{this.name}" 
    args = Array.prototype.slice.call arguments, 1 
    Function::call = newCall 
    this.apply self, args 
    Function::call = newCall 
+0

Das geht für mich in eine unendliche Rekursion, da Slice als Funktion aufgerufen wird. Ich musste den Slice-Aufruf verschieben, bevor ich newCall setzte und das Ergebnis als Variable weitergab. Nicht sicher, ob das jetzt funktioniert –

+1

@AlexLehmann wie man Code ändert, um unendliche Rekursion zu vermeiden? –

5

Die Antwort ist im Wesentlichen richtig, aber hier ist, wie eine unendliche Rekursion zu vermeiden

Javascript

(function() { 
    var oldCall = Function.prototype.call; 
    var newCall = function(self) { 
    Function.prototype.call = oldCall; 
    console.log('Function called:', this.name); 
    var args = Array.prototype.slice.call(arguments, 1); 
    var res = this.apply(self, args); 
    Function.prototype.call = newCall; 
    return res 
    } 
    Function.prototype.call = newCall; 
})(); 
:

EDIT

Da dies Coffee getaggt

Coffee

do -> 
    oldCall = Function::call 
    newCall = (self) -> 
    Function::call = oldCall 
    console.log "Function called: #{this.name}" 
    args = Array.prototype.slice.call arguments, 1 
    res = this.apply self, args 
    Function::call = newCall 
    res 
    Function::call = newCall 
+1

Das ist großartig, aber könnten Sie etwas Licht in die Funktionsweise bringen und vielleicht ein Anwendungsbeispiel geben? Es ist ziemlich fortgeschritten und SE ist auch für Anfänger/Intermediate-Benutzer. : D – zehelvion

Verwandte Themen