Cloudflare Workers
Debugging
Logs
Workers Tail
Observabilidade

Workers: Debugging, Protokolle und Workers Tail – Beobachtbarkeit am Edge ohne Protokollserver

Es gibt keinen persistenten Prozess, kein Dateisystem und console.log geht ohne eine aktive Tail-Sitzung nirgendwo hin – das Debuggen von Workers erfordert ein anderes mentales Modell.

Workers: Debugging, Protokolle und Workers Tail – Beobachtbarkeit am Edge ohne Protokollserver

Wenn ein Ingenieur zum ersten Mal einem Produktionsmitarbeiter einen Betrag von console.log auszahlt und nirgendwo etwas erscheint, vermutet er instinktiv einen Fehler in der Bereitstellung. Das Protokoll verschwindet einfach. Es gibt keinen Anwendungsserver mit dauerhafter Standardausgabe, keine Protokolldatei auf der Festplatte und keinen Prozess, der die Ausgabe zwischen Aufrufen akkumuliert. Jede Worker-Ausführung erfolgt in einem V8-Isolat, das erstellt wird, die Anfrage verarbeitet und verschwindet – es hinterlässt keine Spuren, es sei denn, Sie erfassen sie aktiv. Das Verständnis dieses Modells ist die Voraussetzung für jede Observability-Strategie, die wirklich am Rande funktioniert.

Wrangler Tail: Was es ist und was nicht

wrangler tail öffnet eine Streaming-Verbindung zur Cloudflare-Infrastruktur und überträgt in Echtzeit die Ereignisse Ihrer Workers-Aufrufe erneut: Metadaten jeder Anfrage (Methode, URL, Antwortstatus, CPU-Dauer, Herkunftsland), die gesamte Ausgabe von console.log und console.error, Ausnahmen, die nicht mit Stacktrace abgefangen werden, und das Ergebnis von waitUntil(), wenn es beendet ist.

Was wrangler tail nicht kann: beharren. Wenn Sie die Sitzung schließen, gehen noch nicht eingetroffene Ereignisse verloren. Ereignisse, die vor dem Öffnen der Sitzung stattgefunden haben, sind für Sie ebenfalls nicht vorhanden. wrangler tail ist ein Live-Untersuchungstool – nützlich, um ein Problem zu reproduzieren, während Sie es beobachten, aber unbrauchbar, um zu rekonstruieren, was vor einer Stunde passiert ist.

Sie können die Ausgabe mit --filter-status 500 filtern, um nur Fehler anzuzeigen, oder mit --filter-sampling-rate 0.1, um 10 % des Datenverkehrs abzutasten und bei hoher Auslastung nicht überschwemmt zu werden. Bei Diensten mit Hunderten von Anfragen pro Sekunde macht der ungefilterte Tail das Terminal schnell unlesbar.

Das Problem der stillen Ausnahmen

Es gibt ein Laufzeitverhalten, das erfahrene Ingenieure auffällt: Ein Worker kann dem Client eine 200-Antwort übermitteln und dennoch eine Ausnahme ausgelöst haben – sofern die Ausnahme nach dem Senden der Response ausgelöst wurde.

Das konkrete Szenario: Sie rufen ctx.waitUntil(minhaFuncaoAssincrona()) an, um nach der Antwort Hintergrundarbeiten durchzuführen. Wenn minhaFuncaoAssincrona auf den Markt kommt, hat der Kunde bereits 200 erhalten und ist zufrieden. Die Ausnahme erscheint in wrangler tail als Fehlerereignis im Zusammenhang mit der Anfrage, ändert jedoch nicht den HTTP-Status, den der Client gesehen hat. Ohne geöffnetes Heck wird der Fehler nie gesehen.

Das Gleiche gilt für jedes Versprechen, dass Sie innerhalb des Handlers keine await tun. Wenn Sie ein fetch() ohne Warten und ohne Fehlerbehandlung auslösen und es ablehnt, erscheint die nicht erfasste Ablehnung im Ende, hat aber keinen Einfluss auf die Antwort, die der Client erhalten hat. In einer lokalen Umgebung mit wrangler dev kann dieses Verhalten anders sein – Warnungen sind besser sichtbar. In der Produktion herrscht völlige Stille.

Die Verteidigung ist systematisch: Jeder Handler muss über einen try/catch auf der höchsten Ebene verfügen, der erfasst, mit console.error protokolliert und einen expliziten HTTP 500 zurückgibt. Jedes an waitUntil() übergebene Versprechen muss über eine interne Fehlerbehandlung verfügen. Nicht, weil die Laufzeit sich an Sie erinnert – das wird sie nicht.

Wrangler Dev Local versus --remote

wrangler dev ohne Flags führt einen lokalen Server mit Miniflare aus – einer Node.js-Implementierung der Workers-Laufzeit. Für die meisten Entwicklungsfälle ist dies ausreichend: KV-, D1-, R2- und Queue-Bindungen funktionieren mit lokalen In-Memory- oder SQLite-Implementierungen, und die Feedbackschleife erfolgt sofort, ohne das Cloudflare-Netzwerk einzubeziehen.

wrangler dev --remote ist anders: Es sendet den Worker an die echte Cloudflare-Infrastruktur und leitet Entwicklungsanfragen über den echten Edge weiter. Dies ist erforderlich, wenn Sie Verhaltensweisen testen müssen, die Miniflare nicht originalgetreu simulieren kann – langlebige Objekte in der Produktion mit echtem Zustand, CDN-Caching-Verhalten oder Laufzeitfunktionen, die in der aktuellen Version von Miniflare noch nicht implementiert sind.

Der Kompromiss liegt auf der Hand: --remote erfordert [40-Authentifizierung, hat Netzwerklatenz und alle Schreibvorgänge an KV oder D1 gehen an die echten Ressourcen (es sei denn, Sie richten separate Namespaces/Staging-Banken ein, was Standard sein sollte). Die Verwendung von --remote ohne Isolierung der Staging-Umgebung ist der kürzeste Weg zur Beschädigung von Produktionsdaten während der Entwicklung.

Logpush: vom kurzlebigen Schwanz zur echten Retention

Für jeden Dienst, der rekonstruieren muss, was im Nachhinein passiert ist – Auditing, Post-Mortem-Debugging, Analyse von Fehlermustern – reicht wrangler tail nicht aus. Logpush löst dieses Problem, indem es Workers-Ereignisse an ein konfiguriertes Speicherziel exportiert.

Zu den unterstützten Zielen gehören R2 (Cloudflares eigener Speicher, 0,05 $ pro Million exportierter Zeilen), S3, Datadog, Splunk und einige andere. Die Konfiguration erfolgt über das Dashboard oder die API: Sie wählen den Datensatz (workers-trace-events), das Ziel und die Felder aus, die Sie exportieren möchten – timestamp, event.request.url, event.response.status, event.exceptions, event.logs (einschließlich der Ausgabe von console.log).

Das Wichtige am Feld event.logs: Es erfasst, was Sie an console.log übergeben haben, allerdings als serialisierten Text. Wenn Sie ein komplexes JavaScript-Objekt protokolliert haben, kommt in Logpush die Zeichenfolgendarstellung dieses Objekts an, nicht strukturiertes JSON. Für Protokolle, die am Ziel analysiert und gefiltert werden müssen – um Warnungen in Datadog oder Abfragen in Splunk zu erstellen – vor der Protokollierung explizit in JSON serialisieren: console.log(JSON.stringify({ level: 'error', message, requestId, stack })). Logpush liefert den String; Das Ziel analysiert den JSON.

Was in der Produktion überwacht werden soll – und was die Laufzeit nicht liefert

Worker geben nativ keine verteilten Ablaufverfolgungsspannen aus. Es gibt keine automatische Integration mit OpenTelemetry, es gibt keine Weitergabe des Trace-Kontexts zwischen Unteranfragen ohne manuelle Implementierung. Wenn ein Worker drei Dienste über fetch() aufruft und einer davon 800 ms benötigt, zeigt wrangler tail die Gesamtdauer an, schlüsselt jedoch nicht auf, wo die Zeit verbracht wurde. Um diese Sichtbarkeit zu erreichen, legen Sie die Zeit manuell fest: const t0 = Date.now() vor ​​dem Abruf, Date.now() - t0 danach, und protokollieren das strukturierte Ergebnis mit dem Namen des Dienstes.

Cloudflare hat Baselime übernommen und integriert seine Fähigkeiten unter dem Namen Cloudflare Observability – Protokoll- und Metrikanalyse mit mehr Ergonomie als manuelles Tail, aber echtes verteiltes Tracing erfordert immer noch Instrumentierung im Code oder ein SDK, das traceparent über Unteranfragen weitergibt.

Die nützlichsten Metriken zum Erkennen einer Verschlechterung, bevor der Client sie bemerkt: Perzentilverteilung der CPU-Dauer (p50, p95, p99), nach Route segmentierte Fehlerrate und Anzahl der Unteranforderungen pro Aufruf. Keines davon kommt aus der Laufzeit heraus – sie müssen erstellt, über Logpush exportiert und am Ziel in Warnungen umgewandelt werden. Der Unterschied zwischen einem Service, den Sie vertrauensvoll betreiben, und einem Service, bei dem Sie Angst haben, in Produktion zu gehen, liegt fast immer in der Qualität der Instrumente, die Sie vor dem ersten Vorfall gebaut haben.

Lesen Sie auch