Wie drucke ich einen Stack-Trace in Node.js?

Antworten:

615

Jedes ErrorObjekt hat ein stackElement, das den Punkt abfängt, an dem es erstellt wurde.

var stack = new Error().stack
console.log( stack )

oder einfacher:

console.trace("Here I am!")
isaacs
quelle
1
oder einfach sys.puts(new Error().stack)(nach dem Hinzufügen des Systemmoduls)
sirhc
5
Ab sofort ist sys beraubt. Es wird ersetzt durch 'util'.
Pindatjuh
12
+1 für das Anzeigen new Error().stack, was in Fällen funktioniert, in denen Sie die Konsole nicht einbeziehen möchten.
Eugene Beresovsky
1
Ein Vorteil von traceist, dass es auch die aktuelle Zeile / den aktuellen Kontext anzeigt, was stacknicht der Fall ist. Die Informationen befinden sich im Fehlerobjekt, wenn Sie diese Zeile manuell erstellen möchten.
Studgeek
130
console.log (err.stack) und console.trace () liefern nicht die gleichen Ergebnisse. Während err.stack Ihnen den Stack-Trace für das err-Objekt selbst gibt (so wie wir es normalerweise von Ausnahmen halten), druckt console.trace () den Aufrufstapel an der Stelle aus, an der console.trace () aufgerufen wird. Wenn Sie also einen Fehler bemerken, der von einer tieferen Codeebene ausgelöst wird, enthält console.trace () diesen tieferen Ebenencode nicht in der Stapelverfolgung, da sich dieser Code nicht mehr auf dem Stapel befindet. Console.log (err.stack) enthält jedoch die tieferen Ebenen, solange ein Fehlerobjekt ausgelöst wird.
d512
200

Jetzt gibt es eine spezielle Funktion auf der Konsole dafür:

console.trace()
Mariusz Nowak
quelle
11
Beachten Sie einfach den obigen Kommentar zu console.trace().
Qix - MONICA wurde
5
Standardmäßig werden nur 10 Frames angezeigt. Sie können das Befehlszeilenargument verwenden, um dies zu erhöhen, z. B.--stack_trace_limit=200
Michael,
Was ist, wenn Sie in eine Protokolldatei ausgeben möchten?
Ja.
Das scheint nicht mit Versprechungen und Async / Warten zu funktionieren, oder?
bluenote10
97

Wie bereits beantwortet, können Sie einfach den Befehl trace verwenden :

console.trace("I am here");

Allerdings , wenn Sie auf diese Frage kommen Benutzer darüber , wie der Stack - Trace einer Ausnahme zu protokollieren , können Sie einfach das Exception - Objekt anmelden.

try {  
  // if something unexpected
  throw new Error("Something unexpected has occurred.");     

} catch (e) {
  console.error(e);
}

Es wird protokolliert:

Fehler: Es ist etwas Unerwartetes aufgetreten.
    at main (c: \ Users \ Me \ Documents \ MyApp \ app.js: 9: 15)
    at Object. (c: \ Benutzer \ Me \ Dokumente \ MyApp \ app.js: 17: 1)
    unter Module._compile (module.js: 460: 26)
    unter Object.Module._extensions..js (module.js: 478: 10 )
    bei Module.load (module.js: 355: 32)
    bei Function.Module._load (module.js: 310: 12)
    bei Function.Module.runMain (module.js: 501: 10)
    beim Start (node.js) : 129: 16)
    bei node.js: 814: 3


Wenn Ihre Node.js-Version <als 6.0.0 ist , reicht die Protokollierung des Exception-Objekts nicht aus. In diesem Fall wird nur gedruckt:

[Fehler: Es ist etwas Unerwartetes aufgetreten.]

Verwenden Sie für die Knotenversion <6 console.error(e.stack)anstelle von console.error(e), um die Fehlermeldung plus den vollständigen Stapel zu drucken, wie dies bei der aktuellen Knotenversion der Fall ist.


Hinweis: Wenn die Ausnahme wie eine Zeichenfolge erstellt wird throw "myException", ist es nicht möglich, die Stapelverfolgung abzurufen, und die Protokollierung e.stackliefert undefinierte Ergebnisse .

Um sicher zu gehen, können Sie verwenden

console.error(e.stack || e);

und es wird für alte und neue Node.js-Versionen funktionieren.

Zanon
quelle
Wird nicht console.error(e)drucken alles im eObjekt, einschließlich e.stack?
drmrbrewer
1
@drmrbrewer, danke, dass du darauf hingewiesen hast. Es scheint, dass sich das Verhalten zwischen den Knotenversionen 4.x und 7.x geändert hat (wahrscheinlich eine V8-Änderung). Ich habe meine Antwort aktualisiert.
Zanon
1
@drmrbrewer bestätigte, dass sich dieses Verhalten in Version 6.0.0
Zanon
2
Entschuldigung, ich habe gerade etwas Entscheidendes entdeckt. Siehe meinen Kommentar zum entsprechenden Beitrag: stackoverflow.com/questions/42528677/… . Es scheint, dass das Protokollieren des Fehlers allein tatsächlich den gesamten Inhalt des Fehlers anzeigt. Wenn Sie jedoch versuchen, ihn (wie eine Zeichenfolge) mit anderem Text zu verketten, wird nur der kurze Nachrichtenteil verwendet. Mit dieser Erkenntnis macht alles viel mehr Sinn.
drmrbrewer
1
Sie retten meinen Tag)
Alex
39

So drucken Sie die Stapelverfolgung Errorin der Konsole besser lesbar:

console.log(ex, ex.stack.split("\n"));

Beispielergebnis:

[Error] [ 'Error',
  '    at repl:1:7',
  '    at REPLServer.self.eval (repl.js:110:21)',
  '    at Interface.<anonymous> (repl.js:239:12)',
  '    at Interface.EventEmitter.emit (events.js:95:17)',
  '    at Interface._onLine (readline.js:202:10)',
  '    at Interface._line (readline.js:531:8)',
  '    at Interface._ttyWrite (readline.js:760:14)',
  '    at ReadStream.onkeypress (readline.js:99:10)',
  '    at ReadStream.EventEmitter.emit (events.js:98:17)',
  '    at emitKey (readline.js:1095:12)' ]
ruX
quelle
5

Versuchen Sie Error.captureStackTrace (targetObject [, constructorOpt]) .

const myObj = {};
function c() {
  // pass
}

function b() {
    Error.captureStackTrace(myObj)
    c()
} 

function a() {
    b()
}

a()

console.log(myObj.stack)

Die Funktion aund bwerden im Fehlerstapel erfasst und in gespeichert myObj.

Zheeeng
quelle
2
Wenn ein Fehler eine stackEigenschaft haben soll, müssen Sie dies aufrufen, wenn Node> = 6 : Error.captureStackTrace(error).
CJBarth
Wenn Sie nicht möchten, dass der aufgerufene Frame Error.captureStackTraceim Stack-Trace angezeigt wird, können Sie ihn weglassen, indem Sie ihn als constructorOptArgument übergeben.
Ullauri
3

Soweit ich weiß, ist das Drucken des vollständigen Stack-Trace in NodeJS nicht möglich. Sie können einfach einen "partiellen" Stack-Trace drucken. Sie können nicht sehen, woher Sie im Code stammen und wo die Ausnahme auftritt. Das erklärt Ryan Dahl in diesem Youtube-Video. http://youtu.be/jo_B4LTHi3I um mindestens 56:30 Uhr, um genau zu sein. Hoffe das hilft

ElHacker
quelle
2
stimmt, aber das Modul in @ Timboudreaus Antwort "behebt" das
Bogdan D
3

Die Antwort von @isaacs ist korrekt, aber wenn Sie einen spezifischeren oder saubereren Fehlerstapel benötigen , können Sie diese Funktion verwenden:

function getCleanerStack() {
   var err = new Error();
   Error.captureStackTrace(err, getStack);

   return err.stack;
}

Diese Funktion ist direkt von der console.traceFunktion in inspiriert NodeJS .

Quellcode: Aktuelle Version oder alte Version .

Thaddäus-Tentakel
quelle
1
Es funktioniert nicht, zeigt nur den Stapel der aktuellen Zeile an (nicht die Zeile, in der dieser Fehler aufgetreten ist). err.stackist die richtige Antwort.
Ian Zhong
2

Wenn Sie nur den Stack-Trace des Fehlers (und nicht die Fehlermeldung) protokollieren möchten, enthält Knoten 6 und höher automatisch den Fehlernamen und die Meldung im Stack-Trace. Dies ist etwas ärgerlich, wenn Sie eine benutzerdefinierte Fehlerbehandlung durchführen möchten:

console.log(error.stack.replace(error.message, ''))

Bei dieser Problemumgehung werden nur der Fehlername und die Stapelverfolgung protokolliert (so können Sie beispielsweise die Fehlermeldung formatieren und an einer anderen Stelle in Ihrem Code anzeigen, wie Sie möchten).

Das obige Beispiel würde nur den Fehlernamen drucken, dem die Stapelverfolgung folgt, zum Beispiel:

Error: 
    at /Users/cfisher/Git/squashed/execProcess.js:6:17
    at ChildProcess.exithandler (child_process.js:213:5)
    at emitTwo (events.js:106:13)
    at ChildProcess.emit (events.js:191:7)
    at maybeClose (internal/child_process.js:877:16)
    at Socket.<anonymous> (internal/child_process.js:334:11)
    at emitOne (events.js:96:13)
    at Socket.emit (events.js:188:7)
    at Pipe._handle.close [as _onclose] (net.js:498:12)

Anstatt:

Error: Error: Command failed: sh ./commands/getBranchCommitCount.sh HEAD
git: 'rev-lists' is not a git command. See 'git --help'.

Did you mean this?
        rev-list

    at /Users/cfisher/Git/squashed/execProcess.js:6:17
    at ChildProcess.exithandler (child_process.js:213:5)
    at emitTwo (events.js:106:13)
    at ChildProcess.emit (events.js:191:7)
    at maybeClose (internal/child_process.js:877:16)
    at Socket.<anonymous> (internal/child_process.js:334:11)
    at emitOne (events.js:96:13)
    at Socket.emit (events.js:188:7)
    at Pipe._handle.close [as _onclose] (net.js:498:12)
GrayedFox
quelle
1

Falls jemand immer noch so sucht wie ich, dann gibt es ein Modul namens "Stack-Trace". Es ist sehr beliebt. NPM Link

Dann gehen Sie durch die Spur.

  var stackTrace = require('stack-trace');
  .
  .
  .
  var trace = stackTrace.get();
  trace.map(function (item){ 
    console.log(new Date().toUTCString() + ' : ' +  item.toString() );  
  });

Oder drucken Sie einfach die Spur aus:

var stackTrace = require('stack-trace');
.
.
.
var trace = stackTrace.get();
trace.toString();
Laszlo
quelle
0

Sie können das Node-Stack-Trace- Modul verwenden, bei dem es sich um ein Power-Full-Modul handelt, um Anrufstapel zu verfolgen.

Nitin9791
quelle