1 Punkte von GN⁺ 2024-08-21 | 1 Kommentare | Auf WhatsApp teilen
  • Auf jumpcomedy.com schlugen gegen 22 Uhr alle HTTP-POST-Aufrufe von RTK Query fehl, wodurch Website-Funktionen ausfielen; lokal funktionierte alles, was die Ursachenanalyse erschwerte
  • Während sich Kundenbeschwerden häuften, musste der Betreiber den Ausfall allein bewältigen – ohne Production Support, SRE, Senior Engineers oder Manager
  • Der TypeError des Browsers im Zusammenhang mit fetch lieferte keinen direkten Hinweis, zumal GET und DELETE normal funktionierten
  • Auch Prüfungen von Sentry, Produktionsdatenbank, Cloudflare, Chrome-Update und Rollback auf ältere Versionen brachten keine Veränderung; erst als der lokal leer gelassene PostHog api_key eingetragen wurde, ließ sich das Problem reproduzieren
  • Nach dem Entfernen von PostHog funktionierte alles wieder; später bestätigten GitHub-Issues bei PostHog und Redux Toolkit denselben Ausfall, womit sich der Einfluss eines externen Tools zeigte

Der Druck durch den Ausfall

  • Auf jumpcomedy.com schlugen ab etwa 22 Uhr alle HTTP-POST-Aufrufe auf Basis von RTK Query fehl, sodass zentrale Funktionen nicht mehr richtig arbeiteten
  • Es gab zwar kürzlich deployte Änderungen, aber nichts, was als Ursache nahelag; da sich das Problem lokal nicht reproduzieren ließ, wurde die Fehlersuche noch schwieriger
  • Der Betreiber bat im NextJS- und Vercel-Discord um Hilfe, erhielt jedoch keine Antwort, und es gab auch keine Production-Support-Organisation, an die er die Störungsbehebung hätte übergeben können
  • Kunden-E-Mails häuften sich weiter
    • Anfragen, dass sich Veranstaltungspreise nicht ändern ließen
    • Anfragen, dass sich Promo-Codes nicht entfernen ließen
  • Weil kleine Geschäftskunden auf den Dienst angewiesen waren, empfand der Betreiber Scham, Traurigkeit, ein Gefühl der Unfähigkeit und Impostor-Syndrom

Debugging-Prozess und Ursachenbestätigung

  • Der Browserfehler war ein TypeError, wonach fetch mit einem bereits verwendeten Request-Object ausgeführt wurde, zeigte aber nicht auf die tatsächliche Ursache
  • Mit mehreren console.log()-Ausgaben und Breakpoints wurden Header, Länge des API-Tokens, Aufrufreihenfolge und Ähnliches überprüft, ohne zu einer klaren Ursache zu führen
  • Ein Chrome-Update wurde als mögliche Ursache vermutet, doch das Problem ließ sich auch in Firefox und Edge reproduzieren, sodass es kein reines Browserproblem war
  • Auch ein Zurückrollen auf ältere Versionen änderte nichts
    • Fehler auch mit der Version von vor einem Monat
    • Fehler auch mit der Version von vor drei Monaten
    • Fehler auch mit der Version von vor einem Jahr
  • Um die Unterschiede zwischen lokaler Umgebung und Produktion zu verringern, wurden mehrere Kandidaten geprüft
    • Sentry in Produktion entfernt: keine Veränderung
    • Lokale Umgebung mit der Produktionsdatenbank verbunden: keine Veränderung
    • Cloudflare deaktiviert: keine Veränderung
  • Lokal war aus Kostengründen der PostHog api_key leer gelassen worden; nachdem er hinzugefügt wurde, trat dasselbe Problem auf
  • Im nächsten Commit wurde PostHog entfernt, woraufhin alle Funktionen wieder normal liefen
  • Dasselbe Problem wurde später auch durch GitHub-Issues bestätigt

1 Kommentare

 
GN⁺ 2024-08-21
Hacker-News-Kommentare
  • Nachdem ich ein Jahr lang als SRE in einem großen globalen Unternehmen gearbeitet habe, konnte ich aus dem im Text beschriebenen „Panik“-Modus herauskommen
    Aus Geschäftssicht wirkt jedes Problem wie ein Weltuntergangsereignis, und in so einer Situation gerät man leicht in Panik, aber tatsächlich ist es nur selten so schlimm, und selbst wenn es schlimm ist, überlebt man es meistens unbeschadet
    In solchen Situationen ist der Schlüssel, 5–10 Minuten innezuhalten und sich die Lage so klar wie möglich zu vergegenwärtigen, bevor man sofort versucht, etwas zu reparieren. Angst behindert vernünftiges Urteilsvermögen, und wenn man im Panikzustand wahllos auf Knöpfe drückt, kann sich das Problem noch mehr verheddern. Mein Trick ist, mir eiskaltes Wasser ins Gesicht und über die Hände zu werfen, um den Angstkreislauf zu unterbrechen
    Wenn man so etwas ein paar Mal erlebt hat, merkt man, dass es besser zu bewältigen ist als gedacht, und gewinnt das Selbstvertrauen, schon früher mit schlimmen Situationen fertig geworden zu sein, sodass man weiß, dass man damit klarkommt, auch wenn niemand da ist, den man um Hilfe bitten kann

    • Man sollte sich daran erinnern, dass ein Unternehmen völlig ausflippen kann, wenn etwas „kaputt“ geht, während es bei Problemen, die in Wahrheit vielleicht noch wichtiger sind, überhaupt nicht in Panik gerät
      Etwa wenn gekaufte Software wegen Fehlbesetzung oder misslungener Konfiguration gar nichts leistet, wenn Mitarbeitende jedes Jahr Tausende Stunden durch schlechte User Experience und sinnlose Anforderungen verlieren, wenn Fähigkeiten brachliegen und nichts bewirken, wenn nutzlose Meetings täglich Zeit verschwenden, wenn Funktionen nur existieren, um Audit-Anforderungen zu erfüllen, oder wenn Führungskräfte weiter Geld der Firma verschwenden
      Downtime wirkt nicht schlimmer als diese Probleme, zieht aber viel mehr Aufmerksamkeit und Panik auf sich. Es fühlt sich an wie der Vergleich zwischen Terror und Herzkrankheiten. Das Unternehmen kümmert sich nicht um deinen Schlaf oder deine psychische Gesundheit und wird so viel Druck machen, wie es kann. Das heißt nicht, dass es böswillig ist, aber in diesem Punkt ist es wie ein Tyrann: Es drängt umso mehr, je weiter du nachgibst
    • Die schlimmsten Fehler, die ich bei echten Incidents gesehen habe, kamen meist aus Überreaktionen
      Eines meiner Programmiermottos lautet: „Keine schwarze Magie.“ Wenn ich nicht verstehe, warum etwas funktioniert, dann ist es nicht fertig
      Genauso sehe ich Incident Response. Wenn jemand nicht schlüssig erklären kann, warum sein Vorschlag Wirkung haben sollte, dann sollte man ihn meiner Meinung nach nicht umsetzen. Irgendwann mag ein Moment kommen, in dem man einfach abdrücken muss, aber rückblickend scheint es bei mir nie wirklich so einen Fall gegeben zu haben
      Es war ziemlich schockierend zu sehen, wie normalerweise sehr ruhige leitende Angestellte während eines Ausfalls anfingen, irgendwelche willkürlichen Fix-Kandidaten in den Raum zu werfen
    • Umgekehrt dürften die Leute, die bei jumpcomedy.com gegen 2 Uhr nachts, plus/minus zwei Zeitzonen, Eventpreise ändern mussten, schwer enttäuscht gewesen sein. Einige von ihnen sind vielleicht sogar gestorben
      Man stelle sich vor, wie viel größer der Schaden geworden wäre, wenn niemand diesen Solo-Entwickler gestoppt hätte, als er versuchte, fetch modern zu machen
    • Einer der coolsten VPs, die ich kenne, sagte oft: „Langsam ist flüssig, und flüssig ist schnell
      Es stimmt, dass Angst vernünftiges Urteilsvermögen behindert, und ich möchte noch hinzufügen, dass Angst extrem ansteckend ist. Wenn die Leute an der Front sehen, dass Führungskräfte, Manager oder Kolleginnen und Kollegen in Panik geraten, geraten sie oft ebenfalls in Panik. Zum Glück blieb mein VP immer ruhig und stellte Klarheit über Aktionismus
    • Letztlich trägst du dieses Risiko nicht selbst. Es ist nicht dein Unternehmen, und das Unternehmen kann dich jederzeit abstoßen und wird das auch tun. Natürlich ist das etwas anderes, wenn es dein Unternehmen ist
  • Ich weiß nicht, ob das wirklich ein mentaler Zusammenbruch ist, und es könnte bei Leuten, die wegen technischem Stress einen echten Zusammenbruch erlebt haben, einen falschen Eindruck erwecken
    Bei mir gab es das genau einmal, und es war eine Angstattacke. Ich hatte großes Glück, dass meine Frau neben mir war, mir die Situation erklärte und mir half zu verstehen, was ich durchmachte. Sie hatte das schon mehrfach erlebt, für mich war es das erste und glücklicherweise letzte Mal
    So etwas kann Menschen passieren, und daran ist an sich nichts falsch. Es ist sehr wichtig, wirklich zu verinnerlichen, dass das nicht bedeutet, dass man defekt oder schwach ist
    Bei mir war es am Ende Xanax, das mich zum Stillstand brachte, und weil ich dadurch einschlafen konnte, halte ich es für sinnvoll, etwas davon griffbereit zu haben
    Ich will sagen, dass intrusive Gedanken etwas anderes sind als ein Zustand wie eine Angst- oder Panikattacke, den man tatsächlich nicht kontrollieren kann und der einen funktional lähmt. Wenn so etwas passiert, kann man nicht arbeiten, und das ist auch in Ordnung

    • https://www.webmd.com/mental-health/signs-nervous-breakdown
      Nicht jeder Zusammenbruch äußert sich als Panik- oder Angstattacke. So kann er sich zeigen, aber das ist nicht die einzige Form. Stress wirkt sich von Person zu Person und sogar je nach Stressor sehr unterschiedlich aus
      Man kann von außen kaum „diagnostizieren“, was genau im Kopf dieser Person passiert ist. Selbst wenn es keine voll ausgeprägte Panikattacke war, klingt es doch so, als sei sie für einige Stunden funktional gelähmt gewesen
    • Mit der Aussage „Es ist gut, Xanax in der Nähe zu haben“ sollte man vorsichtig sein
      Wenn man online nachschaut, sieht es so aus, als könne Xanax abhängig machen
      https://www.drugs.com/xanax.html
      Es scheint nichts zu sein, das man leichtfertig einnehmen sollte
    • Ich sollte keine Medikamente nehmen müssen, um mit ständig halbgar veröffentlichten Funktionen, gedankenlos hineingedrückten Änderungen und den daraus resultierenden PagerDuty-Alarmen um 3 Uhr morgens klarzukommen
      Wahrscheinlich werden wir zusehen, wie die große Gruppe von Menschen, die Mitte der 2000er in die Tech-Branche eingestiegen ist, an stressbedingten Erkrankungen zugrunde geht
    • Eines der Dinge, die ich bei der Arbeit in einem Enterprise-Tech-Unternehmen nicht erwartet hatte, war, wie viele Kolleginnen und Kollegen regelmäßig Xanax nehmen
      Als jemand, der das ganze Leben mit starker Angst gelebt hat, ist schon der Gedanke beängstigend, dass eine einzige abhängig machende Pille all das verschwinden lassen könnte. Ich hätte das Gefühl, mein Leben lang daran zu hängen
    • Ehrlich gesagt war ich enttäuscht, dass es nur eine gewöhnliche Geschichte über Dependency-Debugging war. Ich hatte selbst schon ein paar Mal das Gefühl, kurz vor einem Zusammenbruch zu stehen, und hatte auf einen Text gehofft, mit dem ich mich stärker identifizieren könnte
  • Der Stress dieser Person wurde durch eine einzige Zeile Code von PostHog verursacht. Der zurückgesetzte Commit ist dieser hier: https://github.com/PostHog/posthog-js/pull/1371/commits/7598...
    Daraus lassen sich zwei Lehren ziehen. Erstens: Wenn man es ausrollt, besitzt man es auch. Deshalb ist weniger auszurollen besser, und Abhängigkeiten sollten minimiert werden. Zweitens sollte Unwichtiges außerhalb des kritischen Pfads liegen. Der Motor darf nicht stehen bleiben, nur weil der Kompressor der Klimaanlage kaputt ist. Im Browser ist das sehr schwer zu erreichen, aber den Versuch ist es wert

  • Noch schlimmer: Es wirkt, als würde PostHog Teile seines eigenen Codes zur Laufzeit dynamisch aktualisieren, statt alles beim Build zu bündeln.
    In der Dokumentation gibt es eine erweiterte Option, alle Abhängigkeiten in den Build aufzunehmen. Ich verstehe, warum man das so macht, und vielleicht missverstehe ich etwas, aber aus Nutzersicht würde ich erwarten, dass Lazy Loading von Laufzeitcode eine Optimierungsoption ist und nicht der Standard. Meiner Meinung nach sollte man das nur einsetzen, wenn ein vollständiges Bundle zu ernsthaften Auslieferungsverzögerungen führt.

    • Diese Lehren sind eindeutig wertvoll, aber danach kommt jemand aus dem Marketing und verlangt, dass PostHog oder ein anderes Tracking-Skript auf die Website kommt, und akzeptiert kein Nein.
  • Der Bug steckte offenbar in einem monkey-gepatchten window.fetch.
    https://github.com/PostHog/posthog-js/blob/759829c67fcb8720f...
    Die wichtigste Lehre hier ist: Wenn man eine populäre Library baut und globale Funktionen monkey-patcht, dann muss das wirklich hervorragend getestet sein.
    „Lass uns PostHog-Aufrufe sicherheitshalber in try/catch packen“ und „Wegen PostHog können wir buchstäblich keine POST-Requests mit fetch() senden“ sind zwei völlig verschiedene Dinge.

    • Ich habe mir angesehen, warum das nicht in Tests aufgefallen ist, und schon bei ganz normalen Fetch-Aufrufen konnte ein Fehler auftreten. Es scheint sowohl an unzureichender Testabdeckung für die verschiedenen Nutzungsweisen von fetch zu liegen als auch an übermäßigem Mocking: https://github.com/PostHog/posthog-js/blob/main/src/_tests...
      Da die kompletten fetch- und XHR-Funktionen gemockt werden und dann nichts tun, ist es natürlich nicht möglich, Probleme zu entdecken, die bei der Interaktion mit der nativen Implementierung oder anderen Libraries darunter entstehen. Cypress ist auch eingerichtet, daher verstehe ich nicht, warum man Browser-APIs mocken will.
    • Danke, dass du darauf hingewiesen hast. Ich habe den Artikel nicht im Detail gelesen, aber ich habe mich gefragt, wie eine Monitoring-Library die gesamte Anwendung lahmlegen kann.
      Bei einer vernünftigen Integration sollte im schlimmsten Fall nur die Verarbeitung von Monitoring-Events fehlschlagen.
      Dass PostHog eine sehr wichtige globale Funktion patcht, sollte eine gut dokumentierte Eigenschaft sein. Dann wissen die Nutzer davon und können es beim Debuggen von Problemen, die nach außen hin schwer erklärbar sind, sinnvollerweise in Betracht ziehen.
    • Scheint wie spezifiziert funktioniert zu haben. Hat es nicht einfach POST-Requests „gehoggt“?
    • Bei solchen Analytics-Tool-Sammlungen ist das üblich. Ich weiß nicht, wie man überhaupt alles realistisch testen soll, wenn man eine so zentrale API anfasst.
      Heap Analytics macht zum Beispiel immer noch, Stand dieses Monats, irgendetwas mit Hotwire intern, wodurch Hotwire zufällig komplett kaputtgeht und jeder Klick zu einem vollständigen Seiten-Reload wird. Nach meiner Erfahrung betrifft das 30 bis 60 % der Seitenladungen. Es lässt sich beheben, aber ich musste mehr als 50 Stunden debuggen, bis Heap erst nach dem gesamten Hotwire-JavaScript geladen wurde.
  • Wie andere schon gesagt haben, war der Bug, der zu diesem nächtlichen Stress führte, eine Ein-Zeilen-Änderung in der PostHog-Library[0].
    Für mich ist das eine Erinnerung daran, wie wichtig es ist, Variablen präzise zu benennen.
    Der Code res = await originalFetch(url, init) wirkt harmlos genug. Aber wie die TypeScript-Deklaration zeigt, ist der Parameter url nicht zwingend eine URL: url: URL | RequestInfo
    Wenn es kein URL-, sondern ein RequestInfo-Objekt ist, entsteht das Problem. Denn weiter oben in der Funktionsimplementierung wurde bereits ein Request-Objekt erstellt und damit schon „verbraucht“, sodass es hier nicht noch einmal verwendet werden kann.
    Hätte der Parameter einen präziseren Namen wie urlOrRequestInfo gehabt, wäre es bei dieser Änderung schwerer gewesen, das Problem zu übersehen.
    Das ist deutlich spekulativer, aber mit linearen Typen aus der linearen Logik könnte man formalisieren, dass ein Wert „verbraucht“ wird; ein geeignetes Typsystem könnte diese Art von Bug also vielleicht verhindern.
    [0] https://github.com/PostHog/posthog-js/pull/1351/commits/2497...

    • Das Problem bei linearen/affinen Typsystemen ist, dass die Einstiegshürde enorm hoch ist.
      Man muss sich nur die Ownership-Semantik von Sprachen wie Rust ansehen. Unüberwindbar ist sie nicht, und mit Erfahrung wird es vor allem leichter, aber sie ist belastend genug, dass Lernende sich am häufigsten genau darüber beschweren.
  • Es war ein stressiger, aber auch lustiger Artikel. Der selbstanklagende Teil kam mir allerdings allzu bekannt vor.
    Ich betreibe eine recht erfolgreiche iOS/macOS-App und habe einmal einen Release ausgeliefert, der mehr als 350.000 Installationen komplett kaputtgemacht hat. Es war nicht ausschließlich meine Schuld, aber es war mein Produkt, also machte das kaum einen Unterschied.
    Der kalte Schweiß und die Scham damals waren wirklich heftig. Und weil es der App Store war, musste auch der Fix wieder durch den Review-Prozess, was alles verzögerte. Zum Glück ging die Prüfung 30 Minuten nach dem Einreichen los, und wenige Minuten später war es genehmigt.

    • Mein erster Job als Entwickler war nicht deshalb so gut, weil ich klug war, sondern weil die Leute so inkompetent waren, dass sie es „zugelassen“ haben, dass ich in jungen Jahren Dinge für Kunden kaputtmache.
      Mit wachsender Erfahrung und dem Wechsel in Führungsrollen wurde mir klar, dass das extrem wertvoll war. Vielleicht hätte es mich früher gestresst, aber inzwischen ist die Erinnerung so weit weg, dass ich sie kaum noch erreiche. Jetzt stresst es mich definitiv nicht mehr.
      Das mag umstritten sein, aber ich lasse manchmal Leute in frühen Karrierephasen Produktionsumgebungen kaputtmachen. Nämlich dann, wenn es absehbar ist und ich sicher bin, dass wir schnell wiederherstellen können.
      Dass Menschen Raum zum Scheitern brauchen, ist selbstverständlich, aber viele Führungskräfte ziehen die Grenze bei Fehlern, die echte Kunden betreffen. Wenn man nicht gerade etwas Kritisches wie Software zum Landen von Flugzeugen baut — was zum Glück sehr oft der Fall ist —, dann sollte man das Team auch Betriebsstörungen erleben lassen, selbst wenn das bedeutet, dass jemand in Spokane, Washington, das Produkt ein paar Minuten lang nicht benutzen kann.
  • Danke, dass du so einen Beitrag geschrieben hast. Ich lese besonders gern, wie Menschen solche Herausforderungen unter Druck bewältigen, meist mitten in der Nacht.
    Nicht nur die technische Nachbetrachtung, sondern auch die menschliche Perspektive, die aus solchen Geschichten normalerweise entfernt wird, macht es aus meiner Sicht besser. Diese Art technischer Erzählung können meist nur kleine Teams, Solo-Entwickler oder Gründer frei teilen.

  • Schon die Art, wie das Problem verfolgt wurde, zeigt zuerst einmal: Das ist ein Programmierer. Er ging an den eigenen Code und an die Logs. Beides ist vernünftig, und beides kann die Ursache sein, aber der wichtigste Hinweis, den er hatte, nämlich „auf localhost hat es funktioniert“, wurde übersehen
    Egal ob SRE, DevOps, Plattformingenieur oder welcher Titel an dem Tag gerade dranhängt: Ich hätte mich auf die Unterschiede zwischen dem funktionierenden und dem nicht funktionierenden System konzentriert. Ich hätte Unterschiede einzeln hinzugefügt und wieder entfernt oder entfernt und wieder hinzugefügt, bis irgendetwas funktioniert
    Ich sehe dabei zwei Dinge. 1) Es gibt eine funktionierende Umgebung. 2) Die fehlschlagende Umgebung hat ursprünglich ebenfalls funktioniert und erst dann begonnen zu versagen
    Das soll nicht heißen, dass meine Methode überlegen ist. Ich will nur den Unterschied in der Art zeigen, wie man ein Problem betrachtet. Beide engen es entlang dessen ein, was sie kennen. Ich kenne Systeme, und du kennst Code

    • Als ich vor langer Zeit als Elektroniktechniker gearbeitet habe, gab es einen Haufen Prozessorboards eines Perkin Elmer 7/32, die aus dem Betrieb genommen worden waren. Es waren defekte Boards, es gab verschiedene Revisionen, und zu jedem Board lag nur ein Schaltplan für jeweils eine Revision vor
      Ich hielt das für aussichtslos, aber ein älterer und klügerer Techniker brachte mir die Methode bei
      Ein gutes Board wurde auf einen Extender gesteckt, und ein fehlschlagendes Diagnoseprogramm lief in einer Schleife. Mit dem Oszilloskop wurden alle Pins am Stecker betrachtet und dokumentiert. Dann wurde auf ein schlechtes Board gewechselt und das Ganze wiederholt
      Welches Signal ist anders? Diesem Signal folgt man zurück. Wenn der Schaltplan nicht passt, zeichnet man mit Voltmeter und Augen einen Schaltplan, der die tatsächliche Verdrahtung widerspiegelt
      Er nannte das „gute Karte - schlechte Karte“, und es hat tatsächlich funktioniert. Ich würde nicht behaupten, dass es kosteneffizient war, aber wir haben alle Boards repariert, und meine Fähigkeit zur Fehlersuche in digitalen Elektronikschaltungen ist stark gewachsen
      Es war eine Art „Feuerwehr“-Arbeit. Man wartete darauf, dass das System ausfiel, deshalb war es egal, wenn zwei Techniker eine Woche an einem einzelnen Board saßen
  • „Gehen wir auf die Version von vor einem Monat zurück. Geht nicht. Vor drei Monaten? Geht nicht. Scheitert immer noch. Vor einem Jahr? Geht überhaupt nicht.“
    Wurde nur der eigene Code zurückgesetzt, während das PostHog-Update, das am selben Tag alles kaputtgemacht hat, weiterverwendet wurde? Meine Lehre daraus ist, dass man alles zurückrollen können muss, einschließlich der Abhängigkeiten

  • Ein guter Text, der wieder daran erinnert, dass hinter einem Dienst Menschen stehen, und der den Debugging-Prozess gut zeigt
    Realistisch betrachtet sorgt Druck nicht dafür, dass man ein Problem schneller debuggt. Meist behindert er das Denken. Man sollte das Ergebnis so weit wie möglich ausblenden und so ruhig wie möglich bleiben
    Die meisten von uns haben so eine Situation wohl schon erlebt, wenn auch in unterschiedlichem Ausmaß. Natürlich ist der Stress, das eigene Unternehmen zu führen, noch einmal besonders groß