CodeGym /Kursy /ChatGPT Apps /Zarządzanie incydentami i cykl operacyjny

Zarządzanie incydentami i cykl operacyjny

ChatGPT Apps
Poziom 19 , Lekcja 3
Dostępny

1. Czym jest incydent w świecie ChatGPT Apps

W klasycznym webie incydent — to zwykle coś w rodzaju „serwer leży”, „błędów 500 znacznie przybyło”, „latencja wzrosła dwukrotnie”. Formalna definicja z ITIL: incydent — nieplanowane przerwanie usługi lub pogorszenie jakości usługi.

W świecie ChatGPT Apps i GiftGenius obraz jest bardziej złożony. Pojawia się warstwa modeli, które mogą:

  • nie wywołać potrzebnego toola, choć wszystko jest dostępne;
  • wywołać tool z nieprawidłowymi parametrami;
  • „halucynować” wynik, ignorując twój MCP.

Dlatego incydentem może być nie tylko HTTP 500, ale i sytuacja, gdy wszystkie metryki backendu są zielone, a użytkownicy masowo narzekają: „bot głupieje i nie pokazuje prezentów” — bo model przestał wołać suggest_gifts albo myli argumenty. To incydent jakości (Quality incident).

Wygodnie jest myśleć o incydentach kategoriami:

Kategoria Przykład symptomu Przykładowa metryka (SLI)
Availability MCP nie odpowiada, „Error talking to app” w ChatGPT % udanych odpowiedzi /mcp
Latency dobór prezentów zajmuje 10+ sekund p95 czasu wywołania suggest_gifts
Quality model nie wywołuje właściwego toola, myli walutę odsetek zapytań bez tool‑callu przy wyraźnej prośbie
Commerce checkout przestał działać, środki nie są księgowane checkout_success_rate

Incydent — to chwila, gdy metryka faktyczna wychodzi poza ustalone z góry SLO. Na przykład:

  • uzgodniliśmy: p95 doboru prezentów < 4 sekund. Zrobiło się 9 sekund;
  • chcemy, aby 99% checkoutów w tygodniu było udanych, a jest 94%;
  • oczekujemy, że w scenariuszach z zakupem model prawie zawsze wywołuje create_checkout_session, a po logach widzimy gwałtowny wzrost „pominięć”.

Ważne: incydent to nie „ktoś na czacie się poskarżył”. Skarga to trigger, a decyzję „tak, to incydent” podejmujemy, opierając się na SLO/SLI i dashboardach.

2. Jak SLO/SLI zamieniają się w incydenty

W module o obserwowalności definiowałeś już kluczowe metryki: latency, availability, error‑rate, sukces checkoutu. Teraz użyjemy ich jak „strażników u drzwi”.

Najprostszy scenariusz: mamy SLO dla checkout_success_rate. Prowadzimy ustrukturyzowane logi zdarzeń:

// Przykład zdarzenia logu checkout w serwerze MCP
logger.info({
  event: 'checkout_result',
  request_id,
  user_id,
  checkout_session_id,
  status: 'success', // albo 'failed'
  error_code: null,
});

Na bazie tych logów buduje się metryka: odsetek status = "success" wśród wszystkich checkout_result z ostatnich N minut/godzin. Gdy ten odsetek spada poniżej progu (np. 95% za 10 minut), monitoring wysyła alert do kanału on‑call. To jest detekcja incydentu: SLI wyszła poza ramy SLO.

Tak samo mogą wyzwalać się alerty dotyczące:

  • wzrostu error_rate narzędzi suggest_gifts, search_products;
  • wzrostu p95/p99 latency;
  • anomalego spadku liczby workflow_completed (użytkownicy nie dochodzą do końca scenariusza);
  • anomalii kosztowej polegającej na wzroście wydatków LLM bez wzrostu ruchu (incydent ekonomiczny).

To wszystko jest możliwe tylko dlatego, że logujemy w sposób ustrukturyzowany, a nie piszemy w logach „znowu coś nie tak z checkoutem”. Gdy metryki i alerty są ustawione, umiemy zauważać, że coś poszło nie tak. Kolejne pytanie: co dzieje się po detekcji, kto i jak reaguje?

3. Cykl życia incydentu: od detekcji do post‑mortemu

Aby nie żyć w trybie wiecznego pożaru, wygodnie jest opisać standardowy pipeline incydentu. Wiele zespołów SRE formalizuje go jako łańcuch:

flowchart TD
    D["Detection (wykrycie)"] --> T["Triage (ocena powagi)"]
    T --> M["Mitigation (szybkie ograniczenie)"]
    M --> R["Resolution (ostateczna naprawa)"]
    R --> P["Post-mortem (analiza i usprawnienia)"]

Omówmy etapy na przykładzie GiftGenius.

Detection — jak zrozumieć, że jest źle

Wykrycie problemu bywa automatyczne i ręczne.

Automatyczne — to alerty z monitoringu po SLO/SLI:

  • PagerDuty / Opsgenie / e‑mail / bot Slack krzyczy: SEV-1: checkout_success_rate < 60% w ciągu 10 minut;
  • alert dot. latencji: p95(suggest_gifts) > 10 s;
  • anomalia kosztowa: „wydatki na LLM wzrosły 2 razy przy tej samej liczbie workflow_completed”.

Ręczna detekcja — gdy do supportu (lub do ciebie bezpośrednio na Telegramie) spływa lawina wiadomości „płatność nie przechodzi”, „widżet kręci się bez końca”. Niekiedy to właśnie to uwidacznia problem, zanim monitoring nadgoni.

Wniosek praktyczny: nawet jeśli nie masz jeszcze idealnego monitoringu, przyzwyczaj się patrzeć na wszelkie masowe skargi użytkowników przez pryzmat metryk: „jaka metryka za tym stoi i jak ją zmierzyć?”.

Triage — klasyfikacja i priorytetyzacja

Po detekcji trzeba odpowiedzieć na dwa pytania: jak bardzo jest źle i kto biegnie naprawiać.

Wygodnie mieć prostą skalę powagi:

  • SEV-1: krytycznie — użytkownicy nie mogą kupować, App nie działa w kluczowym scenariuszu (np. checkout=0 przy żywym ruchu).
  • SEV-2: poważnie, lecz z degradacją — część użytkowników nie może dokończyć scenariusza, latencja mocno wzrosła, ale system nie jest całkiem martwy.
  • SEV-3: drobne bugi — jedno z dodatkowych tools czasem pada, psuje się tylko edge‑case.

Dla GiftGenius incydenty commerce niemal zawsze to SEV-1: jeśli pieniądze nie „chodzą”, to nie tylko problem techniczny, ale bezpośredni uszczerbek na przychodach i zaufaniu.

Na tym kroku wyznacza się on‑call (albo sam siebie, jeśli jesteś jednoosobowym zespołem) i zapada decyzja: „Tak, to oficjalny incydent SEV‑1, pracujemy wg runbooka N” (runbook — to wcześniej opisana instrukcja krok po kroku; strukturę omówimy w oddzielnej sekcji).

Mitigation — zatrzymać „krwawienie”

Mitigation to nie poszukiwanie przyczyny źródłowej, lecz szybkie działania, aby użytkownicy cierpieli mniej. Przykłady:

  • rollback ostatniego wydania MCP/Agents/ACP;
  • wyłączenie problematycznego feature‑flaga;
  • przełączenie GiftGenius w tryb „tylko podgląd”: rekomendacje pokazujemy, ale nie pozwalamy sfinalizować zakupu;
  • tymczasowe ograniczenie obciążenia (rate limiting) lub wyłączenie ciężkich narzędzi.

Typowy przykład kodu dla „trybu degradującego” w naszym MCP:

// Pseudokod: globalna flaga, którą można szybko przełączyć
let checkoutDisabled = false;

export function setCheckoutDisabled(value: boolean) {
  checkoutDisabled = value;
}

export async function createCheckoutSession(args: CheckoutArgs) {
  if (checkoutDisabled) {
    // Informujemy model, że zakup jest chwilowo niedostępny
    return {
      error: 'checkout_temporarily_disabled',
      message: 'Płatność chwilowo niedostępna, pokaż użytkownikowi wyjaśnienie.',
    };
  }

  // zwykła logika tworzenia sesji
}

W systemie feature‑flagów możesz przełączyć setCheckoutDisabled(true) jako część mitigation: użytkownicy przynajmniej nie będą dostawać 500‑ek i zawieszonych płatności, lecz zobaczą uczciwy komunikat.

Resolution — ostateczne naprawienie

Gdy „krwawienie zatrzymane”, masz czas znaleźć przyczynę korzeniową i ją naprawić:

  • bug w kodzie MCP/ACP;
  • problem u zewnętrznego dostawcy (Stripe, bramka płatnicza);
  • limity na OpenAI API (429, przeciążenie);
  • zepsuty prompt lub zmieniony model, który przestał wywoływać tool.

Resolution zwykle obejmuje:

  • fix (patch/rollback/konfigurację);
  • deploy na staging, następnie na production;
  • sprawdzenie wszystkich SLI/SLO;
  • przywrócenie flag do normalnego stanu.

Post‑mortem — uczymy się na błędach

Po incydencie, szczególnie SEV‑1/SEV‑2, przeprowadza się post‑mortem: dokument, w którym uczciwie odpowiadasz na pytania:

  • co się wydarzyło (fakty i oś czasu);
  • jak to zauważono;
  • jak reagowano;
  • co zadziałało dobrze, a co nie;
  • jakie zmiany wprowadzisz, by to się nie powtarzało.

Post‑mortem nie służy szukaniu winnych, lecz ulepszaniu systemu i procesu. Na jego podstawie aktualizuje się runbooki, alerty, czasem nawet architekturę.

4. Role i odpowiedzialność: nawet jeśli jesteś „sam w polu”

Aby opisany wyżej pipeline incydentu działał w realnym życiu, ważne jest z góry uzgodnić, kto za jakie decyzje odpowiada w czasie pożaru. Nawet jeśli twój zespół mieści się w jednej windzie, warto sformalizować role przy incydentach. To zmniejsza chaos.

Zwykle wyróżnia się:

  • Inżynier on‑call — ten, do którego pierwszy trafia alert i który podejmuje decyzje techniczne dotyczące stabilizacji (rollback, feature‑flagi, tymczasowe obejścia).
  • Incident commander — osoba prowadząca proces: zapisuje oś czasu, decyduje o priorytecie zadań, pilnuje, by zespół się nie miotał. W mikro‑zespole to ten sam on‑call, ale z inną „czapką”.
  • Komunikacja — odpowiada za kontakt z użytkownikami i interesariuszami biznesowymi: wiadomości w Slacku, na stronie statusu, w interfejsie App (widżet/czat), w sklepie ChatGPT.
  • Scribe — zapisuje ważne kroki i fakty; później na tej podstawie powstaje post‑mortem.

W zespole jednoosobowym wszystkie cztery role pełnisz ty — po prostu warto świadomie przełączać tryby: „teraz jestem inżynierem i naprawiam”, „teraz komunikuję”, „teraz zapisuję oś czasu”.

5. Runbook: statut zamiast pamięci

Runbook — to dokument, w którym krok po kroku opisano, co robić przy konkretnym typie incydentu: jakie wykresy oglądać, jakie przyciski naciskać, z czego można zrezygnować. Bardzo zmniejsza to udział improwizacji i poziom stresu.

Struktura runbooka

Zwykle runbook zawiera:

  1. Krótki opis incydentu i sposób jego detekcji. Przykład: „Wzrost błędów ACP checkout > 5% w 5 minut” lub „Error talking to app dla >20% żądań”.
  2. Scope — kogo dotyka problem: cały ruch, tylko region, tylko konkretny tool.
  3. Gdzie patrzeć: linki do dashboardów (SLO dla checkoutu, error‑rate MCP, logi po tool_name = create_checkout_session), do MCP Inspector itd.
  4. Szybkie kroki mitigation: „sprawdzić status Stripe”, „cofnąć ostatnie wydanie ACP”, „włączyć tryb rekomendacji bez zakupu”.
  5. Kroki docelowego rozpoznania i fixa.
  6. Co należy zaktualizować po fakcie: alerty, kod, dokumentację.

Mini‑przykład runbooka dla GiftGenius (checkout się wykrzacza)

Opiszmy go w postaci danych ustrukturyzowanych, aby było bliżej kodu:

type Severity = 'SEV-1' | 'SEV-2' | 'SEV-3';

interface RunbookStep {
  title: string;
  description: string;
}

interface Runbook {
  id: string;
  title: string;
  severity: Severity;
  detection: string;
  steps: RunbookStep[];
}

export const checkoutFailureRunbook: Runbook = {
  id: 'rb-checkout-failure',
  title: 'Wzrost błędów checkout w GiftGenius',
  severity: 'SEV-1',
  detection: 'Alert: checkout_success_rate < 60% za 10 minut',
  steps: [
    {
      title: 'Sprawdzić zewnętrzne statusy',
      description: 'Otworzyć status Stripe i ACP backend, upewnić się, że nie ma globalnego outage.',
    },
    {
      title: 'Sprawdzić niedawne wydania',
      description: 'Sprawdzić, czy były deploye MCP/ACP w ostatnich 30 minutach. W razie potrzeby zrobić rollback.',
    },
  ],
};

W realnym runbooku dodasz więcej kroków: włączyć feature‑flag read‑only, pokazać baner w widżecie, zebrać logi do post‑mortemu.

Przykładowy tekst dla widżetu przy incydencie commerce

W runbooku warto z góry przemyśleć także tekst dla użytkownika. Na przykład widżet GiftGenius może pokazać:

«Mamy obecnie tymczasowe problemy techniczne z płatnościami. Nadal możesz zapisać pomysły na prezenty, a zakup dokończymy nieco później.»

Taki tekst można potem zaszyć w stanie UI:

// Pseudokod stanu widżetu
const [checkoutAvailable, setCheckoutAvailable] = useState(true);

if (!checkoutAvailable) {
  return (
    <Alert>
      Płatność jest tymczasowo niedostępna. Nadal możesz przeglądać i zapisywać pomysły na prezenty.
    </Alert>
  );
}

6. Praktyka na GiftGenius: kod wokół incydentów

Aby temat nie pozostał czysto organizacyjny, spójrzmy na kilka fragmentów kodu, które bezpośrednio pomagają w zarządzaniu incydentami.

Endpoint health‑check dla MCP/Backend

Najprostsze, lecz ważne narzędzie — health‑check. W Next.js 16 można go zrobić przez route handler:

// app/api/health/route.ts
import { NextRequest, NextResponse } from 'next/server';

export function GET(_req: NextRequest) {
  // Można dodać sprawdzenia bazy, kolejek itp.
  return NextResponse.json({
    status: 'ok',
    mcp: 'healthy',
    timestamp: new Date().toISOString(),
  });
}

System monitoringu będzie okresowo odpytywać /api/health. Jeśli zamiast 200 OK pojawią się timeouty lub 5xx, to jednoznaczny sygnał incydentu typu Availability (MCP nie działa).

Klasyfikacja incydentu wg metryk

Po stronie serwisu analitycznego lub skryptu admin‑backendowego można trzymać prostą logikę określania powagi:

type Severity = 'SEV-1' | 'SEV-2' | 'SEV-3';

interface IncidentContext {
  checkoutSuccessRate: number; // 0..1
  giftSearchErrorRate: number; // 0..1
  p95GiftSearchMs: number;
}

export function classifyIncident(ctx: IncidentContext): Severity | null {
  if (ctx.checkoutSuccessRate < 0.6) return 'SEV-1'; // płatności nie działają
  if (ctx.giftSearchErrorRate > 0.3 || ctx.p95GiftSearchMs > 8000) return 'SEV-2';
  return null; // na razie to nie incydent
}

Taki fragment można uruchamiać z crona lub wyzwalać z monitoringu: przy zwrocie SEV‑1 automatycznie tworzy się incydent w twoim systemie i wychodzi powiadomienie do on‑call.

Logowanie kluczowych zdarzeń incydentu

Incydenty to nie tylko metryki, ale i zdarzenia: kiedy incydent utworzono, zmieniono, zamknięto. Warto trzymać je w osobnych logach.

function logIncidentEvent(event: {
  incidentId: string;
  type: 'created' | 'mitigated' | 'resolved';
  severity: Severity;
  requestId?: string;
  message: string;
}) {
  logger.warn({
    level: 'WARN',
    service: 'incident-manager',
    ...event,
    timestamp: new Date().toISOString(),
  });
}

Na przykład przy włączeniu trybu „read‑only” dla GiftGenius:

setCheckoutDisabled(true);
logIncidentEvent({
  incidentId: 'inc-2025-11-21-001',
  type: 'mitigated',
  severity: 'SEV-1',
  message: 'Checkout disabled, app switched to recommendations-only mode',
});

Później te zdarzenia łatwo znaleźć i zestawić z szeregami czasowymi metryk.

7. Kalendarz operacyjny: życie po „hurra, naprawione”

Zarządzanie incydentami to nie tylko gaszenie pożarów, ale i regularna profilaktyka. W praktykach SRE cykl operacyjny często opisuje się jako kalendarz operacyjny z regularnymi przeglądami SLO, kosztów i bezpieczeństwa.

Umownie można podzielić aktywności według częstotliwości.

Co tydzień

Raz w tygodniu (lub co dwa) warto:

  • przeglądać główne SLO: latency, error‑rate, sukces checkoutu, udział incydentów według kategorii;
  • sprawdzać, czy w tygodniu były alerty, które „same się wygasiły”, i decydować, czy wzmocnić/osłabić progi;
  • krótko omówić choć jeden incydent (nawet SEV‑3) — trenuje to mięsień post‑mortemu.

Co miesiąc

Raz w miesiącu dobrze byłoby:

  • robić przegląd kosztów (LLM, prowizje ACP/Stripe, infrastruktura) i zestawiać je z przychodem — powiązanie z tematami 1–2 modułu 19;
  • przeglądać metryki produktowe: activation, retention, konwersję workflow_completedcheckout_success — powiązanie z modułem o marketingu i wzroście;
  • przelecieć logi bezpieczeństwa pod kątem anomalii: dziwne wzorce logowania, błędy autoryzacji, nietypowe skoki liczby żądań (pomost do modułu o bezpieczeństwie).

Co kwartał

Raz na kwartał:

  • rotujesz sekrety: klucze API OpenAI, Stripe, klientów OAuth itd.;
  • sprawdzasz, czy SLO nie są przestarzałe: być może App urósł i teraz p95 na poziomie 2 sekund zamiast 1 — to norma, albo przeciwnie — możesz zaostrzyć cele;
  • przeglądasz runbooki: nowe typy incydentów, zaktualizowane zależności (SDK, MCP‑spec itp.).

Kalendarz można prowadzić po prostu jako stronę Wiki lub README w repozytorium GiftGenius: ważne, by był „żywy” i aktualizowany.

8. Incydenty, pieniądze i produkt: dlaczego pożar commerce jest najgorętszy

Moduł 19 w całości dotyczy ekonomii i „życia operacyjnego” App, a incydenty są tu ściśle powiązane z pieniędzmi. Incydenty commerce — gdy checkout nie przechodzi, środki są blokowane albo pobierane podwójnie — niemal zawsze mają wyższy priorytet niż np. przypadkowy timeout przy wyszukiwaniu prezentów.

Powody są proste:

  • bezpośrednie utraty przychodu tu i teraz;
  • ryzyko utraty zaufania (użytkownikowi pobrano środki, a nie wydano towaru — raczej nie wróci);
  • potencjalne skutki prawne i reputacyjne.

Dlatego w twoim katalogu incydentów GiftGenius incydenty commerce powinny być wyraźnie oznaczone jako SEV‑1 z ostrymi SLO co do czasu reakcji (np. „reakcja on‑call w ciągu 15 minut, mitigation w ciągu godziny”).

Anomalie ekonomiczne (np. koszt LLM gwałtownie wzrósł bez wzrostu przychodu) — to także incydenty, ale zwykle poziomu SEV‑2: nie łamią UX natychmiast, lecz mogą „zjeść” całą marżę, jeśli ich nie zauważysz.

Od strony produktowej każdy duży incydent to okazja do refleksji:

  • czy workflow nie jest zbyt złożony (może prościej = bardziej niezawodnie);
  • czy nie dodać scenariusza fallback: np. jeśli MCP nie odpowiada, model przynajmniej zwraca porady bez danych zewnętrznych;
  • czy nie zmienić UX, by uczciwie komunikować problemy zamiast je ukrywać.

9. Mini‑ćwiczenia (do samodzielnej pracy)

Choć wykład nie jest praktykum, bardzo polecam realnie wykonać poniższe kroki w swoim GiftGenius:

  1. Opisać w jednym dokumencie co najmniej dwa runbooki:
    • „Masowe błędy przy płatności (checkout)”;
    • „MCP nie odpowiada / ChatGPT pokazuje Error talking to app”.
  2. Ułożyć kalendarz operacyjny na miesiąc:
    • jakie SLO będziesz oglądać co tydzień;
    • jaki przegląd kosztów zrobisz na koniec miesiąca;
    • jakie podstawowe kontrole bezpieczeństwa włączysz.

Zajmie to parę godzin, ale bardzo zmieni sposób, w jaki patrzysz na swoją aplikację: przestanie być tylko kodem, a stanie się żywą usługą.

Typowe błędy w zarządzaniu incydentami ChatGPT Apps

Błąd nr 1: „Incydent to tylko wtedy, gdy wszystko padło”
Wielu z przyzwyczajenia uważa za incydent wyłącznie całkowity pad MCP lub bazy. W AI‑Apps często boleśniejsze są „miękkie” incydenty jakości: model przestał wywoływać właściwy tool, flow checkout stał się chaotyczny, użytkownicy nie dochodzą do końca, choć metryki HTTP są zielone. Jeśli nie traktujesz takich sytuacji jako incydentów i ich nie analizujesz, jakość App będzie po cichu degradować.

Błąd nr 2: Brak jasnych SLO i granic „normalnej pracy”
Bez formalnych SLO każda dyskusja o incydencie zmienia się w „wydaje mi się, że wszystko jest wolne” vs „u mnie lokalnie szybko”. Dlatego SLO uważa się za podstawę zarządzania incydentami: czynią powagę problemu obiektywną.

Błąd nr 3: Improwizacja zamiast runbooków
Częsty obrazek: alert, wszyscy w panice wskakują na produkcję, ktoś cofa wydanie, ktoś edytuje konfiguracje, po godzinie „chyba naprawione”, ale nikt nie pamięta, co pomogło. Bez runbooków każdy incydent to mini‑chaos, a zespół się nie uczy. Nawet jeden prosty runbook dla incydentu checkout znacząco obniża poziom stresu.

Błąd nr 4: Ignorowanie komunikacji z użytkownikami
Czasem inżynierowie po cichu naprawiają system, a użytkownicy widzą w tym czasie tylko „kółko” i błąd „coś poszło nie tak”. Dla scenariuszy commerce to szczególnie toksyczne: ludzie martwią się o pieniądze. Warto mieć wcześniej przygotowane szablony komunikatów w widżecie, w opisie App i — w razie potrzeby — w kanałach zewnętrznych, by uczciwie zaznaczać problem i przewidywany czas naprawy.

Błąd nr 5: Zrzucanie winy na „OpenAI” bez rozpoznania swojej części
Łatwo wszystko zrzucić na „OpenAI szwankuje”, ale praktyka pokazuje, że nawet przy problemach upstream wiele można zrobić po swojej stronie: poprawnie obsługiwać timeouty i błędy, przełączać się w tryb bez MCP, zmniejszać liczbę ponowień, by nie pogarszać sytuacji. Koncepcja współdzielonej odpowiedzialności oznacza, że odpowiadasz za swój odcinek łańcucha, nawet jeśli jeden z dostawców zachowuje się niestabilnie.

Błąd nr 6: Brak post‑mortemów i cyklu operacyjnego
Jeśli incydent kończy się zdaniem „no, chyba tyle, jedziemy dalej”, a żadne dokumenty, alerty i kod się nie zmieniają — system jest skazany na powtarzanie tych samych błędów. Post‑mortemy, regularne przeglądy SLO, kosztów i bezpieczeństwa — to nie biurokracja, lecz sposób na dogadanie się z przyszłym sobą i zespołem, by za rok GiftGenius był bardziej niezawodny, a nie bardziej kruchy.

Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION