Jak sprawić, by ruby wydrukował pełną wersję backtrace zamiast okrojonej?

Kiedy dostaję wyjątki, często jest to z głębi stosu wywołań. Kiedy tak się dzieje, częściej niż nie, rzeczywista linia kodu jest ukryta przede mną:

tmp.rb:7:in `t': undefined method `bar' for nil:NilClass (NoMethodError)
        from tmp.rb:10:in `s'
        from tmp.rb:13:in `r'
        from tmp.rb:16:in `q'
        from tmp.rb:19:in `p'
        from tmp.rb:22:in `o'
        from tmp.rb:25:in `n'
        from tmp.rb:28:in `m'
        from tmp.rb:31:in `l'
         ... 8 levels...
        from tmp.rb:58:in `c'
        from tmp.rb:61:in `b'
        from tmp.rb:64:in `a'
        from tmp.rb:67

To "... 8 poziomów..."okrojenie sprawia mi wiele kłopotów. Nie mam większego powodzenia w googlowaniu tego: jak powiedzieć rubiemu, że chcę, aby zrzuty zawierały pełny stos?

Author: Franklin Yu, 2008-12-18

8 answers

Wyjątek#backtrace ma w sobie cały stos:

def do_division_by_zero; 5 / 0; end
begin
  do_division_by_zero
rescue => exception
  puts exception.backtrace
  raise # always reraise
end

(Zainspirowany przez Peter Cooper 'S Ruby Inside blog)

 188
Author: Gareth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-20 11:31:36

Możesz też to zrobić, jeśli chcesz prostą jednolinijkową:

puts caller
 149
Author: anonymous coward,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-24 10:52:43

To tworzy opis błędu i ładne czyste, wcięte stacktrace:

begin               
 # Some exception throwing code
rescue => e
  puts "Error during processing: #{$!}"
  puts "Backtrace:\n\t#{e.backtrace.join("\n\t")}"
end
 91
Author: Ben,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-16 14:41:48

IRB ma ustawienie dla tej okropnej "funkcji", którą można dostosować.

Utwórz plik o nazwie ~/.irbrc, który zawiera następującą linię:

IRB.conf[:BACK_TRACE_LIMIT] = 100

To pozwoli Ci zobaczyć przynajmniej 100 klatek stosu w irb. Nie udało mi się znaleźć równoważnego ustawienia dla nieinteraktywnego środowiska wykonawczego.

Szczegółowe informacje na temat personalizacji IRB można znaleźć w kilof book.

 42
Author: robinluckey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-26 21:48:55

Jedna linijka dla callstack:

begin; Whatever.you.want; rescue => e; puts e.message; puts; puts e.backtrace; end

Jeden liner do callstacka bez wszystkich klejnotów:

begin; Whatever.you.want; rescue => e; puts e.message; puts; puts e.backtrace.grep_v(/\/gems\//); end

Jeden liner dla callstack bez wszystkich klejnotów i względem bieżącego katalogu

begin; Whatever.you.want; rescue => e; puts e.message; puts; puts e.backtrace.grep_v(/\/gems\//).map { |l| l.gsub(`pwd`.strip + '/', '') }; end
 9
Author: Dorian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-07 19:27:43

To naśladuje oficjalny ślad Ruby, jeśli to dla Ciebie ważne.

begin
  0/0  # or some other nonsense
rescue => e
  puts e.backtrace.join("\n\t")
       .sub("\n\t", ": #{e}#{e.class ? " (#{e.class})" : ''}\n\t")
end

Zabawne, że nie obsługuje poprawnie "nieobsługiwanego wyjątku", zgłaszając go jako "RuntimeError", ale lokalizacja jest poprawna.

 6
Author: android.weasel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-04 10:57:40

Otrzymywałem te błędy podczas próby załadowania środowiska testowego (przez test rake lub autotest) i sugestie IRB nie pomogły. Skończyłem owijając cały mój test / test_helper.rb w bloku start/rescue i to wszystko naprawiło.

begin
  class ActiveSupport::TestCase
    #awesome stuff
  end
rescue => e
  puts e.backtrace
end
 3
Author: Ryan Angilly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-31 20:24:44

[sprawdź wszystkie wątki Wstecz, aby znaleźć winowajcę]
Nawet w pełni rozszerzony stos połączeń może nadal ukrywać rzeczywistą linię kodu, gdy używasz więcej niż jednego wątku!

Przykład: jeden wątek jest iteracją Ruby Hash, inny wątek próbuje go zmodyfikować. Bum! Wyjątek! Problem ze śladem stosu, który pojawia się podczas próby zmodyfikowania hash 'busy' polega na tym, że pokazuje on łańcuch funkcji aż do miejsca, w którym próbujesz zmodyfikować hash, ale nie pokaż, kto jest obecnie iteracją równolegle (kto jest właścicielem)! Oto sposób, aby to sprawdzić, drukując ślad stosu dla wszystkich aktualnie uruchomionych wątków. Oto jak to zrobić:

# This solution was found in comment by @thedarkone on https://github.com/rails/rails/issues/24627
rescue Object => boom

    thread_count = 0
    Thread.list.each do |t|
      thread_count += 1
      err_msg += "--- thread #{thread_count} of total #{Thread.list.size} #{t.object_id} backtrace begin \n"
      # Lets see if we are able to pin down the culprit
      # by collecting backtrace for all existing threads:
      err_msg += t.backtrace.join("\n")
      err_msg += "\n---thread #{thread_count} of total #{Thread.list.size} #{t.object_id} backtrace end \n"
    end

    # and just print it somewhere you like:
    $stderr.puts(err_msg)

    raise # always reraise
end

Powyższy fragment kodu jest przydatny nawet do celów edukacyjnych, ponieważ może pokazać (jak np. rentgen), ile wątków faktycznie masz (w porównaniu z tym, jak wiele myślałeś, że masz - dość często te dwie liczby są różne;) {]}

 0
Author: Dmitry Shevkoplyas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-23 19:00:52