> ## 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 für Ruby und 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>
  **Nur im Collector-Modus:** Dies gilt, wenn AppSignal für Ruby im [Collector-Modus](/ruby/configuration/collector) läuft. Andernfalls hat es keine Auswirkung.
</Note>

Im [Collector-Modus](/ruby/configuration/collector) baut AppSignal seine Traces aus OpenTelemetry-Spans auf. Eine Transaktion wird zum Root-Span eines Trace. Jedes Event, das Sie instrumentieren, wird darin zu einem Child-Span.

Ihre eigene OpenTelemetry-Instrumentierung teilt sich daher diese Traces. Diese Seite beschreibt, was Ihnen das bringt, und wie Sie einen Span detaillierter beschreiben, als AppSignal es von sich aus tut.

## Einen Span in OpenTelemetry-Begriffen beschreiben

Attribute sind Schlüssel-Wert-Paare an einem Span. Die [semantischen Konventionen](https://opentelemetry.io/docs/specs/semconv/) benennen die Attribute für gängige Arbeit, etwa eine Datenbankabfrage oder einen ausgehenden HTTP-Request. Verwenden Sie diese Namen, wo sie zutreffen, damit andere Tools lesen können, was Sie erfassen.

Fügen Sie dem Span, den AppSignal gerade aufzeichnet, mit `add_opentelemetry_attributes` Attribute hinzu:

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

Die Attribute werden dem innersten Event hinzugefügt, das zu diesem Zeitpunkt offen ist, im Beispiel oben das Event `query.my_database`. Ist kein Event offen, werden sie stattdessen dem eigenen Span der Transaktion hinzugefügt.

Ein Wert muss ein String, ein Integer, ein Float oder ein Boolean sein. Jeder andere Wert wird in einen String umgewandelt.

## Span-Arten und Instrumentierungs-Scopes

### Span-Art

Die Art eines Spans gibt an, welche Rolle die Arbeit im Trace gespielt hat. Ein Span, der einen eingehenden Request bedient hat, ist ein `:server`-Span. Ein Span, der einen anderen Dienst aufgerufen hat, ist ein `:client`-Span. Das Senden und Empfangen einer Nachricht auf einer Queue sind `:producer`- und `:consumer`-Spans. Arbeit, die innerhalb Ihrer Anwendung blieb, ist ein `:internal`-Span.

Der Span eines Events kann jede dieser fünf Arten haben. Er ist `:internal`, sofern Sie keine andere festlegen. Die Ausnahme ist `Appsignal.instrument_sql`, das einen `:client`-Span aufzeichnet, weil eine Abfrage ein ausgehender Aufruf an einen Datenspeicher ist.

Der Span einer Transaktion kann `:server`, `:consumer`, `:producer` oder `:internal` sein. Er ist `:server`, sofern Sie keine andere Art festlegen. Eine Art außerhalb dieser Liste fällt auf `:server` zurück.

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

### Instrumentierungs-Scope

Ein Instrumentierungs-Scope benennt die Bibliothek, für die ein Stück Instrumentierung geschrieben wurde, als Name-Version-Paar. Das ist nicht immer die Bibliothek, durch die die Arbeit lief. Instrumentierung für einen Datenbank-Adapter bezieht sich auf die Datenbankbibliothek, mit der er spricht, nicht auf den Adapter.

AppSignal schlüsselt die Zeit, die Events benötigt haben, und die Allocations, die sie vorgenommen haben, nach Instrumentierungs-Scope auf. Der Scope entscheidet daher, welcher Bibliothek die Kosten eines Spans zugerechnet werden.

Spans werden unter dem Standard-Scope von AppSignal aufgezeichnet, wenn Sie keinen eigenen festlegen. Legen Sie einen eigenen Scope fest, wenn Sie eine Bibliothek in deren Auftrag instrumentieren, damit deren Kosten dieser Bibliothek zugerechnet werden.

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

### Welche Methoden eine Art oder einen Scope akzeptieren

Übergeben Sie `opentelemetry_kind` und `opentelemetry_scope` an jede Methode, die eine Transaktion startet oder ein Event aufzeichnet:

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

Setzen Sie `opentelemetry_kind` bei `Appsignal.instrument_sql` auf `:internal`, um dessen Standard `:client` zu überschreiben.

## Einen Trace von anderswo fortsetzen

Arbeit kann Ihre Anwendung von einer Stelle aus erreichen, die AppSignal nicht instrumentiert, und dabei einen eigenen OpenTelemetry-Context mitbringen. Dieser Context benennt den Trace, zu dem die Arbeit gehört. Wird er übergeben, lassen sich beide Seiten als ein Trace statt als zwei lesen.

Übergeben Sie den Context als `opentelemetry_context`. Legen Sie mit `opentelemetry_relationship` fest, was der Span der Transaktion damit tun soll:

* `:parent` macht den Span der Transaktion zu einem Child des eingehenden Spans. Die Arbeit setzt denselben Trace fort. Das passiert, wenn Sie einen Context übergeben und sonst nichts angeben.
* `:link` startet einen neuen Trace und zeichnet einen Link zurück zum eingehenden Span auf. Verwenden Sie dies, wenn die Arbeit eine eigenständige Einheit ist statt einer Fortsetzung, was bei einem Hintergrundjob meist der Fall ist.
* `:both` macht den Span zu einem Child und zeichnet zusätzlich den Link auf.
* `:none` ignoriert den eingehenden Context.

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

### Welche Methoden einen Context und eine Relationship akzeptieren

Übergeben Sie `opentelemetry_context` und `opentelemetry_relationship` an jede Methode, die eine Transaktion startet:

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

`Appsignal.report_error` ist die Ausnahme. Es startet eine Transaktion nur, wenn keine offen ist. Beide Argumente gelten, wenn es eine startet, und werden ignoriert, wenn es den Fehler zu einer bereits offenen Transaktion hinzufügt.

Sie brauchen das nur für Arbeit, die AppSignal nicht instrumentiert. Die unter [distributed tracing](/ruby/distributed-tracing) aufgeführten Bibliotheken sind bereits für Sie verbunden.

## Das OpenTelemetry SDK direkt verwenden

Sie können mit dem OpenTelemetry SDK Spans innerhalb von Code erzeugen, den AppSignal verfolgt. AppSignal macht seinen eigenen Span während der Aufzeichnung aktuell, sodass ein von Ihnen erzeugter Span zu einem Child des AppSignal-Events wird, in dem Sie sich befinden.

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

Verwenden Sie `in_span`, statt Spans selbst zu starten und zu beenden. Es macht den Span für die Dauer des Blocks aktuell, beendet ihn danach und tut beides auch dann korrekt, wenn Ihr Code einen Fehler auslöst.

Daten, die Sie über AppSignal melden, werden immer auf einem von AppSignal erzeugten Span aufgezeichnet, nie auf einem von Ihnen erzeugten Span. Ein Fehler, der innerhalb Ihres eigenen Spans an AppSignal gemeldet wird, wird auf dem umgebenden AppSignal-Event aufgezeichnet, oder auf dem Span der Transaktion, wenn kein Event offen ist. Ihre Spans tragen nur das, was Sie selbst auf ihnen erfassen.

## Instrumentierung von Drittanbietern für OpenTelemetry verwenden

Sie können Instrumentierungspakete installieren, die andere Personen geschrieben haben, etwa die, die das OpenTelemetry-Projekt für gängige Bibliotheken veröffentlicht. Installieren und konfigurieren Sie sie so, wie es deren eigene Dokumentation beschreibt. AppSignal benötigt dafür keine Einrichtung, und deren Spans erscheinen neben den eigenen von AppSignal in Ihren Traces.

Das funktioniert, weil diese Pakete ihre Arbeit unter dem jeweils gerade offenen Span aufzeichnen und AppSignal seinen eigenen Span während der Aufzeichnung offen hält. Ihre Spans landen daher innerhalb des Requests oder Jobs, den AppSignal verfolgt, genau dort, wo Sie es erwarten würden.

Andersherum funktioniert es nicht. AppSignal startet eine Transaktion immer als Beginn eines neuen Trace und schaut nicht nach, was OpenTelemetry gerade offen hat. Öffnet ein Paket einen eigenen Span und beginnt darin ein Request oder Job von AppSignal, schließt sich dieser Request nicht dem Trace des Pakets an. Sie erhalten zwei Traces statt eines, ohne Verbindung dazwischen.

Das wirkt sich aus, wenn ein Paket den Einstiegspunkt in Ihre Anwendung instrumentiert, denn AppSignal instrumentiert diese Einstiegspunkte ebenfalls. Instrumentiert ein Paket dagegen Arbeit, die mitten in einem Request stattfindet, den AppSignal bereits verfolgt, was der übliche Fall ist, fügen sich beide zusammen, ohne dass Sie etwas tun müssen.

Wenn Sie tatsächlich einem Trace beitreten müssen, den AppSignal nicht gestartet hat, übergeben Sie dessen Context selbst. Siehe [Einen Trace von anderswo fortsetzen](#einen-trace-von-anderswo-fortsetzen).
