2013-01-05 12 views
36

Come si può ottenere il nome e la linea di una funzione che ha chiamato quella corrente? Mi piacerebbe avere una funzione di debug rudimentale come questo (con npmlog definendo log.debug):Ottieni la funzione nome e linea di chiamata in node.js

function debug() { 
    var callee, line; 
    /* MAGIC */ 
    log.debug(callee + ":" + line, arguments) 
} 

Quando viene chiamato da un'altra funzione che sarebbe stato qualcosa di simile:

function hello() { 
    debug("world!") 
} 
// outputs something like: 
// "hello:2 'world!'" 

Per chiarezza, quello che voglio è essenzialmente analogo a this in Python:

import inspect 
def caller(): 
    return inspect.stack()[2][3] 
// line no from getframeinfo().lineno 

c'è un nodo equivalente per raggiungere questo obiettivo?

+1

Questo potrebbe essere utile, ho fatto una domanda simile, ma non nodo correlati: http://stackoverflow.com/questions/6885659/determining-source-line-and-file-of-function-reference-how -does-firebug-do-it –

risposta

43

Utilizza informazioni dalla qui: Accessing line number in V8 JavaScript (Chrome & Node.js)

è possibile aggiungere alcuni prototipi per fornire l'accesso a questo informazioni da V8:

Object.defineProperty(global, '__stack', { 
get: function() { 
     var orig = Error.prepareStackTrace; 
     Error.prepareStackTrace = function(_, stack) { 
      return stack; 
     }; 
     var err = new Error; 
     Error.captureStackTrace(err, arguments.callee); 
     var stack = err.stack; 
     Error.prepareStackTrace = orig; 
     return stack; 
    } 
}); 

Object.defineProperty(global, '__line', { 
get: function() { 
     return __stack[1].getLineNumber(); 
    } 
}); 

Object.defineProperty(global, '__function', { 
get: function() { 
     return __stack[1].getFunctionName(); 
    } 
}); 

function foo() { 
    console.log(__line); 
    console.log(__function); 
} 

foo() 

Restituisce '28' e 'pippo', rispettivamente.

+1

Grazie Joe.Forse '__line' e' __function' potrebbero essere meglio chiamati '__parent_line' e' __parent_function_name', ma per il resto questo è ottimo (ed è, per inciso, come 'stack-trace' funziona nella mia risposta). –

+0

Usano il secondo frame altrimenti si otterrebbero solo informazioni su __line e __function. :) Interessante su 'stack-trace' dovrà essere verificato. – Joe

+0

Mentre questa soluzione è ottima, è costosa. Non lo userei nel codice di produzione. Se usi logger bunyan, puoi attivare [opzione src] (https://github.com/trentm/node-bunyan#src). Ma ancora una volta, non raccomandano questa opzione per il codice di produzione. Mi piacerebbe un transpiler in grado di sostituire ogni chiamata del registratore con le informazioni sul nome della funzione e il numero di riga prima di eseguire il mio codice. Chiunque ?? – Vibgy

12

ho trovato e installato il modulo node-stack-trace (installato con npm install stack-trace), e quindi definito echo come:

function echo() { 
    var args, file, frame, line, method; 
    args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; 

    frame = stackTrace.get()[1]; 
    file = path.basename(frame.getFileName()); 
    line = frame.getLineNumber(); 
    method = frame.getFunctionName(); 

    args.unshift("" + file + ":" + line + " in " + method + "()"); 
    return log.info.apply(log, args); // changed 'debug' to canonical npmlog 'info' 
}; 
+0

Questo è molto bello, per le altre persone cambiare le righe sopra a questo: args = 1 <= arguments.length? [] .slice.call (argomenti, 0): []; return console.log.apply (this, args); – Kus

+0

Grazie, sto utilizzando Titanium e ho ottenuto questa funzione per registrare l'origine del messaggio: '' 'function log (msg) { stackTrace = require (" stack-trace/lib/stack-trace "); var thistrace = stackTrace.get(); var parent_name = thistrace [1] .getFunctionName(); var parent_eval = thistrace [1] .getEvalOrigin(); msg = sprintf ("[% s] [% s]:% s", parent_eval, parent_name, msg); Ti.API.info (msg); } '' ' –

9

Avevo anche requisiti simili. Ho usato la proprietà stack della classe Error fornita da nodejs.
Sto ancora imparando nodo così, ci possono essere possibilità di errore.

Di seguito è la spiegazione per lo stesso. Modulo npm creato anche per la stessa, se si vuole, è possibile controllare a:
1. npm module 'logat'
2. git repo

supponiamo che l'oggetto 'logger' con il metodo 'log'

var logger = { 
log: log 
} 
function log(msg){ 
    let logLineDetails = ((new Error().stack).split("at ")[3]).trim(); 
    console.log('DEBUG', new Date().toUTCString(), logLineDetails, msg); 
} 

esempio:

//suppose file name: /home/vikash/example/age.js 
function getAge(age) { 
    logger.log('Inside getAge function'); //suppose line no: 9 
} 

uscita del precedente esempio:

DEBUG on Sat, 24 Sept 2016 12:12:10 GMT at getAge(/home/vikash/example/age.js:9:12) 
    Inside getAge function 
Problemi correlati