¿Cómo consigo que ruby imprima una traza inversa completa en lugar de una truncada?


Cuando obtengo excepciones, a menudo es desde lo profundo de la pila de llamadas. Cuando esto sucede, la mayoría de las veces, la línea ofensiva real de código se me oculta:

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

Que "... 8 niveles..."el truncamiento me está causando muchos problemas. No estoy teniendo mucho éxito buscando en Google este: ¿Cómo le digo a ruby que quiero que los volcados incluyan la pila completa?

Author: Franklin Yu, 2008-12-18

8 answers

Exception # backtrace tiene toda la pila en ella:

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

(Inspirado en el blog de Peter Cooper Ruby Inside )

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-20 11:31:36

También podría hacer esto si desea un simple de una sola línea:

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-24 10:52:43

Esto produce la descripción del error y una buena traza limpia y con sangría:

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-16 14:41:48

IRB tiene una configuración para esta horrible "característica", que puede personalizar.

Crea un archivo llamado ~/.irbrc que incluya la siguiente línea:

IRB.conf[:BACK_TRACE_LIMIT] = 100

Esto le permitirá ver 100 marcos de pila en irb, al menos. No he podido encontrar una configuración equivalente para el tiempo de ejecución no interactivo.

Se puede encontrar información detallada sobre la personalización de IRB en el libro de Pickaxe .

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-26 21:48:55

Un forro para callstack:

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

Un forro para callstack sin todas las gemas:

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

Un liner para callstack sin todas las gemas y relativo al directorio actual

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-07 19:27:43

Esto imita el rastro oficial de Ruby, si eso es importante para usted.

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

Curiosamente, no maneja 'excepción no controlada' correctamente, reportándolo como 'RuntimeError', pero la ubicación es correcta.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-04 10:57:40

Estaba recibiendo estos errores al intentar cargar mi entorno de prueba (a través de rake test o autotest) y las sugerencias IRB no ayudaron. Terminé envolviendo todo mi test / test_helper.rb en un bloque de inicio/rescate y eso arregló las cosas.

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-31 20:24:44

[examinar todos los hilos de vuelta para encontrar al culpable]
¡Incluso la pila de llamadas completamente expandida puede ocultar la línea de código ofensiva real de usted cuando usa más de un hilo!

Ejemplo: Un hilo está iterando ruby Hash, otro hilo está tratando de modificarlo. BOOM! Excepción! Y el problema con el seguimiento de pila que obtienes al intentar modificar el hash 'ocupado' es que te muestra una cadena de funciones hasta el lugar donde intentas modificar el hash, pero no lo hace ¡muestra quién lo está iterando en paralelo (quién lo posee)! Esta es la manera de averiguarlo imprimiendo stack trace para TODOS los subprocesos actualmente en ejecución. Así es como se hace esto:

# 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

El fragmento de código anterior es útil incluso con fines educativos, ya que puede mostrarle (como x-ray) cuántos hilos tiene en realidad (frente a cuántos pensó que tenía, muy a menudo esos dos son números diferentes;)

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-23 19:00:52