Przejdź do treści
Leaders of Teams
Menu

CZWDEV TEAMMOFU

Cztery awarie, które nie zgłaszają się same

Każda trasa odpowiada 200, wszystkie testy są zielone, a strona jest zepsuta. Cztery takie awarie z naszej własnej strony — z pomiarami, datami i sposobem, w jaki każdą z nich wyłapaliśmy.

Maciej Kucharski6 min czytania

Najdroższe awarie to nie te, które budzą Cię w nocy. Te są łatwe: coś zwraca 500, monitoring krzyczy, ktoś naprawia. Najdroższe są te, które odpowiadają 200, przechodzą testy i po prostu nie robią tego, po co powstały. Nikt ich nie zgłasza, bo nikt ich nie widzi.

Poniżej cztery takie awarie. Wszystkie z tej strony, którą właśnie czytasz. Wszystkie zmierzone, z datami, bo inaczej byłby to kolejny tekst o „dobrych praktykach”.

1. Strona bez arkusza stylów, przy 200 na każdej trasie

Zaczęło się od pomiaru, który wyglądał dobrze. Piętnaście tras, wszystkie 200, wszystkie z treścią. Dopiero sprawdzenie, co te strony ładują, pokazało problem:

GET /                                       200 · age 338578
GET /_next/static/css/400d9fbd596be37d.css  404

Dokument żył w cache’u prawie cztery doby. Wskazywał na arkusz stylów, który kolejny build usunął — nazwy plików statycznych zawierają skrót ich zawartości, więc każda zmiana w CSS to nowa nazwa. Czytelnik dostawał poprawny HTML i nic poza tym.

Mechanizm jest banalny i dlatego groźny. Dokument i arkusz mają różne czasy życia w cache’u. Dopóki obie wartości są zgodne, nic się nie dzieje. W dniu, w którym dokument przeżyje swój arkusz, strona rozsypuje się bez jednego błędu w logach.

Dwa wnioski, oba kosztowały nas czas:

  • Status odpowiedzi nie jest sygnałem. Sygnałem jest to, czy zasób, na który strona wskazuje, faktycznie istnieje. Nasz skrypt sprawdzający produkcję pobiera z HTML-a skrót arkusza i odpytuje go osobno.
  • Nagłówki naprawione dziś nie naprawiają wpisów zapisanych wczoraj. Poprawka czasu życia rządzi tym, co brzeg zapisze od teraz. Stare kopie z rocznym czasem życia trzeba usunąć ręcznie.

Do czasu takiego wyczyszczenia zrobiliśmy jedno: żądanie nieistniejącego arkusza nie kończy się już 404, tylko dostaje arkusz bieżącego builda. Nieaktualny dokument renderuje się ze stylami zamiast bez nich.

Z jednym zastrzeżeniem, które jest tu ważniejsze niż sama poprawka. Odpowiedź niesie własny nagłówek, a skrypt sprawdzający produkcję wywala się, gdy go zobaczy. Bez tego naprawa skasowałaby objaw, po który ten strażnik w ogóle istnieje. Odporność to nie to samo co cisza.

2. Reguła CSS zbudowana ze zdania w komentarzu

Ta jest zabawna do momentu, w którym policzy się rachunek.

Nasz generator CSS przeszukuje pliki źródłowe w poszukiwaniu czegokolwiek, co wygląda jak nazwa klasy. Nie odróżnia znaczników od prozy. Zwykłe angielskie słowo w komentarzu, które przypadkiem nazywa jakąś klasę, ląduje jako reguła w produkcyjnym arkuszu.

Zdarzyło się to trzy razy:

KiedySkądKoszt
przy testachasercje cytujące prawdziwe klasy+337 B
w dokumentacjilista klas, których zakazujemydwie zakazane klasy na produkcji
przy pisaniu komentarzajedno słowo w zdaniu+29 B i zmieniony skrót pliku

Środkowy wiersz jest najlepszy: dokument opisujący, czego nie wolno używać, sprawił, że generator wyprodukował dokładnie te klasy. Zakaz przeczytany dosłownie i wykonany.

Ostatni jest najgorszy, choć waży najmniej. Zmieniony skrót pliku to nowa nazwa arkusza — czyli dokładnie ten mechanizm, który w punkcie pierwszym zostawił stronę bez stylów. Dwadzieścia dziewięć bajtów prozy poruszyło plik, którego stabilność była właśnie przedmiotem awarii.

Zawężenie przeszukiwanych katalogów zamyka dwa pierwsze przypadki. Trzeciego nie zamyka, bo komentarze mieszkają w kodzie i zawsze będą. Sprawdzamy więc artefakt, nie źródła: każda reguła w zbudowanym arkuszu musi być zapisana jako klasa gdzieś poza komentarzem. Znaczniki to spełniają, proza nie.

3. Element, który maluje się 3,3 s po tym, jak wszystko jest gotowe

Pierwszy pomiar wydajności tej strony pokazał wynik mobilny 92 przy celu 95. Jedyna psująca metryka: czas do wyrenderowania największego elementu — 3313 ms.

Waterfall mówił coś przeciwnego. Dokument 19 kB, odpowiedź serwera 20 ms, wszystko na dysku po 255 ms.

To nie jest sprzeczność, tylko dwa różne pytania. Narzędzie domyślnie symuluje wolne łącze mobilne na zaobserwowanym grafie żądań. Odpowiada więc nie na „ile trwało tutaj”, tylko na „ile trwałoby na średnim telefonie”. Ta druga liczba jest tą, która dotyczy czytelnika.

Element, o który chodziło, okazał się akapitem wiodącym. Zwykły tekst. Przy strategii ładowania krojów, w której tekst pojawia się od razu krojem zastępczym i podmienia się po dojściu właściwego, moment podmiany jest momentem pomiaru. Innymi słowy: ta metryka była funkcją wagi jednego pliku z fontem.

Sprawdziliśmy więc, czego strona z tych krojów faktycznie używa — odczytem wyliczonych stylów każdego elementu na wszystkich trasach, nie z pamięci:

display     wagi 200 / 600 / 800   szerokości 75 / 80 / 100
tekst       wagi 400 / 600         szerokość nigdy nie zmieniana
mono        wagi 400 / 600         (brak osi szerokości)

Krój tekstowy niósł oś szerokości, której nic na stronie nie rusza. Krój mono — wagi od 100 do 800, z których używane są dwie. W foncie zmiennym każda oś mnoży dane zapisane dla każdego znaku.

Po usunięciu tego, czego nie używamy: 311 992 → 259 436 B, a sam krój z krytycznej ścieżki 84 540 → 43 440 B. Wynik 90 → 92.

Że nic to nie zmieniło w wyglądzie, też zostało zmierzone, a nie założone: zrzuty wszystkich szesnastu tras przed i po różnią się co najwyżej o 0,139% pikseli, przy 0,322% szumu między dwoma przebiegami tego samego builda. Żadna strona nie zmieniła wysokości.

Warto zapamiętać kolejność: najpierw pomiar, który element jest mierzony, potem hipoteza, dlaczego jest wolny. Odwrotnie kończy się optymalizowaniem obrazków na stronie, na której o wyniku decyduje font.

4. Lista, która nie była listą

Ta awaria nie miała żadnego objawu wizualnego. Zero.

Każda animowana lista na stronie wyglądała tak:

<ul> → <div> → <li>

Bo żeby elementy pojawiały się jeden po drugim, każdy z nich został owinięty w kontener animujący. Wyglądało dokładnie tak, jak miało wyglądać.

Tyle że lista, między którą a jej elementami stoi kontener, przestaje być listą. Czytnik ekranu nie powie ani „lista”, ani ile ma pozycji. Osoba, która nie widzi ekranu, dostaje ciąg zdań bez struktury, którą wszyscy inni dostają za darmo.

Szło tak od pierwszych sekcji tej strony, na ośmiu podstronach. Nie znalazł tego żaden test, bo żaden test o to nie pytał, i nie znalazł tego nikt patrząc, bo patrzenie tego nie pokazuje. Znalazł to dopiero automatyczny audyt dostępności: 91 na 100 tam, gdzie strona bez animowanej listy miała 100.

Poprawka to jedna zmiana w komponencie animującym — animowanym elementem jest teraz pozycja listy, zamiast stać nad nią. Dostępność wróciła na 100 wszędzie. Koszt: jedenaście bajtów.

Pilnuje tego teraz test sprawdzający strukturę, nie wynik. Wynik mówi „coś jest nie tak”. Struktura mówi gdzie.


Co z tego wynika dla Twojego projektu

Cztery różne awarie, jeden wspólny kształt: system raportował sukces, bo mierzył nie to, co trzeba. Status zamiast zawartości. Źródła zamiast artefaktu. Czas na szybkim łączu zamiast na telefonie. Wygląd zamiast struktury.

Trzy rzeczy, które z tego robimy w każdym projekcie:

  • Mierzymy artefakt, nie intencję. Testy chodzą po tym samym zbudowanym pakiecie, który trafia na serwer — nie po wersji deweloperskiej, bo ta potrafi być zdrowa, gdy wysyłka jest zepsuta.
  • Każdy strażnik przechodzi test negatywny. Zanim uznamy, że coś pilnuje, psujemy to celowo i sprawdzamy, czy się odezwie. Strażnik, którego nigdy nie widziano czerwonego, jest dekoracją.
  • Odporność nie oznacza ciszy. Poprawka, która ukrywa objaw, jest gorsza od awarii, bo kasuje informację. Każde obejście u nas zostawia ślad, na którym wywala się monitoring.

Żadna z tych rzeczy nie jest droga. Wszystkie są tanie przed wdrożeniem i kosztowne po.

Jeśli budujesz albo utrzymujesz coś, o czym nie wiesz, czy naprawdę działa — nie dlatego, że masz błędy, tylko dlatego, że nie masz jak sprawdzić — zobacz, jak prowadzimy projekty. Zaczynamy od pytania, co ma się zmienić w liczbach, bo tylko to da się potem zmierzyć.


Czytaj dalej

Rozmowa

Masz pytanie do tego, co przeczytałeś?

Napisz, co u Ciebie nie działa albo z czym się nie zgadzasz. Odpowiadamy konkretnie, bez prezentacji handlowej.

Piszesz mailem na kontakt@leadersofteams.com — odpowiadamy osobiście.