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?
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"]
Essayer
Thread.current.backtrace.join("\n")
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
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
sistart
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>"]
Thread.current.backtrace
Cela vous donnera un tableau qui contient toutes les lignes que vous pouvez obtenir dans n'importe quelle trace normale.
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)