2013-04-08 11 views
8

Vorrei registrare user_id della persona che effettua una richiesta e il nome del metodo di ogni metodo chiamato per una classe javascript. Per esempio:Come posso registrare ogni chiamata di metodo in node.js senza aggiungere linee di debug ovunque?

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 

Dal momento che tutto è utente asincrono 35 e 78 potrebbero fare cose allo stesso tempo. Quindi voglio assicurarmi che ogni riga di log inizi con user_id in modo che possa grep per esso e vedere solo l'attività di un utente alla volta.

Esiste un modo super intelligente per eseguire questa operazione senza aggiungere istruzioni di registrazione a tutti i metodi?

+0

Eventuali duplicati di [Come il debug di applicazioni Node.JS?] (Http://stackoverflow.com/questions/1911015/how-do-i-debug-node-js- applicazioni) – Sylar

risposta

2

Suppongo che si tratti di un'app Web, nel qual caso se si utilizza la connessione è possibile utilizzare un middleware del logger che registra l'utente e il percorso dell'URL, che è probabilmente sufficiente. Altrimenti, dovrai eseguire alcune metaprogrammazione seguendo le linee di avvolgere ciascuna funzione in una funzione wrapper per eseguire la registrazione.

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

Affinché questo funzioni, è necessario che le funzioni del metodo di classe siano denominate, non anonime.

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

Questa è un'alternativa, non del tutto sicuro di come affidabile che è, però, ci si sente un po 'sbagliato:

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

Come si può vedere, sovrascrive la funzione call - questo crea un piccolo problema quando si tenta di chiamare console.log() quindi è necessario scambiare la funzione. Ma sembra funzionare!

EDIT

Poiché questo è etichettato CoffeeScript:

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

Questo per me è una ricorsione infinita poiché slice è chiamato come una funzione. Ho dovuto spostare la chiamata slice prima di impostare newCall e passare il risultato sotto una variabile. Non sei sicuro che funzioni ora –

+1

@AlexLehmann come modificare il codice per evitare una ricorsione infinita? –

5

La risposta è essenzialmente corretta, ma ecco come evitare una ricorsione infinita

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

CoffeeScript

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

Questo è ottimo ma potresti far luce su come funziona e magari offrire un esempio di utilizzo? È piuttosto avanzato e SE è anche per utenti principianti/intermedi. : D – zehelvion

Problemi correlati