> ## 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.

# Instrumentation personnalisée Python

L'inclusion d'une instrumentation personnalisée dans votre application peut être utile pour identifier les lignes de code spécifiques à l'origine de problèmes de performance.

AppSignal pour Python utilise les objets tracer d'OpenTelemetry ; vous pouvez en savoir plus sur les traces Python dans le [Cookbook Python][cookbook] d'OpenTelemetry.

Les traces sont constituées d'un ou plusieurs spans. On peut considérer une trace comme un graphe acyclique orienté (DAG) de spans :

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

Des attributs spécifiques à AppSignal doivent être ajoutés à un span pour qu'il soit correctement analysé par AppSignal. Notre ensemble de [méthodes helper](#helper-methods) peut être utilisé pour définir ces attributs.

Cette documentation explique comment créer des instrumentations personnalisées en définissant des attributs spécifiques à AppSignal dans les spans de votre application Python.

## Créer un span

Lorsque vous ajoutez une instrumentation personnalisée, importez d'abord le module trace d'OpenTelemetry dans le fichier auquel vous souhaitez ajouter l'instrumentation.

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

Ensuite, à l'aide de ce module trace, créez un nouveau 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>

Une fois que vous avez récupéré le span, vous pouvez utiliser nos [méthodes helper](#helper-method) pour attribuer les attributs requis.

Plus d'informations sur la création et l'obtention de spans sont disponibles dans le [Cookbook Python][cookbook] d'OpenTelemetry.

## Scripts ponctuels et serverless

Lorsque vous exécutez des scripts ponctuels ou des fonctions serverless, vous devez initialiser manuellement AppSignal et l'arrêter à la fin pour vous assurer qu'aucune donnée n'est perdue. Le helper `stop` arrêtera proprement le processus d'agent et attendra un certain temps pour s'assurer que toutes les données sont envoyées aux serveurs AppSignal.

<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>

## Méthodes helper

<Tip>
  Les méthodes helper décrites dans cette section ne sont pas compatibles avec le
  [collector AppSignal](/python/configuration/collector).
</Tip>

Les méthodes helper suivantes définissent des attributs spécifiques à AppSignal sur les spans qui aident à regrouper les spans et à améliorer leur affichage dans AppSignal. Les autres attributs ne sont pas pris en charge sur les spans par AppSignal.

### `set_category`

La catégorie du span est le nom qui apparaît dans la chronologie des événements de performance pour les traces. Elle est également utilisée pour regrouper les spans afin de créer une répartition par groupe sur la page de détail de l'échantillon.

<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>

La catégorie est une chaîne contenant l'événement et le groupe du span enfant. La catégorie doit utiliser un point (`.`) pour exprimer l'héritage hiérarchique de l'événement, avec l'unité la plus élevée en dernier. Pour plus d'informations sur les catégories de span, veuillez consulter le [guide sur les noms d'événements](/api/event-names).

### `set_name`

Plus de détails peuvent être ajoutés au span ; ils sont visibles au survol de l'événement dans la chronologie des événements. Le nom du span est utilisé pour fournir plus d'informations sur l'événement, telles que « Fetch users », la base de données depuis laquelle les utilisateurs sont récupérés ou l'URL qui a été demandée.

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

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

Si cette méthode n'est pas appelée, la valeur avec laquelle `start_as_current_span` a été appelée sera utilisée.

### `set_body`

<Warning>
  🔐 N'envoyez pas d'<strong>informations personnelles identifiables (PII)</strong> à AppSignal. Filtrez les PII (par exemple, noms, e-mails) et utilisez un identifiant, un hash ou un identifiant pseudonymisé à la place. <br /> <br /> Pour les <strong>entités couvertes par la HIPAA</strong>, plus d'informations sur la signature d'un Business Associate Agreement (BAA) sont disponibles dans notre <a href="/support/business-add-ons">documentation Business Add-Ons</a>.
</Warning>

Le corps du span peut inclure des informations supplémentaires sur l'événement, comme la requête HTTP, l'hôte connecté, etc. Veillez à assainir les informations avant de les ajouter au span afin qu'aucune information personnellement identifiable ne soit envoyée à AppSignal. Ces informations seront visibles pour le span au survol de la chronologie des événements.

Pour stocker des requêtes SQL dans le corps du span, veuillez utiliser le [helper `set_sql_body`](#set_sql_body) à la place.

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

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

### `set_sql_body`

<Tip>
  Disponible depuis le package Python 0.3.2.
</Tip>

Définit une requête SQL comme corps du span tel qu'il apparaît dans la chronologie des événements de performance dans la vue de détail de l'échantillon d'incident. Cela est similaire au [helper `set_body`](#set_body), mais est spécialisé pour les requêtes SQL. Toute requête SQL définie comme corps avec cet attribut sera assainie pour éviter d'envoyer des données PII (Personal Identifiable Information) à nos serveurs.

Voir le [helper `set_body`](#set_body) pour plus de détails sur le fonctionnement de l'attribut body.

Lorsque les helpers `set_body` et `set_sql_body` sont tous deux appelés sur le même span, la valeur du helper `set_sql_body` est prioritaire et la valeur du helper `set_body` sera ignorée.

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

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

### `set_root_name`

<Tip>
  Cet attribut s'applique à l'ensemble de la trace. Il peut être défini sur un span enfant et n'a pas besoin d'être défini sur le span parent le plus haut. Cet attribut ne peut être défini qu'une seule fois par trace. S'il est défini plusieurs fois, seul l'attribut d'un seul span de la trace est appliqué.
</Tip>

Chaque trace est regroupée sous un endpoint HTTP, un nom de worker de job en arrière-plan ou un nom de tâche. Nous appelons ce groupe le « nom d'action ». Pour modifier ce nom d'action pour toute la trace, utilisez le helper `set_root_name`.

Utilisez un nom d'action suffisamment générique pour regrouper toutes les traces de cette partie de l'application, sans signaler des noms différents à chaque fois. Définissez `GET /users/:id` (où `:id` est le nom du paramètre d'URL) comme nom d'action, au lieu de `GET /users/123` (où `123` est la valeur réelle fournie dans la requête). Ce dernier signalerait un nouvel incident pour chaque requête unique.

<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>

#### Exemple de cas d'utilisation

Votre application a un endpoint appelé `GET /coffee`.

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

Toutes les requêtes vers cet endpoint généreront des échantillons appelés `GET /coffee`, mais votre endpoint gère plusieurs actions : `coffee?action=buy` et `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 sans nom de racine" width="1030" height="640" data-path="assets/images/screenshots/node/span-without-root-name.png" />

Bien qu'ils utilisent tous l'endpoint `GET /coffee`, ils sont conceptuellement très différents et il serait donc logique qu'ils soient regroupés séparément dans AppSignal plutôt que dans le même échantillon `GET /coffee`. Pour ce faire, vous pouvez utiliser le helper `set_root_name` :

<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>

L'utilisation de `set_root_name` modifiera le nom du span racine, regroupant les échantillons des requêtes `coffee?action=buy` et `coffee?action=sell` en actions distinctes :

<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="Span avec nom de racine" width="1052" height="780" data-path="assets/images/screenshots/node/root-name-span.png" />

## Autres données de trace

Pour personnaliser encore davantage les données stockées sur la trace, veuillez consulter nos guides sur le [Tagging](/guides/tagging) et la [Personnalisation des données](/guides/custom-data) pour ajouter des tags, des paramètres, des données de session, des données personnalisées et plus encore.

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