4 Punkte von GN⁺ 2025-01-11 | 1 Kommentare | Auf WhatsApp teilen
  • Die Anfrage eines Kunden nach OpenTelemetry-Unterstützung zeigte, dass die bestehende Observability auf Basis von Prometheus, Jaeger und OpenTracing nicht vollständig den OTel-Anforderungen für Metriken, Logs und Traces entsprach
  • Logs und Metriken ließen sich durch das Hinzufügen eines Appenders und zusätzlicher Konfigurationen relativ einfach migrieren, aber verteiltes Tracing war deutlich schwieriger, weil Spring und Akka innerhalb derselben JVM denselben Trace-Kontext gemeinsam nutzen mussten
  • OTel und Lightbend Telemetry/OpenTracing verwenden unterschiedliche Tracer-APIs und SpanContext-Implementierungen, wodurch dieselbe Transaktion in separate Traces zerfiel
  • Die Lösung bestand darin, den OTel-Kontext in eine Java-Map zu injecten, ihn als Jaeger-SpanContext zu extrahieren und dann mit GlobalExtendedTracer.get().local().activateContext() von Lightbend manuell zu aktivieren
  • OTel hilft bei der Standardisierung von Observability, aber beim Mischen mit bestehender Akka- und Jaeger-basierter Instrumentierung kann eine explizite Verknüpfung der Kontexte nötig sein

Die Observability-Signale, die OTel vereinheitlichen will

  • OpenTelemetry (OTel) ist ein Observability-Framework und Toolkit, das zuvor getrennte Tool-Bereiche über die drei Signale Metriken, Logs und Traces standardisieren will
  • Die bisherige Kombination war nach Rollen aufgeteilt
    • Prometheus: Metriken
    • Zentrale Aggregatoren wie Logstash und Elasticsearch: Logs
    • OpenTracing: verteiltes Tracing
  • OTel liefert nicht nur Spezifikationen, sondern auch zentrale Komponenten
    • OpenTelemetry Protocol (OTLP): das Protokoll, mit dem Anwendungen Telemetriedaten melden
    • OpenTelemetry Collector: eine herstellerneutrale Komponente zum Empfangen, Verarbeiten und Exportieren von Telemetriedaten
    • SDKs für mehr als 10 Sprachen: Implementierungen für OTLP und Telemetry-Export
  • Anwendungen senden Signale über automatische Instrumentierung, APIs und Sprach-SDKs an den OTel Collector; auch die Infrastruktur kann Signale an den Collector senden

Die bestehende Unterstützung in IPF und die Kundenanfrage

  • IPF hatte bereits ELK-Stack-Integration, Monitoring und Observability-Dokumentation, und Kunden nutzten dies schon in Produktionsumgebungen
  • Aufgrund der Natur des Frameworks war nicht absehbar, in welche Umgebungen Anwendungen mit der Bibliothek deployt werden würden; deshalb durfte kein bestimmter Vendor erzwungen werden und es mussten Abstraktionen sowie überschreibbare Defaults bereitgestellt werden
  • Die Standardempfehlung war, Logs an Aggregatoren wie Elasticsearch oder LogScale zu senden und Prometheus als de-facto-Standard für Metriken zu aktivieren und zu unterstützen
  • Kunden fragten nahezu gleichzeitig in drei Fällen OTel-basiertes Tracing an, und im Zuge dessen entstand auch der Trend, Logs und Metriken gemeinsam auf OTel umzustellen
  • Logs und Metriken ließen sich mit einem neuen Appender und zusätzlicher Konfiguration relativ einfach umsetzen, doch Tracing blieb ein separates Problem

Warum Kontextpropagierung im verteilten Tracing nötig ist

  • Um in einem verteilten System eine einzelne Transaktion nachzuverfolgen, müssen Informationen weitergegeben werden, die bestimmte Aufrufe und die Transaktion zwischen Systemen verknüpfen; das nennt man context propagation
  • Ein Trace ist eine übergeordnete Struktur, die mehrere Arbeitseinheiten, sogenannte Spans, umfasst; es kann mehrere Spans geben, und sie können verschachtelt sein
  • In einer E-Commerce-Site kann der Ablauf nach einem Klick auf den „buy now“-Button zu einem einzigen Trace zusammengefasst werden
    • ein Span für die Kommunikation des Frontends mit dem Backend
    • Kind-Spans für die Kommunikation des Backends mit Zahlungs-, Versand- und Auftragsverwaltungssystemen
    • zusätzliche Kind-Spans, wenn die jeweiligen Downstream-Services wiederum mit anderen Systemen kommunizieren
  • Bei Verwendung von OTel meldet jeder verteilte Service seinen Teil des Trace an den OTel Collector, und OTel setzt den Gesamtfluss unter einer einzigen Trace-ID zusammen

Vier Standards für Kontextpropagierung und das Erbe von OpenTracing

  • OTel muss vier Implementierungen der Kontextpropagierung unterstützen
  • Der Akka-Bereich von IPF unterstützte bereits das zur Ausmusterung vorgesehene OpenTracing und nutzte die OpenTracing-Unterstützung von Lightbend Telemetry
  • Lightbend Telemetry 2.20.0 ergänzte Unterstützung für OpenTelemetry-Logs/Events und Metriken, aber die entscheidende Tracing-Unterstützung fehlte
  • Theoretisch schien OTel-Tracing dem Rebranding von OpenTracing nahezukommen, und auch das OpenTracing von Lightbend Telemetry unterstützte die vier Propagierungsformate, sodass es funktionieren sollte – in der Praxis sah das Ergebnis jedoch anders aus

Der unterbrochene Trace zwischen Spring und Akka

  • IPF verwendet Spring und Akka gemeinsam
    • Spring Boot und Spring IoC: Bootstrap der Anwendung, Konfiguration und Verdrahtung von Abhängigkeiten
    • Akka: Event Sourcing, Scheduling, Clustering, Sharding, Integration usw.
  • Kunden können einen Zahlungsablauf über einen Spring-REST-Controller oder eine mit @KafkaListener annotierte Methode starten
  • Vor OTel funktionierten die drei Bereiche ohne größere Konflikte
    • Metrics: Spring und Akka stellten unterschiedliche Prometheus-Endpunkte bereit
    • Logs: Beide Frameworks verwendeten SLF4J und Logback
    • Traces: Beide verwendeten OpenTracing
  • Mit OTel wurden Metriken und Logs korrekt übertragen, weil Spring und Akka unabhängig voneinander arbeiteten; beim Tracing musste jedoch innerhalb der JVM derselbe Trace-Kontext gemeinsam genutzt werden
  • Das eigentliche Problem war, dass innerhalb der Anwendung zwei unterschiedliche APIs dasselbe Tracing-Konzept ausdrückten, aber nicht miteinander kommunizierten
  • Das korrekte Verhalten wäre gewesen, dass der Akka-HTTP-Client die vorhandene Trace-ID 123 wiederverwendet und nur eine neue Span-ID erzeugt, sodass eine neue Arbeitseinheit innerhalb desselben Trace entsteht; tatsächlich wurden jedoch zwei voneinander unabhängige Traces erzeugt

opentracing-shim und Konflikte zwischen Implementierungen

  • Auf OTel-Seite gibt es das opentracing-shim, das ein OTel-Tracer wie einen OpenTracing-Tracer aussehen lässt
  • Lightbend Telemetry verwendete jedoch eine benutzerdefinierte Tracer-Implementierung, weshalb sowohl das Shim als auch Jaeger scheiterten
  • In den Logs erschienen die folgenden Fehler
    • Expected to have an OpenTelemetry Span but got cinnamon.opentracing.TraceLocal$ContextOnlySpan
    • Expected to have a JaegerSpanContext but got io.opentelemetry.opentracingshim.SpanContextShim
  • Jaeger erhielt den OTel-Shim-Kontext und scheiterte, OTel erhielt den Lightbend-Kontext und scheiterte ebenfalls

Untersuchung von Java Agent und internem Tracing von Lightbend

  • Sowohl die OTel- als auch die Lightbend-Telemetry-Instrumentierung nutzen einen Java Agent, um sich in Aufrufe bestimmter Methoden bestimmter Klassen einzuhängen und Aktivitäten an den Tracer zu melden
  • Die Instrumentierung von Lightbend Telemetry ist nicht Open Source; um das Verhalten zu verstehen, musste daher der dekompilierte Tracer-Code untersucht werden
  • Mit einem verkleinerten Reproduktionsbeispiel wurde festgestellt, an welcher Stelle der OTel-Trace-Kontext auf der Spring-Seite beim Übergang zur Akka-Seite verloren ging
  • Die Stelle, an der Jaeger scheiterte, war dieser Code in JaegerTracer.java
  • Der Aufrufer war die proprietäre Instrumentierungsklasse OpenTracingAkkaPersistenceActorInstrumentation.class von Lightbend Telemetry
  • Im dekompilierten Code war der entscheidende Faktor der Zustand von var5
    • Wenn var5, ein OpenTracing-SpanContext, nicht null war, wurde der neue Span als Kind des aktuell aktiven Span angehängt
    • Wenn var5 null war, entstand ein Span ohne Beziehung zum bestehenden Trace
    • Wenn var5 kein Jaeger-SpanContext war, schlug Jaeger fehl

OTel und OpenTracing per manueller Konvertierung verbinden

  • Der SpanContext wurde aus this.traceLocal.currentContext() geholt, und traceLocal wurde im ExtendedTracer von Lightbend initialisiert
  • In der Lightbend-Dokumentation gab es eine Möglichkeit, global auf den ExtendedTracer zuzugreifen
    • GlobalExtendedTracer.get()
  • GlobalExtendedTracer.get() liefert einen ExtendedTracer zurück, und local() gibt denselben TraceLocal zurück, den auch die Instrumentierungsbibliothek verwendet
  • Dieser TraceLocal besitzt die Methode activateContext, die einen OpenTracing-SpanContext entgegennimmt
  • Der Lösungsablauf bestand aus vier Schritten
    • Das OTel-Shim nicht verwenden
    • Den aktuellen OpenTelemetry-Kontext in eine Java-Map injecten
    • Mit den Werten aus dieser Map einen Jaeger-SpanContext extrahieren
    • Vor dem Eintritt in Akka den Jaeger-SpanContext im TraceLocal von Lightbend aktivieren
  • Verwendet wurden dafür die OTel-Propagators-API-Operationen inject and extract operations
  • Der zentrale Code folgt diesem Ablauf
    • eine leere HashMap erzeugen
    • OTel-Kontext mit GlobalOpenTelemetry.get().getPropagators().getTextMapPropagator().inject(...) in die Map injizieren
    • mit new TextMapCodec(false).extract(new TextMapAdapter(otelContext)) einen JaegerSpanContext erzeugen
    • den Kontext mit GlobalExtendedTracer.get().local().activateContext(openTracingContext) vor dem Eintritt in Akka aktivieren

Bestätigtes Verhalten und Empfehlungen für den Betrieb

  • Nach der manuellen Verknüpfung setzte sich der Trace wie erwartet fort
    • Beginnend mit dem Spring-REST-Aufruf /submit war der gesamte Ablauf zu einem einzigen Trace verbunden
    • Mit der OTel-API instrumentierte Teile und mit der OpenTracing-API instrumentierte Teile konnten gemischt verwendet werden
    • Der Trace wurde über HTTP-Grenzen hinweg propagiert
  • Im Beispiel wurden unterschiedliche Namen verwendet, um die beiden Instrumentierungsarten zu unterscheiden; in realen Kundenumgebungen wird jedoch empfohlen, otel.service.name und cinnamon.application aufeinander abzustimmen, damit die Anwendung nach außen als eine einzige erscheint

Warum es so kompliziert war und welche Bedenken bleiben

  • Um Lightbend Telemetry auf die OTel-API umzuschreiben, müsste viel bestehende, an die Jaeger-API gebundene Instrumentierung auf die OTel-API portiert werden; das kann ein großer Aufwand sein
  • Der OTel Collector unterstützt das Einsammeln von Traces im Legacy-Zipkin-Format, sodass Lightbend über diese Legacy-Unterstützung vollständige OTel-Unterstützung anbieten könnte
  • Die unmittelbare Ursache der Komplexität lag darin, zwei Instrumentierungssysteme zu kombinieren, die unterschiedliche Tracing-Bibliotheken verwenden
  • Das OTel-Projekt versucht mit Standardisierungsansätzen wie Semantic Conventions, den Observability-Bereich zu ordnen; es ist anfangs etwas komplex zu verstehen, wird aber als nützliches FOSS-Projekt bewertet
  • Es bleibt die Sorge, ob Akka den Trace-Kontext innerhalb des Actor-Modells korrekt zwischen Threads weitergibt
    • In kleinen Lasttests funktionierte es wie erwartet
    • Ein entsprechendes Ticket bei Akka ist bereits eröffnet

1 Kommentare

 
GN⁺ 2025-01-11
Meinungen auf Hacker News
  • Während ich Otel lernte und portierte, fühlte es sich die ganze Zeit so an, als wäre ich wieder in der Java-Welt gelandet. Jedes Mal, wenn ich den Code Zeile für Zeile nachvollzog, wirkte es wie EnterpriseFizzBuzz, es gab keinerlei Discoverability, und die eigene Terminologie sah aus, als hätten sie Leute erfunden, die auf irgendetwas drauf waren.
    In NodeJS lag die CPU-Auslastung etwa viermal so hoch wie bei StatsD, und am Ende habe ich eine eigene Aggregation gebaut, um die Nutzung zu senken und auch die Tag-Explosion zu reduzieren. Bei StatsD ist es in Ordnung, wenn mehrere Prozesse dieselben Tags melden, aber OTEL überschreibt sie einfach.
    Unter Spitzenlast lief ein CPU-Kern bei 60–80 % Auslastung, und bevor sich etwas änderte, konnten wir nicht einmal vertikal skalieren. Für Sprachen, die einen Prozess pro Core verwenden, wirkt OTEL geradezu aktiv feindlich, fast wie ein Witz. Man fährt besser damit, einfach Prometheus zu verwenden; faktisch gibt es auch keine anderen Wettbewerber.

    • Ich sehe OTEL als etwas, das einer Art Vendor Lock-in nahekommt. Denn um einen Standard zu schaffen, blieb wohl nur, die Anforderungen mehrerer Großunternehmen und schlampiger Startups irgendwie zu kompromisseln und mit der Heißklebepistole zusammenzukleben.
      Als ich in .NET eine einfache otel-Konfiguration ausprobieren wollte, las ich stundenlang die Doku des Vendors, den meine Organisation ausgewählt hatte, und verstand sie trotzdem nicht. Also ging ich in einen Discord, den ein Kollege betreibt. Ein Teil von deren Geschäftsmodell war „Zahl, wenn du ordentliches otel in einem Open-Source-Produkt nutzen willst“, und mir war sofort klar, dass es den Preis wert wäre, egal wie hoch er ist.
      Statt eine OTEL-Implementierung zu bauen, würde ich lieber ohne Vorerfahrung noch eine stabile Event-/Publish-Subscribe-Library entwickeln.
    • Zu „es gibt auch keine anderen Wettbewerber“: Je nach Fall ist auch Apache SkyWalking einen Blick wert. Es frisst nicht viele Ressourcen und ist recht einfach zu konfigurieren und zu betreiben, auch wenn UI und Dokumentation weniger ausgereift sind: https://skywalking.apache.org/
      Auch die Minimalkonfiguration ist tatsächlich ziemlich klein: Web-UI, Serverinstanz und eine DB, die man bereits kennt, reichen: https://skywalking.apache.org/docs/main/latest/en/setup/back...
      Es hat gewisse Ähnlichkeit mit Zabbix im Monitoring-Bereich. Beides wird niemanden vom Hocker hauen, ist aber praktisch genug.
    • Zu demselben Schluss komme ich auch. Man nimmt einfach Prometheus und die Client-Library für die gewünschte Sprache; das ist tausendmal einfacher als die OTEL-Geschichte.
    • Ich verwende otel im C++-Bereich und habe, um kumulative Metriken über mehrere Anwendungen hinweg zu bekommen, ein Integer-Attribut mit relativ niedriger Kardinalität wie process.vpid angelegt. Man kann es etwa über ein globales Objekt so koordinieren, dass der Wert während der Lebensdauer der App eindeutig ist.
      Danach braucht man etwas, das aufsummiert und dieses Attribut entfernt. Bei statsd/delta bringt ein verlorenes Signal die gesamten Daten durcheinander, beim kumulativen Ansatz verliert man nur Präzision.
      Mein Anwendungsfall sind Push-basierte Metriken aus „Batch“-Tools, keine scrapebaren, lang laufenden Prozesse.
    • Das deckt sich mit meiner Erfahrung. Es war sehr schwer zu verstehen, was nötig ist, um den gewünschten Effekt zu erzielen.
  • Otel wirkt komplex, weil verschiedene Observability-Vendors die Umsetzung von Observability mit ihren proprietären SDKs, Agents und APIs extrem einfach gemacht haben. Otel versucht, dieses Problem zu lösen, und ich finde, die Leute dahinter machen das hervorragend.
    Es ist auch lobenswert, dass Grafana OpenTelemetry als erstklassigen Bestandteil des Ökosystems angenommen hat.
    Ich habe jahrelang die Nutzung von Datadog vorangetrieben, aber für eine Größenordnung zwischen Mittelstand und Großunternehmen wurde der Preis schwer tragbar. Mit der Zeit, als die OpenTelemetry-APIs und -SDKs stabiler wurden, machten wir es zum Standard für Application Observability.
    Allerdings könnte die Dokumentation insgesamt besser sein, und dass die Onboarding-Dokumente je nach Sprache unterschiedlich sind, ist nicht ideal.
    Unser Team nutzt derzeit einen NodeJS/Typescript-Stack, und wir haben ein Paket-Bundle sowie einen beispielhaften Grafana-Stack gebaut, damit man schnell mit OpenTelemetry starten kann: https://github.com/zonneplan/open-telemetry-js

    • Das Problem, das dadurch entstanden ist, dass alle es extrem einfach gemacht haben, löst dieses Produkt also, indem es es kompliziert macht? ;P
    • Ich bevorzuge gegenüber Datadog einfach gutes Metrik-Collecting. Andererseits verstehe ich theoretisch, dass OTEL gegenüber meiner bevorzugten Herangehensweise einen Mehrwert hat.
      Das größte Problem bei allen APM-Vendors ist: Sobald man mit einem magischen Agent Kernel-Hooks bekommt, passieren alle möglichen Dinge, die Entwickler nicht erklären können.
      In einem früheren Unternehmen führten wir Dynatrace ein; zum Glück hatte die App bereits ausreichend eingebaute Metriken, sodass der Lead-SRE sie als „vorbildlich“ instrumentiert ansah. Doch sobald der Dynatrace-Agent auf den App-Hosts installiert war, tauchten mehrere Heisenbugs auf, die Node-Neustarts erforderten, und auch Performance-Einbußen wurden direkt gemessen.
      Ironischerweise haben uns die Metriken den Schmerz erspart, aber niemand wusste, wie man das beheben sollte. Am schlimmsten war der Fall, dass bei MSSQL-Updates ein Failover den ADO.NET-Connection-Pool auf seltsame Weise kontaminierte.
  • Die Struktur wird nur so komplex, wie es nötig ist. Man kann magische Funktionen vermeiden und nur die Teilmenge nutzen, die im jeweiligen Kontext den größten Wert liefert und leicht zu verstehen ist.
    In unserem Team ist es sehr simpel. Wir verwenden eine Library, die nur Traces sendet; Traces liefern den größten Mehrwert für die Beobachtbarkeit von Anwendungen und können auch andere Datentypen enthalten. Im Grunde verwendet man also Hashmaps statt Strings und Floats.
    Statt automatischer Instrumentierung nutzen wir manuelle Instrumentierung, legen bewusst fest, was wir beobachten wollen, und verstehen gut, welcher Code Spans ausgibt. Außerdem haben wir Namenskonventionen, die zur Code-Struktur passen.
    Als Backend nutzen wir einen günstigen Third-Party-Service zusammen mit einer All-in-one-Jaeger-Installation für die lokale Entwicklung. Letztere braucht nur eine einzelne ausführbare Datei oder einen einzelnen Docker-Container und speichert Spans nicht auf der Festplatte. Sie dient vor allem dazu, Teammitglieder zu beruhigen, damit sie den Third-Party-Service nicht überfluten.
    Für Infrastruktur-Monitoring haben wir ein bestehendes Setup, und in unserem Fall sehen wir keinen großen Mehrwert darin, alle Infrastruktur-Logs und -Metriken zu sammeln. OTEL-Metriken und -Logs halte ich noch für in einer frühen Phase, auch wenn die Anbieter das nicht so sagen.

    • Es kann zwar beliebig komplex werden, aber nicht so einfach, wie ich es gern hätte. Der Mindestschwierigkeitsgrad ist ziemlich hoch.
      Ich suche noch nach einem Endpoint, um einfache einmalige Metriken aus Teilen der Infrastruktur zu senden, die sich noch nicht scrapen lassen.
    • Manuelle Instrumentierung hat sich für mich nicht einfacher angefühlt. Eher wie ein Tausch: Die Lernkurve beginnt lange bevor man Ergebnisse sieht, dafür versteht man die Performance-Kosten dieser Rube-Goldberg-Maschine klarer.
      Otel kann für neue Projekte okay sein, aber es in einem produktiven Service mit bereits vorhandener Telemetrie einzuschalten, fühlte sich an, als würde man bei einem fahrenden Auto die Reifen wechseln.
    • Kannst du teilen, welcher günstige Third-Party-Service das ist?
    • Das ist sehr vernünftiger Rat. Die meisten haben wahrscheinlich schon etwas für Metriken und Logs, und wenn es keinen Return on Investment für den Wechsel gibt, gibt es keinen Grund, es trotzdem zu tun.
    • „Magie vermeiden und nur eine Teilmenge nutzen“ funktioniert nur, wenn auch alle verwendeten Libraries genau diese Teilmenge nutzen. Meiner Erfahrung nach war das ganz überwiegend nicht der Fall, und der Artikel zeigt konkrete Beispiele dafür sehr gut.
      Ich glaube gern, dass es in einem Greenfield-Projekt, das nur otel und keine Nicht-otel-Frameworks verwendet, gut sein kann. Aber in so einer Welt lebe ich noch nicht.
  • Eines der größten Probleme war die lokale Developer Experience. Ich wollte lokal Logs, Traces und Metriken unterstützen, aber dafür nicht jede Menge Docker-Images hochfahren. Vor dem Deployment wollte ich in Logs sehen, wie Metriken, Traces, Baggage und Activity-Spans aussehen.
    Kürzlich hat das .NET-Team .NET Aspire veröffentlicht, und das ist sehr gut. Im lokalen Entwicklungs-Stack lässt sich alles leicht an einem Ort visualisieren, und es funktioniert wie ein Orchestrator in Code.
    Beim Deployment auf k8s richtet man den OTEL-Endpoint auf den DataDog Agent, und alles funktioniert einfach. Wir vermeiden die Custom-Trace-Libraries und SDKs von DataDog und nutzen nur OTEL.
    Die Developer Experience ist inzwischen ziemlich gut.
    https://learn.microsoft.com/en-us/dotnet/aspire/fundamentals...
    https://docs.datadoghq.com/opentelemetry/#overview

    • Für diesen Zweck ist dieses Projekt wirklich gut: https://github.com/grafana/docker-otel-lgtm
    • Es gibt auch https://github.com/CtrlSpice/otel-desktop-viewer
    • Man kann einfach https://github.com/openobserve/openobserve verwenden.
      Die Einrichtung auf der lokalen Entwicklungsmaschine dauert beim ersten Mal 5 Minuten, danach reicht es, in einem separaten Terminal-Tab /path/to/openobserve auszuführen. Wenn man die enorme Komplexität eines einzelnen statisch gelinkten Binary vermeiden will, gibt es auch Docker-Images für lokale und entfernte Ausführung :P
      Es ist ein All-in-one-OpenTelemetry-Backend mit hübschen Graphen, und in meinen Projekten ist es bisher nie auf eine für mich erkennbare Weise ausgefallen.
    • .NET Aspire überzeugt mich nicht. Es löst das kleine Problem von Service Discovery und Orchestrierung mehrerer Service-Projekte in der lokalen Entwicklung, macht es dafür aber zu einem Concern auf Anwendungsebene.
      Mit Aspire fügt man auf App-Ebene unnötige Komplexität hinzu und bindet sich an ein enges Ökosystem. Für lokale Entwicklung gibt es viele bewährte Alternativen wie docker compose, und Aspire ist auch nicht wirklich deutlich einfacher als docker compose und Umgebungsvariablen.
    • Es gibt ein offizielles All-in-one-Docker-Image, in dem alles enthalten ist.
  • Wenn man otel in Python macht, sollte man den Client von Logfire verwenden. Das gilt auch dann, wenn man den Logfire-Service nicht nutzt.
    Er ist Open Source und kann an jeden otel-kompatiblen Endpoint senden. Außerdem ist der vom pydantic-Team entwickelte Client zehnmal besser und einfacher als die offiziellen otel-Libraries.
    Es gibt auch ein interessantes Interview, in dem Samuel Colvin erklärt, wie es dazu kam: https://www.bitecode.dev/p/samuel-colvin-on-logfire-mixing-p...

  • Deshalb habe ich ein Open-Source-Projekt gestartet, das darauf abzielt, die Einführung von OpenTelemetry so einfach wie einen einzigen Befehl zu machen: https://github.com/odigos-io/odigos

  • Heutzutage übernehmen viele Web-Frameworks den Großteil der Instrumentierung. Wenn man zum Beispiel opentelemetry-js nutzt und etwas wie https://signoz.io selbst hostet, kann man es in weniger als einer Stunde zum Laufen bringen und bekommt auch ohne eigenen Code viele Daten

    • Das SigNoz-Repository ist hier: https://github.com/signoz/signoz
    • Kontextweitergabe in einer multithreaded, asynchronen Runtime ist nicht trivial. Es gibt mehrere Wege, aber JVM-Agenten, die Bytecode instrumentieren, sind deshalb beliebt, weil sie transparent funktionieren
  • OpenTelemetry ist aus Traces heraus gewachsen, aber Metrics und Logs sollte man viel besser spezialisierten Lösungen überlassen
    Es fühlt sich wie das Problem einer „leaky abstraction“ oder eines „leaky framework“ an. Wenn man alles unter ein Dach bringen will, kann eine SQL-Datenbank das alles auch gleichzeitig. Das heißt aber nicht, dass man es tun sollte

    • Cramer möchte Traces aus OTel herausnehmen. Ironisch, wenn man bedenkt, dass er einer der Gründer von OpenTracing ist
      https://cra.mr/the-problem-with-otel/
    • Metrics und Logging eine Position innerhalb eines Traces zu geben, halte ich für wirklich nützlich
      Trotzdem mag ich den Umgang mit OTel jedes Mal immer noch nicht
  • Wenn man bis zum Ende liest, merkt man, dass der Schmerz größtenteils selbst verursacht ist. Im Standard-Stack von Python (mysql, flask, redis, requests usw.) war es sehr einfach. Ein paar Imports oben im Service, und alles verband sich automatisch und verfolgte ohne großes Aufheben alles

    • Stimmt, aber nur, wenn alles im Stack Auto-Instrumentierung unterstützt. aiohttp ist zum Beispiel in der neuesten Version bei 3.11.X, und die Auto-Instrumentierung gibt zwar an, 3.X zu unterstützen [0], aber das tatsächliche Ergebnis hängt davon ab, wie aktuell das verwendete aiohttp ist und in welchem Zustand die Auto-Instrumentierung selbst ist
      Wenn alles zusammenpasst, funktioniert es wie Magie, aber dieses Nadelöhr ist ziemlich eng
      [0]: https://github.com/open-telemetry/opentelemetry-python-contr...
    • Ich musste das kürzlich an eine sehr einfache Flask-App anbinden. Sie muss nur im internen Intranet laufen, daher betreibe ich auf einem einzelnen Server per docker compose otel-collector-contrib, jaeger-all-in-one und prometheus
      Traces funktionieren, der spanmetrics exporter ist ebenfalls konfiguriert, und wenn ich direkt in prometheus abfrage, sehe ich die spanmetrics. Aber egal, was ich tue: Im „monitor“-Tab von jaeger tauchen sie nicht auf
      Nachdem ich drei Tage damit verbracht hatte, sagte mein Chef: „Warum instrumentieren wir nicht einfach manuell, schicken alles an einen SQL Server und bauen ein Grafana-Dashboard?“ — aber das möchte ich auch nicht
      Selbst der einfachste Use Case funktioniert nicht. Muss ich jetzt noch Grafana obendrauf setzen?
    • Das gilt nur, bis man den Server hinter etwas wie gunicorn betreibt. In dem Moment hören alle automatischen Imports auf, und man muss alles selbst machen
  • Der Grund für die Komplexität ist, dass es nicht für die Engineers entwickelt wurde, die es implementieren, sondern für Unternehmen, die Otel-kompatible Software verkaufen

    • Da bin ich mir nicht sicher. Vendoren wären vermutlich mit ihrem proprietären Code, ihren Agenten und Backends zufrieden gewesen. Wegen des Lock-in-Effekts müssten alle neuen Code schreiben, wodurch die Wechselkosten sehr hoch würden
    • Das war nicht der Eindruck, den ich von den Beitragenden hatte
      Eher wirkten die Backends bei der Einführung ziemlich langsam
    • Es mag pingelig klingen, aber früher bezeichnete „implementieren“ die erstere Tätigkeit: sich hinzusetzen und Software gemäß einer Spezifikation zu schreiben. Nicht wie bei letzterem, vorhandene Software zu nehmen und auf einem Server bereitzustellen
      Bedeutungen ändern sich, also ist das in Ordnung, aber es ist interessant, dass uns jetzt ein Wort für Software gemäß einer Spezifikation schreiben fehlt und nur noch „vorhandene Software auf einem Server bereitstellen“ übrig geblieben ist