CodeGym /Các khóa học /ChatGPT Apps /Incident management và chu trình vận hành

Incident management và chu trình vận hành

ChatGPT Apps
Mức độ , Bài học
Có sẵn

1. Sự cố là gì trong thế giới ChatGPT Apps

Trong web cổ điển, sự cố thường là kiểu “server sập”, “lỗi 500 tăng mạnh”, “độ trễ tăng gấp đôi”. Định nghĩa chính thức từ ITIL: sự cố là việc gián đoạn dịch vụ ngoài kế hoạch hoặc suy giảm chất lượng dịch vụ.

Trong thế giới ChatGPT Apps và GiftGenius, bức tranh phức tạp hơn. Chúng ta có thêm lớp model, có thể:

  • không gọi đúng tool dù mọi thứ đều sẵn sàng;
  • gọi tool với tham số sai;
  • “hallucinate” kết quả, bỏ qua MCP của bạn.

Vì vậy, sự cố không chỉ là HTTP 500, mà còn cả tình huống mọi metric backend đều xanh, nhưng người dùng đồng loạt phàn nàn: “bot chậm và không hiển thị quà” — bởi vì model ngừng gọi suggest_gifts hoặc nhầm lẫn tham số. Đây là sự cố chất lượng (Quality incident).

Thuận tiện là phân loại sự cố theo các nhóm:

Danh mục Ví dụ triệu chứng Ví dụ chỉ số (SLI)
Availability MCP không phản hồi, “Error talking to app” trong ChatGPT % phản hồi thành công /mcp
Latency chọn gợi ý quà tặng mất hơn 10 giây p95 thời gian gọi suggest_gifts
Quality model không gọi đúng tool, nhầm lẫn đơn vị tiền tệ tỷ lệ yêu cầu không có tool-call khi có yêu cầu rõ ràng
Commerce checkout không thực hiện được, tiền không được xử lý checkout_success_rate

Sự cố là thời điểm chỉ số thực tế vượt ra ngoài SLO đã thỏa thuận trước. Ví dụ:

  • chúng ta đã đặt: p95 chọn quà < 4 giây. Giờ là 9 giây;
  • chúng ta muốn 99% checkout mỗi tuần thành công, nhưng giờ còn 94%;
  • chúng ta kỳ vọng trong các kịch bản mua hàng, model gần như luôn gọi create_checkout_session, nhưng log cho thấy số “bỏ sót” tăng đột biến.

Quan trọng: sự cố không phải là “ai đó than phiền trong chat”. Khiếu nại là tín hiệu kích hoạt; quyết định “đúng, đây là sự cố” được đưa ra dựa trên SLO/SLI và dashboard.

2. Cách SLO/SLI trở thành sự cố

Trong module về observability, bạn đã đặt ra các chỉ số chính: latency, availability, error-rate, tỷ lệ checkout thành công. Bây giờ dùng chúng như “người gác cổng”.

Kịch bản đơn giản nhất: chúng ta có SLO cho checkout_success_rate. Chúng ta ghi log sự kiện theo cấu trúc:

// Ví dụ log sự kiện checkout trong MCP-server
logger.info({
  event: 'checkout_result',
  request_id,
  user_id,
  checkout_session_id,
  status: 'success', // hoặc 'failed'
  error_code: null,
});

Trên các log này, ta xây một metric: tỷ lệ status = "success" trong tất cả checkout_result trong N phút/giờ gần đây. Khi tỷ lệ này xuống dưới ngưỡng (ví dụ 95% trong 10 phút), hệ thống giám sát gửi cảnh báo vào kênh on-call. Đây chính là phát hiện sự cố: SLI vượt khỏi khung SLO.

Cảnh báo cũng có thể kích hoạt bởi:

  • tăng error_rate của các công cụ suggest_gifts, search_products;
  • tăng p95/p99 latency;
  • giảm bất thường số lượng workflow_completed (người dùng không đi hết kịch bản);
  • tăng bất thường chi phí LLM mà không tăng lưu lượng (sự cố kinh tế).

Tất cả điều này chỉ khả thi vì ta log có cấu trúc, chứ không viết vào log kiểu “có gì đó lại sai với checkout”. Khi metric và cảnh báo đã được cấu hình, ta biết cách nhận ra khi nào có vấn đề. Câu hỏi tiếp theo: sau khi phát hiện thì chuyện gì xảy ra, ai và bằng cách nào phản ứng?

3. Vòng đời sự cố: từ phát hiện đến post-mortem

Để không sống mãi trong chế độ chữa cháy, hữu ích khi mô tả pipeline chuẩn của sự cố. Nhiều đội SRE chuẩn hóa nó thành chuỗi:

flowchart TD
    D["Detection (phát hiện)"] --> T["Triage (đánh giá mức độ nghiêm trọng)"]
    T --> M["Mitigation (giảm thiểu nhanh)"]
    M --> R["Resolution (khắc phục triệt để)"]
    R --> P["Post-mortem (tổng kết và cải tiến)"]

Cùng xem từng bước với ví dụ GiftGenius.

Detection — làm sao biết mọi thứ đang tệ

Việc phát hiện có thể tự động hoặc thủ công.

Tự động — là các cảnh báo từ hệ thống giám sát dựa trên SLO/SLI:

  • PagerDuty / Opsgenie / email / Slack bot cảnh báo: SEV-1: checkout_success_rate < 60% trong 10 phút;
  • cảnh báo về latency: p95(suggest_gifts) > 10 s;
  • bất thường về chi phí: “Chi phí LLM tăng gấp 2 lần với cùng số lượng workflow_completed”.

Phát hiện thủ công — khi hỗ trợ (hoặc chính bạn qua Telegram) nhận được hàng loạt tin nhắn “không thanh toán được”, “widget quay mãi”. Đôi khi điều này làm nổi bật vấn đề trước khi giám sát bắt kịp.

Kết luận thực tế: ngay cả khi bạn chưa có hệ thống giám sát hoàn hảo, hãy tập nhìn mọi khiếu nại hàng loạt của người dùng qua lăng kính metric: “đằng sau đó là metric nào và đo thế nào?”.

Triage — phân loại và ưu tiên

Sau khi phát hiện, cần trả lời hai câu hỏi: mức độ tệ đến đâuai sẽ vào sửa.

Hữu ích khi có thang mức độ đơn giản:

  • SEV-1: nghiêm trọng nhất — người dùng không thể mua hàng, App không hoạt động theo kịch bản chính (ví dụ checkout=0 khi vẫn có traffic).
  • SEV-2: nghiêm trọng nhưng chỉ suy giảm — một phần người dùng không hoàn tất kịch bản, latency tăng mạnh nhưng không về 0.
  • SEV-3: lỗi nhỏ — một tool phụ đôi khi lỗi, chỉ vỡ ở edge case.

Với GiftGenius, các sự cố commerce gần như luôn là SEV-1: nếu tiền không lưu thông, đó không chỉ là vấn đề kỹ thuật mà còn là thiệt hại trực tiếp về doanh thu và niềm tin.

Ở bước này cũng chỉ định on-call (hoặc chính bạn nếu đội chỉ có một người) và đưa ra quyết định: “Đúng, đây là sự cố chính thức SEV‑1, làm theo runbook số N” (runbook là hướng dẫn từng bước đã được soạn sẵn; cấu trúc sẽ bàn ở phần riêng).

Mitigation — dừng “chảy máu”

Mitigation không phải là tìm nguyên nhân gốc, mà là các biện pháp nhanh để giảm đau cho người dùng. Ví dụ:

  • rollback bản phát hành gần nhất của MCP/Agents/ACP;
  • tắt feature flag gây vấn đề;
  • chuyển GiftGenius sang chế độ “viewer”: vẫn hiển thị khuyến nghị nhưng không cho phép mua;
  • giảm tải tạm thời (rate limiting) hoặc tắt các tool nặng.

Ví dụ điển hình cho “chế độ suy giảm” trong MCP của chúng ta:

// Pseudo-code: cờ toàn cục có thể chuyển nhanh
let checkoutDisabled = false;

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

export async function createCheckoutSession(args: CheckoutArgs) {
  if (checkoutDisabled) {
    // Thông báo cho model rằng thanh toán tạm thời không khả dụng
    return {
      error: 'checkout_temporarily_disabled',
      message: 'Thanh toán tạm thời không khả dụng, hãy hiển thị lời giải thích cho người dùng.',
    };
  }

  // logic tạo session như bình thường
}

Trong hệ thống feature flag, bạn có thể gọi setCheckoutDisabled(true) như một phần của mitigation: người dùng ít nhất sẽ không nhận 500 hoặc thanh toán treo, mà thấy thông báo rõ ràng.

Resolution — khắc phục triệt để

Khi “chảy máu đã dừng”, bạn có thời gian tìm nguyên nhân gốc và sửa nó:

  • bug trong code MCP/ACP;
  • vấn đề với nhà cung cấp bên ngoài (Stripe, cổng thanh toán);
  • giới hạn OpenAI API (429, quá tải);
  • prompt hỏng hoặc đổi model khiến nó ngừng gọi tool.

Resolution thường bao gồm:

  • fix (patch/rollback/config);
  • triển khai lên staging, rồi lên production;
  • kiểm tra tất cả SLI/SLO;
  • đưa các flag về trạng thái bình thường.

Post-mortem — học từ lỗi

Sau sự cố, đặc biệt SEV‑1/SEV‑2, thực hiện post-mortem: tài liệu trả lời trung thực các câu hỏi:

  • điều gì đã xảy ra (theo sự kiện và timeline);
  • phát hiện bằng cách nào;
  • đã phản ứng ra sao;
  • điều gì làm tốt và chưa tốt;
  • bạn sẽ thay đổi gì để không lặp lại.

Post-mortem không phải để tìm người chịu lỗi, mà để cải thiện hệ thống và quy trình. Dựa trên đó, cập nhật runbook, cảnh báo, thậm chí cả kiến trúc.

4. Vai trò và trách nhiệm: ngay cả khi bạn “một mình một đội”

Để pipeline sự cố trên hoạt động trong thực tế, cần thống nhất trước ai chịu trách nhiệm quyết định gì trong lúc “cháy nhà”. Dù đội của bạn rất nhỏ, nên chuẩn hóa vai trò khi có sự cố. Điều này giảm hỗn loạn.

Thường có các vai trò:

  • Kỹ sư on-call — người nhận cảnh báo đầu tiên và đưa ra quyết định kỹ thuật để ổn định (rollback, feature flags, giải pháp tạm).
  • Incident commander — điều phối quy trình: ghi timeline, quyết định ưu tiên, bảo đảm đội không chạy tán loạn. Ở micro-team có thể là chính on-call đổi “mũ”.
  • Truyền thông — phụ trách liên lạc với người dùng và các bên kinh doanh: thông báo trên Slack, trang trạng thái, giao diện App (widget/chat), cửa hàng ChatGPT.
  • Scribe — ghi lại các bước và sự kiện quan trọng; dựa vào đó viết post-mortem.

Trong đội một người, cả bốn vai trò đều là bạn; chỉ cần chủ động chuyển “chế độ”: “giờ tôi là kỹ sư và đang sửa”, “giờ tôi đang truyền thông”, “giờ tôi ghi timeline”.

5. Runbook: quy chuẩn thay cho trí nhớ

Runbook là tài liệu mô tả từng bước cần làm cho một loại sự cố cụ thể: xem biểu đồ nào, bấm nút nào, có thể hy sinh điều gì. Nó giảm bớt ứng biến và mức căng thẳng.

Cấu trúc runbook

Thường runbook gồm:

  1. Mô tả ngắn về sự cố và cách phát hiện. Ví dụ: “Tăng lỗi ACP checkout > 5% trong 5 phút” hoặc “Error talking to app cho >20% yêu cầu”.
  2. Scope — ai bị ảnh hưởng: toàn bộ traffic, chỉ một vùng, hay chỉ tool cụ thể.
  3. Xem ở đâu: link tới dashboard (SLO cho checkout, error-rate MCP, log theo tool_name = create_checkout_session), tới MCP Inspector, v.v.
  4. Các bước mitigation nhanh: “kiểm tra trạng thái Stripe”, “rollback bản phát hành ACP gần nhất”, “bật chế độ chỉ khuyến nghị, không thanh toán”.
  5. Các bước phân tích triệt để và sửa lỗi.
  6. Những thứ cần cập nhật sau cùng: cảnh báo, code, tài liệu.

Ví dụ mini runbook cho GiftGenius (checkout bị lỗi)

Mô tả dưới dạng dữ liệu có cấu trúc cho gần với code:

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: 'Tăng lỗi checkout trong GiftGenius',
  severity: 'SEV-1',
  detection: 'Cảnh báo: checkout_success_rate < 60% trong 10 phút',
  steps: [
    {
      title: 'Kiểm tra trạng thái bên ngoài',
      description: 'Mở trang trạng thái Stripe và ACP backend, bảo đảm không có outage toàn cục.',
    },
    {
      title: 'Kiểm tra các bản phát hành gần đây',
      description: 'Xem có deploy MCP/ACP trong 30 phút qua không. Nếu cần thì rollback.',
    },
  ],
};

Trong runbook thực tế bạn sẽ thêm nhiều bước hơn: bật feature flag read-only, hiển thị banner trong widget, thu thập log cho post-mortem.

Ví dụ nội dung cho widget khi có sự cố commerce

Trong runbook, nên soạn trước nội dung cho người dùng. Ví dụ, widget của GiftGenius có thể hiển thị:

“Hiện chúng tôi đang gặp sự cố kỹ thuật tạm thời với thanh toán. Bạn vẫn có thể lưu các ý tưởng quà tặng yêu thích và chúng ta sẽ hoàn tất mua hàng sau.”

Nội dung này có thể được gắn vào trạng thái UI:

// Pseudocode cho trạng thái widget
const [checkoutAvailable, setCheckoutAvailable] = useState(true);

if (!checkoutAvailable) {
  return (
    <Alert>
      Thanh toán tạm thời không khả dụng. Bạn vẫn có thể xem và lưu ý tưởng quà tặng.
    </Alert>
  );
}

6. Thực hành với GiftGenius: code xoay quanh sự cố

Để chủ đề không chỉ mang tính tổ chức, hãy xem vài đoạn code trực tiếp hữu ích cho incident management.

Health-check endpoint cho MCP/Backend

Công cụ đơn giản nhưng quan trọng — health check. Trong Next.js 16 có thể làm qua route handler:

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

export function GET(_req: NextRequest) {
  // Có thể bổ sung kiểm tra DB, hàng đợi, v.v.
  return NextResponse.json({
    status: 'ok',
    mcp: 'healthy',
    timestamp: new Date().toISOString(),
  });
}

Hệ thống giám sát sẽ thăm dò định kỳ /api/health. Nếu thay vì 200 OK lại là timeout hoặc 5xx, đó là tín hiệu rõ ràng của sự cố Availability (MCP không sống).

Phân loại sự cố theo chỉ số

Ở phía dịch vụ phân tích hoặc script admin backend, có thể giữ logic đơn giản để xác định mức độ:

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'; // tiền không luân chuyển
  if (ctx.giftSearchErrorRate > 0.3 || ctx.p95GiftSearchMs > 8000) return 'SEV-2';
  return null; // chưa phải sự cố
}

Đoạn này có thể chạy theo cron hoặc kích hoạt từ giám sát: khi trả về SEV‑1, tự động tạo sự cố trong hệ thống của bạn và gửi thông báo cho on-call.

Ghi log các sự kiện chính của sự cố

Sự cố không chỉ là số liệu, mà còn là các sự kiện: khi sự cố được tạo, thay đổi, đóng. Nên giữ chúng trong log riêng.

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(),
  });
}

Ví dụ, khi bật chế độ “read-only” cho GiftGenius:

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

Sau đó, các sự kiện này dễ dàng được tìm và đối chiếu với chuỗi thời gian của các metric.

7. Lịch vận hành: cuộc sống sau “đã sửa xong!”

Incident management không chỉ là dập lửa, mà còn là phòng ngừa định kỳ. Trong thực hành SRE, chu trình vận hành thường được mô tả như một lịch vận hành với các lần rà soát định kỳ về SLO, chi phí và bảo mật.

Có thể chia hoạt động theo chu kỳ.

Hàng tuần

Mỗi tuần (hoặc hai tuần) nên:

  • xem lại các SLO chính: latency, error-rate, checkout thành công, tỷ lệ sự cố theo nhóm;
  • xem liệu có cảnh báo nào trong tuần “tự êm” không và quyết định có nên siết/nới ngưỡng;
  • rút gọn post-mortem của ít nhất một sự cố (kể cả SEV‑3) — luyện cơ post-mortem.

Hàng tháng

Mỗi tháng nên:

  • rà soát chi phí (LLM, phí ACP/Stripe, hạ tầng) và đối chiếu với doanh thu — liên kết với các chủ đề 1–2 của module 19;
  • xem metric sản phẩm: activation, retention, chuyển đổi workflow_completedcheckout_success — liên kết với module về marketing và tăng trưởng;
  • đi qua nhật ký bảo mật để tìm bất thường: mẫu đăng nhập lạ, lỗi ủy quyền, đột biến yêu cầu (cầu nối tới module bảo mật).

Hàng quý

Mỗi quý bạn nên:

  • xoay vòng secret: API key OpenAI, Stripe, OAuth client, v.v.;
  • kiểm tra SLO có lỗi thời không: có thể App đã lớn, p95 2 giây thay vì 1 giây là bình thường, hoặc ngược lại bạn có thể siết mục tiêu;
  • xem lại runbook: loại sự cố mới, phụ thuộc cập nhật (SDK, MCP-spec, v.v.).

Có thể quản lý lịch đơn giản bằng một trang Wiki hoặc README trong repo GiftGenius: điều quan trọng là nó “sống” và được cập nhật.

8. Sự cố, tiền và sản phẩm: vì sao cháy commerce là nóng nhất

Module 19 nói về kinh tế và “đời sống vận hành” của App, và ở đây sự cố gắn chặt với tiền. Sự cố commerce — khi checkout không chạy, tiền bị chặn hoặc bị trừ hai lần — hầu như luôn ưu tiên cao hơn, so với, chẳng hạn, timeout ngẫu nhiên khi tìm quà.

Lý do đơn giản:

  • mất doanh thu trực tiếp ngay lúc đó;
  • nguy cơ mất niềm tin (người dùng bị trừ tiền mà không nhận hàng khó quay lại);
  • hệ quả pháp lý và danh tiếng tiềm ẩn.

Do đó, trong danh mục sự cố của GiftGenius, sự cố commerce cần được đánh dấu rõ là SEV‑1 với SLO phản ứng nghiêm ngặt (ví dụ “on-call phản hồi trong 15 phút, mitigation trong vòng một giờ”).

Các bất thường kinh tế (ví dụ chi phí LLM tăng mạnh mà doanh thu không tăng) — cũng là sự cố, nhưng thường ở mức SEV‑2: chúng không phá UX ngay lập tức nhưng có thể “ăn” hết biên lợi nhuận nếu không để ý.

Về phía sản phẩm, bất kỳ sự cố lớn nào cũng là dịp suy nghĩ:

  • workflow có quá phức tạp không (có thể đơn giản hơn sẽ ổn định hơn);
  • có nên thêm kịch bản fallback: ví dụ nếu MCP không phản hồi, model ít nhất vẫn đưa ra lời khuyên mà không cần dữ liệu ngoài;
  • có cần thay đổi UX để truyền thông minh bạch về vấn đề, thay vì che giấu.

9. Bài tập nhỏ (tự thực hành)

Dù là bài giảng, mình rất khuyến nghị bạn thực sự làm các bước sau trên GiftGenius của mình:

  1. Mô tả trong một tài liệu ít nhất hai runbook:
    • “Lỗi thanh toán hàng loạt (checkout)”;
    • “MCP không phản hồi / ChatGPT hiển thị Error talking to app”.
  2. Lập lịch vận hành cho một tháng:
    • các SLO bạn sẽ xem mỗi tuần;
    • tổng quan chi phí bạn sẽ làm vào cuối tháng;
    • các kiểm tra bảo mật sẽ đưa vào (ít nhất là cơ bản).

Việc này tốn vài giờ, nhưng sẽ thay đổi mạnh cách bạn nhìn về ứng dụng của mình: nó không chỉ là code mà là một dịch vụ sống.

Các lỗi điển hình trong incident management cho ChatGPT Apps

Lỗi số 1: “Sự cố chỉ là khi mọi thứ sập”
Nhiều người quen coi sự cố chỉ là MCP hay DB ngã hẳn. Trong AI‑Apps, các sự cố “mềm” về chất lượng thường đau hơn: model ngừng gọi tool cần thiết, luồng checkout trở nên rối rắm, người dùng không đi hết hành trình dù các metric HTTP đều xanh. Nếu bạn không coi các tình huống đó là sự cố và không mổ xẻ chúng, chất lượng App sẽ suy giảm âm thầm.

Lỗi số 2: Thiếu SLO rõ ràng và ranh giới “vận hành bình thường”
Không có SLO chính thức, mọi tranh luận về sự cố biến thành “tôi thấy chậm” vs “máy tôi nhanh”. Vì vậy SLO là nền tảng cho incident management: chúng làm mức độ nghiêm trọng trở nên khách quan.

Lỗi số 3: Ứng biến thay vì runbook
Cảnh tượng phổ biến: có cảnh báo, mọi người hoảng loạn nhảy vào prod, người thì rollback, người thì chỉnh config, một giờ sau “hình như đã sửa”, nhưng không ai nhớ cái gì thực sự giúp. Không có runbook, mỗi sự cố là một tiểu hỗn loạn, và đội không học được. Chỉ một runbook đơn giản cho sự cố checkout cũng giảm mạnh stress.

Lỗi số 4: Bỏ qua truyền thông với người dùng
Đôi khi kỹ sư âm thầm sửa hệ thống, còn người dùng chỉ thấy “vòng quay” và lỗi “đã có sự cố”. Với kịch bản commerce điều này đặc biệt độc hại: mọi người lo lắng về tiền. Cần có sẵn mẫu thông báo trong widget, mô tả App và, khi cần, các kênh bên ngoài để nói rõ vấn đề và thời gian dự kiến khắc phục.

Lỗi số 5: Đổ lỗi “OpenAI có vấn đề” mà không xem phần của mình
Dễ đổ hết cho “OpenAI chậm”, nhưng thực tế cho thấy ngay cả khi upstream có vấn đề, bạn vẫn làm được nhiều thứ phía mình: xử lý timeout và lỗi đúng cách, chuyển sang chế độ không MCP, giảm số lần retry để không làm trầm trọng thêm. Khái niệm shared responsibility ngụ ý bạn chịu trách nhiệm cho phần của mình trong chuỗi, ngay cả khi một nhà cung cấp hoạt động thiếu ổn định.

Lỗi số 6: Không có post-mortem và chu trình vận hành
Nếu sự cố kết thúc bằng câu “thôi, xong rồi, tiếp tục thôi”, còn tài liệu, cảnh báo và code không đổi — hệ thống sẽ lặp lại lỗi cũ. Post-mortem, các rà soát định kỳ SLO, chi phí và bảo mật — không phải quan liêu, mà là cách thỏa thuận với chính mình và đội trong tương lai, để sau một năm GiftGenius đáng tin cậy hơn chứ không mong manh hơn.

Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION