Как напечатать трассировку стека в Node.js?

Ответы:

615

Любой Errorобъект имеет stackчлен, который захватывает точку, в которой он был построен.

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

или проще:

console.trace("Here I am!")
Айзекс
источник
1
или просто sys.puts(new Error().stack)(после добавления системного модуля)
sirhc
5
На данный момент sys ограничен. Он заменен на 'util'.
Пиндатюх
12
+1 также за показ new Error().stack, который работает в тех случаях, когда вы не хотите задействовать консоль.
Евгений Бересовский
1
Одним из преимуществ traceявляется то, что он показывает текущую строку / контекст, а также stackнет. Информация находится в объекте ошибки, если вы хотите вручную создать эту строку, я думаю.
Studgeek
130
console.log (err.stack) и console.trace () не дают одинаковых результатов. В то время как err.stack дает вам трассировку стека для самого объекта err (функционирующего так, как мы все обычно думаем об исключениях), console.trace () распечатает стек вызовов в точке, где вызывается console.trace (). Поэтому, если вы поймете, что какой-то более глубокий уровень кода выдает какую-то ошибку, console.trace () не будет содержать этот более глубокий уровень кода в трассировке стека, поскольку этот код больше не находится в стеке. Однако console.log (err.stack) будет содержать более глубокие слои, пока он генерирует объект Error.
d512
200

Теперь на консоли есть специальная функция для этого:

console.trace()
Мариуш Новак
источник
11
Просто убедитесь , что прислушаться вышеупомянутый комментарий о console.trace().
Qix - МОНИКА БЫЛА НЕЗАБЫВАЕМАЯ
5
По умолчанию это будет показывать только 10 кадров, вы можете использовать аргумент командной строки, чтобы увеличить это, например--stack_trace_limit=200
Майкл
1
Что делать, если вы хотите вывести в файл журнала?
Я.
Кажется, это не работает с обещаниями и асинхронностью / ожиданием?
bluenote10
97

Как уже ответили, вы можете просто использовать команду трассировки :

console.trace("I am here");

Однако, если вы пришли к этому вопросу в поисках того, как зарегистрировать трассировку стека исключения , вы можете просто зарегистрировать объект Exception.

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

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

Это войдет:

Ошибка: произошло нечто неожиданное.
    в основном (c: \ Users \ Me \ Documents \ MyApp \ app.js: 9: 15)
    в Object. (c: \ Users \ Me \ Documents \ MyApp \ app.js: 17: 1)
    в Module._compile (module.js: 460: 26)
    в Object.Module._extensions..js (module.js: 478: 10 )
    в Module.load (module.js: 355: 32)
    в Function.Module._load (module.js: 310: 12)
    в Function.Module.runMain (module.js: 501: 10)
    при запуске (node.js) : 129: 16)
    в node.js: 814: 3


Если ваша версия Node.js <6.0.0 , регистрации объекта Exception будет недостаточно. В этом случае он будет печатать только:

[Ошибка: произошло нечто неожиданное.]

Для версии узла <6 используйте console.error(e.stack)вместо console.error(e)печати сообщение об ошибке плюс полный стек, как в текущей версии узла.


Примечание: если исключение создается в виде строки throw "myException", невозможно получить трассировку стека и e.stackвыходы журналов не определены .

Чтобы быть в безопасности, вы можете использовать

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

и это будет работать для старых и новых версий Node.js.

Zanon
источник
Не будет console.error(e)печатать все в eобъекте, в том числе e.stack?
drmrbrewer
1
@drmrbrewer, спасибо, что указали на это. Кажется, что поведение изменилось между версиями Node 4.x и 7.x (вероятно, изменение V8). Я обновил свой ответ.
Zanon
1
@drmrbrewer подтвердил, что это поведение изменилось в версии 6.0.0
Zanon
2
извините, я только что обнаружил что-то важное. Смотрите мой комментарий к соответствующему сообщению: stackoverflow.com/questions/42528677/… . Кажется, что регистрация ошибки сама по себе действительно показывает все содержание ошибки, но попытка связать ее (например, строку) с другим текстом приведет к использованию только части краткого сообщения. Все это имеет больше смысла в этой реализации.
drmrbrewer
1
ты спас мой день)
Алекс
39

Чтобы распечатать трассировку стека Errorв консоли более читабельным способом:

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

Пример результата:

[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
источник
9

С легкодоступным модулем Node можно получить трассировки стека полной длины из Node (хотя и с небольшим снижением производительности): http://www.mattinsler.com/post/26396305882/announcing-longjohn-long-stack -traces-для-узла-JS

Тим Будро
источник
4
Ссылка устарела, но вы можете просмотреть архивную копию здесь или проверить библиотеку .
Кодирование
5

Попробуйте Error.captureStackTrace (targetObject [, constructorOpt]) .

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

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

function a() {
    b()
}

a()

console.log(myObj.stack)

Функция aи bфиксируется в стеке ошибок и сохраняется в myObj.

Zheeeng
источник
2
Если вы хотите об ошибке иметь stackсвойство, вам нужно вызвать это , если узел> = 6: Error.captureStackTrace(error).
cjbarth
Обратите внимание, что если вы не хотите, чтобы фрейм, который вызывал, Error.captureStackTraceотображался в трассировке стека, вы можете опустить его, передав его в качестве constructorOptаргумента.
Ullauri
3

Насколько я знаю, печать полной трассировки стека в nodejs невозможна, вы можете просто напечатать «частичную» трассировку стека, вы не можете видеть, откуда вы пришли в коде, именно там, где происходит исключение. Это то, что Райан Даль объясняет в этом видео на YouTube. http://youtu.be/jo_B4LTHi3I в мин 56:30 за точность. Надеюсь это поможет

ElHacker
источник
2
правда, но модуль в ответе @ Timboudreau "исправляет", что
Богдан D
3

Ответ @isaacs правильный, но если вам нужен более конкретный или более чистый стек ошибок , вы можете использовать эту функцию:

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

   return err.stack;
}

Эта функция вдохновлена ​​непосредственно из console.traceфункции в NodeJS .

Исходный код: Последняя версия или Старая версия .

Щупальца кальмара
источник
1
это не работает, только показывает стек из текущей строки (а не строки, в которой произошла эта ошибка). err.stackболее правильный ответ.
Ян Чжун
2

Если вы хотите регистрировать только трассировку стека ошибки (а не сообщения об ошибке), узел 6 и выше автоматически включает имя ошибки и сообщение в трассировку стека, что немного раздражает, если вы хотите выполнить некоторую пользовательскую обработку ошибок:

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

Этот обходной путь будет регистрировать только имя ошибки и трассировку стека (так что вы можете, например, отформатировать сообщение об ошибке и отобразить его так, как вы хотите где-то еще в вашем коде).

В приведенном выше примере будет напечатано только имя ошибки, за которым следует трассировка стека, например:

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)

Вместо:

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
источник
1

В случае, если кто-то все еще ищет это, как я, то есть модуль, который мы можем использовать, называемый «трассировка стека». Это действительно популярно. НПМ Ссылка

Затем идите по следу.

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

Или просто напечатайте след:

var stackTrace = require('stack-trace');
.
.
.
var trace = stackTrace.get();
trace.toString();
Laszlo
источник