Elixir og Phoenix: Skalerbar backendutvikling · leksjon

Feilhåndtering og strukturert logging

Implementer robuste strategier for feilhåndtering, og lær å bruke strukturert logging til effektiv feilsøking og overvåking.

Leksjon 3 av 411 trinn

Feilhåndtering og strukturert logging er en gratis leksjon i Elixir og Phoenix: Skalerbar backendutvikling på CoddyKit. Dette er leksjon 3 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Elixir og Phoenix: Skalerbar backendutvikling, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Elixir og Phoenix: Skalerbar backendutvikling inneholder totalt 4 leksjoner.

Hvorfor feilhåndtering er viktig

I alle applikasjoner kan ting gå galt. Brukere kan skrive inn ugyldige data, eksterne tjenester kan svikte, eller filer finnes kanskje ikke.

Feilhåndtering handler om å forutse slike problemer og utforme applikasjonen slik at den reagerer kontrollert, unngår krasj og gir en god brukeropplevelse.

Elixirs filosofi «Let It Crash»

Elixir, som er bygget på Erlang VM, følger en unik tilnærming kalt «Let It Crash». I stedet for å forsøke å forhindre alle mulige feil er Elixir-prosesser utformet slik at de er isolerte.

Hvis en prosess krasjer, kan en supervisor oppdage det og starte prosessen på nytt, slik at høy tilgjengelighet opprettholdes. Dette gjelder imidlertid først og fremst feil på prosessnivå. For forventede funksjonelle utfall brukes et annet mønster.

Tupler: {:ok, value} eller {:error, reason}

For operasjoner som på en forutsigbar måte kan lykkes eller mislykkes, bruker Elixir ofte et mønster der tupler returneres: {:ok, result} ved suksess og {:error, reason} ved feil.

Dette gjør utfallet eksplisitt og unngår unntak i forventede situasjoner, noe som gir tydeligere kode.

defmodule AccountService do
  def withdraw(balance, amount) when amount > 0 and balance >= amount do
    {:ok, balance - amount}
  end

  def withdraw(balance, amount) when amount <= 0 do
    {:error, :invalid_amount}
  end

  def withdraw(balance, amount) when balance < amount do
    {:error, :insufficient_funds}
  end
end

IO.puts "Withdrawal 1: #{inspect AccountService.withdraw(100, 50)}"
IO.puts "Withdrawal 2: #{inspect AccountService.withdraw(100, 150)}"
IO.puts "Withdrawal 3: #{inspect AccountService.withdraw(100, 0)}"

Håndtere resultater med `case`

Når en funksjon returnerer en {:ok, ...}- eller {:error, ...}-tuppel, kan du bruke Elixirs kraftige mønstersamsvar med en case-setning til å håndtere begge utfallene eksplisitt.

Dette gjør feilhåndteringsflyten svært tydelig og lett å lese.

defmodule PaymentProcessor do
  def process_payment(amount, account_balance) do
    case AccountService.withdraw(account_balance, amount) do
      {:ok, new_balance} ->
        IO.puts "Payment successful! New balance: #{new_balance}"
        {:ok, new_balance}
      {:error, :insufficient_funds} ->
        IO.puts "Payment failed: Insufficient funds."
        {:error, :payment_failed}
      {:error, reason} ->
        IO.puts "Payment failed: Unknown reason #{reason}."
        {:error, :payment_failed}
    end
  end
end

# Assuming AccountService from previous scene is available
# Example usage:
PaymentProcessor.process_payment(30, 100)
PaymentProcessor.process_payment(120, 100)

Kraften i `with` for kjeding

Når du har flere operasjoner som kan returnere {:error, ...}-tupler og er avhengige av at tidligere trinn lykkes, er with-spesialformen svært nyttig.

Den lar deg kjede disse operasjonene. Hvis et trinn returnerer en {:error, ...}, stopper with-blokken umiddelbart og returnerer feilen, noe som forenkler komplekse flyter.

defmodule OrderProcessor do
  def process_order(user_id, item_id, quantity) do
    with {:ok, user} <- get_user(user_id),
         {:ok, item} <- get_item(item_id),
         {:ok, total_cost} <- calculate_cost(item, quantity),
         {:ok, _} <- deduct_funds(user, total_cost) do
      {:ok, "Order processed successfully for user #{user.name}"}
    else
      {:error, reason} -> {:error, reason}
    end
  end

  defp get_user(1), do: {:ok, %{name: "Alice"}}
  defp get_user(_), do: {:error, :user_not_found}

  defp get_item(101), do: {:ok, %{price: 20}}
  defp get_item(_), do: {:error, :item_not_found}

  defp calculate_cost(%{price: p}, q), do: {:ok, p * q}

  defp deduct_funds(%{name: "Alice"}, 40), do: {:ok, :deducted}
  defp deduct_funds(_, _), do: {:error, :payment_failed}
end

IO.puts "Processing good order: #{inspect OrderProcessor.process_order(1, 101, 2)}"
IO.puts "Processing bad order (item): #{inspect OrderProcessor.process_order(1, 999, 1)}"

Mer enn grunnleggende logger: Strukturert logging

Tradisjonelle logger ser ofte ut som rene tekstmeldinger, som er vanskelige for maskiner å tolke og søke i. Strukturert logging løser dette ved å skrive ut logger i et konsekvent, maskinlesbart format, vanligvis JSON.

Dette gjør det mye enklere å filtrere, analysere og visualisere loggdataene dine med verktøy som Kibana eller Splunk, og gir dypere innsikt i hvordan applikasjonen oppfører seg.

Førstevalget ditt: `Logger`-modulen

Elixir leveres med en kraftig innebygd loggfasilitet: Logger-modulen. Den lar deg sende ut loggmeldinger på ulike alvorlighetsnivåer, for eksempel :debug, :info, :warn og :error.

Som standard skriver Logger ut til konsollen, men den kan konfigureres i stor grad slik at logger sendes til filer, eksterne tjenester eller andre mål.

defmodule MyApp do
  require Logger

  def start_process(id) do
    Logger.info "Starting process with ID: #{id}"
    # ... some work ...
    if id == 101 do
      Logger.warn "Process #{id} encountered a minor issue."
    else
      Logger.debug "Process #{id} completed successfully."
    end
  end

  def critical_error(message) do
    Logger.error "Critical error detected: #{message}"
  end
end

MyApp.start_process(100)
MyApp.start_process(101)
MyApp.critical_error("Database connection lost")

Kontekstuelle logger med metadata

En av de beste funksjonene i Logger for strukturert logging er muligheten til enkelt å legge til metadata (ekstra nøkkel-verdi-par) i loggmeldingene.

Disse metadataene gir viktig kontekst, for eksempel en user_id, request_id eller bestemte parametere. Det gjør det mye enklere å spore problemer og forstå hva som skjedde under en hendelse.

defmodule WebRequestLogger do
  require Logger

  def log_request(method, path, user_id, duration_ms) do
    Logger.info "Request processed",
      method: method,
      path: path,
      user_id: user_id,
      duration: "#{duration_ms}ms"
  end

  def log_error(error_message, user_id, request_id) do
    Logger.error error_message,
      user_id: user_id,
      request_id: request_id,
      component: :api_handler
  end
end

WebRequestLogger.log_request("GET", "/users/1", 123, 55)
WebRequestLogger.log_error("Invalid API key", 456, "abc-123")

Styr loggutdata med nivåer

Hver loggmelding har et nivå (debug, info, warn, error, critical). Du kan konfigurere Elixir-applikasjonens Logger til bare å skrive ut meldinger på eller over et bestemt nivå.

I et produksjonsmiljø kan du for eksempel sette nivået til :info for å unngå for mange :debug-logger, mens du i utviklingsmiljøet kan sette det til :debug for full oversikt.

  • :debug: Detaljert informasjon som er nyttig ved feilsøking.
  • :info: Generelle meldinger om drift.
  • :warn: Potensielt skadelige situasjoner.
  • :error: Feilhendelser som fortsatt kan tillate at applikasjonen fortsetter.
  • :critical: Alvorlige feilhendelser som sannsynligvis fører til at applikasjonen avsluttes.

Test forståelsen

Hvilke av disse er fordeler ved å bruke strukturert logging i Elixir-applikasjoner?

Leksjonsoppsummering: Robusthet og innsikt

I denne leksjonen har du lært å bygge mer robuste Elixir-applikasjoner og få bedre innsikt i hvordan de oppfører seg:

  • Forstått Elixirs tilnærming til feilhåndtering gjennom filosofien «Let It Crash».
  • Behersket bruken av {:ok, value}- og {:error, reason}-tupler for eksplisitt funksjonell feilhåndtering.
  • Brukt with-spesialformen til elegant å kjede sammen operasjoner som kan mislykkes.
  • Oppdaget fordelene ved strukturert logging for maskinlesbare og søkbare logger.
  • Lært å bruke Elixirs Logger-modul, blant annet ved å legge til verdifulle metadata i loggene og konfigurere loggnivåer.

Disse teknikkene er grunnleggende for å utvikle produksjonsklare og observerbare Elixir-systemer!

Gratis å komme i gang

Lær deg Elixir med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
12
Leksjoner
48

Ofte stilte spørsmål

Er leksjonen «Feilhåndtering og strukturert logging» gratis?

Ja – hele teksten i «Feilhåndtering og strukturert logging» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av Elixir og Phoenix: Skalerbar backendutvikling-kurset, kan du oppgradere til CoddyKit PRO. Kurset i Elixir og Phoenix: Skalerbar backendutvikling inneholder totalt 4 leksjoner.

Hva lærer jeg i «Feilhåndtering og strukturert logging»?

Implementer robuste strategier for feilhåndtering, og lær å bruke strukturert logging til effektiv feilsøking og overvåking. Du øver på Elixir og Phoenix: Skalerbar backendutvikling med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med Elixir og Phoenix: Skalerbar backendutvikling?

Ingen tidligere erfaring er nødvendig. Elixir og Phoenix: Skalerbar backendutvikling på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 3 av 4.

Hvor lang tid tar leksjonen «Feilhåndtering og strukturert logging»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne Elixir og Phoenix: Skalerbar backendutvikling-leksjonen?

Ja. Alle Elixir og Phoenix: Skalerbar backendutvikling-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. Benchmarking og profilering av Elixir
  2. Overvåking med Telemetry og måledata
  3. Feilhåndtering og strukturert logging
  4. Distribuert sporing med OpenTelemetry
← Tilbake til Elixir og Phoenix: Skalerbar backendutvikling