Rails: journalisation de l'ensemble de la trace de pile d'une exception

110

J'ai essayé de trouver la bonne façon d'enregistrer une trace de pile. Je suis tombé sur ce lien qui indique que logger.error $ !, $ !. backtrace est la voie à suivre, mais cela ne fonctionne pas pour moi log_error . Selon la documentation, je ne vois pas comment le passage d'un deuxième argument à la méthode d'erreur fonctionnerait de toute façon parce que l'enregistreur ruby ​​qui utilise un rail n'accepte qu'un seul argument.

Étrangement (ou peut-être pas) le deuxième argument est accepté sans aucune plainte des interprètes. Cependant, tout ce que je lui transmets est ignoré.

Quelqu'un peut-il expliquer ce que je manque? Un aperçu de ce à quoi sert le deuxième argument de l'erreur et de quoi la manger?

Moiz Raja
la source

Réponses:

204

Si vous regardez la source de la classe BufferedLogger dans ActiveSupport, vous verrez que le deuxième argument est 'progname'. Ceci n'est utilisé que lorsque le premier argument est nul et que vous ne lui avez donné aucun bloc ou que le bloc renvoie une valeur non vraie.

En substance, vous ne pouvez pas utiliser le deuxième paramètre pour générer des éléments supplémentaires.

Ce que vous voulez faire est quelque chose de plus proche de:

begin
  raise
rescue => e
  logger.error e.message
  logger.error e.backtrace.join("\n")
end

En fonction de la configuration de votre journalisation, il peut être préférable d'itérer chaque ligne de la trace arrière et de l'imprimer séparément car certains enregistreurs ne génèrent pas de nouvelles lignes, auquel cas vous feriez quelque chose comme:

begin
  raise
rescue => e
  logger.error e.message
  e.backtrace.each { |line| logger.error line }
end
darkliquid
la source
5
Je rejoindrais en utilisant "\ r \ n" pour maintenir la compatibilité multiplateforme.
James Watkins
10
N'utiliseriez-vous pas à la $/place, pour être compatible multiplateforme? Laissez Ruby s'en occuper, comme cela \r\nn'est spécifique qu'à quelques plates-formes.
vgoff le
12
Vous pouvez obtenir votre message divisé et illisible car appeler le journal plusieurs fois n'est pas thread-safe. Alors que l'enregistreur lui-même est thread-safe. Habituellement, je joins mon message en une seule chaîne, puis je le consigne.
Morozov
À l'époque, l'enregistreur ne semblait pas prendre en charge les nouvelles lignes dans les entrées de journal, d'où le fractionnement, mais oui, vous avez tout à fait raison et vous devez être conscient des limites de cette approche
darkliquid
+1 @JackWatson réponse absolument étrange car elle n'est pas sûre pour les threads. C'est une chose importante car nous parlons d'applications Web ici
EvAlex
16

Voilà la réponse.

begin
  raise
rescue => e
  logger.error ([e.message]+e.backtrace).join($/)
end
kuboon
la source
9
moins de ponctuation:Rails.logger.error [e.message, *e.backtrace].join($/)
artm