Naar hoofdinhoud gaan
Standaard probeert AppSignal zoveel mogelijk exceptions (errors) vast te leggen. Met onze integraties voor veel frameworks en background job gems zullen weinig exceptions ontsnappen. In de meeste gevallen treden errors die niet worden veroorzaakt door bugs in uw code op wanneer uw app interageert met de echte wereld. Bots kunnen langskomen en automatisch formulieren proberen te posten; verouderde links kunnen bezoekers naar content leiden die niet meer bestaat, enzovoort. Om te voorkomen dat deze errors als problemen in AppSignal worden gemeld, is het mogelijk om exception handling aan uw code toe te voegen of AppSignal specifieke errors helemaal te laten negeren.

Errors negeren

De AppSignal-configuratie maakt het mogelijk om errors te negeren. Door een lijst met specifieke errors op te geven, stuurt AppSignal geen alerts wanneer deze errors worden geworpen.

Exception handling

Een error simpelweg negeren onderdrukt meldingen, maar kan mogelijk een groter probleem verbergen. Daarom raden we u aan exception handling toe te voegen met begin .. rescue-blokken aan uw applicatie. Met begin .. rescue kunt u specifieke exceptions opvangen en een alternatief codepad toevoegen voor wanneer een exception optreedt, zoals het renderen van 404-pagina’s of het de gebruiker geven van meer gedetailleerde foutmeldingen over wat er mis is gegaan.
begin
  user = Post.find(1)
rescue RecordNotFound => e
  render :text => "Could not find post", :status => 404
end
Er zijn een paar scenario’s die op deze manier afgehandeld moeten worden om juiste HTTP-responses te geven wanneer resources niet bestaan of wanneer een formulier-submission mislukt. Lees onze primer over Exception handling voor meer informatie over hoe het werkt en hoe u het correct implementeert.

Rails rescue_from

Rails biedt een mechanisme om exceptions op controllerniveau af te handelen. Door een rescue_from-statement te definiëren voor een specifieke error is het mogelijk om een alternatief codepad aan te maken voor wanneer die exception wordt geworpen. Omdat dit op elk controllerniveau gedefinieerd kan worden, is het mogelijk om exception handling op applicatieniveau toe te voegen.
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
Meer informatie over rescue_from is te vinden in de Rails-gids over ActionController.

404’s afhandelen

Als een bezoeker een URL bezoekt die niet door uw routing of controller kan worden afgehandeld, gooien Rack en andere frameworks een exception. Het is meestal een goed idee om deze exceptions af te handelen met een 404-response voor uw gebruikers. In controllers waar een find-operatie wordt uitgevoerd op basis van een parameter uit een URL, wordt aanbevolen om ActiveRecord::RecordNotFound af te handelen (of het equivalent in uw ORM van keuze) om ook een 404-response te tonen. Dit kan echter echte bugs verbergen, dus dit moet met zorg gebeuren.

Ongeldige authenticity tokens afhandelen

Rails heeft een mechanisme dat uw formulieren beschermt tegen het te gemakkelijk worden ingevuld door bots. Telkens wanneer een formulier wordt gepost zonder een correcte authenticity token, wordt een ActionController::InvalidAuthenticityToken geworpen. Soms kunnen legitieme gebruikers ook tegen deze errors aanlopen, dus is het een goed idee om een aparte foutpagina te hebben die uitlegt wat er mis is gegaan. We adviseren om deze pagina terug te geven met een 422 (Unprocessable Entity) response.

Hackpogingen afhandelen

U kunt errors krijgen omdat bots of hackers proberen beveiligingsproblemen uit te buiten, zoals de beruchte YAML-exploit. Nieuwere versies van Rails gooien een Hash::DisallowedType wanneer dit gebeurt. Een RangeError is ook vaak een resultaat van een hackpoging. U kunt deze soorten errors rescue’en en een 403 (Forbidden) response retourneren.

Helpermethoden voor exception-reporting

AppSignal biedt één interface om exceptions te rapporteren met Appsignal.report_error. Als uw applicatie Ruby gem versie 3 of ouder gebruikt, zie de legacy exception handling-sectie.

Appsignal.report_error

Applicaties kunnen exception handling hebben waarbij ze het Ruby-proces niet willen laten crashen. Door exception handling toe te voegen, borrelt de exception niet meer omhoog naar de AppSignal-instrumentation. AppSignal rapporteert deze exceptions niet. Als u de exception wilt rapporteren zonder dat de applicatie crasht, gebruik dan de Appsignal.report_error-helper om deze vanuit de exception handling aan AppSignal te rapporteren. Als er een AppSignal-transactie actief is, voegt deze helper de exception toe aan de huidige transactie. Applicaties kunnen meerdere exceptions rapporteren op één transactie. Als er geen transactie actief is, maakt deze helper een nieuwe transactie aan en rapporteert de exception op de nieuw aangemaakte transactie. AppSignal rapporteert de exception altijd op deze manier wanneer Appsignal.report_error wordt gebruikt.
begin
  # Some code that raises an exception
rescue => error
  Appsignal.report_error(error)
  puts "Exiting. An error occurred: #{error}"
  exit 1
end

Metadata toevoegen

Het aanpassen van de metadata op de transactie voor de exception is mogelijk door een block door te geven aan de Appsignal.report_error-helper. Zie onze gidsen over Tagging en Data Customization voor meer informatie over welk soort data in dit block kan worden toegevoegd. De metadata die in het block van Appsignal.report_error wordt ingesteld, is alleen van toepassing op de exception die aan de helper is gegeven. Metadata die buiten de Appsignal.report_error-blocks wordt ingesteld, wordt toegevoegd aan alle exceptions als er een actieve transactie is.
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

Meerdere exceptions rapporteren

Meerdere errors kunnen in één transactie worden gerapporteerd, zoals een Rails-controller-actie die een HTTP-request afhandelt of een Sidekiq background job. Er kunnen maximaal 10 errors op één transactie worden ingesteld. Als er meerdere exceptions in één transactie worden gerapporteerd, is de metadata die in het block van Appsignal.report_error wordt ingesteld alleen van toepassing op de exception die aan de helper is gegeven. Metadata die buiten de Appsignal.report_error-blocks wordt ingesteld, wordt aan alle exceptions toegevoegd.
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

Exceptions rapporteren die een proces laten crashen

Standaard rapporteert AppSignal exceptions die een Ruby-proces laten crashen, zolang AppSignal is gestart voordat de exception zich voordoet.
# some_script.rb
require "appsignal"

Appsignal.start

raise "I will crash the process!"
Om deze functionaliteit uit te schakelen, zet u de enable_at_exit_reporter config-optie op false.

Kortlevende Ruby-processen

Bij het rapporteren van exceptions vanuit Ruby-scripts, Rake-taken of kortlevende Ruby-processen, lees de documentatie op die pagina’s over wanneer u het beste Appsignal.stop kunt aanroepen om ervoor te zorgen dat alle exceptions naar AppSignal worden gerapporteerd.

Legacy exception handling

Lees deze sectie als u AppSignal voor Ruby gem versie 3 of ouder gebruikt. Voor nieuwere versies van onze Ruby gem, gebruik de Appsignal.report_error helper. AppSignal biedt twee helpermethoden voor exception-reporting; welke u gebruikt, hangt af van de context van de error. De methoden zijn:
  • set_error: De set_error-helper stelt de error in op de momenteel actieve transactie. Als er geen transactie actief is, wordt er geen error gerapporteerd. Het instellen van een error op de momenteel actieve transactie overschrijft elke error die eerder op de transactie is ingesteld.
  • send_error: Gebruik send_error om errors te rapporteren wanneer er geen AppSignal-transactie actief is.

Appsignal.set_error

Er zijn scenario’s waarin u uw eigen exception handling heeft en niet wilt dat het Ruby-proces crasht. Door uw eigen exception handling toe te voegen, borrelt de error niet meer omhoog naar de AppSignal-integratie en wordt deze dus niet automatisch geregistreerd. Als u de error toch wilt tracken, kunt u Appsignal.set_error gebruiken om de exception toe te voegen aan de huidige AppSignal-transactie. De error wordt in AppSignal geregistreerd, maar uw proces crasht niet.
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
De exception wordt door AppSignal getrackt zoals elke andere error, en stelt u in staat om custom error-afhandeling en fallbacks te bieden. set_error aanroepen werkt alleen wanneer er een AppSignal-transactie actief is. Anders wordt de error genegeerd. Een transactie is actief in de meeste van onze automatisch ondersteunde integraties en wanneer Appsignal.monitor of Appsignal.monitor_transaction wordt gebruikt. Voor meer informatie over wanneer u Appsignal.monitor_transaction moet gebruiken, raadpleegt u onze gids over instrumentation voor scripts en background jobs. Zie Appsignal.send_error voor het versturen van errors zonder een AppSignal-transactie.
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 biedt een mechanisme om errors naar AppSignal te sturen zonder dat er een transactie hoeft te worden gestart. Dit is nuttig om errors te tracken die voorkomen in code die niet in een web- of background-job-context staat, zoals afzonderlijke Rake-taken of Ruby-scripts. Dit is nuttig voor instrumentation die niet automatisch AppSignal-transacties aanmaakt om te profileren, zoals onze integraties. U kunt de methode Appsignal.send_error gebruiken om een exception rechtstreeks naar AppSignal te sturen vanaf elke plek in uw code zonder eerst een AppSignal-transactie met Appsignal.monitor te starten.
begin
  # some code
rescue => e
  Appsignal.send_error(e)
end

Metadata toevoegen

In AppSignal voor Ruby gem 2.9 en nieuwer kan een extra block worden doorgegeven aan de methode Appsignal.send_error om meer metadata aan de error-transactie toe te voegen. Dit omvat metadata zoals de actienaam en parameters. Oudere versies van de Ruby gem staan niet toe dat er aanvullende metadata wordt ingesteld.
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

Deze helper is verwijderd in Ruby gem versie 4. Gebruik in plaats daarvan een Ruby rescue- block met de Appsignal.report_error helper.
Een alternatieve manier om errors met AppSignal te tracken is door code die mogelijk een exception werpt te omwikkelen in een listen_for_error-block. Als binnen dat block een exception wordt geworpen, wordt deze automatisch door AppSignal getrackt en opnieuw geworpen. Hierdoor kunnen de applicatie en frameworks de exception als normaal afhandelen.
require "rake"
require "appsignal"

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