> ## 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 Python-Instrumentierung

Das Einbinden benutzerdefinierter Instrumentierung in Ihre Anwendung kann hilfreich sein, um die spezifischen Codezeilen zu identifizieren, die Performance-Probleme verursachen.

AppSignal für Python verwendet OpenTelemetry-Tracer-Objekte; weitere Informationen zu Python-Traces finden Sie im [Python Cookbook][cookbook] von OpenTelemetry.

Traces bestehen aus einem oder mehreren Spans. Ein Trace kann als gerichteter azyklischer Graph (DAG) von Spans betrachtet werden:

<img src="https://mintcdn.com/appsignal-715f5a51/nF8c1Rwq1cS7b5hg/assets/images/abstract-trace.png?fit=max&auto=format&n=nF8c1Rwq1cS7b5hg&q=85&s=8e955df41909f6fadf6d607478d6badb" alt="Trace-Diagramm" width="1826" height="650" data-path="assets/images/abstract-trace.png" />

AppSignal-spezifische Attribute müssen einem Span hinzugefügt werden, damit er von AppSignal erfolgreich geparst werden kann. Mit unserem Satz von [Helper-Methoden](#helper-methods) können diese Attribute gesetzt werden.

Diese Dokumentation erklärt, wie Sie benutzerdefinierte Instrumentierungen erstellen, indem Sie AppSignal-spezifische Attribute in den Spans Ihrer Python-Anwendung setzen.

## Einen Span erstellen

Importieren Sie beim Hinzufügen benutzerdefinierter Instrumentierung zunächst das OpenTelemetry-Trace-Modul in die Datei, der Sie Instrumentierung hinzufügen möchten.

<CodeGroup>
  ```python Python theme={null}
  from opentelemetry import trace
  ```
</CodeGroup>

Erstellen Sie dann mit diesem Trace-Modul einen neuen Span:

<CodeGroup>
  ```python Python theme={null}
  tracer = trace.get_tracer(__name__)
  with tracer.start_as_current_span("Span name"):
      # Here you can execute your app logic

      # And set AppSignal span details:
      from appsignal import set_category

      set_category("category.name")
  ```
</CodeGroup>

Sobald Sie den Span abgerufen haben, können Sie unsere [Helper-Methoden](#helper-method) verwenden, um die erforderlichen Attribute zuzuweisen.

Weitere Informationen zum Erstellen und Abrufen von Spans finden Sie im [Python Cookbook][cookbook] von OpenTelemetry.

## Einmalige Aufrufe und Serverless

Wenn Sie einmalige Skripte oder Serverless-Funktionen ausführen, müssen Sie AppSignal manuell initialisieren und am Ende stoppen, um sicherzustellen, dass keine Daten verloren gehen. Der Helper `stop` beendet den Agent-Prozess sauber und wartet eine Weile, um sicherzustellen, dass alle Daten an die AppSignal-Server gesendet werden.

<CodeGroup>
  ```python Python theme={null}
  appsignal = Appsignal(
      active=True,
      name="My Python App",
      push_api_key="YOUR_PUSH_API_KEY",
  )

  appsignal.start()

  # Your code here along with the instrumentation
  # ...

  appsignal.stop()
  ```
</CodeGroup>

## Helper-Methoden

<Tip>
  Die in diesem Abschnitt beschriebenen Helper-Methoden sind nicht mit dem
  [AppSignal Collector](/python/configuration/collector) kompatibel.
</Tip>

Die folgenden Helper-Methoden setzen AppSignal-spezifische Attribute auf Spans, die helfen, Spans zu gruppieren und ihre Darstellung in AppSignal zu verbessern. Andere Attribute werden von AppSignal auf Spans nicht unterstützt.

### `set_category`

Die Span-Kategorie ist der Name, der im Performance-Event-Timeline für Traces erscheint. Sie wird auch verwendet, um Spans zu gruppieren und auf der Sample-Detailseite eine Aufschlüsselung pro Gruppe zu erstellen.

<CodeGroup>
  ```python Python theme={null}
  from appsignal import set_category

  set_category("category.name")
  set_category("query.users")
  set_category("update.users")
  set_category("view.users")
  ```
</CodeGroup>

Die Kategorie ist eine Zeichenkette, die das untergeordnete Span-Event und die Gruppe enthält. Die Kategorie sollte einen Punkt (`.`) verwenden, um die hierarchische Vererbung des Events auszudrücken, wobei die höchste Einheit zuletzt steht. Weitere Informationen zu Span-Kategorien finden Sie im [Leitfaden für Event-Namen](/api/event-names).

### `set_name`

Dem Span können weitere Details hinzugefügt werden, die sichtbar sind, wenn Sie mit dem Mauszeiger über das Event in der Event-Timeline fahren. Der Span-Name wird verwendet, um weitere Informationen über das Event bereitzustellen, beispielsweise „Fetch users", die Datenbank, aus der sie abgerufen werden, oder die angeforderte URL.

<CodeGroup>
  ```python Python theme={null}
  from appsignal import set_name

  set_name("Fetch users")
  ```
</CodeGroup>

Wenn diese Methode nicht aufgerufen wird, wird der Wert verwendet, mit dem `start_as_current_span` aufgerufen wurde.

### `set_body`

<Warning>
  🔐 Senden Sie keine <strong>personenbezogenen Daten (Personal Identifiable Information, PII)</strong> an AppSignal. Filtern Sie PII (z. B. Namen, E-Mail-Adressen) und verwenden Sie stattdessen eine ID, einen Hash oder einen pseudonymisierten Bezeichner. <br /> <br /> Für <strong>HIPAA-pflichtige Stellen</strong> finden Sie weitere Informationen zum Abschluss eines Business Associate Agreement (BAA) in unserer <a href="/support/business-add-ons">Business Add-Ons-Dokumentation</a>.
</Warning>

Der Body des Spans kann zusätzliche Informationen über das Event enthalten, etwa den HTTP-Request, den verbundenen Host usw. Stellen Sie sicher, dass Sie die Informationen bereinigen, bevor Sie sie dem Span hinzufügen, damit keine personenbezogenen Daten an AppSignal gesendet werden. Diese Informationen sind für den Span sichtbar, wenn Sie mit dem Mauszeiger über die Event-Timeline fahren.

Um SQL-Abfragen im Body des Spans zu speichern, verwenden Sie stattdessen den [Helper `set_sql_body`](#set_sql_body).

<CodeGroup>
  ```python Python theme={null}
  from appsignal import set_body

  set_body("Span body")
  ```
</CodeGroup>

### `set_sql_body`

<Tip>
  Verfügbar ab Python-Paket 0.3.2.
</Tip>

Setzen Sie eine SQL-Abfrage als Body des Spans, wie sie in der Performance-Event-Timeline in der Detailansicht des Incident-Samples erscheint. Dies ist ähnlich zum [Helper `set_body`](#set_body), aber spezialisiert auf SQL-Abfragen. Jede mit diesem Attribut als Body gesetzte SQL-Abfrage wird bereinigt, um zu vermeiden, dass personenbezogene Daten (PII) an unsere Server gesendet werden.

Weitere Details zur Funktionsweise des Body-Attributs finden Sie beim [Helper `set_body`](#set_body).

Wenn sowohl der `set_body`- als auch der `set_sql_body`-Helper auf demselben Span aufgerufen werden, ist der Wert des `set_sql_body`-Helpers maßgeblich und der Wert des `set_body`-Helpers wird ignoriert.

<CodeGroup>
  ```python Python theme={null}
  from appsignal import set_sql_body

  set_body("SELECT * FROM users")
  ```
</CodeGroup>

### `set_root_name`

<Tip>
  Dieses Attribut gilt für den gesamten Trace. Es kann an einem untergeordneten Span gesetzt werden und muss nicht am obersten übergeordneten Span gesetzt werden. Dieses Attribut kann nur einmal pro Trace gesetzt werden. Wenn es mehrfach gesetzt wird, wird nur das Attribut eines einzigen Spans im Trace angewendet.
</Tip>

Jeder Trace wird unter einem HTTP-Endpunkt, einem Worker-Namen für Hintergrundjobs oder einem Task-Namen gruppiert. Wir nennen diese Gruppe den „Action-Namen". Um diesen Action-Namen für den gesamten Trace zu ändern, verwenden Sie den Helper `set_root_name`.

Verwenden Sie einen Action-Namen, der allgemein genug ist, um alle Traces aus diesem Teil der App zu gruppieren, ohne jedes Mal unterschiedliche Namen zu melden. Setzen Sie `GET /users/:id` (wobei `:id` der Name des URL-Parameters ist) als Action-Namen anstelle von `GET /users/123` (wobei `123` der tatsächliche Wert im Request ist). Letzteres würde für jeden eindeutigen Request einen neuen Incident melden.

<CodeGroup>
  ```python Python theme={null}
  from appsignal import set_root_name

  set_root_name("GET /custom")
  # With URL parameters
  set_root_name("GET /users/:id")
  ```
</CodeGroup>

#### Beispielanwendungsfall

Ihre Anwendung hat einen Endpunkt namens `GET /coffee`.

<CodeGroup>
  ```python Python theme={null}
  def coffee(request):
    return render(request, "coffee.html", {})
  ```
</CodeGroup>

Alle Anfragen an diesen Endpunkt erzeugen Samples namens `GET /coffee`, aber Ihr Endpunkt behandelt mehrere Aktionen: `coffee?action=buy` und `coffee?action=sell`.

<img src="https://mintcdn.com/appsignal-715f5a51/4TRZP0Sq9Zq7PAPW/assets/images/screenshots/node/span-without-root-name.png?fit=max&auto=format&n=4TRZP0Sq9Zq7PAPW&q=85&s=c17dd17713da423bac8d380df6274a1e" alt="Span ohne Root-Name" width="1030" height="640" data-path="assets/images/screenshots/node/span-without-root-name.png" />

Obwohl alle den Endpunkt `GET /coffee` verwenden, sind sie konzeptionell sehr unterschiedlich und es wäre daher sinnvoll, sie in AppSignal getrennt zu gruppieren, anstatt im selben `GET /coffee`-Sample. Dafür können Sie den Helper `set_root_name` verwenden:

<CodeGroup>
  ```python Python theme={null}
  from appsignal import set_root_name

  def coffee(request):
    if request.GET.action == "buy":
      set_root_name("Buy coffee")
      # Buy coffee...
    elif request.GET.action == "sell":
      set_root_name("Sell coffee")
      # Sell coffee...

    return render(request, "coffee.html", {})
  ```
</CodeGroup>

Die Verwendung von `set_root_name` ändert den Namen des Root-Spans und gruppiert die Samples für die Anfragen `coffee?action=buy` und `coffee?action=sell` in getrennte Aktionen:

<img src="https://mintcdn.com/appsignal-715f5a51/4TRZP0Sq9Zq7PAPW/assets/images/screenshots/node/root-name-span.png?fit=max&auto=format&n=4TRZP0Sq9Zq7PAPW&q=85&s=2d6521845df3d5bcd8938900b4b643ac" alt="Root-Name-Span" width="1052" height="780" data-path="assets/images/screenshots/node/root-name-span.png" />

## Andere Trace-Daten

Um die im Trace gespeicherten Daten noch weiter anzupassen, lesen Sie bitte unsere Leitfäden zu [Tagging](/guides/tagging) und [Datenanpassung](/guides/custom-data), um Tags, Parameter, Sitzungsdaten, benutzerdefinierte Daten und mehr hinzuzufügen.

[cookbook]: https://opentelemetry.io/docs/instrumentation/python/cookbook/
