Jak uzyskać wynik console.trace () jako ciąg znaków w javascript z chrome lub firefox?

99

console.trace()wyświetla wynik na konsoli.
Chcę otrzymać wyniki jako ciąg znaków i zapisać je do pliku.

Nie definiuję nazw funkcji i nie mogę też uzyskać ich nazw callee.caller.name.

js_
źródło
1
to nie działa w PhantomJS :(
ekkis

Odpowiedzi:

103

Nie jestem pewien co do przeglądarki Firefox, ale w wersji 8 / chrome można użyć metody w konstruktorze Error o nazwie captureStackTrace. ( Więcej informacji tutaj )

Tak więc hacky sposób to:

var getStackTrace = function() {
  var obj = {};
  Error.captureStackTrace(obj, getStackTrace);
  return obj.stack;
};

console.log(getStackTrace());

Normalnie getStackTraceznajdowałby się na stosie, gdy zostanie przechwycony. Drugi argument wyklucza getStackTracedołączenie go do śladu stosu.

chjj
źródło
18
Dziękuję za informację. To działało w Chrome, ale nie działało w Firefoksie. Więc szukałem ponownie i znalazłem Error().stack. Chociaż nazwy obiektów i funkcji są tracone w Firefoksie, a nazwa obiektu jest tracona w chrome (tak samo jak Error.captureStackTrace), Error().stackdziała w obu przeglądarkach i daje mi wystarczająco dużo informacji do debugowania.
js_
Dokładnie taki sam wynik jak odpowiedź @Konstantin Smolyanin. W rezultacie te same ograniczone szczegóły.
Codebeat
To nie powinna być akceptowana odpowiedź. Otrzymany tutaj stos jest „obcięty” i zawiera tylko „górną część”, podczas gdy console.trace () pokaże pełny stos. Zobacz przykład z głębokością stosu 30 tutaj: stackoverflow.com/questions/62768598/…
mathheadinclouds
34

Error.stack jest tym, czego potrzebujesz. Działa w Chrome i Firefox. Na przykład

try { var a = {}; a.debug(); } catch(ex) {console.log(ex.stack)}

da w Chrome:

TypeError: Object #<Object> has no method 'debug'
    at eval at <anonymous> (unknown source)
    at eval (native)
    at Object._evaluateOn (unknown source)
    at Object._evaluateAndWrap (unknown source)
    at Object.evaluate (unknown source)

aw przeglądarce Firefox:

@http://www.google.com.ua/:87 _firebugInjectedEvaluate("with(_FirebugCommandLine){try { var a = {}; a.debug() } catch(ex) {console.log(ex.stack)}\n};")
@http://www.google.com.ua/:87 _firebugEvalEvent([object Event])
@http://www.google.com.ua/:67
Molecular Man
źródło
2
Dziękuję za odpowiedź. Ale to działa tylko wtedy, gdy wystąpił wyjątek. Muszę uzyskać ślad stosu bez wyjątku.
js_
8
A co z(new Error).stack
JasonSmith,
Powinno to spowodować wyjątek w a.debug () - jest to kosztowny sposób na pobranie stosu, ale powinien działać.
fijiaaron
To podejście jest również przydatne, gdy próbujesz uzyskać ślad z jakiegoś kodu, który może działać tylko na, np. PhantomJS lub podobnym, z dowolnego powodu.
Waxspin
18

To da ślad stosu (jako tablicę ciągów) dla nowoczesnych przeglądarek Chrome, Firefox, Opera i IE10 +

function getStackTrace () {

  var stack;

  try {
    throw new Error('');
  }
  catch (error) {
    stack = error.stack || '';
  }

  stack = stack.split('\n').map(function (line) { return line.trim(); });
  return stack.splice(stack[0] == 'Error' ? 2 : 1);
}

Stosowanie:

console.log(getStackTrace().join('\n'));

Wyklucza ze stosu własne wywołanie, a także tytuł „Błąd” używany przez przeglądarki Chrome i Firefox (ale nie IE).

Nie powinno się zawieszać w starszych przeglądarkach, ale po prostu zwrócić pustą tablicę. Jeśli potrzebujesz bardziej uniwersalnego rozwiązania, spójrz na stacktrace.js . Lista obsługiwanych przeglądarek jest naprawdę imponująca, ale moim zdaniem jest bardzo duża jak na to małe zadanie, do którego jest przeznaczone: 37 KB zminimalizowanego tekstu wraz ze wszystkimi zależnościami.

Konstantin Smolyanin
źródło
12

Istnieje biblioteka o nazwie stacktrace.js, która umożliwia śledzenie stosu w różnych przeglądarkach. Możesz go użyć po prostu dołączając skrypt i wywołując w dowolnym momencie:

var trace = printStackTrace();
fijiaaron
źródło
Spojrzałbym na github.com/stacktracejs/stacktrace.js, ponieważ implementacja zmieniła się, aby obsługiwać obietnice ES6.
Erez Cohen
Zauważ, że na razie należy tego użyć: github.com/stacktracejs/stacktrace.js/tree/stable?files=1 (nowa wersja nie została jeszcze wydana)
Erez Cohen
10

To tylko niewielkie ulepszenie doskonałego kodu Konstantina. Zmniejsza to trochę koszt rzucania i łapania i po prostu tworzy instancję stosu błędów:

function getStackTrace () {
    let stack = new Error().stack || '';
    stack = stack.split('\n').map(function (line) { return line.trim(); });
    return stack.splice(stack[0] == 'Error' ? 2 : 1);
}

Zwykle chcę mieć określony poziom śledzenia stosu (dla mojego niestandardowego rejestratora), więc jest to również możliwe podczas wywoływania:

getStackTrace()[2]; // get stack trace info 2 levels-deep
sgouros
źródło
6

potrzebujesz tylko var stack = new Error().stack. to jest uproszczona wersja odpowiedzi @sgouros.

function foo() {
  bar();
}
function bar() {
  baz();
}
function baz() {
  console.log(new Error().stack);
}

foo();

Prawdopodobnie nie będzie działać w każdej przeglądarce (działa w Chrome).

jcubic
źródło