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

# AppSignal pour Ruby et OpenTelemetry

export const Compatibility = ({versions = [], label = "Available in"}) => {
  if (!Array.isArray(versions) || versions.length === 0) {
    return null;
  }
  const defaultPillStyle = {
    borderColor: "#d4d4d8",
    background: "#f4f4f5",
    color: "#3f3f46"
  };
  const pillStyles = {
    "AppSignal for Elixir": {
      background: "#f3e8ff",
      borderColor: "#d8b4fe",
      color: "#6b21a8"
    },
    "AppSignal for Front-end": {
      background: "#fef9c3",
      borderColor: "#fde047",
      color: "#854d0e"
    },
    "AppSignal for Go": {
      background: "#ccfbf1",
      borderColor: "#5eead4",
      color: "#115e59"
    },
    "AppSignal for JavaScript": {
      background: "#fef9c3",
      borderColor: "#fde047",
      color: "#854d0e"
    },
    "AppSignal for Node.js": {
      background: "#dcfce7",
      borderColor: "#86efac",
      color: "#166534"
    },
    "AppSignal for Python": {
      background: "#dbeafe",
      borderColor: "#93c5fd",
      color: "#1e40af"
    },
    "AppSignal for Ruby": {
      background: "#fee2e2",
      borderColor: "#fca5a5",
      color: "#991b1b"
    },
    "AppSignal for Rust": {
      background: "#ffedd5",
      borderColor: "#fdba74",
      color: "#9a3412"
    }
  };
  const getPillStyle = name => ({
    ...defaultPillStyle,
    ...pillStyles[name] || ({})
  });
  return <div className="not-prose my-4 rounded-lg border border-zinc-200 bg-zinc-50 px-4 py-3 text-sm dark:border-white/10 dark:bg-white/5">
      <div className="flex flex-wrap items-center gap-x-2 gap-y-1">
        <span className="font-semibold text-zinc-700 dark:text-zinc-200">
          {label}:
        </span>
        {versions.map((v, i) => <span key={`${v.name}-${v.version}-${i}`} className="inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-xs font-medium" style={getPillStyle(v.name)}>
            <span>{v.name}</span>
            <span className="opacity-70">
              {v.version}
              {v.exact ? "" : "+"}
            </span>
          </span>)}
      </div>
    </div>;
};

<Compatibility versions={[{ name: "AppSignal for Ruby", version: "5.0.0" }]} />

<Note>
  **Mode collector uniquement :** ceci s'applique lorsqu'AppSignal pour Ruby s'exécute en [mode collector](/ruby/configuration/collector). Cela n'a aucun effet dans les autres cas.
</Note>

En [mode collector](/ruby/configuration/collector), AppSignal construit ses traces à partir de spans OpenTelemetry. Une transaction devient le span racine d'une trace. Chaque événement que vous instrumentez devient un span enfant à l'intérieur de celle-ci.

Votre propre instrumentation OpenTelemetry partage donc ces traces. Cette page décrit ce que cela vous apporte, et comment décrire un span plus en détail que ne le fait AppSignal par lui-même.

## Décrire un span dans les termes d'OpenTelemetry

Les attributs sont des paires clé-valeur sur un span. Les [conventions sémantiques](https://opentelemetry.io/docs/specs/semconv/) nomment les attributs à utiliser pour des tâches courantes, comme une requête de base de données ou une requête HTTP sortante. Utilisez ces noms lorsqu'ils s'appliquent, afin que d'autres outils puissent lire ce que vous enregistrez.

Ajoutez des attributs au span qu'AppSignal enregistre actuellement avec `add_opentelemetry_attributes` :

<CodeGroup>
  ```ruby Ruby theme={null}
  Appsignal.instrument("query.my_database") do
    Appsignal::Transaction.current.add_opentelemetry_attributes(
      "db.system.name" => "mysql",
      "db.namespace" => "orders"
    )
    run_the_query
  end
  ```
</CodeGroup>

Les attributs sont ajoutés à l'événement le plus imbriqué qui est ouvert à ce moment-là, soit l'événement `query.my_database` dans l'exemple ci-dessus. Lorsqu'aucun événement n'est ouvert, ils sont ajoutés au span propre de la transaction à la place.

Une valeur doit être une chaîne de caractères, un entier, un flottant ou un booléen. Toute autre valeur est convertie en chaîne de caractères.

## Types de span et portées d'instrumentation

### Type de span

Le type d'un span indique quel rôle le travail a joué dans la trace. Un span qui a servi une requête entrante est un span `:server`. Un span qui a appelé un autre service est un span `:client`. L'envoi et la réception d'un message sur une queue sont des spans `:producer` et `:consumer`. Le travail resté à l'intérieur de votre application est un span `:internal`.

Le span d'un événement peut être de l'un de ces cinq types. Il est `:internal` sauf si vous en définissez un. L'exception est `Appsignal.instrument_sql`, qui enregistre un span `:client`, car une requête est un appel sortant vers un système de stockage de données.

Le span d'une transaction peut être `:server`, `:consumer`, `:producer` ou `:internal`. Il est `:server` sauf si vous en définissez un. Un type en dehors de cette liste retombe sur `:server`.

<CodeGroup>
  ```ruby Ruby theme={null}
  Appsignal.instrument("request.my_api", :opentelemetry_kind => :client) do
    call_the_api
  end
  ```
</CodeGroup>

### Portée d'instrumentation

Une portée d'instrumentation nomme la bibliothèque pour laquelle un élément d'instrumentation est écrit, sous la forme d'une paire nom-version. Ce n'est pas toujours la bibliothèque à travers laquelle le travail est passé. L'instrumentation d'un adaptateur de base de données est rattachée à la bibliothèque de base de données à laquelle il parle, pas à l'adaptateur.

AppSignal répartit le temps pris par les événements et les allocations qu'ils ont effectuées par portée d'instrumentation. La portée détermine donc à quelle bibliothèque le coût d'un span est attribué.

Les spans sont enregistrés sous la portée par défaut d'AppSignal lorsque vous n'en définissez pas. Définissez votre propre portée lorsque vous instrumentez une bibliothèque pour son compte, afin que son coût soit attribué à cette bibliothèque.

<CodeGroup>
  ```ruby Ruby theme={null}
  Appsignal.instrument(
    "query.my_database",
    :opentelemetry_scope => ["my_database", "2.1.0"]
  ) do
    run_the_query
  end
  ```
</CodeGroup>

### Quelles méthodes acceptent un type ou une portée

Passez `opentelemetry_kind` et `opentelemetry_scope` à toute méthode qui démarre une transaction ou enregistre un événement :

* `Appsignal.monitor`
* `Appsignal.monitor_and_stop`
* `Appsignal.send_error`
* `Appsignal.report_error`
* `Appsignal.instrument`
* `Appsignal.instrument_sql`

Définissez `opentelemetry_kind` sur `:internal` pour `Appsignal.instrument_sql` afin de remplacer son type par défaut `:client`.

## Poursuivre une trace venue d'ailleurs

<a id="poursuivre-une-trace-venue-dailleurs" />

Un travail peut atteindre votre application depuis un endroit qu'AppSignal n'instrumente pas, en apportant son propre contexte OpenTelemetry. Ce contexte nomme la trace à laquelle le travail appartient. Le transmettre permet de lire les deux côtés comme une seule trace plutôt que deux.

Passez le contexte en tant que `opentelemetry_context`. Indiquez ce que le span de la transaction doit en faire avec `opentelemetry_relationship` :

* `:parent` fait du span de la transaction un enfant du span entrant. Le travail poursuit la même trace. C'est ce qui se passe lorsque vous passez un contexte sans rien préciser d'autre.
* `:link` démarre une nouvelle trace et enregistre un lien vers le span entrant. Utilisez ceci lorsque le travail constitue une unité à part plutôt qu'une continuation, ce qui est généralement le cas pour une tâche en arrière-plan.
* `:both` fait du span un enfant et enregistre le lien.
* `:none` ignore le contexte entrant.

<CodeGroup>
  ```ruby Ruby theme={null}
  context = OpenTelemetry.propagation.extract(message.headers)

  Appsignal.monitor(
    :action => "MessageConsumer#perform",
    :namespace => "background_job",
    :opentelemetry_kind => :consumer,
    :opentelemetry_relationship => :link,
    :opentelemetry_context => context
  ) do
    handle(message)
  end
  ```
</CodeGroup>

### Quelles méthodes acceptent un contexte et une relation

Passez `opentelemetry_context` et `opentelemetry_relationship` à toute méthode qui démarre une transaction :

* `Appsignal.monitor`
* `Appsignal.monitor_and_stop`
* `Appsignal.send_error`
* `Appsignal.report_error`

`Appsignal.report_error` fait exception. Elle ne démarre une transaction que lorsqu'aucune n'est ouverte. Les deux arguments s'appliquent lorsqu'elle en démarre une, et sont ignorés lorsqu'elle ajoute l'erreur à une transaction déjà ouverte.

Vous n'avez besoin de tout cela que pour du travail qu'AppSignal n'instrumente pas. Les bibliothèques listées sous [distributed tracing](/ruby/distributed-tracing) sont déjà connectées pour vous.

## Utiliser directement le SDK OpenTelemetry

Vous pouvez créer des spans avec le SDK OpenTelemetry à l'intérieur du code qu'AppSignal trace. AppSignal rend son propre span courant pendant qu'il enregistre, de sorte qu'un span que vous créez devient un enfant de l'événement AppSignal à l'intérieur duquel vous vous trouvez.

<CodeGroup>
  ```ruby Ruby theme={null}
  tracer = OpenTelemetry.tracer_provider.tracer("my-app")

  Appsignal.instrument("checkout") do
    # This span is recorded as a child of the "checkout" event.
    tracer.in_span("charge_card") do |span|
      span.set_attribute("payment.provider", "stripe")
      charge_the_card
    end
  end
  ```
</CodeGroup>

Utilisez `in_span` plutôt que de démarrer et de terminer les spans vous-même. Cela rend le span courant pendant toute la durée du bloc, le termine ensuite, et fait les deux correctement même lorsque votre code lève une erreur.

Les données que vous signalez via AppSignal sont toujours enregistrées sur un span créé par AppSignal, jamais sur un span que vous avez créé. Une erreur signalée à AppSignal à l'intérieur de votre propre span est enregistrée sur l'événement AppSignal qui l'entoure, ou sur le span de la transaction lorsqu'aucun événement n'est ouvert. Vos spans ne portent que ce que vous y enregistrez vous-même.

## Utiliser une instrumentation OpenTelemetry tierce

Vous pouvez installer des packages d'instrumentation écrits par d'autres personnes, comme ceux que le projet OpenTelemetry publie pour les bibliothèques courantes. Installez-les et configurez-les comme le décrit leur propre documentation. AppSignal n'a besoin d'aucune configuration pour eux, et leurs spans apparaissent dans vos traces aux côtés de ceux d'AppSignal.

Cela fonctionne parce que ces packages enregistrent leur travail sous le span actuellement ouvert, quel qu'il soit, et qu'AppSignal garde son propre span ouvert pendant qu'il enregistre. Leurs spans atterrissent donc à l'intérieur de la requête ou du job qu'AppSignal trace, à l'endroit où vous vous y attendriez.

Cela ne fonctionne pas dans l'autre sens. AppSignal démarre toujours une transaction comme le début d'une nouvelle trace, et ne regarde pas ce qu'OpenTelemetry a actuellement ouvert. Si un package ouvre son propre span et qu'une requête ou un job AppSignal démarre à l'intérieur de celui-ci, cette requête ne rejoint pas la trace du package. Vous obtenez deux traces au lieu d'une, sans lien entre elles.

Cela compte lorsqu'un package instrumente le point d'entrée de votre application, car AppSignal instrumente également ces points d'entrée. Lorsqu'un package instrumente un travail qui se déroule au milieu d'une requête déjà tracée par AppSignal, ce qui est le cas habituel, les deux s'assemblent sans que vous ayez à faire quoi que ce soit.

Lorsque vous avez réellement besoin de rejoindre une trace qu'AppSignal n'a pas démarrée, passez son contexte vous-même. Consultez [poursuivre une trace venue d'ailleurs](#poursuivre-une-trace-venue-dailleurs).
