> ## Documentation Index
> Fetch the complete documentation index at: https://docs.appsignal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Benutzerdefinierte Instrumentierung für Elixir

Um herauszufinden, welche bestimmten Codeabschnitte Performance-Probleme verursachen,
ist es nützlich, Ihrer Anwendung benutzerdefinierte Instrumentierung hinzuzufügen. Dies
ermöglicht es uns, bessere Aufschlüsselungen darüber zu erstellen, welcher Code am langsamsten läuft und auf welchen Aktionstyp die meiste Zeit verwendet wurde.

Benutzerdefinierte Instrumentierung ist auf zwei Arten möglich: mit Funktions-Decoratoren und
Instrumentierungs-Helferfunktionen. Die Funktions-Decoratoren sind am einfachsten zu verwenden,
aber weniger flexibel als die Instrumentierungs-Helferfunktionen.

Diese Kurzanleitung hilft Ihnen beim Einrichten benutzerdefinierter Instrumentierung. Weitere Details zur
Verwendung bestimmter Helfer finden Sie in den Hex-Dokumenten für das [AppSignal-Paket](https://hexdocs.pm/appsignal/).

<Tip>
  **Hinweis**: Stellen Sie sicher, dass Sie [AppSignal
  integriert haben](/elixir/instrumentation/integrating-appsignal), bevor Sie Ihrer Anwendung benutzerdefinierte Instrumentierung
  hinzufügen, wenn sie nicht automatisch durch eine unserer unterstützten
  [Integrationen](/elixir/integrations) integriert wird.
</Tip>

<Tip>
  **Hinweis**: Diese Seite beschreibt nur, wie Sie Performance-Instrumentierung zu
  Ihrem Code hinzufügen. Um Fehler zu verfolgen, lesen Sie bitte unseren Leitfaden zur [Ausnahmebehandlung](/elixir/instrumentation/exception-handling).
</Tip>

## `Appsignal.instrument/2-3`

Die Funktion `instrument/2` wird verwendet, um Instrumentierung hinzuzufügen, indem ein Codeabschnitt
in eine Span eingewickelt wird. Eine Span wird schließlich zu einem Sample oder zu einem Event im Sample einer anderen
Span in AppSignal.

### Spans zu Traces hinzufügen

Im folgenden Beispiel haben wir einen Phoenix-Controller mit einer `index/2`-Funktion,
die eine langsame Funktion aufruft. Die Funktion `slow` wird mit der Funktion
`Appsignal.instrument/2` instrumentiert, die sie als separates Event in
dieser Phoenix-Anfrage erfasst. Sie wird auf AppSignal.com in der Event-Timeline dieses
Samples angezeigt, um mehr Einblick zu geben, wo die meiste Zeit während der
Anfrage verbracht wurde.

<CodeGroup>
  ```elixir Elixir theme={null}
  defmodule AppsignalPhoenixExampleWeb.PageController do
    use AppsignalPhoenixExampleWeb, :controller

    def index(conn, _params) do
      slow()
      render(conn, "index.html")
    end

    defp slow do
      Appsignal.instrument("slow", fn ->
        :timer.sleep(1000)
      end)
    end
  end
  ```
</CodeGroup>

Hier umschließen wir den Inhalt unserer Funktion mit einem Aufruf von `Appsignal.instrument3`
und übergeben `"slow"` als Namen für das Event.

### Neue Traces starten

Im Phoenix-Beispiel wurde bereits ein AppSignal-Trace gestartet, dank der
First-Party-Unterstützung für Phoenix im AppSignal-Paket. Nicht alle
Frameworks und Pakete werden derzeit direkt unterstützt und starten automatisch
Traces. Dasselbe gilt für Ihre eigenen reinen Elixir-Anwendungen.

Wie beim Hinzufügen von Spans zu bereits instrumentierten Traces wird eine neue Root-Span
mit der Funktion `Appsignal.instrument/2` erstellt:

<CodeGroup>
  ```elixir Elixir theme={null}
  defmodule AppsignalElixirExample do
    def example_fn do
      Appsignal.instrument("instrument", fn ->
        :timer.sleep(500)
      end)
    end
  end
  ```
</CodeGroup>

Dieses Beispiel erstellt ein Sample namens "instrument" im "background"-Namespace
in AppSignal. Der Name wird auch als Kategoriename für die Haupt-Span verwendet.
Um einen anderen Kategorienamen zu verwenden, verwenden Sie stattdessen `instrument/3`:

<CodeGroup>
  ```elixir Elixir theme={null}
  defmodule AppsignalElixirExample do
    def example_fn do
      Appsignal.instrument("instrument", "call.instrument", fn ->
        :timer.sleep(500)
      end)
    end
  end
  ```
</CodeGroup>

Wenn Sie eine Funktion übergeben, die ein Argument annimmt, ruft die Funktion `instrument/2-3` sie mit der geöffneten Span auf, um weitere Anpassungen zu ermöglichen. Siehe die Dokumentation auf hex.pm für [alle verfügbaren Span-Funktionen](https://hexdocs.pm/appsignal/Appsignal.Span.html).

<CodeGroup>
  ```elixir Elixir theme={null}
  defmodule AppsignalElixirExample do
    def example_fn do
      Appsignal.instrument("Build complicated SQL query", "prepare_query.sql", fn span ->
        # Example of building a complex SQL query in the instrument block and performing it
        query = "SOME complicate SQL query"
        # The body is only set here because it's the value being calculated and instrumented in this function
        Appsignal.Span.set_sql(span, query)
        Database.perform_query(query)
      end)
    end
  end
  ```
</CodeGroup>

### Ausnahmebehandlung {/* id: helper-exception-handling */}

Um Fehler mithilfe benutzerdefinierter Instrumentierung zu melden, lesen Sie bitte mehr in unserem Leitfaden zur [Ausnahmebehandlung](/elixir/instrumentation/exception-handling).

## Funktions-Decoratoren

Mit dem Decorator-Modul `Appsignal.Instrumentation.Decorators` ist es
möglich, Ihren Elixir-Anwendungen benutzerdefinierte Instrumentierung hinzuzufügen, ohne
den Inhalt der Funktionen zu ändern.

### Transaktions-Events {/* id: decorator-transaction-events */}

Im folgenden Beispiel haben wir einen Phoenix-Controller mit einer `index/2`-Funktion,
die eine langsame Funktion aufruft. Die Funktion `slow` wird mit dem AppSignal-
`transaction_event`-Decorator instrumentiert, der sie als separates Event in dieser Phoenix-
Anfrage erfasst. Sie wird auf AppSignal.com in der Event-Timeline dieses Transaktions-
Samples angezeigt, um mehr Einblick zu geben, wo die meiste Zeit während der Anfrage verbracht wurde.

<CodeGroup>
  ```elixir Elixir theme={null}
  # Phoenix controller example
  defmodule PhoenixExample.PageController do
    use PhoenixExample.Web, :controller
    # Include this
    use Appsignal.Instrumentation.Decorators

    def index(conn, _params) do
      slow()
      render conn, "index.html"
    end

    # Decorate this function to add custom instrumentation
    @decorate transaction_event()
    defp slow do
      :timer.sleep(1000)
    end
  end
  ```
</CodeGroup>

Wenn Sie bestimmte Events unter derselben Event-Gruppe gruppieren möchten (andere
Gruppen sind `phoenix_controller`, `phoenix_render`, `ecto` usw.), können Sie dem `transaction_event`-Decorator auch einen Gruppennamen übergeben.

<CodeGroup>
  ```elixir Elixir theme={null}
  @decorate transaction_event("github_api")
  defp get_data_from_github do
    # Third-party API call
  end
  ```
</CodeGroup>

Dies erstellt ein Event `get_data_from_github.github_api` in der Event-Timeline.
Weitere Informationen darüber, wie Event-Namen verwendet werden, finden Sie in unseren
[Event-Benennungsrichtlinien](/api/event-names).

### Transaktionen {/* id: decorator-transactions */}

Im Phoenix-Beispiel wurde bereits eine AppSignal-Transaktion gestartet, dank
der First-Party-Unterstützung für Phoenix im AppSignal-Paket. Nicht alle Frameworks
und Pakete werden derzeit direkt unterstützt und starten automatisch Transaktionen.
Dasselbe gilt für Ihre eigenen reinen Elixir-Anwendungen.

Um `transaction_event`-Decoratoren zu verfolgen, müssen wir zuvor eine
AppSignal-Transaktion starten. Wir können eine Transaktion mit dem
Funktions-Decorator `transaction` starten.

<CodeGroup>
  ```elixir Elixir theme={null}
  # Pure Elixir example
  defmodule FunctionDecoratorsExample do
    # Include this
    use Appsignal.Instrumentation.Decorators

    # No transaction is started beforehand like in Phoenix, so we need to start
    # it ourselves.
    @decorate transaction()
    def call do
      slow()
      # ...
    end

    # Decorate this function to add custom instrumentation
    @decorate transaction_event()
    defp slow do
      :timer.sleep(1000)
    end
  end
  ```
</CodeGroup>

**Hinweis**: Stellen Sie bei reinen Elixir-Anwendungen sicher, dass die AppSignal-
Anwendung gestartet wird, bevor Sie eine Transaktion starten. Weitere Informationen finden Sie
in unserer Anleitung zur [Integration von AppSignal](/elixir/instrumentation/integrating-appsignal).

### Namespaces {/* id: decorator-namespaces */}

Um zwischen HTTP-Anfragen und Hintergrund-Jobs zu unterscheiden, können wir der Transaktion einen
Namespace übergeben, sobald wir sie starten.

Die folgenden zwei Namespaces sind offizielle, von AppSignal unterstützte Namespaces.

* `http_request` – der Standard – wird als „web“-Namespace bezeichnet
* `background_job` – erstellt den „background“-Namespace

<CodeGroup>
  ```elixir Elixir theme={null}
  defmodule FunctionDecoratorsExample do
    # Include this
    use Appsignal.Instrumentation.Decorators

    # No namespace argument defaults to `:http_request`
    @decorate transaction()
    def web_function do
      # do stuff
    end

    # The "background" namespace
    @decorate transaction(:background_job)
    def background_function do
      # do stuff
    end
  end
  ```
</CodeGroup>

Weitere Informationen darüber, was Namespaces sind, finden Sie in unserer Dokumentation zu
[Namespaces](/application/namespaces).

### Benutzerdefinierte Namespaces {/* id: decorator-custom-namespaces */}

Sie können auch eigene Namespaces erstellen, um Transaktionen in einem separaten Teil
Ihrer Anwendung wie einem Verwaltungsbereich zu verfolgen. Dies gruppiert alle Transaktionen
mit diesem Namespace in einem separaten Abschnitt auf AppSignal.com, sodass langsame Admin-Controller
die Durchschnittswerte der Geschwindigkeit Ihrer Anwendung nicht beeinträchtigen.

<CodeGroup>
  ```elixir Elixir theme={null}
  @decorate transaction(:admin)
  def some_function do
    # do stuff
  end
  ```
</CodeGroup>

### Phoenix-Channels {/* id: decorator-phoenix-channels */}

Es gibt einen benutzerdefinierten Funktions-Decorator für Phoenix-Channels. Dieser Decorator soll
vor die `handle_in/3`-Funktion eines `Phoenix.Channel`-Moduls gesetzt werden.

<CodeGroup>
  ```elixir Elixir theme={null}
  defmodule FunctionDecoratorsExample.MyChannel do
    # Include this
    use Appsignal.Instrumentation.Decorators

    # Add this channel function decorator
    @decorate channel_action()
    def handle_in("ping", _payload, socket) do
      # your code here..
    end
  end
  ```
</CodeGroup>

Channel-Events werden unter dem „background“-Namespace angezeigt und zeigen das
Channel-Modul und das verwendete Action-Argument.

## Spans manuell erstellen und schließen

In einigen Fällen kann es nützlich sein, Spans manuell zu verwalten. Sie können die
Span-API verwenden, um z. B. Aufgaben zu instrumentieren:

<CodeGroup>
  ```elixir Elixir theme={null}
  def index(conn, _params) do
    current = Appsignal.Tracer.current_span()
    fn ->
      span = "http_request"
      |> Appsignal.Tracer.create_span(current)
      |> Appsignal.Span.set_name("name")
      |> Appsignal.Span.set_attribute("appsignal:category", "category")
      :timer.sleep(1000)
      Appsignal.Tracer.close_span(span)
    end
    |> Task.async()
    |> Task.await()
    render(conn, "index.html")
  end
  ```
</CodeGroup>
