Passer au contenu principal
Par défaut, AppSignal essaie d’enregistrer autant d’exceptions (erreurs) que possible. Avec nos intégrations pour de nombreux frameworks et gems de tâches en arrière-plan, peu d’exceptions échapperont au suivi. Dans la plupart des cas, les erreurs qui ne sont pas causées par des bugs dans votre code se produisent lorsque votre application interagit avec le monde réel. Des bots peuvent passer et essayer de poster des formulaires automatiquement, des liens obsolètes peuvent diriger les visiteurs vers du contenu qui n’existe plus, etc. Pour éviter que ces erreurs ne soient signalées comme des problèmes dans AppSignal, il est possible d’ajouter une gestion des exceptions à votre code ou même de laisser AppSignal ignorer entièrement des erreurs spécifiques.

Ignorer les erreurs

La configuration d’AppSignal permet d’ignorer des erreurs. En fournissant une liste d’erreurs spécifiques, AppSignal n’enverra pas d’alertes lorsque ces erreurs sont levées.

Gestion des exceptions

Le simple fait d’ignorer une erreur fera taire les notifications, mais pourrait potentiellement masquer un problème plus important. Pour cette raison, nous vous recommandons d’ajouter une gestion des exceptions avec des blocs begin .. rescue à votre application. En utilisant begin .. rescue, vous pouvez attraper des exceptions spécifiques et ajouter un chemin de code alternatif pour le cas où une exception se produit, comme le rendu de pages 404 ou la fourniture à l’utilisateur de messages d’erreur plus détaillés sur ce qui a mal tourné.
begin
  user = Post.find(1)
rescue RecordNotFound => e
  render :text => "Could not find post", :status => 404
end
Il existe quelques scénarios qui devraient être gérés de cette manière pour fournir des réponses HTTP appropriées lorsque des ressources n’existent pas ou lorsqu’une soumission de formulaire échoue. Lisez notre introduction sur la gestion des exceptions pour plus d’informations sur son fonctionnement et comment l’implémenter correctement.

Rails rescue_from

Rails fournit un mécanisme pour gérer les exceptions au niveau du contrôleur. En définissant une instruction rescue_from pour une erreur spécifique, il est possible de créer un chemin de code alternatif pour le cas où cette exception est levée. Parce que cela peut être défini à n’importe quel niveau de contrôleur, cela permet d’ajouter une gestion des exceptions au niveau de l’application.
class ApplicationController < ActionController::Base
  rescue_from ActiveRecord::RecordNotFound, :with => :record_not_found

  private

  def record_not_found
    render :text => "404: Resource not found", :status => 404
  end
end
Plus d’informations sur rescue_from peuvent être trouvées dans le guide Rails sur ActionController.

Gérer les 404

Si un visiteur arrive sur une URL qui ne peut pas être gérée par votre routage ou contrôleur, Rack et d’autres frameworks lèveront une exception. C’est généralement une bonne idée de gérer ces exceptions avec une réponse 404 pour vos utilisateurs. Dans les contrôleurs où une opération find est effectuée en fonction d’un paramètre d’une URL, il est recommandé de gérer ActiveRecord::RecordNotFound (ou l’équivalent dans votre ORM préféré) pour afficher également une réponse 404. Cela peut cependant masquer de vrais bugs, donc cela doit être fait avec précaution.

Gérer les jetons d’authenticité invalides

Rails dispose d’un mécanisme qui protège vos formulaires contre le remplissage trop facile par des bots. Chaque fois qu’un formulaire est posté sans jeton d’authenticité correct, une ActionController::InvalidAuthenticityToken sera levée. Parfois, des utilisateurs légitimes peuvent également rencontrer ces erreurs, c’est donc une bonne idée d’avoir une page d’erreur distincte expliquant ce qui s’est passé. Nous conseillons de renvoyer cette page avec une réponse 422 (Unprocessable Entity).

Gérer les tentatives de piratage

Vous pourriez obtenir des erreurs parce que des bots ou des pirates essaient d’exploiter des problèmes de sécurité tels que le célèbre exploit YAML. Les versions plus récentes de Rails lèveront un Hash::DisallowedType lorsque cela se produit. Une RangeError est également souvent le résultat d’une tentative de piratage. Vous pourriez attraper ce type d’erreurs et renvoyer une réponse 403 (Forbidden).

Méthodes d’assistance pour le signalement des exceptions

AppSignal fournit une interface unique pour signaler les exceptions avec Appsignal.report_error. Si votre application utilise la version 3 ou antérieure de la gem Ruby, consultez la section sur la gestion des exceptions héritée.

Appsignal.report_error

Les applications peuvent avoir une gestion des exceptions où elles ne veulent pas faire planter le processus Ruby. En ajoutant la gestion des exceptions, l’exception ne remontera plus jusqu’à l’instrumentation AppSignal. AppSignal ne signalera pas ces exceptions. Si vous voulez signaler l’exception sans faire planter l’application, utilisez l’assistant Appsignal.report_error pour la signaler à AppSignal depuis la gestion des exceptions. Si une Transaction AppSignal est active, cet assistant ajoutera l’exception à la Transaction en cours. Les applications peuvent signaler plusieurs exceptions sur une seule Transaction. Si aucune Transaction n’est active, cet assistant créera une nouvelle Transaction et signalera l’exception sur la Transaction nouvellement créée. AppSignal signalera toujours l’exception de cette façon lors de l’utilisation de Appsignal.report_error.
begin
  # Some code that raises an exception
rescue => error
  Appsignal.report_error(error)
  puts "Exiting. An error occurred: #{error}"
  exit 1
end

Ajout de métadonnées

Il est possible de personnaliser les métadonnées sur la Transaction pour l’exception en passant un bloc à l’assistant Appsignal.report_error. Consultez nos guides Tagging et Personnalisation des données pour plus d’informations sur le type de données qui peuvent être ajoutées dans ce bloc. Les métadonnées définies dans le bloc de Appsignal.report_error ne s’appliquent qu’à l’exception passée à l’assistant. Les métadonnées définies en dehors des blocs Appsignal.report_error sont ajoutées à toutes les exceptions s’il y a une transaction active.
begin
  # some code
rescue => error
  Appsignal.report_error(error) do
    Appsignal.set_namespace("admin")
    Appsignal.set_action("MyCustomAction#perform")
    Appsignal.add_params(:param1 => "value1", :param2 => "value2")
    Appsignal.add_tags(:tag1 => "value1", :tag2 => "value2")
    Appsignal.add_custom_data(
      :i18n => {
        :locale => "en_GB",
        :default_locale => "en_US"
      }
    )
  end
end

Signaler plusieurs exceptions

Plusieurs erreurs peuvent être signalées dans une seule Transaction, comme une action de contrôleur Rails traitant une requête HTTP ou un job en arrière-plan Sidekiq. Un maximum de 10 erreurs peut être défini sur une seule Transaction. Si plusieurs exceptions sont signalées dans une seule Transaction, les métadonnées définies dans le bloc de Appsignal.report_error ne s’appliquent qu’à l’exception passée à l’assistant. Les métadonnées définies en dehors des blocs Appsignal.report_error sont ajoutées à toutes les exceptions.
def index
  # This tag is added to all exceptions
  Appsignal.add_tags(:some_tag_for_all_errors => true)

  begin
    raise "something went wrong"
  rescue => error
    # Report the first exception
    Appsignal.report_error(error) do
      # This tag is only added to the first exception
      Appsignal.add_tags(:some_tag => true)
    end
  end

  begin
    raise "something else went wrong"
  rescue => error
    # Report the second exception
    Appsignal.report_error(error) do
      # This tag is only added to the second exception
      Appsignal.add_tags(:other_tag => true)
    end
  end

  # This tag is added to all exceptions
  Appsignal.add_tags(:another_tag_for_all_errors => true)
end

Signaler les exceptions qui font planter un processus

Par défaut, AppSignal signalera les exceptions qui font planter un processus Ruby tant qu’AppSignal est démarré avant que l’exception ne se produise.
# some_script.rb
require "appsignal"

Appsignal.start

raise "I will crash the process!"
Pour désactiver cette fonctionnalité, définissez l’option de configuration enable_at_exit_reporter sur false.

Processus Ruby de courte durée

Lorsque vous signalez des exceptions à partir de scripts Ruby, de tâches Rake, de processus Ruby de courte durée, lisez la documentation sur ces pages pour savoir quand appeler Appsignal.stop pour vous assurer que toutes les exceptions sont signalées à AppSignal.

Gestion des exceptions héritée

Lisez cette section lorsque vous utilisez la version 3 ou antérieure de la gem AppSignal pour Ruby. Pour les versions plus récentes de notre gem Ruby, utilisez l’assistant Appsignal.report_error. AppSignal fournit deux méthodes d’assistance pour le signalement des exceptions, celle que vous utilisez dépendra du contexte de l’erreur. Les méthodes sont :
  • set_error : l’assistant set_error définit l’erreur sur la Transaction actuellement active. Si aucune transaction n’est active, aucune erreur n’est signalée. Définir une erreur sur la transaction actuellement active remplace toute erreur précédemment définie sur la transaction.
  • send_error : utilisez send_error pour signaler des erreurs lorsqu’aucune transaction AppSignal n’est active.

Appsignal.set_error

Il existe des scénarios où vous avez votre propre gestion des exceptions et où vous ne voulez pas faire planter le processus Ruby. En ajoutant votre propre gestion des exceptions, l’erreur ne remonte plus jusqu’à l’intégration AppSignal et n’est donc pas enregistrée automatiquement. Si vous voulez toujours suivre l’erreur, vous pouvez utiliser Appsignal.set_error pour ajouter l’exception à la Transaction AppSignal en cours. L’erreur sera enregistrée dans AppSignal, mais votre processus ne plantera pas.
require "yaml"
class SomeClass
  def call
    YAML.load(File.read("config.yml"))
  rescue SystemCallError => exception
    Appsignal.set_error(exception)
    puts "No config file found. Using defaults."
  end
end
L’exception sera suivie par AppSignal comme toute autre erreur, et cela vous permet de fournir une gestion d’erreur personnalisée et des solutions de repli. L’appel à set_error ne fonctionne que lorsqu’il existe une transaction AppSignal active. Sinon, l’erreur sera ignorée. Une transaction est active dans la plupart de nos intégrations automatiquement prises en charge et lors de l’utilisation de Appsignal.monitor ou Appsignal.monitor_transaction. Pour plus d’informations sur le moment où utiliser Appsignal.monitor_transaction, consultez notre guide d’instrumentation pour les scripts et les tâches en arrière-plan. Consultez Appsignal.send_error pour envoyer des erreurs sans transaction AppSignal.
require "yaml"

Appsignal.monitor :action => "My action" do
  begin
    YAML.load(File.read("config.yml"))
  rescue SystemCallError => exception
    Appsignal.set_error(exception)
    puts "No config file found. Using defaults."
  end
end

Appsignal.send_error

AppSignal fournit un mécanisme pour envoyer des erreurs à AppSignal sans avoir à démarrer une transaction. C’est utile pour suivre les erreurs qui se produisent dans du code qui n’est pas dans un contexte de requête web ou de tâche en arrière-plan, comme des tâches Rake ou des scripts Ruby séparés. C’est utile pour l’instrumentation qui ne crée pas automatiquement de transactions AppSignal à profiler, comme nos intégrations. Vous pouvez utiliser la méthode Appsignal.send_error pour envoyer directement une exception à AppSignal depuis n’importe quel endroit de votre code sans démarrer une transaction AppSignal avec Appsignal.monitor au préalable.
begin
  # some code
rescue => e
  Appsignal.send_error(e)
end

Ajout de métadonnées

Dans la gem AppSignal pour Ruby 2.9 et plus récente, un bloc supplémentaire peut être passé à la méthode Appsignal.send_error pour ajouter plus de métadonnées à la transaction d’erreur. Cela inclut des métadonnées telles que le nom de l’action et les paramètres. Les anciennes versions de la gem Ruby ne permettront pas de définir des métadonnées supplémentaires.
begin
  # some code
rescue => e
  Appsignal.send_error(e) do |transaction|
    transaction.set_action("my_action")
    transaction.set_namespace("my_namespace")
    transaction.params = { :time => Time.now.utc }
  end
end

Appsignal.listen_for_error

Cet assistant est supprimé dans la version 4 de la gem Ruby. Utilisez plutôt un bloc rescue Ruby avec l’assistant Appsignal.report_error.
Une autre façon de suivre les erreurs avec AppSignal consiste à envelopper le code qui pourrait lever une exception dans un bloc listen_for_error. Si une exception est levée dans ce bloc, elle est automatiquement suivie par AppSignal et re-levée. Cela permet à l’application et aux frameworks de gérer l’exception comme d’habitude.
require "rake"
require "appsignal"

task :fail do
  Appsignal.listen_for_error do
    raise "I am an exception in a Rake task"
  end
end