web-dev-qa-db-fra.com

Comment obtenir un objet trace de pile dans Ruby?

J'ai besoin d'obtenir un objet trace de pile dans Ruby; ne pas l'imprimer, juste pour le faire enregistrer et vider pour une analyse ultérieure. Est-ce possible? Comment?

57
pupeno

Vous pouvez utiliser Kernel.caller pour cela. La même méthode est utilisée lors de la génération de traces de pile pour les exceptions.

De la documentation:

def a(skip)
  caller(skip)
end
def b(skip)
  a(skip)
end
def c(skip)
  b(skip)
end
c(0) #=> ["prog:2:in `a'", "prog:5:in `b'", "prog:8:in `c'", "prog:10"]
c(1) #=> ["prog:5:in `b'", "prog:8:in `c'", "prog:11"]
c(2) #=> ["prog:8:in `c'", "prog:12"]
c(3) #=> ["prog:13"]
79
Sven Koschnicke

Essayer

Thread.current.backtrace.join("\n")
31
Alex Bondar

Essayez error.backtrace :

# Returns any backtrace associated with the exception.  
# The backtrace is an array of strings, each containing either ``filename:lineNo: in `method’’’ or ``filename:lineNo.’‘

def a
  raise "boom"
end

def b
  a()
end

begin
  b()
rescue => detail
  print detail.backtrace.join("\n")
end

produit:

prog.rb:2:in `a'
prog.rb:6:in `b'
prog.rb:10
12
Nikita Rybak

Pour Ruby 2.0+, vous pouvez utiliser Kernel#caller_locations . C'est essentiellement la même chose que Kernel#caller (couvert par réponse de Sven Koschnicke ), sauf qu'au lieu de renvoyer un tableau de chaînes, il retourne un tableau de Thread::Backtrace::Location objets. Thread::Backtrace::Location fournit des méthodes telles que path , lineno et base_label , ce qui peut être utile lorsque vous avez besoin d'accéder à des détails spécifiques sur la trace de la pile, et pas seulement à une chaîne brute.

De les docs :

caller_locations (start = 1, length = nil) → array or nil

caller_locations (range) → tableau ou nil

Renvoie la pile d'exécution actuelle, un tableau contenant des objets d'emplacement de trace arrière.

Voir Thread::Backtrace::Location pour plus d'informations.

Le paramètre de démarrage facultatif détermine le nombre d'entrées de pile initiales à omettre du haut de la pile.

Un deuxième paramètre facultatif length peut être utilisé pour limiter le nombre d'entrées renvoyées par la pile.

Renvoie nil si start est supérieur à la taille de la pile d'exécution actuelle.

Facultativement, vous pouvez passer une plage, qui renverra un tableau contenant les entrées dans la plage spécifiée.

Exemple d'utilisation:

def a
  caller_locations(0)
end
def b
  a
end
def c
  b
end

c.map(&:base_label)
#=> ["a", "b", "c", "<main>"]
7
Ajedi32
Thread.current.backtrace

Cela vous donnera un tableau qui contient toutes les lignes que vous pouvez obtenir dans n'importe quelle trace normale.

3
Rajat Bansal

Vous pouvez également créer le vôtre si vous le souhaitez. Comme démontré dans Eloquent Ruby par Russ Olsen:

# define a proc to use that will handle your trace 
proc_object = proc do |event, file, line, id, binding, klass| 
  puts "#{event} in #{file}/#{line} #{id} #{klass}"
end 

# tell Ruby to use your proc on traceable events
set_trace_func(proc_object)
2
Sammy Larbi